Mercurial
comparison postdog/main.c @ 118:249881ceff7b
[PostDog] Updated some core logic. Will create a bookmark for postdog until the launch as this is annoying to deal with.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 07 Jan 2026 13:24:38 -0800 |
| parents | b91f2dd6f84d |
| children | 7387eec8e7f8 |
comparison
equal
deleted
inserted
replaced
| 117:b91f2dd6f84d | 118:249881ceff7b |
|---|---|
| 44 size_t size; | 44 size_t size; |
| 45 } ResponseBuffer; | 45 } ResponseBuffer; |
| 46 | 46 |
| 47 typedef struct { | 47 typedef struct { |
| 48 char *filename; | 48 char *filename; |
| 49 char *title; | |
| 49 Rectangle rect; | 50 Rectangle rect; |
| 50 long time_modified; | 51 long time_modified; |
| 51 boolean deleted; | 52 boolean deleted; |
| 52 } HistoryItem; | 53 } HistoryItem; |
| 53 | 54 |
| 67 | 68 |
| 68 static uint32 counter = 0; | 69 static uint32 counter = 0; |
| 69 HistoryItem *history_items = NULL; | 70 HistoryItem *history_items = NULL; |
| 70 HistoryItem *new_history_items = NULL; | 71 HistoryItem *new_history_items = NULL; |
| 71 | 72 |
| 73 // Global UI state | |
| 74 char *url_input_text = NULL; | |
| 75 char *url_result_text = NULL; | |
| 76 char **url_body_map = NULL; | |
| 77 int active_method_dropdown = 0; | |
| 78 | |
| 72 int CompareHistoryItemsByDate(const void *a, const void *b) { | 79 int CompareHistoryItemsByDate(const void *a, const void *b) { |
| 73 HistoryItem *itemA = (HistoryItem *)a; | 80 HistoryItem *itemA = (HistoryItem *)a; |
| 74 HistoryItem *itemB = (HistoryItem *)b; | 81 HistoryItem *itemB = (HistoryItem *)b; |
| 75 return (itemB->time_modified - itemA->time_modified); | 82 return (itemB->time_modified - itemA->time_modified); |
| 83 } | |
| 84 | |
| 85 char *PostDog_Extract_Title(const char *filename) | |
| 86 { | |
| 87 char full_file_path[512] = {0}; | |
| 88 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); | |
| 89 FILE *file = fopen(full_file_path, "r"); | |
| 90 if (!file) | |
| 91 return strdup(filename); | |
| 92 | |
| 93 char *title = malloc(sizeof(char) * 512); | |
| 94 if (!fgets(title, 512, file)) { | |
| 95 fclose(file); | |
| 96 return strdup(filename); | |
| 97 } | |
| 98 | |
| 99 return title; | |
| 76 } | 100 } |
| 77 | 101 |
| 78 // TODO: Make this into generic fucntion so I can use it across different thing. | 102 // TODO: Make this into generic fucntion so I can use it across different thing. |
| 79 void PostDog_List_Directory(const char *path, HistoryItem **p_file_arr) | 103 void PostDog_List_Directory(const char *path, HistoryItem **p_file_arr) |
| 80 { | 104 { |
| 89 printf("Directory is empty or cannot be read.\n"); | 113 printf("Directory is empty or cannot be read.\n"); |
| 90 } else { | 114 } else { |
| 91 do { | 115 do { |
| 92 HistoryItem item = {0}; | 116 HistoryItem item = {0}; |
| 93 item.filename = strdup(fileinfo.name); | 117 item.filename = strdup(fileinfo.name); |
| 94 item.time_modified = fileinfo.time_write; | 118 item.title = PostDog_Extract_Title(fileinfo.name); |
| 119 item.time_modified = fileinfo.time_write; | |
| 95 item.deleted = FALSE; | 120 item.deleted = FALSE; |
| 96 Dowa_Array_Push(file_arr, item); | 121 Dowa_Array_Push(file_arr, item); |
| 97 } while (_findnext(handle, &fileinfo) == 0); | 122 } while (_findnext(handle, &fileinfo) == 0); |
| 98 _findclose(handle); | 123 _findclose(handle); |
| 99 } | 124 } |
| 111 snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); | 136 snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); |
| 112 if (stat(full_path, &file_stat) == 0) | 137 if (stat(full_path, &file_stat) == 0) |
| 113 { | 138 { |
| 114 HistoryItem item = {0}; | 139 HistoryItem item = {0}; |
| 115 item.filename = strdup(entry->d_name); | 140 item.filename = strdup(entry->d_name); |
| 141 item.title = PostDog_Extract_Title(entry->d_name); | |
| 116 item.time_modified = file_stat.st_mtime; | 142 item.time_modified = file_stat.st_mtime; |
| 117 item.deleted = FALSE; | 143 item.deleted = FALSE; |
| 118 Dowa_Array_Push(file_arr, item); | 144 Dowa_Array_Push(file_arr, item); |
| 119 } | 145 } |
| 120 } | 146 } |
| 186 } | 212 } |
| 187 fwrite(values, 1, strlen(values), file); | 213 fwrite(values, 1, strlen(values), file); |
| 188 fclose(file); | 214 fclose(file); |
| 189 } | 215 } |
| 190 | 216 |
| 191 void PostDog_Request_SaveFile( | 217 void PostDog_Request_SaveFile(void) |
| 192 const char *url, | 218 { |
| 193 const char *method, | 219 const char *method = PostDog_Enum_To_String(active_method_dropdown); |
| 194 const char *headers, | |
| 195 const char *body, | |
| 196 const char *response) | |
| 197 { | |
| 198 size_t new_file_size = 1024 * 1024; | 220 size_t new_file_size = 1024 * 1024; |
| 199 Dowa_Arena *arena = Dowa_Arena_Create(1024 * 1024 * 2); | 221 Dowa_Arena *arena = Dowa_Arena_Create(1024 * 1024 * 2); |
| 200 char *new_file = Dowa_Arena_Allocate(arena, 1024 * 1024); | 222 char *new_file = Dowa_Arena_Allocate(arena, 1024 * 1024); |
| 223 char *title = malloc(strlen(method) + strlen(url_input_text) + 2); | |
| 224 sprintf(title, "%s %s", method, url_input_text); | |
| 201 snprintf( | 225 snprintf( |
| 202 new_file, | 226 new_file, |
| 203 new_file_size, | 227 new_file_size, |
| 204 "%s\n" | 228 "%s\n" |
| 205 "---\n" | 229 "---\n" |
| 207 "---\n" | 231 "---\n" |
| 208 "%s\n" | 232 "%s\n" |
| 209 "---\n" | 233 "---\n" |
| 210 "%s\n" | 234 "%s\n" |
| 211 "---\n" | 235 "---\n" |
| 236 "%s\n" | |
| 237 "---\n" | |
| 238 "%s\n" | |
| 239 "---\n" | |
| 240 "%s\n" | |
| 241 "---\n" | |
| 212 "%s\n", | 242 "%s\n", |
| 213 url, | 243 title, |
| 244 url_input_text, | |
| 214 method, | 245 method, |
| 215 headers, | 246 url_body_map[TAB_HEADER], |
| 216 body, | 247 url_body_map[TAB_BODY], |
| 217 response | 248 url_body_map[TAB_GET_PARAMS], |
| 249 url_body_map[TAB_BAR], | |
| 250 url_result_text | |
| 218 ); | 251 ); |
| 219 char *filename = Dowa_Arena_Allocate(arena, 1024); | 252 char *filename = Dowa_Arena_Allocate(arena, 1024); |
| 220 if (!filename) | 253 if (!filename) |
| 221 { | 254 { |
| 222 perror("Error opening file"); | 255 perror("Error opening file"); |
| 234 snprintf(filename, 1024, "%s.txt", uuid4); | 267 snprintf(filename, 1024, "%s.txt", uuid4); |
| 235 PostDog_History_CreateFile(filename, new_file); | 268 PostDog_History_CreateFile(filename, new_file); |
| 236 | 269 |
| 237 HistoryItem item = {0}; | 270 HistoryItem item = {0}; |
| 238 item.filename = strdup(filename); | 271 item.filename = strdup(filename); |
| 272 item.title = title; | |
| 239 item.deleted = FALSE; | 273 item.deleted = FALSE; |
| 240 memcpy(item.filename, filename, strlen(filename) + 1); | |
| 241 Dowa_Array_Push(new_history_items, item); | 274 Dowa_Array_Push(new_history_items, item); |
| 242 | 275 |
| 243 Dowa_Arena_Free(arena); | 276 Dowa_Arena_Free(arena); |
| 244 } | 277 } |
| 245 | 278 |
| 261 buf->data[buf->size] = 0; | 294 buf->data[buf->size] = 0; |
| 262 | 295 |
| 263 return real_size; | 296 return real_size; |
| 264 } | 297 } |
| 265 | 298 |
| 266 int PostDog_Http_Request( | 299 int PostDog_Http_Request(void) |
| 267 const char *url, | 300 { |
| 268 const char *method, | 301 const char *method = PostDog_Enum_To_String(active_method_dropdown); |
| 269 const char *headers, | |
| 270 const char *body, | |
| 271 char *response, size_t response_size) | |
| 272 { | |
| 273 CURL *curl; | 302 CURL *curl; |
| 274 CURLcode res; | 303 CURLcode res; |
| 275 ResponseBuffer buffer = { .data = malloc(1), .size = 0 }; | 304 ResponseBuffer buffer = { .data = malloc(1), .size = 0 }; |
| 276 | 305 |
| 277 response[0] = '\n'; | 306 url_result_text[0] = '\n'; |
| 278 | 307 |
| 279 if (buffer.data == NULL) | 308 if (buffer.data == NULL) |
| 280 { | 309 { |
| 281 snprintf(response, response_size, "Error: Failed to allocate memory"); | 310 snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: Failed to allocate memory"); |
| 282 return -1; | 311 return -1; |
| 283 } | 312 } |
| 284 buffer.data[0] = '\0'; | 313 buffer.data[0] = '\0'; |
| 285 | 314 |
| 286 curl_global_init(CURL_GLOBAL_DEFAULT); | 315 curl_global_init(CURL_GLOBAL_DEFAULT); |
| 289 if (curl) | 318 if (curl) |
| 290 { | 319 { |
| 291 struct curl_slist *headerList = NULL; | 320 struct curl_slist *headerList = NULL; |
| 292 | 321 |
| 293 // Set URL | 322 // Set URL |
| 294 curl_easy_setopt(curl, CURLOPT_URL, url); | 323 curl_easy_setopt(curl, CURLOPT_URL, url_input_text); |
| 295 | 324 |
| 296 // Set HTTP method | 325 // Set HTTP method |
| 297 if (strcmp(method, "POST") == 0) | 326 if (strcmp(method, "POST") == 0) |
| 298 { | 327 { |
| 299 curl_easy_setopt(curl, CURLOPT_POST, 1L); | 328 curl_easy_setopt(curl, CURLOPT_POST, 1L); |
| 300 if (body && strlen(body) > 0) | 329 if (url_body_map[TAB_BODY] && strlen(url_body_map[TAB_BODY]) > 0) |
| 301 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | 330 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, url_body_map[TAB_BODY]); |
| 302 } | 331 } |
| 303 else if (strcmp(method, "PUT") == 0) | 332 else if (strcmp(method, "PUT") == 0) |
| 304 { | 333 { |
| 305 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); | 334 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); |
| 306 if (body && strlen(body) > 0) | 335 if (url_body_map[TAB_BODY] && strlen(url_body_map[TAB_BODY]) > 0) |
| 307 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); | 336 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, url_body_map[TAB_BODY]); |
| 308 } | 337 } |
| 309 else if (strcmp(method, "DELETE") == 0) | 338 else if (strcmp(method, "DELETE") == 0) |
| 310 { | 339 { |
| 311 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); | 340 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); |
| 312 } | 341 } |
| 313 // Default is GET | 342 // Default is GET |
| 314 | 343 |
| 315 // Parse and add headers | 344 // Parse and add headers |
| 316 if (headers && strlen(headers) > 0) | 345 if (url_body_map[TAB_HEADER] && strlen(url_body_map[TAB_HEADER]) > 0) |
| 317 { | 346 { |
| 318 char *headersCopy = strdup(headers); | 347 char *headersCopy = strdup(url_body_map[TAB_HEADER]); |
| 319 char *line = strtok(headersCopy, "\n"); | 348 char *line = strtok(headersCopy, "\n"); |
| 320 while (line != NULL) { | 349 while (line != NULL) { |
| 321 // Trim whitespace | |
| 322 while (*line == ' ' || *line == '\t') line++; | 350 while (*line == ' ' || *line == '\t') line++; |
| 323 if (strlen(line) > 0) | 351 if (strlen(line) > 0) |
| 324 headerList = curl_slist_append(headerList, line); | 352 headerList = curl_slist_append(headerList, line); |
| 325 line = strtok(NULL, "\n"); | 353 line = strtok(NULL, "\n"); |
| 326 } | 354 } |
| 332 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); | 360 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); |
| 333 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); | 361 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); |
| 334 | 362 |
| 335 // Follow redirects | 363 // Follow redirects |
| 336 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); | 364 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); |
| 337 // Set timeout | |
| 338 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); | 365 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); |
| 339 // Perform request | |
| 340 res = curl_easy_perform(curl); | 366 res = curl_easy_perform(curl); |
| 341 | 367 |
| 342 if (res != CURLE_OK) | 368 if (res != CURLE_OK) |
| 343 snprintf(response, response_size, "Error: %s\n", curl_easy_strerror(res)); | 369 snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: %s\n", curl_easy_strerror(res)); |
| 344 else | 370 else |
| 345 { | 371 { |
| 346 long response_code; | 372 long response_code; |
| 347 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); | 373 curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); |
| 348 | 374 |
| 349 if (buffer.size > response_size) | 375 if (buffer.size > RESULT_BUFFER_LENGTH) |
| 350 printf("TODO: Realloc\n"); | 376 printf("TODO: Realloc\n"); |
| 351 | 377 |
| 352 snprintf(response, response_size, "HTTP Status: %ld\n\n%s", | 378 snprintf(url_result_text, RESULT_BUFFER_LENGTH, "HTTP Status: %ld\n\n%s", |
| 353 response_code, buffer.data ? buffer.data : ""); | 379 response_code, buffer.data ? buffer.data : ""); |
| 354 } | 380 } |
| 355 | 381 |
| 356 // Cleanup | |
| 357 if (headerList) curl_slist_free_all(headerList); | 382 if (headerList) curl_slist_free_all(headerList); |
| 358 curl_easy_cleanup(curl); | 383 curl_easy_cleanup(curl); |
| 359 } | 384 } |
| 360 else | 385 else |
| 361 snprintf(response, response_size, "Error: Failed to initialize curl"); | 386 snprintf(url_result_text, RESULT_BUFFER_LENGTH, "Error: Failed to initialize curl"); |
| 362 | 387 |
| 363 free(buffer.data); | 388 free(buffer.data); |
| 364 curl_global_cleanup(); | 389 curl_global_cleanup(); |
| 365 | 390 |
| 366 PostDog_Request_SaveFile( | 391 PostDog_Request_SaveFile(); |
| 367 url, | |
| 368 method, | |
| 369 headers, | |
| 370 body, | |
| 371 response); | |
| 372 return 0; | 392 return 0; |
| 373 } | 393 } |
| 374 | 394 |
| 375 void PostDog_Update_URL(char **p_url_input_text, char* get_params) | 395 void PostDog_Update_URL(void) |
| 376 { | 396 { |
| 377 char *url_input_text = *p_url_input_text; | 397 // Save existing query string if present |
| 378 | |
| 379 // Reset | |
| 380 char *question_mark = strchr(url_input_text, '?'); | 398 char *question_mark = strchr(url_input_text, '?'); |
| 381 if (question_mark) | 399 if (question_mark) |
| 382 *question_mark = '\0'; | 400 *question_mark = '\0'; |
| 383 | 401 |
| 384 int get_params_length = (int)strlen(get_params) ; | 402 int get_params_length = (int)strlen(url_body_map[TAB_GET_PARAMS]); |
| 385 if (get_params_length == 0) | 403 if (get_params_length == 0) |
| 386 return; | 404 return; |
| 387 | 405 |
| 388 char *separator = "?"; | 406 char *separator = "?"; |
| 389 | 407 |
| 390 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024); | 408 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024); |
| 391 char **lines = Dowa_String_Split(get_params, "\n", get_params_length, 1, arena); | 409 char **lines = Dowa_String_Split(url_body_map[TAB_GET_PARAMS], "\n", get_params_length, 1, arena); |
| 392 for (int i = 0; i < Dowa_Array_Length(lines); i++) | 410 for (int i = 0; i < Dowa_Array_Length(lines); i++) |
| 393 { | 411 { |
| 394 char *line = lines[i]; | 412 char *line = lines[i]; |
| 395 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena); | 413 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena); |
| 396 | 414 |
| 424 if (strstr(value, "DELETE")) | 442 if (strstr(value, "DELETE")) |
| 425 return 3; | 443 return 3; |
| 426 return 0; | 444 return 0; |
| 427 } | 445 } |
| 428 | 446 |
| 429 void PostDog_Params_Reset( | 447 void PostDog_Params_Reset(void) |
| 430 char **p_url_input_text, | 448 { |
| 431 int *p_active_method_dropdown, | 449 url_input_text[0] = '\0'; |
| 432 char **url_body_map, | 450 url_result_text[0] = '\0'; |
| 433 char **p_url_result_text | |
| 434 ) | |
| 435 { | |
| 436 char *url_input_text = *p_url_input_text; | |
| 437 char *url_result_text = *p_url_result_text; | |
| 438 int active_method_dropdown = *p_active_method_dropdown; | |
| 439 | |
| 440 url_input_text = ""; | |
| 441 url_result_text = ""; | |
| 442 active_method_dropdown = 0; | 451 active_method_dropdown = 0; |
| 443 for (int i = 0; i < Dowa_Array_Length(url_body_map); i++) | 452 for (int i = 0; i < Dowa_Array_Length(url_body_map); i++) |
| 444 url_body_map[i] = ""; | 453 url_body_map[i][0] = '\0'; |
| 445 } | 454 } |
| 446 | 455 |
| 447 void PostDog_Load_File( | 456 void PostDog_Load_File(const char *filename) |
| 448 const char *filename, | 457 { |
| 449 char **p_url_input_text, | |
| 450 int *p_active_method_dropdown, | |
| 451 char **url_body_map, | |
| 452 char **p_url_result_text | |
| 453 ) { | |
| 454 char *url_input_text = *p_url_input_text; | |
| 455 char *url_result_text = *p_url_result_text; | |
| 456 int active_method_dropdown = *p_active_method_dropdown; | |
| 457 | |
| 458 char full_file_path[512] = {0}; | 458 char full_file_path[512] = {0}; |
| 459 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); | 459 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename); |
| 460 FILE *file = fopen(full_file_path, "r"); | 460 FILE *file = fopen(full_file_path, "r"); |
| 461 if (!file) | 461 if (!file) |
| 462 return; | 462 return; |
| 473 | 473 |
| 474 char **values = Dowa_String_Split(file_buffer, "---\n", file_size, 4, split_arena); | 474 char **values = Dowa_String_Split(file_buffer, "---\n", file_size, 4, split_arena); |
| 475 | 475 |
| 476 for (int i = 0; i < Dowa_Array_Length(values); i++) | 476 for (int i = 0; i < Dowa_Array_Length(values); i++) |
| 477 { | 477 { |
| 478 if (i == 0) | 478 switch (i) |
| 479 { | 479 { |
| 480 snprintf(url_input_text, strlen(values[i]) + 1, "%s", values[i]); | 480 case 0: // Title - skip |
| 481 url_input_text[strcspn(url_input_text, "\n")] = '\0'; | 481 break; |
| 482 } | 482 |
| 483 else if (i == 1) | 483 case 1: // URL |
| 484 active_method_dropdown = PostDog_String_To_MethodEnum(values[i]); | 484 snprintf(url_input_text, strlen(values[i]) + 1, "%s", values[i]); |
| 485 else if (i <= 3) | 485 url_input_text[strcspn(url_input_text, "\n")] = '\0'; |
| 486 { | 486 break; |
| 487 snprintf(url_body_map[i-2], strlen(values[i]) + 1, "%s", values[i]); | 487 |
| 488 for (int j = strlen(values[i]); j > 0; j--) | 488 case 2: // Method |
| 489 active_method_dropdown = PostDog_String_To_MethodEnum(values[i]); | |
| 490 break; | |
| 491 | |
| 492 case 3: // Headers (TAB_HEADER) | |
| 493 case 4: // Body (TAB_BODY) | |
| 494 case 5: // Get Params (TAB_GET_PARAMS) | |
| 495 case 6: // Bar (TAB_BAR) | |
| 489 { | 496 { |
| 490 if (url_body_map[i-2][j] == '\n') | 497 int map_index = i - 3; // 3->0, 4->1, 5->2, 6->3 |
| 498 snprintf(url_body_map[map_index], strlen(values[i]) + 1, "%s", values[i]); | |
| 499 // Trim trailing newlines | |
| 500 for (int j = strlen(values[i]); j > 0; j--) | |
| 491 { | 501 { |
| 492 url_body_map[i-2][j] = '\0'; | 502 if (url_body_map[map_index][j] == '\n') |
| 493 break; | 503 { |
| 504 url_body_map[map_index][j] = '\0'; | |
| 505 break; | |
| 506 } | |
| 494 } | 507 } |
| 508 break; | |
| 495 } | 509 } |
| 496 } | 510 |
| 497 else | 511 default: // Response (index 7+) |
| 498 snprintf(url_result_text, strlen(values[i]) + 1, "%s", values[i]); | 512 snprintf(url_result_text, strlen(values[i]) + 1, "%s", values[i]); |
| 513 break; | |
| 514 } | |
| 499 } | 515 } |
| 500 | 516 |
| 501 Dowa_Arena_Free(init_arena); | 517 Dowa_Arena_Free(init_arena); |
| 502 Dowa_Arena_Free(split_arena); | 518 Dowa_Arena_Free(split_arena); |
| 503 } | 519 } |
| 593 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0); | 609 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0); |
| 594 GuiSetFont(customFont); | 610 GuiSetFont(customFont); |
| 595 GuiSetStyle(DEFAULT, TEXT_SIZE, 10); | 611 GuiSetStyle(DEFAULT, TEXT_SIZE, 10); |
| 596 Image logo_original = LoadImage("postdog/epi_all_colors.png"); | 612 Image logo_original = LoadImage("postdog/epi_all_colors.png"); |
| 597 ImageResize(&logo_original, 60, 60); | 613 ImageResize(&logo_original, 60, 60); |
| 614 SetWindowIcon(logo_original); | |
| 598 Texture2D logo_texture = LoadTextureFromImage(logo_original); | 615 Texture2D logo_texture = LoadTextureFromImage(logo_original); |
| 599 UnloadImage(logo_original); | 616 UnloadImage(logo_original); |
| 600 | 617 |
| 601 // -- Starting pos ---// | 618 // -- Starting pos ---// |
| 602 Rectangle history_sidebar = { 0 }; | 619 Rectangle history_sidebar = { 0 }; |
| 612 Rectangle url_text_bounds = { 0 }; | 629 Rectangle url_text_bounds = { 0 }; |
| 613 Rectangle url_enter_button = { 0 }; | 630 Rectangle url_enter_button = { 0 }; |
| 614 Rectangle method_dropdown = { 0 }; | 631 Rectangle method_dropdown = { 0 }; |
| 615 | 632 |
| 616 | 633 |
| 617 char *url_input_text = (char *)malloc(sizeof(char) * URL_TEXT_BUFFER_LENGTH); | 634 // Initialize global UI state |
| 635 url_input_text = (char *)malloc(sizeof(char) * URL_TEXT_BUFFER_LENGTH); | |
| 618 snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, "https://httpbin.org/get"); | 636 snprintf(url_input_text, URL_TEXT_BUFFER_LENGTH, "https://httpbin.org/get"); |
| 619 | 637 |
| 620 char **url_body_map = NULL; | |
| 621 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * HEADER_BUFFER_LENGTH)); | 638 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * HEADER_BUFFER_LENGTH)); |
| 622 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * BODY_BUFFER_LENGTH)); | 639 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * BODY_BUFFER_LENGTH)); |
| 623 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); | 640 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); |
| 624 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); | 641 Dowa_Array_Push(url_body_map, (char *)malloc(sizeof(char) * DEFAULT_TEXT_BUFFER_LENGTH)); |
| 625 | 642 |
| 626 snprintf(url_body_map[TAB_HEADER], HEADER_BUFFER_LENGTH, "Content-Type: application/json"); | 643 snprintf(url_body_map[TAB_HEADER], HEADER_BUFFER_LENGTH, "Content-Type: application/json"); |
| 627 snprintf(url_body_map[TAB_BODY], HEADER_BUFFER_LENGTH, ""); | 644 snprintf(url_body_map[TAB_BODY], HEADER_BUFFER_LENGTH, ""); |
| 628 | 645 |
| 629 char *url_result_text = (char *)malloc(sizeof(char) * RESULT_BUFFER_LENGTH); | 646 url_result_text = (char *)malloc(sizeof(char) * RESULT_BUFFER_LENGTH); |
| 630 | 647 |
| 631 int active_method_dropdown = 0; | |
| 632 bool method_edit = false; | 648 bool method_edit = false; |
| 633 | 649 |
| 634 int sendRequest; | 650 int sendRequest; |
| 635 | 651 |
| 636 // -- input --// | 652 // -- input --// |
| 688 | 704 |
| 689 int32 number_of_skipped_items = 0; | 705 int32 number_of_skipped_items = 0; |
| 690 for (int i = 0; i < total; i++) | 706 for (int i = 0; i < total; i++) |
| 691 { | 707 { |
| 692 HistoryItem *curr_history_items = i < new_history_items_length ? | 708 HistoryItem *curr_history_items = i < new_history_items_length ? |
| 693 &new_history_items[i] : &history_items[i - new_history_items_length]; | 709 &new_history_items[i - new_history_items_length - 1] : &history_items[i - new_history_items_length]; |
| 694 | 710 |
| 695 if (curr_history_items->deleted) | 711 if (curr_history_items->deleted) |
| 696 { | 712 { |
| 697 number_of_skipped_items++; | 713 number_of_skipped_items++; |
| 698 continue; | 714 continue; |
| 812 }; | 828 }; |
| 813 | 829 |
| 814 Rectangle source = { 0, 0, logo_texture.width, logo_texture.height }; | 830 Rectangle source = { 0, 0, logo_texture.width, logo_texture.height }; |
| 815 DrawTexturePro(logo_texture, source, dest, (Vector2){0, 0}, 0.0f, WHITE); | 831 DrawTexturePro(logo_texture, source, dest, (Vector2){0, 0}, 0.0f, WHITE); |
| 816 | 832 |
| 817 // Draw history items with scissor mode for clipping | |
| 818 BeginScissorMode(history_list_area.x, history_list_area.y, history_list_area.width, history_list_area.height); | 833 BeginScissorMode(history_list_area.x, history_list_area.y, history_list_area.width, history_list_area.height); |
| 819 for (int i = 0; i < total; i++) | 834 for (int i = 0; i < total; i++) |
| 820 { | 835 { |
| 821 HistoryItem *curr_history_items = i < new_history_items_length ? | 836 HistoryItem *curr_history_items = i < new_history_items_length ? |
| 822 &new_history_items[i] : &history_items[i - new_history_items_length]; | 837 &new_history_items[i - new_history_items_length - 1] : &history_items[i - new_history_items_length]; |
| 823 | 838 |
| 824 if (curr_history_items->deleted) | 839 if (curr_history_items->deleted) |
| 825 continue; | 840 continue; |
| 826 | 841 |
| 827 float diff = curr_history_items->rect.height*0.3; | 842 float diff = curr_history_items->rect.height*0.3; |
| 836 DrawRectangleRec(icon_area, Fade(YELLOW, 0.1f)); | 851 DrawRectangleRec(icon_area, Fade(YELLOW, 0.1f)); |
| 837 | 852 |
| 838 Rectangle icon_area_left_column = LeftColumn(icon_area, 0.5, 0); | 853 Rectangle icon_area_left_column = LeftColumn(icon_area, 0.5, 0); |
| 839 Rectangle icon_area_right_column = RightColumn(icon_area, icon_area_left_column, 0); | 854 Rectangle icon_area_right_column = RightColumn(icon_area, icon_area_left_column, 0); |
| 840 | 855 |
| 841 GuiDrawText(curr_history_items->filename, AddPadding(filename_area, padding), TEXT_ALIGN_CENTER, RED); | 856 GuiDrawText(curr_history_items->title, AddPadding(filename_area, padding), TEXT_ALIGN_CENTER, RED); |
| 842 if (GuiButton(AddPaddingHorizontal(icon_area_left_column, padding), "view")) | 857 if (GuiButton(AddPaddingHorizontal(icon_area_left_column, padding), "view")) |
| 843 PostDog_Load_File( | 858 PostDog_Load_File(curr_history_items->filename); |
| 844 curr_history_items->filename, | |
| 845 &url_input_text, | |
| 846 &active_method_dropdown, | |
| 847 url_body_map, | |
| 848 &url_result_text | |
| 849 ); | |
| 850 if (GuiButton(AddPaddingHorizontal(icon_area_right_column,padding), "delete")) | 859 if (GuiButton(AddPaddingHorizontal(icon_area_right_column,padding), "delete")) |
| 851 { | 860 { |
| 852 if (!remove(PostDog_Construct_URL(curr_history_items->filename))) | 861 if (!remove(PostDog_Construct_URL(curr_history_items->filename))) |
| 853 curr_history_items->deleted = TRUE; | 862 curr_history_items->deleted = TRUE; |
| 854 else | 863 else |
| 855 fprintf(stderr, "Wasn't able to delete file: %s \n", curr_history_items->filename); | 864 fprintf(stderr, "Wasn't able to delete file: %s \n", curr_history_items->filename); |
| 856 } | 865 } |
| 857 } | 866 } |
| 858 EndScissorMode(); | 867 EndScissorMode(); |
| 859 | 868 |
| 860 // Draw scroll indicator for history | |
| 861 if (total > 0) | 869 if (total > 0) |
| 862 { | 870 { |
| 863 float content_height = total * (item_height + padding); | 871 float content_height = total * (item_height + padding); |
| 864 if (content_height > history_list_area.height) | 872 if (content_height > history_list_area.height) |
| 865 { | 873 { |
| 881 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit)) | 889 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit)) |
| 882 url_input_edit = !url_input_edit; | 890 url_input_edit = !url_input_edit; |
| 883 | 891 |
| 884 sendRequest = GuiButton(url_enter_button, "ENTER"); | 892 sendRequest = GuiButton(url_enter_button, "ENTER"); |
| 885 if (sendRequest) | 893 if (sendRequest) |
| 886 PostDog_Http_Request( | 894 PostDog_Http_Request(); |
| 887 url_input_text, | |
| 888 PostDog_Enum_To_String(active_method_dropdown), | |
| 889 url_body_map[TAB_HEADER], | |
| 890 url_body_map[TAB_BODY], | |
| 891 url_result_text, | |
| 892 RESULT_BUFFER_LENGTH | |
| 893 ); | |
| 894 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) | 895 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) |
| 895 method_edit = !method_edit; | 896 method_edit = !method_edit; |
| 896 | 897 |
| 897 // Input Tabs Rect | 898 // Input Tabs Rect |
| 898 DrawRectangleRec(input_area, Fade(BLUE, 0.1f)); | 899 DrawRectangleRec(input_area, Fade(BLUE, 0.1f)); |
| 899 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f)); | 900 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f)); |
| 900 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); | 901 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); |
| 901 GuiDrawRectangle(input_body, 1, GetColor(GuiGetStyle(TEXTBOX, BORDER)), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); | 902 GuiDrawRectangle(input_body, 1, GetColor(GuiGetStyle(TEXTBOX, BORDER)), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); |
| 902 | 903 |
| 903 // Create scrollable input body with offset | |
| 904 BeginScissorMode(input_body.x, input_body.y, input_body.width, input_body.height); | 904 BeginScissorMode(input_body.x, input_body.y, input_body.width, input_body.height); |
| 905 Rectangle scrolled_input = AddPadding(input_body, padding * 2); | 905 Rectangle scrolled_input = AddPadding(input_body, padding * 2); |
| 906 scrolled_input.y += input_body_scroll_offset; | 906 scrolled_input.y += input_body_scroll_offset; |
| 907 scrolled_input.height = MAX_SCROLL_HEIGHT; | 907 scrolled_input.height = MAX_SCROLL_HEIGHT; |
| 908 if (JUNE_GuiTextBox(scrolled_input, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) | 908 if (JUNE_GuiTextBox(scrolled_input, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) |
| 909 input_body_bool = !input_body_bool; | 909 input_body_bool = !input_body_bool; |
| 910 EndScissorMode(); | 910 EndScissorMode(); |
| 911 | 911 |
| 912 // Draw scroll indicator for input body | |
| 913 if (input_body_scroll_offset < 0) { | 912 if (input_body_scroll_offset < 0) { |
| 914 float scrollbar_height = 50; // Fixed size indicator | 913 float scrollbar_height = 10; |
| 915 float max_scroll = 1000; // Estimated max scroll | 914 float scrollbar_y = input_body.y - (input_body_scroll_offset / MAX_SCROLL_HEIGHT) * (input_body.height - scrollbar_height); |
| 916 float scrollbar_y = input_body.y - (input_body_scroll_offset / max_scroll) * (input_body.height - scrollbar_height); | |
| 917 Rectangle scrollbar = { | 915 Rectangle scrollbar = { |
| 918 input_body.x + input_body.width - 5, | 916 input_body.x + input_body.width - 5, |
| 919 scrollbar_y, | 917 scrollbar_y, |
| 920 5, | 918 5, |
| 921 scrollbar_height | 919 scrollbar_height |
| 923 DrawRectangleRec(scrollbar, Fade(BLUE, 0.5f)); | 921 DrawRectangleRec(scrollbar, Fade(BLUE, 0.5f)); |
| 924 } | 922 } |
| 925 | 923 |
| 926 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab); | 924 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab); |
| 927 | 925 |
| 928 PostDog_Update_URL(&url_input_text, url_body_map[TAB_GET_PARAMS]); | 926 PostDog_Update_URL(); |
| 929 | 927 |
| 930 // Result Rect | 928 // Result Rect |
| 931 DrawRectangleRec(result_area, Fade(GREEN, 0.1f)); | 929 DrawRectangleRec(result_area, Fade(GREEN, 0.1f)); |
| 932 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f)); | 930 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f)); |
| 933 | 931 |
| 937 scrolled_result.y += result_body_scroll_offset; | 935 scrolled_result.y += result_body_scroll_offset; |
| 938 scrolled_result.height = MAX_SCROLL_HEIGHT; | 936 scrolled_result.height = MAX_SCROLL_HEIGHT; |
| 939 GuiTextBoxMulti(scrolled_result, url_result_text, RESULT_BUFFER_LENGTH, false); | 937 GuiTextBoxMulti(scrolled_result, url_result_text, RESULT_BUFFER_LENGTH, false); |
| 940 EndScissorMode(); | 938 EndScissorMode(); |
| 941 | 939 |
| 942 // Draw scroll indicator for result body | |
| 943 if (result_body_scroll_offset < 0) { | 940 if (result_body_scroll_offset < 0) { |
| 944 float scrollbar_height = 50; // Fixed size indicator | 941 float scrollbar_height = 10; |
| 945 float max_scroll = 1000; // Estimated max scroll | 942 float scrollbar_y = result_body.y - (result_body_scroll_offset / MAX_SCROLL_HEIGHT) * (result_body.height - scrollbar_height); |
| 946 float scrollbar_y = result_body.y - (result_body_scroll_offset / max_scroll) * (result_body.height - scrollbar_height); | |
| 947 Rectangle scrollbar = { | 943 Rectangle scrollbar = { |
| 948 result_body.x + result_body.width - 5, | 944 result_body.x + result_body.width - 5, |
| 949 scrollbar_y, | 945 scrollbar_y, |
| 950 5, | 946 5, |
| 951 scrollbar_height | 947 scrollbar_height |