changeset 57:d4cdb87212fb

[PostDog] Working version.
author June Park <parkjune1995@gmail.com>
date Fri, 19 Dec 2025 18:00:30 -0800
parents 0dcfbf5ba997
children ccb42d5bf8fd
files postdog/main.c
diffstat 1 files changed, 133 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/postdog/main.c	Fri Dec 19 13:59:11 2025 -0800
+++ b/postdog/main.c	Fri Dec 19 18:00:30 2025 -0800
@@ -16,13 +16,21 @@
 
 #define SCREEN_WIDTH 1280
 #define SCREEN_HEIGHT 780
-#define SIDEBAR_WIDTH 200
-#define URL_INPUT_HEIGHT 40
-#define PADDING 15
-
 #define TEXT_SIZE 10
 #define LINE_HEIGHT 15
+#define GENERIC_PADDING 15
 
+#define SIDEBAR_WIDTH 200
+#define SIDEBAR_PADDING_GENERAL 5
+#define SIDEBAR_AREA_PADDING_X 10
+#define SIDEBAR_AREA_PADDING_Y 10
+#define SIDEBAR_REFERSH_BUTTON_WIDTH 90
+#define SIDEBAR_REFERSH_BUTTON_HEIGHT 20
+#define SIDEBAR_HISTORY_ITEM_HEIGHT 45
+
+#define URL_INPUT_HEIGHT 40
+
+#define TAB_LEN 3
 #define METHOD_BUTTON_WIDTH 100
 #define METHOD_BUTTON_HEIGHT 40
 #define SEND_BUTTON_WIDTH 100
@@ -48,10 +56,10 @@
 } HistoryItem;
 
 typedef enum {
-  ActiveTab_JSON = 0
+  ActiveTab_JSON = 0,
   ActiveTab_Headers, 
   ActiveTab_Params,
-} ActiveTab
+} ActiveTab;
 
 // Callback function for curl to write response data
 static size_t Postdog_Curl_Callback(void *contents, size_t size, size_t nmemb, void *userp)
@@ -449,21 +457,21 @@
     // Layout calculations
     Rectangle sidebar = { 0, 10, SIDEBAR_WIDTH, screenHeight };
 
-    float mainX = SIDEBAR_WIDTH + PADDING;
-    float mainWidth = screenWidth - SIDEBAR_WIDTH - PADDING * 2;
+    float mainX = SIDEBAR_WIDTH + GENERIC_PADDING;
+    float mainWidth = screenWidth - SIDEBAR_WIDTH - GENERIC_PADDING * 2;
 
     // URL input box - leave space for SEND button on the right
     Rectangle urlBox = {
       mainX,
-      PADDING,
-      mainWidth - SEND_BUTTON_WIDTH - PADDING,
+      GENERIC_PADDING,
+      mainWidth - SEND_BUTTON_WIDTH - GENERIC_PADDING,
       URL_INPUT_HEIGHT
     };
 
     // SEND button positioned beside URL input
     Rectangle sendButton = {
-      urlBox.x + urlBox.width + PADDING,
-      PADDING,
+      urlBox.x + urlBox.width + GENERIC_PADDING,
+      GENERIC_PADDING,
       SEND_BUTTON_WIDTH,
       SEND_BUTTON_HEIGHT
     };
@@ -471,20 +479,20 @@
     // Method dropdown below URL
     Rectangle methodButton = {
       mainX,
-      urlBox.y + urlBox.height + PADDING,
+      urlBox.y + urlBox.height + GENERIC_PADDING,
       METHOD_BUTTON_WIDTH,
       METHOD_BUTTON_HEIGHT
     };
 
     float tabHeight = 30;
-    float contentY = methodButton.y + methodButton.height + PADDING + tabHeight;
-    float contentHeight = screenHeight - contentY - PADDING;
+    float contentY = methodButton.y + methodButton.height + GENERIC_PADDING + tabHeight;
+    float contentHeight = screenHeight - contentY - GENERIC_PADDING;
 
