comparison postdog/main.c @ 161:87d8d3eb3491

[PostDog] WIP to make it more mordern looking
author June Park <parkjune1995@gmail.com>
date Thu, 15 Jan 2026 08:29:26 -0800
parents 05cf9467a1c3
children 058de208e640
comparison
equal deleted inserted replaced
160:948de3f54cea 161:87d8d3eb3491
1 #include <stdio.h> 1 #include <stdio.h>
2 #include <stdlib.h> 2 #include <stdlib.h>
3 #include <string.h> 3 #include <string.h>
4 #include <time.h> 4 #include <time.h>
5 #include <sys/stat.h> 5 #include <sys/stat.h>
6 #include <pthread.h> 6 #include <uv.h>
7 7
8 #ifdef _WIN32 8 #ifdef _WIN32
9 #include <direct.h> 9 #include <direct.h>
10 #include <io.h> 10 #include <io.h>
11 #define mkdir(path, mode) _mkdir(path) 11 #define mkdir(path, mode) _mkdir(path)
16 #include <dirent.h> 16 #include <dirent.h>
17 #include <unistd.h> 17 #include <unistd.h>
18 #endif 18 #endif
19 19
20 20
21 #include "third_party/raylib/include/raylib.h"
22 #define RAYGUI_IMPLEMENTATION
23 #include "third_party/raylib/include/raygui.h"
24
25 #include "dowa/dowa.h" 21 #include "dowa/dowa.h"
26 #include "seobeo/seobeo.h" 22 #include "seobeo/seobeo.h"
23 #include "third_party/raylib/include/raylib.h"
24 #include "third_party/raylib/include/raygui.h"
25 #include "third_party/raylib/custom.h"
27 26
28 #ifndef POSTDOG_PATHS 27 #ifndef POSTDOG_PATHS
29 #define POSTDOG_PATHS "/Users/mrjunejune/zenbu/postdog/history" 28 #define POSTDOG_PATHS "/Users/mrjunejune/zenbu/postdog/history"
30 #endif 29 #endif
31 30
37 #define DEFAULT_TEXT_BUFFER_LENGTH 1024 * 4 36 #define DEFAULT_TEXT_BUFFER_LENGTH 1024 * 4
38 #define URL_TEXT_BUFFER_LENGTH 1024 * 10 37 #define URL_TEXT_BUFFER_LENGTH 1024 * 10
39 #define BODY_BUFFER_LENGTH 1024 * 1024 * 5 38 #define BODY_BUFFER_LENGTH 1024 * 1024 * 5
40 #define RESULT_BUFFER_LENGTH 1024 * 1024 * 5 39 #define RESULT_BUFFER_LENGTH 1024 * 1024 * 5
41 40
41 #define URL_TEXT_DEFAULT "https://httpbin.org/get"
42 #define HEADER_TEXT_DEFAULT "Content-Type: application/json"
43 #define BODY_TEXT_DEFAULT ""
44 #define GET_PARAM_TEXT_DEFAULT "foo bar"
45
42 // ============================================================================ 46 // ============================================================================
43 // TextArea Component 47 // TextArea Component
44 // ============================================================================ 48 // ============================================================================
45 49
46 #define TEXT_SIZE_DEFAULT 10 // used to calcualte spacing 50 #define TEXT_SIZE_DEFAULT 10 // used to calcualte spacing
47 #define TEXT_AREA_FONT_SIZE 16
48 #define TEXT_AREA_LINE_HEIGHT 20 51 #define TEXT_AREA_LINE_HEIGHT 20
49 #define TEXT_AREA_PADDING 8 52 #define TEXT_AREA_PADDING 30
50 #define TEXT_AREA_CURSOR_WIDTH 2 53 #define TEXT_AREA_CURSOR_WIDTH 2
51 #define TEXT_AREA_MAX_UNDO_STATES 64 54 #define TEXT_AREA_MAX_UNDO_STATES 64
52 #define TEXT_AREA_MAX_INSTANCES 8 55 #define TEXT_AREA_MAX_INSTANCES 8
53 56
54 typedef struct { 57 typedef struct {
182 char temp[1024]; 185 char temp[1024];
183 int len = TA_Min_Int(end - start, 1023); 186 int len = TA_Min_Int(end - start, 1023);
184 strncpy(temp, text + start, len); 187 strncpy(temp, text + start, len);
185 temp[len] = '\0'; 188 temp[len] = '\0';
186 189
187 return MeasureTextEx(GuiGetFont(), temp, font_size, TEXT_SIZE_DEFAULT/TEXT_AREA_FONT_SIZE).x; 190 return MeasureTextEx(GuiGetFont(), temp, font_size, TEXT_SIZE_DEFAULT/GuiGetStyle(DEFAULT, TEXT_SIZE)).x;
188 } 191 }
189 192
190 static int GetCharIndexFromPos(const char *text, Rectangle bounds, Vector2 pos, 193 static int GetCharIndexFromPos(const char *text, Rectangle bounds, Vector2 pos,
191 boolean wrap, float scroll_y, int font_size, int line_height) { 194 boolean wrap, float scroll_y, int font_size, int line_height) {
192 if (!text || strlen(text) == 0) return 0; 195 if (!text || strlen(text) == 0) return 0;
475 } 478 }
476 } 479 }
477 480
478 // Content area 481 // Content area
479 float content_height = GetContentHeight(text, bounds, should_text_wrap, 482 float content_height = GetContentHeight(text, bounds, should_text_wrap,
480 TEXT_AREA_FONT_SIZE, TEXT_AREA_LINE_HEIGHT); 483 GuiGetStyle(DEFAULT, TEXT_SIZE), TEXT_AREA_LINE_HEIGHT);
481 float visible_height = bounds.height - TEXT_AREA_PADDING * 2; 484 float visible_height = bounds.height - TEXT_AREA_PADDING * 2;
482 float max_scroll = TA_Max_Float(0, content_height - visible_height); 485 float max_scroll = TA_Max_Float(0, content_height - visible_height);
483 486
484 // Handle scrolling 487 // Handle scrolling
485 float wheel = GetMouseWheelMove(); 488 float wheel = GetMouseWheelMove();
501 } 504 }
502 505
503 // Mouse Selection 506 // Mouse Selection
504 if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && mouse_in_bounds) { 507 if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && mouse_in_bounds) {
505 int click_pos = GetCharIndexFromPos(text, bounds, mouse_pos, should_text_wrap, 508 int click_pos = GetCharIndexFromPos(text, bounds, mouse_pos, should_text_wrap,
506 state->scroll_offset_y, TEXT_AREA_FONT_SIZE, 509 state->scroll_offset_y, GuiGetStyle(DEFAULT, TEXT_SIZE),
507 TEXT_AREA_LINE_HEIGHT); 510 TEXT_AREA_LINE_HEIGHT);
508 state->cursor_pos = click_pos; 511 state->cursor_pos = click_pos;
509 state->selection_start = -1; 512 state->selection_start = -1;
510 state->selection_end = -1; 513 state->selection_end = -1;
511 state->is_selecting = TRUE; 514 state->is_selecting = TRUE;
513 state->last_blink_time = current_time; 516 state->last_blink_time = current_time;
514 } 517 }
515 518
516 if (state->is_selecting && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { 519 if (state->is_selecting && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) {
517 int drag_pos = GetCharIndexFromPos(text, bounds, mouse_pos, should_text_wrap, 520 int drag_pos = GetCharIndexFromPos(text, bounds, mouse_pos, should_text_wrap,
518 state->scroll_offset_y, TEXT_AREA_FONT_SIZE, 521 state->scroll_offset_y, GuiGetStyle(DEFAULT, TEXT_SIZE),
519 TEXT_AREA_LINE_HEIGHT); 522 TEXT_AREA_LINE_HEIGHT);
520 if (drag_pos != state->cursor_pos) { 523 if (drag_pos != state->cursor_pos) {
521 if (state->selection_start < 0) { 524 if (state->selection_start < 0) {
522 state->selection_start = state->cursor_pos; 525 state->selection_start = state->cursor_pos;
523 } 526 }
846 } 849 }
847 850
848 // Auto-scroll to keep cursor visible 851 // Auto-scroll to keep cursor visible
849 Vector2 cursor_screen = GetCursorScreenPos(text, state->cursor_pos, bounds, 852 Vector2 cursor_screen = GetCursorScreenPos(text, state->cursor_pos, bounds,
850 should_text_wrap, state->scroll_offset_y, 853 should_text_wrap, state->scroll_offset_y,
851 TEXT_AREA_FONT_SIZE, TEXT_AREA_LINE_HEIGHT); 854 GuiGetStyle(DEFAULT, TEXT_SIZE), TEXT_AREA_LINE_HEIGHT);
852 855
853 float visible_top = bounds.y + TEXT_AREA_PADDING; 856 float visible_top = bounds.y + TEXT_AREA_PADDING;
854 float visible_bottom = bounds.y + bounds.height - TEXT_AREA_PADDING - TEXT_AREA_LINE_HEIGHT; 857 float visible_bottom = bounds.y + bounds.height - TEXT_AREA_PADDING - TEXT_AREA_LINE_HEIGHT;
855 858
856 if (cursor_screen.y < visible_top) { 859 if (cursor_screen.y < visible_top) {
861 864
862 state->scroll_offset_y = TA_Max_Float(0, TA_Min_Float(state->scroll_offset_y, max_scroll)); 865 state->scroll_offset_y = TA_Max_Float(0, TA_Min_Float(state->scroll_offset_y, max_scroll));
863 } 866 }
864 867
865 // Drawing 868 // Drawing
866 DrawRectangleRec(bounds, is_edit_mode ? DARKGRAY : (Color){40, 40, 40, 255}); 869 DrawRectangleRounded(bounds, 0.2, 1, is_edit_mode ? DARKGRAY : (Color){40, 40, 40, 255});
867 DrawRectangleLinesEx(bounds, 1, is_edit_mode ? WHITE : GRAY); 870 // DrawRectangleRec(bounds, is_edit_mode ? DARKGRAY : (Color){40, 40, 40, 255});
871 // DrawRectangleLinesEx(bounds, 1, is_edit_mode ? WHITE : GRAY);
872 DrawRectangleRoundedLines(bounds, 0.2, 1, is_edit_mode ? WHITE : GRAY);
868 873
869 BeginScissorMode((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height); 874 BeginScissorMode((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height);
870 875
871 float content_x = bounds.x + TEXT_AREA_PADDING; 876 float content_x = bounds.x + TEXT_AREA_PADDING;
872 float content_y = bounds.y + TEXT_AREA_PADDING - state->scroll_offset_y; 877 float content_y = bounds.y + TEXT_AREA_PADDING - state->scroll_offset_y;
887 boolean is_end = (i == text_len); 892 boolean is_end = (i == text_len);
888 boolean is_newline = (!is_end && text[i] == '\n'); 893 boolean is_newline = (!is_end && text[i] == '\n');
889 boolean should_draw_line = is_end || is_newline; 894 boolean should_draw_line = is_end || is_newline;
890 895
891 if (should_text_wrap && !is_end && !is_newline) { 896 if (should_text_wrap && !is_end && !is_newline) {
892 int line_width = MeasureTextRange(text, line_char_start, i + 1, TEXT_AREA_FONT_SIZE); 897 int line_width = MeasureTextRange(text, line_char_start, i + 1, GuiGetStyle(DEFAULT, TEXT_SIZE));
893 if (line_width > content_width && i > line_char_start) { 898 if (line_width > content_width && i > line_char_start) {
894 should_draw_line = TRUE; 899 should_draw_line = TRUE;
895 } 900 }
896 } 901 }
897 902
900 905
901 if (sel_min < line_end && sel_max > line_char_start) { 906 if (sel_min < line_end && sel_max > line_char_start) {
902 int highlight_start = TA_Max_Int(sel_min, line_char_start); 907 int highlight_start = TA_Max_Int(sel_min, line_char_start);
903 int highlight_end = TA_Min_Int(sel_max, line_end); 908 int highlight_end = TA_Min_Int(sel_max, line_end);
904 909
905 float x1 = content_x + MeasureTextRange(text, line_char_start, highlight_start, TEXT_AREA_FONT_SIZE); 910 float x1 = content_x + MeasureTextRange(text, line_char_start, highlight_start, GuiGetStyle(DEFAULT, TEXT_SIZE));
906 float x2 = content_x + MeasureTextRange(text, line_char_start, highlight_end, TEXT_AREA_FONT_SIZE); 911 float x2 = content_x + MeasureTextRange(text, line_char_start, highlight_end, GuiGetStyle(DEFAULT, TEXT_SIZE));
907 float y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT; 912 float y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT;
908 913
909 DrawRectangle((int)x1, (int)y, (int)(x2 - x1), TEXT_AREA_LINE_HEIGHT, 914 DrawRectangle((int)x1, (int)y, (int)(x2 - x1), TEXT_AREA_LINE_HEIGHT,
910 Fade(SKYBLUE, 0.5f)); 915 Fade(SKYBLUE, 0.5f));
911 } 916 }
925 boolean is_end = (i == text_len); 930 boolean is_end = (i == text_len);
926 boolean is_newline = (!is_end && text[i] == '\n'); 931 boolean is_newline = (!is_end && text[i] == '\n');
927 boolean should_draw_line = is_end || is_newline; 932 boolean should_draw_line = is_end || is_newline;
928 933
929 if (!is_end && !is_newline) { 934 if (!is_end && !is_newline) {
930 int line_width = MeasureTextRange(text, line_char_start, i + 1, TEXT_AREA_FONT_SIZE); 935 int line_width = MeasureTextRange(text, line_char_start, i + 1, GuiGetStyle(DEFAULT, TEXT_SIZE));
931 if (line_width > content_width && i > line_char_start) { 936 if (line_width > content_width && i > line_char_start) {
932 should_draw_line = TRUE; 937 should_draw_line = TRUE;
933 } 938 }
934 } 939 }
935 940
942 Vector2 draw_text_vector = { 947 Vector2 draw_text_vector = {
943 .x = content_x, 948 .x = content_x,
944 .y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT 949 .y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT
945 }; 950 };
946 DrawTextEx(GuiGetFont(), line_buffer, draw_text_vector, 951 DrawTextEx(GuiGetFont(), line_buffer, draw_text_vector,
947 TEXT_AREA_FONT_SIZE, TEXT_SIZE_DEFAULT/TEXT_AREA_FONT_SIZE, WHITE); 952 GuiGetStyle(DEFAULT, TEXT_SIZE), TEXT_SIZE_DEFAULT/GuiGetStyle(DEFAULT, TEXT_SIZE), WHITE);
948 953
949 visual_line++; 954 visual_line++;
950 line_char_start = is_newline ? i + 1 : i; 955 line_char_start = is_newline ? i + 1 : i;
951 } else if (is_newline) { 956 } else if (is_newline) {
952 visual_line++; 957 visual_line++;
968 Vector2 draw_text_vector = { 973 Vector2 draw_text_vector = {
969 .x = content_x, 974 .x = content_x,
970 .y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT 975 .y = content_y + visual_line * TEXT_AREA_LINE_HEIGHT
971 }; 976 };
972 DrawTextEx(GuiGetFont(), line_buffer, draw_text_vector , 977 DrawTextEx(GuiGetFont(), line_buffer, draw_text_vector ,
973 TEXT_AREA_FONT_SIZE, TEXT_SIZE_DEFAULT/TEXT_AREA_FONT_SIZE, WHITE); 978 GuiGetStyle(DEFAULT, TEXT_SIZE), TEXT_SIZE_DEFAULT/GuiGetStyle(DEFAULT, TEXT_SIZE), WHITE);
974 } 979 }
975 visual_line++; 980 visual_line++;
976 line_start = i + 1; 981 line_start = i + 1;
977 } 982 }
978 } 983 }
980 985
981 // Draw cursor 986 // Draw cursor
982 if (is_edit_mode && state->cursor_visible) { 987 if (is_edit_mode && state->cursor_visible) {
983 Vector2 cursor_pos = GetCursorScreenPos(text, state->cursor_pos, bounds, 988 Vector2 cursor_pos = GetCursorScreenPos(text, state->cursor_pos, bounds,
984 should_text_wrap, state->scroll_offset_y, 989 should_text_wrap, state->scroll_offset_y,
985 TEXT_AREA_FONT_SIZE, TEXT_AREA_LINE_HEIGHT); 990 GuiGetStyle(DEFAULT, TEXT_SIZE), TEXT_AREA_LINE_HEIGHT);
986 991
987 DrawRectangle((int)cursor_pos.x, (int)cursor_pos.y, 992 DrawRectangle((int)cursor_pos.x, (int)cursor_pos.y,
988 TEXT_AREA_CURSOR_WIDTH, TEXT_AREA_LINE_HEIGHT, WHITE); 993 TEXT_AREA_CURSOR_WIDTH, TEXT_AREA_LINE_HEIGHT, WHITE);
989 } 994 }
990 995
1064 #define TEXT_AREA_ID_INPUT_PARAMS 3 1069 #define TEXT_AREA_ID_INPUT_PARAMS 3
1065 #define TEXT_AREA_ID_INPUT_WS 4 1070 #define TEXT_AREA_ID_INPUT_WS 4
1066 #define TEXT_AREA_ID_RESULT 5 1071 #define TEXT_AREA_ID_RESULT 5
1067 1072
1068 static uint32 counter = 0; 1073 static uint32 counter = 0;
1074 static uv_mutex_t history_mutex;
1075 static uv_loop_t *main_loop = NULL;
1069 HistoryItem *history_items = NULL; 1076 HistoryItem *history_items = NULL;
1070 HistoryItem *new_history_items = NULL; 1077 HistoryItem *new_history_items = NULL;
1071 1078
1072 // Global UI state 1079 // Global UI state
1073 char *url_input_text = NULL; 1080 char *url_input_text = NULL;
1075 char **input_body_array = NULL; 1082 char **input_body_array = NULL;
1076 int active_method_dropdown = 0; 1083 int active_method_dropdown = 0;
1077 int active_input_tab = 0; 1084 int active_input_tab = 0;
1078 Seobeo_WebSocket *ws = NULL; 1085 Seobeo_WebSocket *ws = NULL;
1079 boolean WS_BREAK = FALSE; 1086 boolean WS_BREAK = FALSE;
1080 pthread_t websocket_thread_id; 1087 uv_thread_t websocket_thread_id;
1081 Color TEXT_COLOR = BLACK; 1088 Color TEXT_COLOR = BLACK;
1082 boolean LOADING = FALSE; 1089 boolean LOADING = FALSE;
1083 1090
1084 int CompareHistoryItemsByDate(const void *a, const void *b) { 1091 int CompareHistoryItemsByDate(const void *a, const void *b) {
1085 HistoryItem *itemA = (HistoryItem *)a; 1092 HistoryItem *itemA = (HistoryItem *)a;
1096 return strdup(filename); 1103 return strdup(filename);
1097 1104
1098 char *title = malloc(sizeof(char) * 512); 1105 char *title = malloc(sizeof(char) * 512);
1099 if (!fgets(title, 512, file)) { 1106 if (!fgets(title, 512, file)) {
1100 fclose(file); 1107 fclose(file);
1108 free(title);
1101 return strdup(filename); 1109 return strdup(filename);
1102 } 1110 }
1111 fclose(file);
1112
1113 // Strip trailing newline
1114 title[strcspn(title, "\n")] = '\0';
1103 1115
1104 return title; 1116 return title;
1105 } 1117 }
1106 1118
1107 // TODO: Make this into generic fucntion so I can use it across different thing. 1119 // TODO: Make this into generic fucntion so I can use it across different thing.
1149 Dowa_Array_Push(file_arr, item); 1161 Dowa_Array_Push(file_arr, item);
1150 } 1162 }
1151 } 1163 }
1152 closedir(dp); 1164 closedir(dp);
1153 #endif 1165 #endif
1166
1167 // Update the caller's pointer in case array was reallocated
1168 *p_file_arr = file_arr;
1169
1154 int count = Dowa_Array_Length(file_arr); 1170 int count = Dowa_Array_Length(file_arr);
1155 if (count > 1) { 1171 if (count > 1) {
1156 qsort(file_arr, count, sizeof(HistoryItem), CompareHistoryItemsByDate); 1172 qsort(file_arr, count, sizeof(HistoryItem), CompareHistoryItemsByDate);
1157 } 1173 }
1158 } 1174 }
1198 case 3: return "DELETE"; 1214 case 3: return "DELETE";
1199 } 1215 }
1200 return 0; 1216 return 0;
1201 } 1217 }
1202 1218
1203 char *PostDog_Construct_URL(char *filename) 1219 char *PostDog_Construct_URL(char *filename, char *out_buffer, size_t buffer_size)
1204 { 1220 {
1205 char full_file_path[512] = {0}; 1221 snprintf(out_buffer, buffer_size, "%s/%s", POSTDOG_PATHS, filename);
1206 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); 1222 return out_buffer;
1207 return &full_file_path; 1223 }
1208 } 1224
1209 1225 boolean PostDog_History_CreateFile(char *filename, char* values)
1210 void PostDog_History_CreateFile(char *filename, char* values)
1211 { 1226 {
1212 char full_file_path[512] = {0}; 1227 char full_file_path[512] = {0};
1213 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); 1228 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename);
1214 FILE *file = fopen(full_file_path, "w"); 1229 FILE *file = fopen(full_file_path, "w");
1215 if (!file) 1230 if (!file)
1216 { 1231 {
1217 printf("Failed to create a file: %s\n", full_file_path); 1232 fprintf(stderr, "Failed to create a file: %s\n", full_file_path);
1218 return; 1233 return FALSE;
1219 } 1234 }
1220 fwrite(values, 1, strlen(values), file); 1235 fwrite(values, 1, strlen(values), file);
1221 fclose(file); 1236 fclose(file);
1237 return TRUE;
1222 } 1238 }
1223 1239
1224 void PostDog_Request_SaveFile(void) 1240 void PostDog_Request_SaveFile(void)
1225 { 1241 {
1226 const char *method = PostDog_Enum_To_String(active_method_dropdown); 1242 const char *method = PostDog_Enum_To_String(active_method_dropdown);
1267 { 1283 {
1268 perror("Error uuid"); 1284 perror("Error uuid");
1269 exit(EXIT_FAILURE); 1285 exit(EXIT_FAILURE);
1270 } 1286 }
1271 1287
1288 uv_mutex_lock(&history_mutex);
1289
1272 int32 seed = (uint32)time(NULL) ^ counter++; 1290 int32 seed = (uint32)time(NULL) ^ counter++;
1273 Dowa_String_UUID(seed, uuid4); 1291 Dowa_String_UUID(seed, uuid4);
1274 snprintf(filename, 1024, "%s.txt", uuid4); 1292 snprintf(filename, 1024, "%s.txt", uuid4);
1275 PostDog_History_CreateFile(filename, new_file); 1293
1276 1294 if (PostDog_History_CreateFile(filename, new_file))
1277 HistoryItem item = {0}; 1295 {
1278 item.filename = strdup(filename); 1296 HistoryItem item = {0};
1279 item.title = strdup(title); 1297 item.filename = strdup(filename);
1280 item.deleted = FALSE; 1298 item.title = strdup(title);
1281 1299 item.deleted = FALSE;
1282 Dowa_Array_Push(new_history_items, item); 1300
1301 Dowa_Array_Push(new_history_items, item);
1302 }
1303
1304 uv_mutex_unlock(&history_mutex);
1283 Dowa_Arena_Free(arena); 1305 Dowa_Arena_Free(arena);
1284 } 1306 }
1285 1307
1286 void PostDog_Websocket_Listen(void) 1308 void PostDog_Websocket_Listen(void)
1287 { 1309 {
1313 } 1335 }
1314 1336
1315 int PostDog_Websocket_Send(void) 1337 int PostDog_Websocket_Send(void)
1316 { 1338 {
1317 if (Seobeo_WebSocket_Send_Text(ws, input_body_array[active_input_tab]) < 0) 1339 if (Seobeo_WebSocket_Send_Text(ws, input_body_array[active_input_tab]) < 0)
1340 {
1318 snprintf(result_text + strlen(result_text), RESULT_BUFFER_LENGTH - strlen(result_text), 1341 snprintf(result_text + strlen(result_text), RESULT_BUFFER_LENGTH - strlen(result_text),
1319 "Failed to send message\n"); 1342 "Failed to send message\n");
1320 else 1343 return -1;
1321 snprintf(result_text + strlen(result_text), RESULT_BUFFER_LENGTH - strlen(result_text), 1344 }
1322 "\n%s", input_body_array[active_input_tab]); 1345 snprintf(result_text + strlen(result_text), RESULT_BUFFER_LENGTH - strlen(result_text),
1323 } 1346 "\n%s", input_body_array[active_input_tab]);
1324 1347 return 0;
1325 void PostDog_Websocket_Destroy(pthread_t thread_id) 1348 }
1349
1350 void PostDog_Websocket_Destroy(uv_thread_t thread_id)
1326 { 1351 {
1327 Seobeo_WebSocket_Destroy(ws); 1352 Seobeo_WebSocket_Destroy(ws);
1328 pthread_detach(thread_id); 1353 uv_thread_join(&thread_id);
1329 } 1354 }
1330 1355
1331 void *PostDog_Websocket_Start(void *arg) 1356 void PostDog_Websocket_Start(void *arg)
1332 { 1357 {
1333 PostDog_Websocket_Connect(); 1358 PostDog_Websocket_Connect();
1334 PostDog_Websocket_Listen(); 1359 PostDog_Websocket_Listen();
1335 return NULL; 1360 }
1336 } 1361
1337 1362 uv_thread_t PostDog_Websocket_Start_Thread()
1338 pthread_t PostDog_Websocket_Start_Thread() 1363 {
1339 { 1364 uv_thread_t thread_id;
1340 pthread_t thread_id; 1365
1341 1366 if (uv_thread_create(&thread_id, PostDog_Websocket_Start, NULL) != 0)
1342 if (pthread_create(&thread_id, NULL, PostDog_Websocket_Start, NULL) != 0)
1343 { 1367 {
1344 perror("Failed to create thread"); 1368 perror("Failed to create thread");
1345 return 0; 1369 memset(&thread_id, 0, sizeof(thread_id));
1370 return thread_id;
1346 } 1371 }
1347 1372
1348 return thread_id; 1373 return thread_id;
1349 } 1374 }
1350 1375
1351 int PostDog_Http_Request(void) 1376 int PostDog_Http_Request(void)
1352 { 1377 {
1353 Seobeo_Client_Request *req = Seobeo_Client_Request_Create(url_input_text); 1378 Seobeo_Client_Request *req = Seobeo_Client_Request_Create(url_input_text);
1403 Seobeo_Client_Response_Destroy(res); 1428 Seobeo_Client_Response_Destroy(res);
1404 PostDog_Request_SaveFile(); 1429 PostDog_Request_SaveFile();
1405 return 0; 1430 return 0;
1406 } 1431 }
1407 1432
1408 void *PostDog_Http_Thread(void *arg) 1433 void PostDog_Http_Work(uv_work_t *req)
1409 { 1434 {
1410 PostDog_Http_Request(); 1435 PostDog_Http_Request();
1411 printf("HTTP request finished.\n"); 1436 printf("HTTP request finished.\n");
1437 }
1438
1439 void PostDog_Http_Work_Done(uv_work_t *req, int status)
1440 {
1412 LOADING = FALSE; 1441 LOADING = FALSE;
1413 return NULL; 1442 free(req);
1414 } 1443 }
1415 1444
1416 void PostDog_Http_Thread_Request() 1445 void PostDog_Http_Thread_Request()
1417 { 1446 {
1418 pthread_t thread_id; 1447 uv_work_t *work_req = malloc(sizeof(uv_work_t));
1419 LOADING = TRUE; 1448 if (!work_req)
1420 if (pthread_create(&thread_id, NULL, PostDog_Http_Thread, NULL) != 0)
1421 { 1449 {
1422 perror("Failed to create thread"); 1450 perror("Failed to allocate work request");
1423 return; 1451 return;
1424 } 1452 }
1425 pthread_detach(thread_id); 1453 LOADING = TRUE;
1454 if (uv_queue_work(main_loop, work_req, PostDog_Http_Work, PostDog_Http_Work_Done) != 0)
1455 {
1456 perror("Failed to queue work");
1457 free(work_req);
1458 LOADING = FALSE;
1459 }
1426 } 1460 }
1427 1461
1428 void PostDog_Update_URL(void) 1462 void PostDog_Update_URL(void)
1429 { 1463 {
1430 // Save existing query string if present 1464 // Save existing query string if present
1555 1589
1556 Dowa_Arena_Free(init_arena); 1590 Dowa_Arena_Free(init_arena);
1557 Dowa_Arena_Free(split_arena); 1591 Dowa_Arena_Free(split_arena);
1558 } 1592 }
1559 1593
1560 Rectangle AddPadding(Rectangle rect, float padding)
1561 {
1562 return (Rectangle){
1563 rect.x + padding,
1564 rect.y + padding,
1565 rect.width - (2 * padding),
1566 rect.height - (2 * padding)
1567 };
1568 }
1569
1570 Rectangle AddPaddingAll(Rectangle rect, float top, float right,float down, float left)
1571 {
1572 return (Rectangle){
1573 rect.x + left,
1574 rect.y + top,
1575 rect.width - (right + left),
1576 rect.height - (top + down),
1577 };
1578 }
1579
1580
1581
1582 Rectangle AddPaddingHorizontal(Rectangle rect, float padding)
1583 {
1584 return (Rectangle){
1585 rect.x + padding,
1586 rect.y,
1587 rect.width - (2 * padding),
1588 rect.height
1589 };
1590 }
1591
1592 Rectangle AddPaddingVertical(Rectangle rect, float padding)
1593 {
1594 return (Rectangle){
1595 rect.x,
1596 rect.y + padding,
1597 rect.width,
1598 rect.height - (2 * padding)
1599 };
1600 }
1601
1602 // Layout helper functions
1603 Rectangle RightOf(Rectangle ref, float padding)
1604 {
1605 return (Rectangle){
1606 .x = ref.x + ref.width + padding,
1607 .y = ref.y,
1608 .width = 0,
1609 .height = ref.height
1610 };
1611 }
1612
1613 Rectangle Below(Rectangle ref, float padding)
1614 {
1615 return (Rectangle){
1616 .x = ref.x,
1617 .y = ref.y + ref.height + padding,
1618 .width = ref.width,
1619 .height = 0
1620 };
1621 }
1622
1623 Rectangle LeftColumn(Rectangle container, float ratio, float padding)
1624 {
1625 return (Rectangle){
1626 .x = container.x + padding,
1627 .y = container.y + padding,
1628 .width = (container.width * ratio) - padding,
1629 .height = container.height - (2 * padding)
1630 };
1631 }
1632
1633 Rectangle RightColumn(Rectangle container, Rectangle leftCol, float padding)
1634 {
1635 return (Rectangle){
1636 .x = leftCol.x + leftCol.width + padding,
1637 .y = container.y + padding,
1638 .width = container.width - leftCol.width - (3 * padding),
1639 .height = container.height - (2 * padding)
1640 };
1641 }
1642
1643 Rectangle HorizontalSplit(Rectangle container, float ratio)
1644 {
1645 return (Rectangle){
1646 .x = container.x,
1647 .y = container.y,
1648 .width = container.width * ratio,
1649 .height = container.height
1650 };
1651 }
1652
1653 int main() 1594 int main()
1654 { 1595 {
1596 // -- initialize libuv --//
1597 main_loop = uv_default_loop();
1598 uv_mutex_init(&history_mutex);
1599
1655 // -- initizlied --// 1600 // -- initizlied --//
1656 InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "PostDog"); 1601 InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "PostDog");
1657 SetWindowState(FLAG_WINDOW_RESIZABLE); 1602 SetWindowState(FLAG_WINDOW_RESIZABLE);
1658 SetTargetFPS(60); 1603 SetTargetFPS(60);
1659 1604
1660 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0); 1605 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0);
1661 GuiSetFont(customFont); 1606 GuiSetFont(customFont);
1662 GuiSetStyle(DEFAULT, TEXT_SIZE, 15); 1607 GuiSetStyle(DEFAULT, TEXT_SIZE, 15);
1663 Image logo_original = LoadImage("postdog/epi_all_colors.png"); 1608 Image logo_original = LoadImage("postdog/logo_bigger.png");
1664 ImageResize(&logo_original, 60, 60); 1609 ImageResize(&logo_original, 200, 600);
1665 SetWindowIcon(logo_original); 1610 SetWindowIcon(logo_original);
1666 Texture2D logo_texture = LoadTextureFromImage(logo_original); 1611 Texture2D logo_texture = LoadTextureFromImage(logo_original);
1667 UnloadImage(logo_original); 1612 UnloadImage(logo_original);
1668 1613
1669 // Arena for text area undo states 1614 // Arena for text area undo states
1670 g_text_area_arena = Dowa_Arena_Create(1024 * 1024 * 8); // 8MB for undo states 1615 g_text_area_arena = Dowa_Arena_Create(1024 * 1024 * 4);
1671 1616
1672 // -- Starting pos ---// 1617 // -- Starting pos ---//
1618 Rectangle full_screen = { 0 };
1673 Rectangle history_sidebar_rect = { 0 }; 1619 Rectangle history_sidebar_rect = { 0 };
1674 Dowa_Array_Reserve(history_items, 10); 1620 Dowa_Array_Reserve(history_items, 10);
1675 Dowa_Array_Reserve(new_history_items, 10); 1621 Dowa_Array_Reserve(new_history_items, 10);
1676 PostDog_History_Load(&history_items); 1622 PostDog_History_Load(&history_items);
1677 int32 *history_deleted_items = NULL; 1623 int32 *history_deleted_items = NULL;
1684 Rectangle method_dropdown_rect = { 0 }; 1630 Rectangle method_dropdown_rect = { 0 };
1685 1631
1686 1632
1687 // Initialize global UI state 1633 // Initialize global UI state
1688 url_input_text = (char *)malloc(sizeof(char) * URL_TEXT_BUFFER_LENGTH); 1634 url_input_text = (char *)malloc(sizeof(char) * URL_TEXT_BUFFER_LENGTH);
1689 snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, "wss://mrjunejune.com/echo"); 1635 snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, URL_TEXT_DEFAULT);
1690 1636
1691 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * HEADER_BUFFER_LENGTH)); 1637 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * HEADER_BUFFER_LENGTH));
1692 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * BODY_BUFFER_LENGTH)); 1638 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * BODY_BUFFER_LENGTH));
1693 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); 1639 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH));
1694 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); 1640 Dowa_Array_Push(input_body_array, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH));
1695 1641
1696 snprintf(input_body_array[TAB_HEADER], HEADER_BUFFER_LENGTH, "Content-Type: application/json"); 1642 snprintf(input_body_array[TAB_HEADER], HEADER_BUFFER_LENGTH, HEADER_TEXT_DEFAULT);
1697 snprintf(input_body_array[TAB_BODY], HEADER_BUFFER_LENGTH, ""); 1643 snprintf(input_body_array[TAB_BODY], HEADER_BUFFER_LENGTH, BODY_TEXT_DEFAULT);
1644 snprintf(input_body_array[TAB_GET_PARAMS], HEADER_BUFFER_LENGTH, GET_PARAM_TEXT_DEFAULT);
1698 1645
1699 result_text = (char *)malloc(sizeof(char) * RESULT_BUFFER_LENGTH); 1646 result_text = (char *)malloc(sizeof(char) * RESULT_BUFFER_LENGTH);
1700 result_text[0] = '\0'; 1647 result_text[0] = '\0';
1701 1648
1702 bool method_edit = false; 1649 bool method_edit = false;
1722 // Scroll offsets 1669 // Scroll offsets
1723 float history_scroll_offset = 0; 1670 float history_scroll_offset = 0;
1724 1671
1725 while (!WindowShouldClose()) 1672 while (!WindowShouldClose())
1726 { 1673 {
1674 // Process libuv events (non-blocking)
1675 uv_run(main_loop, UV_RUN_NOWAIT);
1676
1727 int screen_width = GetScreenWidth(); 1677 int screen_width = GetScreenWidth();
1728 int screen_height = GetScreenHeight(); 1678 int screen_height = GetScreenHeight();
1729 1679
1730 if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyDown(KEY_EQUAL)) 1680 if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyDown(KEY_EQUAL))
1731 GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetStyle(DEFAULT, TEXT_SIZE) + 1); 1681 GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetStyle(DEFAULT, TEXT_SIZE) + 1);
1734 GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetStyle(DEFAULT, TEXT_SIZE) - 1); 1684 GuiSetStyle(DEFAULT, TEXT_SIZE, GuiGetStyle(DEFAULT, TEXT_SIZE) - 1);
1735 1685
1736 Rectangle screen_rect = { 0, 0, screen_width, screen_height }; 1686 Rectangle screen_rect = { 0, 0, screen_width, screen_height };
1737 1687
1738 // -- Side bar --// 1688 // -- Side bar --//
1739 history_sidebar_rect = LeftColumn(screen_rect, 0.15, padding); 1689 history_sidebar_rect = LeftColumn(screen_rect, 0.20, padding);
1740 Rectangle content_area_rect = RightColumn(screen_rect, history_sidebar_rect, padding); 1690 Rectangle content_area_rect = RightColumn(screen_rect, history_sidebar_rect, padding);
1741 Rectangle logo_area_rect = (Rectangle){ 1691 Rectangle logo_area_rect = (Rectangle){
1742 .x = history_sidebar_rect.x, 1692 .x = history_sidebar_rect.x,
1743 .y = history_sidebar_rect.y, 1693 .y = history_sidebar_rect.y,
1744 .width = history_sidebar_rect.width, 1694 .width = history_sidebar_rect.width,
1745 .height = 80 1695 .height = 300
1746 }; 1696 };
1697
1698
1699 DrawRectangleSelectiveRounded(history_sidebar_rect, 10, 10, ORANGE, TRUE, FALSE, FALSE, TRUE);
1700 DrawRectangleSelectiveRounded(content_area_rect, 10, 10, WHITE, FALSE, TRUE, TRUE, FALSE);
1747 1701
1748 Rectangle history_list_area_rect = Below(logo_area_rect, padding); 1702 Rectangle history_list_area_rect = Below(logo_area_rect, padding);
1749 history_list_area_rect.x += padding; 1703 history_list_area_rect.x += padding;
1750 history_list_area_rect.width = history_sidebar_rect.width - (2 * padding); 1704 history_list_area_rect.width = history_sidebar_rect.width - (2 * padding);
1751 history_list_area_rect.height = history_sidebar_rect.height - logo_area_rect.height - padding; 1705 history_list_area_rect.height = history_sidebar_rect.height - logo_area_rect.height - padding;
1786 float url_control_y = url_area_rect.y + (url_area_rect.height - TEXT_SIZE * 2) / 2; 1740 float url_control_y = url_area_rect.y + (url_area_rect.height - TEXT_SIZE * 2) / 2;
1787 1741
1788 url_text_bounds_rect = (Rectangle){ 1742 url_text_bounds_rect = (Rectangle){
1789 .x = url_area_rect.x + padding, 1743 .x = url_area_rect.x + padding,
1790 .y = url_control_y, 1744 .y = url_control_y,
1791 .width = 7 * (TEXT_SIZE / 2), 1745 .width = 10 * (TEXT_SIZE / 2),
1792 .height = TEXT_SIZE * 2 1746 .height = TEXT_SIZE * 2
1793 }; 1747 };
1794 1748
1795 url_input_bounds_rect = RightOf(url_text_bounds_rect, padding); 1749 url_input_bounds_rect = RightOf(url_text_bounds_rect, padding);
1796 url_input_bounds_rect.width = url_area_rect.width * 0.7; 1750 url_input_bounds_rect.width = url_area_rect.width * 0.7;
1797 url_input_bounds_rect.height = TEXT_SIZE * 2; 1751 url_input_bounds_rect.height = TEXT_SIZE * 2.5;
1798 1752
1799 url_enter_button_rect = RightOf(url_input_bounds_rect, padding); 1753 url_enter_button_rect = RightOf(url_input_bounds_rect, padding);
1800 url_enter_button_rect.width = url_area_rect.width * 0.1; 1754 url_enter_button_rect.width = url_area_rect.width * 0.1;
1801 url_enter_button_rect.height = TEXT_SIZE * 2; 1755 url_enter_button_rect.height = TEXT_SIZE * 2;
1802 1756
1866 ) 1820 )
1867 SetMouseCursor(MOUSE_CURSOR_POINTING_HAND); 1821 SetMouseCursor(MOUSE_CURSOR_POINTING_HAND);
1868 1822
1869 if (Clicked(mouse_position, logo_area_rect)) 1823 if (Clicked(mouse_position, logo_area_rect))
1870 PostDog_Params_Reset(); 1824 PostDog_Params_Reset();
1825
1826 // --- Begin Drawing --- //
1871 BeginDrawing(); 1827 BeginDrawing();
1872 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); 1828 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
1873 1829
1874 // DrawRectangleRec(history_sidebar_rect, Fade(GRAY, 0.1f)); 1830 // DrawRectangleRec(history_sidebar_rect, Fade(GRAY, 0.1f));
1875 DrawRectangleRounded(history_sidebar_rect, 0.5, 1, Fade(BLUE, 0.1f)); 1831 DrawRectangleRounded(history_sidebar_rect, 0.5, 1, Fade(BLUE, 0.1f));
1910 // DrawRectangleRec(AddPadding(filename_area_rect, 5), Fade(BLUE, 0.1f)); 1866 // DrawRectangleRec(AddPadding(filename_area_rect, 5), Fade(BLUE, 0.1f));
1911 1867
1912 Rectangle icon_area_left_column = LeftColumn(icon_area, 0.5, 0); 1868 Rectangle icon_area_left_column = LeftColumn(icon_area, 0.5, 0);
1913 Rectangle icon_area_right_column = RightColumn(icon_area, icon_area_left_column, 0); 1869 Rectangle icon_area_right_column = RightColumn(icon_area, icon_area_left_column, 0);
1914 1870
1915 filename_area_rect.y += 2*padding; 1871 Rectangle temp = AddPadding(filename_area_rect, padding);
1916 GuiDrawText(curr_history_items->title, AddPadding(filename_area_rect, padding), TEXT_ALIGN_CENTER, BLACK); 1872
1873 // ADD this back
1874 // GuiDrawText(curr_history_items->title, temp, TEXT_ALIGN_CENTER, BLACK);
1917 if ( 1875 if (
1918 InArea(mouse_position, icon_area_left_column) || 1876 InArea(mouse_position, icon_area_left_column) ||
1919 InArea(mouse_position, icon_area_right_column) 1877 InArea(mouse_position, icon_area_right_column)
1920 ) 1878 )
1921 SetMouseCursor(MOUSE_CURSOR_POINTING_HAND); 1879 SetMouseCursor(MOUSE_CURSOR_POINTING_HAND);
1922 1880
1923 if (GuiButton(AddPadding(icon_area_left_column, padding), "view")) 1881 if (GuiButton(AddPadding(icon_area_left_column, padding), "view"))
1924 PostDog_Load_File(curr_history_items->filename); 1882 PostDog_Load_File(curr_history_items->filename);
1925 if (GuiButton(AddPadding(icon_area_right_column, padding), "delete")) 1883 if (GuiButton(AddPadding(icon_area_right_column, padding), "delete"))
1926 { 1884 {
1927 if (!remove(PostDog_Construct_URL(curr_history_items->filename))) 1885 char delete_path[512];
1886 if (!remove(PostDog_Construct_URL(curr_history_items->filename, delete_path, sizeof(delete_path))))
1928 curr_history_items->deleted = TRUE; 1887 curr_history_items->deleted = TRUE;
1929 else 1888 else
1930 fprintf(stderr, "Wasn't able to delete file: %s \n", curr_history_items->filename); 1889 fprintf(stderr, "Wasn't able to delete file: %s \n", curr_history_items->filename);
1931 } 1890 }
1932 } 1891 }
1948 DrawRectangleRec(scrollbar_rect, Fade(WHITE, 0.5f)); 1907 DrawRectangleRec(scrollbar_rect, Fade(WHITE, 0.5f));
1949 } 1908 }
1950 } 1909 }
1951 1910
1952 // URL area Rect 1911 // URL area Rect
1953 GuiDrawText("URL: ", url_text_bounds_rect, TEXT_ALIGN_CENTER, BLACK);
1954 DrawRectangleRec(url_area_rect, Fade(BLACK, 0.1f)); 1912 DrawRectangleRec(url_area_rect, Fade(BLACK, 0.1f));
1955 1913
1956 if (GuiTextBox(url_input_bounds_rect, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit)) 1914 if (GuiTextArea(21, url_input_bounds_rect, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit, FALSE, g_text_area_arena))
1957 url_input_edit = !url_input_edit; 1915 url_input_edit = !url_input_edit;
1958 1916
1959 if (url_input_edit) 1917 if (url_input_edit)
1960 { 1918 {
1961 if (IsKeyPressed(KEY_ENTER)) 1919 if (IsKeyPressed(KEY_ENTER))
1963 PostDog_Http_Thread_Request(); 1921 PostDog_Http_Thread_Request();
1964 url_input_edit = !url_input_edit; 1922 url_input_edit = !url_input_edit;
1965 } 1923 }
1966 } 1924 }
1967 1925
1968 sendRequest = GuiButton(url_enter_button_rect, "ENTER"); 1926 if (GuiButtonRounded(url_enter_button_rect, "New Request", 0.2, 1))
1969 if (sendRequest)
1970 PostDog_Http_Thread_Request(); 1927 PostDog_Http_Thread_Request();
1971 1928
1972 if (GuiDropdownBox(method_dropdown_rect, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) 1929 DrawRectangleSelectiveRounded(body_area_rect, 10, 10, ORANGE, TRUE, FALSE, FALSE, TRUE);
1973 method_edit = !method_edit; 1930 DrawRectangleSelectiveRounded(result_area_rect, 10, 10, WHITE, FALSE, TRUE, TRUE, FALSE);
1974 1931
1975 // Input Tabs Rect 1932 // Input Tabs Rect
1976 DrawRectangleRec(input_area_rect, Fade(BLUE, 0.1f)); 1933 DrawRectangleRec(input_area_rect, Fade(BLUE, 0.1f));
1977 DrawRectangleRec(input_tab_rect, Fade(DARKBLUE, 0.1f)); 1934 DrawRectangleRec(input_tab_rect, Fade(DARKBLUE, 0.1f));
1978 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); 1935 GuiSetStyle(TOGGLE, GROUP_PADDING, 0);
2013 // TODO: Add animations. 1970 // TODO: Add animations.
2014 DrawRectangleRec(result_area_rect, LOADING ? Fade(RED, 0.1f) : Fade(GREEN, 0.1f)); 1971 DrawRectangleRec(result_area_rect, LOADING ? Fade(RED, 0.1f) : Fade(GREEN, 0.1f));
2015 boolean result_toggle = GuiTextArea(TEXT_AREA_ID_RESULT, result_body_rect, result_text, 1972 boolean result_toggle = GuiTextArea(TEXT_AREA_ID_RESULT, result_body_rect, result_text,
2016 RESULT_BUFFER_LENGTH, result_body_edit_mode, TRUE, g_text_area_arena); 1973 RESULT_BUFFER_LENGTH, result_body_edit_mode, TRUE, g_text_area_arena);
2017 1974
2018 GuiToggleGroup(input_tab_item_rect, "Header;Body;Get Param;Websocket", &active_input_tab);
2019 if (result_toggle) 1975 if (result_toggle)
2020 result_body_edit_mode = !result_body_edit_mode; 1976 result_body_edit_mode = !result_body_edit_mode;
2021 1977
1978 if (GuiDropdownBoxRounded(url_text_bounds_rect, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit, 0.2, 1))
1979 method_edit = !method_edit;
2022 EndDrawing(); 1980 EndDrawing();
2023 } 1981 }
2024 1982
2025 GuiTextAreaResetAllStates(); 1983 GuiTextAreaResetAllStates();
2026 Dowa_Arena_Free(g_text_area_arena); 1984 Dowa_Arena_Free(g_text_area_arena);
1985
1986 // Cleanup libuv
1987 uv_mutex_destroy(&history_mutex);
1988 uv_loop_close(main_loop);
1989
2027 CloseWindow(); 1990 CloseWindow();
2028 return 0; 1991 return 0;
2029 } 1992 }