comparison postdog/main.c @ 114:e2a73e64e8e6

[Postdog] Got history working.
author June Park <parkjune1995@gmail.com>
date Tue, 06 Jan 2026 08:15:37 -0800
parents d6d578b49a19
children 96db6c3f38d6
comparison
equal deleted inserted replaced
113:7a4e942814bc 114:e2a73e64e8e6
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 <dirent.h>
7 #include "dowa/dowa.h" 6 #include "dowa/dowa.h"
8 7
9 #include <curl/curl.h> 8 #include <curl/curl.h>
10 #include "third_party/raylib/include/raylib.h" 9 #include "third_party/raylib/include/raylib.h"
11 #define RAYGUI_IMPLEMENTATION 10 #define RAYGUI_IMPLEMENTATION
12 #include "third_party/raylib/include/raygui.h" 11 #include "third_party/raylib/include/raygui.h"
12
13 #ifndef POSTDOG_PATHS
14 #define POSTDOG_PATHS "/Users/mrjunejune/zenbu/postdog/history"
15 #endif
13 16
14 #define SCREEN_WIDTH 1280 17 #define SCREEN_WIDTH 1280
15 #define SCREEN_HEIGHT 780 18 #define SCREEN_HEIGHT 780
16 #define TEXT_SIZE 10 19 #define TEXT_SIZE 10
17 20
25 #define URL_TEXT_BUFFER 1024 * 10 28 #define URL_TEXT_BUFFER 1024 * 10
26 #define BODY_BUFFER_LENGTH 1024 * 1025 * 5 29 #define BODY_BUFFER_LENGTH 1024 * 1025 * 5
27 #define RESULT_BUFFER_LENGTH 1024 * 1025 * 5 30 #define RESULT_BUFFER_LENGTH 1024 * 1025 * 5
28 #define AREANA_BUFFER_LENGTH 1024 * 1025 * 15 31 #define AREANA_BUFFER_LENGTH 1024 * 1025 * 15
29 32
33
34 #ifdef _WIN32
35 #include <direct.h>
36 #include <io.h>
37 #define mkdir(path, mode) _mkdir(path)
38 #define access _access
39 #define F_OK 0
40 #else
41 #include <sys/stat.h>
42 #include <dirent.h>
43 #include <unistd.h>
44 #endif
45
30 typedef Dowa_KV(char*, char*) INPUT_HASHMAP; 46 typedef Dowa_KV(char*, char*) INPUT_HASHMAP;
31 47
32 typedef struct { 48 typedef struct {
33 char *data; 49 char *data;
34 size_t size; 50 size_t size;
35 } ResponseBuffer; 51 } ResponseBuffer;
36 52
37 typedef struct { 53 typedef struct {
38 char filename[256]; 54 char *filename;
39 char displayName[128]; 55 Rectangle rect;
40 char method[16]; 56 long time_modified;
41 time_t timestamp;
42 } HistoryItem; 57 } HistoryItem;
58
59 typedef struct {
60 Rectangle rectangle;
61 char *label;
62 bool active;
63 } TabItem;
64
65 typedef enum {
66 TAB_HEADER = 0,
67 TAB_BODY,
68 TAB_GET_PARAMS,
69 TAB_BAR,
70 TAB_LENGTH
71 } PostDog_Tab_Enum;
72
73 static uint32 counter = 0;
74 HistoryItem *history_items = NULL;
75 HistoryItem *new_history_items = NULL;
76
77 int CompareHistoryItemsByDate(const void *a, const void *b) {
78 HistoryItem *itemA = (HistoryItem *)a;
79 HistoryItem *itemB = (HistoryItem *)b;
80 return (itemB->time_modified - itemA->time_modified);
81 }
82
83 // TODO: Make this into generic fucntion so I can use it across different thing.
84 void PostDog_List_Directory(const char *path, HistoryItem **p_file_arr)
85 {
86 HistoryItem *file_arr = *p_file_arr;
87 #ifdef _WIN32
88 struct _finddata_t fileinfo;
89 intptr_t handle;
90 char search_path[256];
91 sprintf(search_path, "%s\\*", path);
92
93 if ((handle = _findfirst(search_path, &fileinfo)) == -1L) {
94 printf("Directory is empty or cannot be read.\n");
95 } else {
96 do {
97 HistoryItem item = {0};
98 item.filename = strdup(fileinfo.name);
99 item.rect = (Rectangle){0};
100 item.time_modified = fileinfo.time_write;
101 Dowa_Array_Push(file_arr, item);
102 } while (_findnext(handle, &fileinfo) == 0);
103 _findclose(handle);
104 }
105 #else
106 struct dirent *entry;
107 struct stat file_stat;
108 DIR *dp = opendir(path);
109 if (dp == NULL) return;
110
111 char full_path[256];
112 while ((entry = readdir(dp)))
113 {
114 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
115 continue;
116 snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
117 if (stat(full_path, &file_stat) == 0)
118 {
119 HistoryItem item = {0};
120 item.filename = strdup(entry->d_name);
121 item.time_modified = file_stat.st_mtime;
122 Dowa_Array_Push(file_arr, item);
123 }
124 }
125 closedir(dp);
126 #endif
127 int count = Dowa_Array_Length(file_arr);
128 if (count > 1) {
129 qsort(file_arr, count, sizeof(HistoryItem), CompareHistoryItemsByDate);
130 }
131 }
132
133 int PostDog_History_Load(HistoryItem **p_history_files)
134 {
135 if (access(POSTDOG_PATHS, F_OK) == -1)
136 {
137 printf("Directory '%s' not found. Creating it...\n", POSTDOG_PATHS);
138 if (mkdir(POSTDOG_PATHS, 0777) != 0)
139 return -1;
140 return 0;
141 }
142 printf("Directory '%s' already exists.\n", POSTDOG_PATHS);
143 PostDog_List_Directory(POSTDOG_PATHS, p_history_files);
144 return 0;
145 }
146
147 bool InArea(Vector2 mouse_position, Rectangle area)
148 {
149 return (
150 mouse_position.x >= area.x &&
151 mouse_position.x < area.x + area.width &&
152 mouse_position.y >= area.y &&
153 mouse_position.y < area.y + area.height
154 );
155 }
156
157 bool Clicked(Vector2 mouse_position, Rectangle area)
158 {
159 return (InArea(mouse_position, area) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
160 }
43 161
44 char *PostDog_Enum_To_String(int active_enum) 162 char *PostDog_Enum_To_String(int active_enum)
45 { 163 {
46 switch(active_enum) 164 switch(active_enum)
47 { 165 {
48 case 0: return "GET"; 166 case 0: return "GET";
49 case 1: return "POST"; 167 case 1: return "POST";
50 case 2: return "PUT"; 168 case 2: return "PUT";
51 case 3: return "DELETE"; 169 case 3: return "DELETE";
52 } 170 }
171 return 0;
172 }
173
174 void PostDog_History_CreateFile(char *filename, char* values)
175 {
176 char full_file_path[512] = {0};
177 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename);
178 FILE *file = fopen(full_file_path, "w");
179 if (!file)
180 {
181 printf("Failed to create a file: %s\n", full_file_path);
182 return;
183 }
184 fwrite(values, 1, strlen(values), file);
185 fclose(file);
186 }
187
188 void PostDog_Request_SaveFile(
189 const char *url,
190 const char *method,
191 const char *headers,
192 const char *body,
193 const char *response)
194 {
195 size_t new_file_size = 1024 * 1024;
196 Dowa_Arena *arena = Dowa_Arena_Create(1024 * 1024 * 2);
197 char *new_file = Dowa_Arena_Allocate(arena, 1024 * 1024);
198 snprintf(
199 new_file,
200 new_file_size,
201 "%s\n"
202 "---\n"
203 "%s\n"
204 "---\n"
205 "%s\n"
206 "---\n"
207 "%s\n"
208 "---\n"
209 "%s\n",
210 url,
211 method,
212 headers,
213 body,
214 response
215 );
216 char *filename = Dowa_Arena_Allocate(arena, 1024);
217 if (!filename)
218 {
219 perror("Error opening file");
220 exit(EXIT_FAILURE);
221 }
222 char *uuid4 = (char *)Dowa_Arena_Allocate(arena, 37);
223 if (!uuid4)
224 {
225 perror("Error uuid");
226 exit(EXIT_FAILURE);
227 }
228
229 int32 seed = (uint32)time(NULL) ^ counter++;
230 Dowa_String_UUID(seed, uuid4);
231 snprintf(filename, 1024, "%s.txt", uuid4);
232 PostDog_History_CreateFile(filename, new_file);
233
234 HistoryItem item = (HistoryItem){ .filename = malloc(sizeof(char) * strlen(filename) + 1), .rect = (Rectangle){0} };
235 memcpy(item.filename, filename, strlen(filename) + 1);
236 Dowa_Array_Push(new_history_items, item);
237
238 Dowa_Arena_Free(arena);
53 } 239 }
54 240
55 static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp) 241 static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp)
56 { 242 {
57 size_t real_size = size * nmemb; 243 size_t real_size = size * nmemb;
70 buf->data[buf->size] = 0; 256 buf->data[buf->size] = 0;
71 257
72 return real_size; 258 return real_size;
73 } 259 }
74 260
75 int PostDog_Make_HttpRequest( 261 int PostDog_Http_Request(
76 const char *url, 262 const char *url,
77 const char *method, 263 const char *method,
78 const char *headers, 264 const char *headers,
79 const char *body, 265 const char *body,
80 char *response, size_t responseSize) 266 char *response, size_t responseSize)
104 290
105 // Set HTTP method 291 // Set HTTP method
106 if (strcmp(method, "POST") == 0) 292 if (strcmp(method, "POST") == 0)
107 { 293 {
108 curl_easy_setopt(curl, CURLOPT_POST, 1L); 294 curl_easy_setopt(curl, CURLOPT_POST, 1L);
109 if (body && strlen(body) > 0) { 295 if (body && strlen(body) > 0)
110 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); 296 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
111 }
112 } 297 }
113 else if (strcmp(method, "PUT") == 0) 298 else if (strcmp(method, "PUT") == 0)
114 { 299 {
115 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); 300 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
116 if (body && strlen(body) > 0) { 301 if (body && strlen(body) > 0)
117 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body); 302 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
118 }
119 } 303 }
120 else if (strcmp(method, "DELETE") == 0) 304 else if (strcmp(method, "DELETE") == 0)
121 { 305 {
122 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); 306 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
123 } 307 }
129 char *headersCopy = strdup(headers); 313 char *headersCopy = strdup(headers);
130 char *line = strtok(headersCopy, "\n"); 314 char *line = strtok(headersCopy, "\n");
131 while (line != NULL) { 315 while (line != NULL) {
132 // Trim whitespace 316 // Trim whitespace
133 while (*line == ' ' || *line == '\t') line++; 317 while (*line == ' ' || *line == '\t') line++;
134 if (strlen(line) > 0) { 318 if (strlen(line) > 0)
135 headerList = curl_slist_append(headerList, line); 319 headerList = curl_slist_append(headerList, line);
136 }
137 line = strtok(NULL, "\n"); 320 line = strtok(NULL, "\n");
138 } 321 }
139 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList); 322 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerList);
140 free(headersCopy); 323 free(headersCopy);
141 } 324 }
144 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback); 327 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Postdog_Curl_Callback);
145 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer); 328 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buffer);
146 329
147 // Follow redirects 330 // Follow redirects
148 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); 331 curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
149
150 // Set timeout 332 // Set timeout
151 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L); 333 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30L);
152
153 // Perform request 334 // Perform request
154 res = curl_easy_perform(curl); 335 res = curl_easy_perform(curl);
155 336
156 if (res != CURLE_OK) 337 if (res != CURLE_OK)
157 snprintf(response, responseSize, "Error: %s\n", curl_easy_strerror(res)); 338 snprintf(response, responseSize, "Error: %s\n", curl_easy_strerror(res));
172 } 353 }
173 354
174 free(buffer.data); 355 free(buffer.data);
175 curl_global_cleanup(); 356 curl_global_cleanup();
176 357
358 PostDog_Request_SaveFile(
359 url,
360 method,
361 headers,
362 body,
363 response);
177 return 0; 364 return 0;
178 } 365 }
179 366
180 typedef struct {
181 Rectangle rectangle;
182 char *label;
183 bool active;
184 } TabItem;
185
186 typedef enum {
187 TAB_HEADER = 0,
188 TAB_BODY,
189 TAB_GET_PARAMS,
190 TAB_BAR,
191 } PostDog_Tab_Enum;
192
193 void PostDog_Update_URL(char **p_url_input_text, char* get_params) 367 void PostDog_Update_URL(char **p_url_input_text, char* get_params)
194 { 368 {
195 char *url_input_text = *p_url_input_text; 369 char *url_input_text = *p_url_input_text;
196 370
197 // Reset 371 // Reset
198 char *question_mark = strchr(url_input_text, '?'); 372 char *question_mark = strchr(url_input_text, '?');
199 if (question_mark) 373 if (question_mark)
200 *question_mark = '\0'; 374 *question_mark = '\0';
201 375
202 int get_params_length = (int)strlen(get_params) ; 376 int get_params_length = (int)strlen(get_params) ;
205 379
206 char *separator = "?"; 380 char *separator = "?";
207 381
208 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024); 382 Dowa_Arena *arena = Dowa_Arena_Create(1024*1024);
209 char **lines = Dowa_String_Split(get_params, "\n", get_params_length, 1, arena); 383 char **lines = Dowa_String_Split(get_params, "\n", get_params_length, 1, arena);
210
211 size_t url_len = strlen(url_input_text);
212 size_t url_capacity = URL_TEXT_BUFFER;
213
214 for (int i = 0; i < Dowa_Array_Length(lines); i++) 384 for (int i = 0; i < Dowa_Array_Length(lines); i++)
215 { 385 {
216 char *line = lines[i]; 386 char *line = lines[i];
217 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena); 387 char **key_value = Dowa_String_Split(line, " ", (int)strlen(line), 1, arena);
218 388
219 if (Dowa_Array_Length(key_value) < 2) 389 if (Dowa_Array_Length(key_value) < 2)
220 continue; // Skip this line, not break entire loop 390 break;
221
222 // Check buffer capacity before each append
223 size_t needed = url_len + strlen(separator) + strlen(key_value[0]) + 1 + 10; // +10 for "=" and safety
224 if (needed >= url_capacity) break;
225 391
226 strcat(url_input_text, separator); 392 strcat(url_input_text, separator);
227 strcat(url_input_text, key_value[0]); 393 strcat(url_input_text, key_value[0]);
228 strcat(url_input_text, "="); 394 strcat(url_input_text, "=");
229 url_len = strlen(url_input_text);
230
231 for (int i = 1; i < Dowa_Array_Length(key_value); i++) 395 for (int i = 1; i < Dowa_Array_Length(key_value); i++)
232 { 396 {
233 if (!key_value[i] || key_value[i][0] == '\0') 397 if (!key_value[i] || key_value[i][0] == '\0')
234 break; 398 break;
235
236 size_t value_len = strlen(key_value[i]);
237 needed = url_len + value_len + 4; // +4 for "%20" if needed
238 if (needed >= url_capacity) break;
239
240 printf("\n\n------\n\n");
241 printf("key_value[%i]: %s, p = %p\n", i, key_value[i], key_value[i]);
242 printf("\n\n------\n\n");
243
244 if (i > 1) strcat(url_input_text, "%20"); 399 if (i > 1) strcat(url_input_text, "%20");
245 strcat(url_input_text, key_value[i]); 400 strcat(url_input_text, key_value[i]);
246 url_len = strlen(url_input_text);
247 } 401 }
248 separator = "&"; 402 separator = "&";
249 } 403 }
250 404
251 Dowa_Arena_Free(arena); 405 Dowa_Arena_Free(arena);
406 }
407
408 int PostDog_String_To_MethodEnum(char *value)
409 {
410 if (strstr(value, "GET"))
411 return 0;
412 if (strstr(value, "POST"))
413 return 1;
414 if (strstr(value, "PUT"))
415 return 2;
416 if (strstr(value, "DELETE"))
417 return 3;
418 return 0;
419 }
420
421 void PostDog_Params_Reset(
422 char **p_url_input_text,
423 int *p_active_method_dropdown,
424 char **url_body_map,
425 char **p_url_result_text
426 )
427 {
428 char *url_input_text = *p_url_input_text;
429 char *url_result_text = *p_url_result_text;
430 int active_method_dropdown = *p_active_method_dropdown;
431
432 url_input_text = "";
433 url_result_text = "";
434 active_method_dropdown = 0;
435 for (int i = 0; i < Dowa_Array_Length(url_body_map); i++)
436 url_body_map[i] = "";
437 }
438
439 void PostDog_Load_File(
440 const char *filename,
441 char **p_url_input_text,
442 int *p_active_method_dropdown,
443 char **url_body_map,
444 char **p_url_result_text
445 ) {
446 char *url_input_text = *p_url_input_text;
447 char *url_result_text = *p_url_result_text;
448 int active_method_dropdown = *p_active_method_dropdown;
449
450 char full_file_path[512] = {0};
451 snprintf(full_file_path, 512, "%s/%s", POSTDOG_PATHS, filename);
452 FILE *file = fopen(full_file_path, "r");
453 if (!file)
454 return;
455
456 fseek(file, 0, SEEK_END);
457 size_t file_size = ftell(file);
458 fseek(file, 0, SEEK_SET);
459
460 Dowa_Arena *init_arena = Dowa_Arena_Create(file_size + 2);
461 Dowa_Arena *split_arena = Dowa_Arena_Create(file_size * 2);
462 char *file_buffer = Dowa_Arena_Allocate(init_arena, file_size+1);
463 fread(file_buffer, 1, file_size, file);
464 char **values = Dowa_String_Split(file_buffer, "---\n", file_size, 4, split_arena);
465 Dowa_Arena_Free(init_arena);
466 for (int i = 0; i < Dowa_Array_Length(values); i++)
467 {
468 if (i == 0)
469 {
470 snprintf(url_input_text, strlen(values[i]) + 1, "%s", values[i]);
471 url_input_text[strcspn(url_input_text, "\n")] = '\0';
472 }
473 else if (i == 1)
474 active_method_dropdown = PostDog_String_To_MethodEnum(values[i]);
475 else if (i <= 3)
476 {
477 snprintf(url_body_map[i-2], strlen(values[i]) + 1, "%s", values[i]);
478 for (int j = strlen(values[i]); j > 0; j--)
479 {
480 if (url_body_map[i-2][j] == '\n')
481 {
482 url_body_map[i-2][j] = '\0';
483 break;
484 }
485 }
486 }
487 else
488 snprintf(url_result_text, strlen(values[i]) + 1, "%s", values[i]);
489 }
490 }
491
492 Rectangle AddPadding(Rectangle rect, float padding)
493 {
494 return (Rectangle){
495 rect.x + padding,
496 rect.y + padding,
497 rect.width - (2 * padding),
498 rect.height - (2 * padding)
499 };
252 } 500 }
253 501
254 int main() 502 int main()
255 { 503 {
256 // -- initizlied --// 504 // -- initizlied --//
258 SetWindowState(FLAG_WINDOW_RESIZABLE); 506 SetWindowState(FLAG_WINDOW_RESIZABLE);
259 SetTargetFPS(60); 507 SetTargetFPS(60);
260 508
261 Dowa_Arena *arena = Dowa_Arena_Create(AREANA_BUFFER_LENGTH); 509 Dowa_Arena *arena = Dowa_Arena_Create(AREANA_BUFFER_LENGTH);
262 510
511 Font customFont = LoadFontEx("postdog/Roboto-Regular.ttf", 20, 0, 0);
512 GuiSetFont(customFont);
513 GuiSetStyle(DEFAULT, TEXT_SIZE, 20);
514
263 // -- Starting pos ---// 515 // -- Starting pos ---//
516 // Everyhting is relative to sidebar at this point lol
264 float side_bar_x = 10; 517 float side_bar_x = 10;
265 float side_bar_y = 10; 518 float side_bar_y = 10;
266
267 Rectangle history_sidebar = { .x = side_bar_x, .y = side_bar_y, .width = 0, .height = 0 }; 519 Rectangle history_sidebar = { .x = side_bar_x, .y = side_bar_y, .width = 0, .height = 0 };
520 Dowa_Array_Reserve(history_items, 10);
521 Dowa_Array_Reserve(new_history_items, 10);
522 PostDog_History_Load(&history_items);
268 523
269 Rectangle url_area = { 0 }; 524 Rectangle url_area = { 0 };
270 Rectangle textBounds = { 0 }; 525 Rectangle textBounds = { 0 };
271 Rectangle url_input_bounds = { 0 }; 526 Rectangle url_input_bounds = { 0 };
272 bool url_input_bool = false; 527 bool url_input_edit = false;
273 Rectangle url_text_bounds = { 0 }; 528 Rectangle url_text_bounds = { 0 };
274 Rectangle url_enter_button = { 0 }; 529 Rectangle url_enter_button = { 0 };
275 Rectangle method_dropdown = { 0 }; 530 Rectangle method_dropdown = { 0 };
276 531
532
277 char *url_input_text = (char *)Dowa_Arena_Allocate(arena, URL_TEXT_BUFFER); 533 char *url_input_text = (char *)Dowa_Arena_Allocate(arena, URL_TEXT_BUFFER);
278 snprintf(url_input_text, URL_TEXT_BUFFER, "https://httpbin.org/get"); 534 snprintf(url_input_text, URL_TEXT_BUFFER, "https://httpbin.org/get");
279 535
280 INPUT_HASHMAP *url_body_map = NULL; 536 char **url_body_map = NULL;
281 Dowa_HashMap_Push_Arena(url_body_map, "Header", (char *)Dowa_Arena_Allocate(arena, HEADER_BUFFER_LENGTH), arena); 537 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, HEADER_BUFFER_LENGTH), arena);
282 Dowa_HashMap_Push_Arena(url_body_map, "Body", (char *)Dowa_Arena_Allocate(arena, BODY_BUFFER_LENGTH), arena); 538 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, BODY_BUFFER_LENGTH), arena);
283 Dowa_HashMap_Push_Arena(url_body_map, "Get Param", (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); 539 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena);
284 Dowa_HashMap_Push_Arena(url_body_map, "Bar", (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena); 540 Dowa_Array_Push_Arena(url_body_map, (char *)Dowa_Arena_Allocate(arena, DEFAULT_TEXT_BUFFER_LENGTH), arena);
285 541
286 snprintf(url_body_map[0].value, HEADER_BUFFER_LENGTH, "Content-Type: application/json"); 542 snprintf(url_body_map[TAB_HEADER], HEADER_BUFFER_LENGTH, "Content-Type: application/json");
287 snprintf(url_body_map[1].value, HEADER_BUFFER_LENGTH, ""); 543 snprintf(url_body_map[TAB_BODY], HEADER_BUFFER_LENGTH, "");
288 544
289 char *url_result_text = (char *)Dowa_Arena_Allocate(arena, RESULT_BUFFER_LENGTH); 545 char *url_result_text = (char *)Dowa_Arena_Allocate(arena, RESULT_BUFFER_LENGTH);
290 546
291 int active_method_dropdown = 0; 547 int active_method_dropdown = 0;
292 bool method_edit = false; 548 bool method_edit = false;
303 // -- result --// 559 // -- result --//
304 Rectangle result_area = { 0 }; 560 Rectangle result_area = { 0 };
305 Rectangle result_body = { 0 }; 561 Rectangle result_body = { 0 };
306 562
307 // General styling. 563 // General styling.
308 int padding = 10; // TODO make it % based? 564 float padding = 10; // TODO make it % based?
309 int active_input_tab = 0; 565 int active_input_tab = 0;
310 566
311 while (!WindowShouldClose()) 567 while (!WindowShouldClose())
312 { 568 {
313 int screen_width = GetScreenWidth(); 569 int screen_width = GetScreenWidth();
314 int screen_height = GetScreenHeight(); 570 int screen_height = GetScreenHeight();
315 571
316 history_sidebar.width = screen_width * 0.15; 572 history_sidebar.width = screen_width * 0.15;
317 history_sidebar.height = screen_width - 10; 573 history_sidebar.height = screen_width - 10;
574
575 int32 new_history_items_length = Dowa_Array_Length(new_history_items);
576 int32 history_item_length = Dowa_Array_Length(history_items);
577 int32 total = new_history_items_length + history_item_length;
578 for (int i = 0; i < total; i++)
579 {
580 HistoryItem *curr_history_items = i < new_history_items_length ? &new_history_items[i] : &history_items[i - new_history_items_length];
581 curr_history_items->rect.x = history_sidebar.x + padding;
582 curr_history_items->rect.y = history_sidebar.y + (padding * 2 * (i+1)) + (i * history_sidebar.height * 0.05);
583 curr_history_items->rect.width = history_sidebar.width - (padding * 2);
584 curr_history_items->rect.height = history_sidebar.height * 0.05;
585 }
318 586
319 // -- URL Area --// 587 // -- URL Area --//
320 url_area.x = (side_bar_x + history_sidebar.width); 588 url_area.x = (side_bar_x + history_sidebar.width);
321 url_area.y = (side_bar_y); 589 url_area.y = (side_bar_y);
322 url_area.width = (screen_width - history_sidebar.width) * 0.9; 590 url_area.width = (screen_width - history_sidebar.width) * 0.9;
369 result_body.x = result_area.x + padding; 637 result_body.x = result_area.x + padding;
370 result_body.y = result_area.y + input_tab.height + padding; 638 result_body.y = result_area.y + input_tab.height + padding;
371 result_body.width = url_area.width * 0.49 - padding; 639 result_body.width = url_area.width * 0.49 - padding;
372 result_body.height = result_area.height - input_tab.height - padding; 640 result_body.height = result_area.height - input_tab.height - padding;
373 641
642 Vector2 mouse_position = GetMousePosition();
643
374 BeginDrawing(); 644 BeginDrawing();
375 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); 645 ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
376 646
377 // Sidebar Rect
378 DrawRectangleRec(history_sidebar, Fade(GRAY, 0.1f)); 647 DrawRectangleRec(history_sidebar, Fade(GRAY, 0.1f));
648 for (int i = 0; i < total; i++)
649 {
650 HistoryItem *curr_history_items = i < new_history_items_length ? &new_history_items[i] : &history_items[i - new_history_items_length];
651 DrawRectangleRec(curr_history_items->rect, Fade(RED, 0.1f));
652 GuiDrawText(curr_history_items->filename, AddPadding(curr_history_items->rect, padding), TEXT_ALIGN_CENTER, RED);
653 }
379 654
380 // URL area Rect 655 // URL area Rect
381 GuiDrawText("URL: ", url_text_bounds, TEXT_ALIGN_CENTER, RED); 656 GuiDrawText("URL: ", url_text_bounds, TEXT_ALIGN_CENTER, RED);
382 DrawRectangleRec(url_area, Fade(RED, 0.1f)); 657 DrawRectangleRec(url_area, Fade(RED, 0.1f));
383 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_bool)) 658 if (GuiTextBox(url_input_bounds, url_input_text, DEFAULT_TEXT_BUFFER_LENGTH, url_input_edit))
384 url_input_bool = !url_input_bool; 659 url_input_edit = !url_input_edit;
660
385 sendRequest = GuiButton(url_enter_button, "ENTER"); 661 sendRequest = GuiButton(url_enter_button, "ENTER");
386 if (sendRequest) 662 if (sendRequest)
387 PostDog_Make_HttpRequest( 663 PostDog_Http_Request(
388 url_input_text, 664 url_input_text,
389 PostDog_Enum_To_String(active_method_dropdown), 665 PostDog_Enum_To_String(active_method_dropdown),
390 url_body_map[0].value, 666 url_body_map[TAB_HEADER],
391 url_body_map[1].value, 667 url_body_map[TAB_BODY],
392 url_result_text, 668 url_result_text,
393 RESULT_BUFFER_LENGTH 669 RESULT_BUFFER_LENGTH
394 ); 670 );
395 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit)) 671 if (GuiDropdownBox(method_dropdown, "GET;POST;PUT;DELETE", &active_method_dropdown, method_edit))
396 method_edit = !method_edit; 672 method_edit = !method_edit;
397 673
398 // Input Tabs Rect 674 // Input Tabs Rect
399 DrawRectangleRec(input_area, Fade(BLUE, 0.1f)); 675 DrawRectangleRec(input_area, Fade(BLUE, 0.1f));
400 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f)); 676 DrawRectangleRec(input_tab, Fade(DARKBLUE, 0.1f));
401 GuiSetStyle(TOGGLE, GROUP_PADDING, 0); 677 GuiSetStyle(TOGGLE, GROUP_PADDING, 0);
402 if (JUNE_GuiTextBox(input_body, url_body_map[active_input_tab].value, DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool)) 678 if (JUNE_GuiTextBox(input_body, url_body_map[active_input_tab], DEFAULT_TEXT_BUFFER_LENGTH, input_body_bool))
403 input_body_bool = !input_body_bool; 679 input_body_bool = !input_body_bool;
404 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab); 680 GuiToggleGroup(input_tab_item, "Header;Body;Get Param;Bar", &active_input_tab);
405 PostDog_Update_URL(&url_input_text, url_body_map[TAB_GET_PARAMS].value); 681
682 PostDog_Update_URL(&url_input_text, url_body_map[TAB_GET_PARAMS]);
406 683
407 // Result Rect 684 // Result Rect
408 DrawRectangleRec(result_area, Fade(GREEN, 0.1f)); 685 DrawRectangleRec(result_area, Fade(GREEN, 0.1f));
409 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f)); 686 DrawRectangleRec(result_body, Fade(DARKGREEN, 0.1f));
410 GuiTextBoxMulti(result_body, url_result_text, RESULT_BUFFER_LENGTH, false); 687 GuiTextBoxMulti(result_body, url_result_text, RESULT_BUFFER_LENGTH, false);
688
689 if (url_input_edit && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C))
690 {
691 SetClipboardText(url_input_text);
692 }
693 else if (input_body_bool && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C))
694 {
695 SetClipboardText(url_body_map[active_input_tab]);
696 }
697 else if (InArea(mouse_position, result_body))
698 {
699 DrawRectangleRec(result_body, Fade(GREEN, 0.3f));
700 if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C))
701 SetClipboardText(url_result_text);
702 }
703
704 for (int i = 0; i < Dowa_Array_Length(history_items); i++)
705 {
706 if (Clicked(mouse_position, history_items[i].rect))
707 PostDog_Load_File(
708 history_items[i].filename,
709 &url_input_text,
710 &active_method_dropdown,
711 url_body_map,
712 &url_result_text
713 );
714 }
411 EndDrawing(); 715 EndDrawing();
412 } 716 }
413 CloseWindow(); 717 CloseWindow();
414 return 0; 718 return 0;
415 } 719 }