-    float panelWidth = (mainWidth - PADDING) / 2;
+    float panelWidth = (mainWidth - GENERIC_PADDING) / 2;
 
     Rectangle tabBar = {
       mainX,
-      methodButton.y + methodButton.height + PADDING,
+      methodButton.y + methodButton.height + GENERIC_PADDING,
       panelWidth,
       tabHeight
     };
@@ -497,7 +505,7 @@
     };
 
     Rectangle responsePanel = {
-      mainX + panelWidth + PADDING,
+      mainX + panelWidth + GENERIC_PADDING,
       contentY,
       panelWidth,
       contentHeight
@@ -506,21 +514,29 @@
     BeginDrawing();
       ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
 
-      // Sidebar with history
+      // --- Sidebar Component---
       DrawRectangleRec(sidebar, Fade(GRAY, 0.1f));
       GuiGroupBox(sidebar, "HISTORY");
 
-      // Refresh history button
-      Rectangle refreshBtn = { sidebar.x + 5, sidebar.y + 5, 90, 20 };
-      if (GuiButton(refreshBtn, "Refresh")) {
+      Rectangle refreshBtn = { 
+        sidebar.x + SIDEBAR_PADDING_GENERAL, 
+        sidebar.y + SIDEBAR_PADDING_GENERAL,
+        SIDEBAR_REFERSH_BUTTON_WIDTH,
+        SIDEBAR_REFERSH_BUTTON_HEIGHT
+      };
+      if (GuiButton(refreshBtn, "Refresh"))
+      {
         historyCount = PostDog_HistoryDistory_ItemsLoad(historyItems, MAX_HISTORY_ITEMS);
       }
 
-      // Scroll area for history
-      Rectangle historyArea = { sidebar.x + 5, sidebar.y + 30, sidebar.width - 10, sidebar.height - 40 };
-
-      // Handle scroll
-      if (CheckCollisionPointRec(GetMousePosition(), historyArea)) {
+      Rectangle historyArea = { 
+        sidebar.x + SIDEBAR_PADDING_GENERAL,
+        sidebar.y + SIDEBAR_AREA_PADDING_Y, 
+        sidebar.width - SIDEBAR_AREA_PADDING_X, 
+        sidebar.height - SIDEBAR_AREA_PADDING_Y
+      };
+      if (CheckCollisionPointRec(GetMousePosition(), historyArea))
+      {
         float wheel = GetMouseWheelMove();
         historyScroll.y += wheel * 20;
         if (historyScroll.y < 0) historyScroll.y = 0;
@@ -528,39 +544,48 @@
 
       BeginScissorMode(historyArea.x, historyArea.y, historyArea.width, historyArea.height);
 
-      if (historyCount == 0) {
-        DrawText("No requests yet", historyArea.x + 5, historyArea.y + 5, 10, DARKGRAY);
-      } else {
-        int yPos = historyArea.y + 5 - (int)historyScroll.y;
-        int itemHeight = 45;
-
-        for (int i = 0; i < historyCount; i++) {
-          if (yPos > historyArea.y - itemHeight && yPos < historyArea.y + historyArea.height) {
-            Rectangle itemRect = { historyArea.x, yPos, historyArea.width, itemHeight - 2 };
+      if (historyCount == 0)
+      {
+        DrawText("No requests yet", historyArea.x + 5, historyArea.y + 25, 10, DARKGRAY);
+      } 
+      else
+      {
+        int item_y_position = historyArea.y + 5 - (int)historyScroll.y;
+        for (
+            int current_history_item_number = 0;
+            current_history_item_number < historyCount;
+            current_history_item_number++
+        )
+        {
+          if (item_y_position > historyArea.y - SIDEBAR_HISTORY_ITEM_HEIGHT && item_y_position < historyArea.y + historyArea.height)
+          {
+            Rectangle itemRect = { historyArea.x, item_y_position, historyArea.width, SIDEBAR_HISTORY_ITEM_HEIGHT - 2 };
 
             // Draw button for history item
-            Color bgColor = (selectedHistoryIndex == i) ? Fade(BLUE, 0.3f) : Fade(LIGHTGRAY, 0.5f);
-
-            if (CheckCollisionPointRec(GetMousePosition(), itemRect) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
-              // Load this request
+            Color bgColor = (selectedHistoryIndex == current_history_item_number) ? Fade(BLUE, 0.3f) : Fade(LIGHTGRAY, 0.5f);
+            if (CheckCollisionPointRec(GetMousePosition(), itemRect) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
+            {
+              // TODO: This is cringe as fuck probably should just have a strucut that we assign and then zero out lol
               char tempUrl[1024], tempMethod[16], tempHeaders[HEADER_INPUT_BUFFER_LEN], tempBody[JSON_INPUT_BUFFER_LEN];
 
               if (PostDog_HistoryDirectory_LoadRequest(
-                    historyItems[i].filename, tempUrl, tempMethod, tempHeaders, tempBody) == 0)
+                    historyItems[current_history_item_number].filename, tempUrl, tempMethod, tempHeaders, tempBody) == 0)
               {
                 strncpy(urlInput, tempUrl, sizeof(urlInput) - 1);
                 strncpy(headersInput, tempHeaders, sizeof(headersInput) - 1);
                 strncpy(jsonInput, tempBody, sizeof(jsonInput) - 1);
 
                 // Set method
-                for (int m = 0; m < 4; m++) {
-                  if (strcmp(methods[m], tempMethod) == 0) {
+                for (int m = 0; m < 4; m++)
+                {
+                  if (strcmp(methods[m], tempMethod) == 0)
+                  {
                     methodActive = m;
                     break;
                   }
                 }
 
-                selectedHistoryIndex = i;
+                selectedHistoryIndex = current_history_item_number;
                 strcpy(responseText, "Request loaded from history. Click SEND to execute.");
               }
             }
@@ -569,44 +594,45 @@
             DrawRectangleLinesEx(itemRect, 1, GRAY);
 
             // Draw method badge
-            DrawText(historyItems[i].method, itemRect.x + 5, yPos + 5, 10, BLACK);
+            DrawText(historyItems[current_history_item_number].method, itemRect.x + 5, item_y_position + 5, 10, BLACK);
 
             // Draw timestamp (date only)
             char dateStr[16] = "";
-            if (strlen(historyItems[i].filename) >= 8) {
+            if (strlen(historyItems[current_history_item_number].filename) >= 8)
+            {
               snprintf(dateStr, sizeof(dateStr), "%.4s-%.2s-%.2s",
-                       historyItems[i].filename, historyItems[i].filename + 4, historyItems[i].filename + 6);
+                       historyItems[current_history_item_number].filename, historyItems[current_history_item_number].filename + 4, historyItems[current_history_item_number].filename + 6);
             }
-            DrawText(dateStr, itemRect.x + 5, yPos + 18, 8, DARKGRAY);
+            DrawText(dateStr, itemRect.x + 5, item_y_position + 18, 8, DARKGRAY);
 
             // Draw time
             char timeStr[16] = "";
-            if (strlen(historyItems[i].filename) >= 15) {
+            if (strlen(historyItems[current_history_item_number].filename) >= 15) {
               snprintf(timeStr, sizeof(timeStr), "%.2s:%.2s:%.2s",
-                       historyItems[i].filename + 9, historyItems[i].filename + 11, historyItems[i].filename + 13);
+                       historyItems[current_history_item_number].filename + 9, historyItems[current_history_item_number].filename + 11, historyItems[current_history_item_number].filename + 13);
             }
-            DrawText(timeStr, itemRect.x + 5, yPos + 28, 8, DARKGRAY);
+            DrawText(timeStr, itemRect.x + 5, item_y_position + 28, 8, DARKGRAY);
           }
 
-          yPos += itemHeight;
+          item_y_position += SIDEBAR_HISTORY_ITEM_HEIGHT;
         }
       }
 
       EndScissorMode();
 
-      // URL Input
-      GuiLabel((Rectangle){ mainX, PADDING - 15, 100, 20 }, "URL:");
+      // --- URL Input Component ---
+      GuiLabel((Rectangle){ mainX, GENERIC_PADDING - 15, 100, 20 }, "URL:");
       if (GuiTextBox(urlBox, urlInput, 1024, urlEditMode))
       {
         urlEditMode = !urlEditMode;
       }
-      // Copy support for URL
-      if (urlEditMode && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) {
+      if (urlEditMode && (IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C))
+      {
         SetClipboardText(urlInput);
       }
 
       // Send button (beside URL)
-      if (GuiButton(sendButton, "SEND"))
+      if (GuiButton(sendButton, "SEND") || (urlEditMode && IsKeyDown(KEY_ENTER)))
       {
         strcpy(responseText, "Sending request...\n");
 
@@ -624,9 +650,9 @@
         // Reload history to show the new request
         historyCount = PostDog_HistoryDistory_ItemsLoad(historyItems, MAX_HISTORY_ITEMS);
 
+        // Making the requests.
         PostDog_Make_HttpRequest(urlInput, selectedMethod, requestHeaders,
                        requestBody, tempResponse, sizeof(tempResponse));
-
         strncpy(responseText, tempResponse, sizeof(responseText) - 1);
         responseText[sizeof(responseText) - 1] = '\0';
       }
@@ -649,22 +675,25 @@
 
       if (GuiButton(paramsTab, activeTab == ActiveTab_Params ? "#191#Params" : "Params"))
       {
-        activeTab = ActiveTab_Headers;
+        activeTab = ActiveTab_Params;
       }
 
       const char *panelTitle;
       switch(activeTab) {
         case  ActiveTab_JSON:
         {
-          panelTitle = "Request Body (JSON)"
+          panelTitle = "Request Body (JSON)";
+          break;
         }
         case  ActiveTab_Headers:
         {
-          panelTitle = "Request Headers"
+          panelTitle = "Request Headers";
+          break;
         } 
         case  ActiveTab_Params:
         {
-          panelTitle = "Query Parameters"
+          panelTitle = "Query Parameters";
+          break;
         }
       }
 
@@ -695,7 +724,8 @@
       if (CheckCollisionPointRec(GetMousePosition(), textArea))
       {
         float wheel = GetMouseWheelMove();
-        switch(activeTab) {
+        switch(activeTab)
+        {
           case  ActiveTab_JSON:
           {
             jsonScroll.y += wheel * 20;
@@ -713,105 +743,57 @@
           }
         }
       }
-      if (activeTab == 0)
+
+      char *copyFromInput;
+      bool *currentMode; 
+      switch(activeTab)
       {
-        BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height);
-
-        int yPos = textArea.y + 5 - (int)jsonScroll.y;
-        char *textCopy = strdup(jsonInput);
-        char *line = strtok(textCopy, "\n");
-
-        while (line != NULL && yPos < textArea.y + textArea.height)
+        case  ActiveTab_JSON:
         {
-          if (yPos + LINE_HEIGHT > textArea.y) {
-            DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY);
-          }
-          yPos += LINE_HEIGHT;
-          line = strtok(NULL, "\n");
-        }
-        free(textCopy);
-
-        EndScissorMode();
-
-        if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) {
-          SetClipboardText(jsonInput);
+          PostDog_Render_TextWithScroll(textArea, jsonScroll, jsonInput);
+          copyFromInput = jsonInput;
+          currentMode = &jsonEditMode;
+          break;
         }
-
-        // Edit button
-        Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height - 10, 50, 20 };
-        if (GuiButton(editBtn, "Edit")) {
-          jsonEditMode = !jsonEditMode;
-        }
-      } else if (activeTab == 1) {
-        BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height);
-
-        int yPos = textArea.y + 5 - (int)headersScroll.y;
-        char *textCopy = strdup(headersInput);
-        char *line = strtok(textCopy, "\n");
-
-        while (line != NULL && yPos < textArea.y + textArea.height)
+        case  ActiveTab_Headers:
         {
-          if (yPos + LINE_HEIGHT > textArea.y)
-          {
-            DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY);
-          }
-          yPos += LINE_HEIGHT;
-          line = strtok(NULL, "\n");
-        }
-        free(textCopy);
-
-        EndScissorMode();
+          PostDog_Render_TextWithScroll(textArea, headersScroll, headersInput);
+          copyFromInput = headersInput;
+          currentMode = &headersEditMode;
+          break;
+        } 
+        case  ActiveTab_Params:
+        {
+          PostDog_Render_TextWithScroll(textArea, paramsScroll, paramsInput);
+          copyFromInput = paramsInput;
+          currentMode = &paramsEditMode;
 
-        if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) {
-          SetClipboardText(headersInput);
-        }
+          Rectangle updateUrlBtn = { textArea.x + 30, textArea.y + textArea.height - 10, 120, 20 };
+          // TODO: Automatic update
+          if (GuiButton(updateUrlBtn, "Update URL"))
+          {
+            char tempUrl[1024];
+            strncpy(tempUrl, urlInput, sizeof(tempUrl) - 1);
 
-        // Edit button
-        Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height + 5, 50, 20 };
-        if (GuiButton(editBtn, "Edit")) {
-          headersEditMode = !headersEditMode;
-        }
-      } else {
-        // Params input with manual scroll
-        BeginScissorMode(textArea.x, textArea.y, textArea.width, textArea.height);
+            // Remove existing params if any
+            char *questionMark = strchr(tempUrl, '?');
+            if (questionMark) *questionMark = '\0';
 
-        int yPos = textArea.y + 5 - (int)paramsScroll.y;
-        char *textCopy = strdup(paramsInput);
-        char *line = strtok(textCopy, "\n");
-
-        while (line != NULL && yPos < textArea.y + textArea.height) {
-          if (yPos + LINE_HEIGHT > textArea.y) {
-            DrawText(line, textArea.x + 5, yPos, TEXT_SIZE, DARKGRAY);
+            updateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput);
           }
-          yPos += LINE_HEIGHT;
-          line = strtok(NULL, "\n");
+          break;
         }
-        free(textCopy);
-
-        EndScissorMode();
-
-        if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C)) {
-          SetClipboardText(paramsInput);
-        }
+      }
 
-        // Buttons
-        Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height + 5, 50, 20 };
-        if (GuiButton(editBtn, "Edit"))
-        {
-          paramsEditMode = !paramsEditMode;
-        }
+      if ((IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_LEFT_CONTROL)) && IsKeyPressed(KEY_C))
+      {
+        SetClipboardText(copyFromInput);
+      }
 
-        Rectangle updateUrlBtn = { textArea.x, textArea.y + textArea.height + 5, 120, 20 };
-        if (GuiButton(updateUrlBtn, "Update URL"))
-        {
-          char tempUrl[1024];
-          strncpy(tempUrl, urlInput, sizeof(tempUrl) - 1);
-          // Remove existing params if any
-          char *questionMark = strchr(tempUrl, '?');
-          if (questionMark) *questionMark = '\0';
-
-          updateUrlWithParams(urlInput, sizeof(urlInput), tempUrl, paramsInput);
-        }
+      Rectangle editBtn = { textArea.x + textArea.width - 60, textArea.y + textArea.height - 10, 50, 20 };
+      if (GuiButton(editBtn, "Edit"))
+      {
+        *currentMode = !(*currentMode);
       }
 
       // Response Panel with scroll