#include #include #include // Include string.h for strdup and strlen #include "gui.h" #include "reporter.h" #include "gemini.h" #include "github.h" #include "utils.h" // Needed for get_git_repo_info // FIX 1: Duplicate code block removed. // The initial block (lines 1-17 of the original input) contained the required includes // and the definition of AppData. The second block (lines 19-37) was a redundant copy. // Structure to pass data to callbacks typedef struct { GtkWidget *window; GtkWidget *github_token_entry; GtkWidget *gemini_key_entry; GtkWidget *status_label; char *traceback; char *sys_info; char *app_path; } AppData; static void on_send_clicked(GtkWidget *widget, gpointer data) { AppData *app_data = (AppData *)data; const char *github_token = gtk_entry_get_text(GTK_ENTRY(app_data->github_token_entry)); const char *gemini_key = gtk_entry_get_text(GTK_ENTRY(app_data->gemini_key_entry)); if (strlen(github_token) == 0 || strlen(gemini_key) == 0) { gtk_label_set_text(GTK_LABEL(app_data->status_label), "Error: Both tokens are required."); return; } gtk_label_set_text(GTK_LABEL(app_data->status_label), "Analyzing with Gemini..."); // Process UI updates while (gtk_events_pending()) gtk_main_iteration(); // 1. Analyze with Gemini char *analysis = analyze_crash(gemini_key, app_data->traceback, app_data->sys_info); if (!analysis) { gtk_label_set_text(GTK_LABEL(app_data->status_label), "Error: Gemini analysis failed."); return; } gtk_label_set_text(GTK_LABEL(app_data->status_label), "Submitting to GitHub..."); while (gtk_events_pending()) gtk_main_iteration(); // 2. Submit to GitHub char *owner = NULL; char *repo = NULL; // NOTE: get_git_repo_info was previously fixed in utils.c to accept three arguments. if (!get_git_repo_info(app_data->app_path, &owner, &repo)) { gtk_label_set_text(GTK_LABEL(app_data->status_label), "Error: Could not determine GitHub repo."); free(analysis); return; } int success = submit_issue(github_token, owner, repo, "Automated Crash Report", analysis, app_data->traceback, app_data->sys_info); if (success) { gtk_label_set_text(GTK_LABEL(app_data->status_label), "Success! Issue created."); } else { gtk_label_set_text(GTK_LABEL(app_data->status_label), "Error: GitHub submission failed."); } free(analysis); free(owner); free(repo); } void show_crash_report_window(const char *traceback, const char *app_path) { AppData *app_data = malloc(sizeof(AppData)); // FIX 2: Replaced non-breaking spaces (U+00A0) in the argument assignment // and initialization logic throughout the function with standard spaces/tabs. app_data->traceback = strdup(traceback); app_data->sys_info = get_system_info(); app_data->app_path = strdup(app_path ? app_path : "."); // Use current directory if app_path is NULL GtkWidget *dialog = gtk_dialog_new_with_buttons("Crash Reporter", NULL, GTK_DIALOG_MODAL, NULL); gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 400); app_data->window = dialog; GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); GtkWidget *grid = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(grid), 10); gtk_grid_set_column_spacing(GTK_GRID(grid), 10); gtk_container_set_border_width(GTK_CONTAINER(grid), 20); gtk_container_add(GTK_CONTAINER(content_area), grid); // Header GtkWidget *label = gtk_label_new("The application has crashed.\nPlease provide tokens to analyze and report the bug."); gtk_label_set_use_markup(GTK_LABEL(label), TRUE); gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 2, 1); // GitHub Token GtkWidget *gh_label = gtk_label_new("GitHub Token:"); app_data->github_token_entry = gtk_entry_new(); gtk_entry_set_placeholder_text(GTK_ENTRY(app_data->github_token_entry), "ghp_..."); gtk_grid_attach(GTK_GRID(grid), gh_label, 0, 1, 1, 1); gtk_grid_attach(GTK_GRID(grid), app_data->github_token_entry, 1, 1, 1, 1); GtkWidget *gh_link = gtk_link_button_new_with_label("https://github.com/settings/tokens", "Get GitHub Token"); gtk_grid_attach(GTK_GRID(grid), gh_link, 1, 2, 1, 1); // Gemini Key GtkWidget *gem_label = gtk_label_new("Gemini API Key:"); app_data->gemini_key_entry = gtk_entry_new(); gtk_entry_set_placeholder_text(GTK_ENTRY(app_data->gemini_key_entry), "AIza..."); gtk_grid_attach(GTK_GRID(grid), gem_label, 0, 3, 1, 1); gtk_grid_attach(GTK_GRID(grid), app_data->gemini_key_entry, 1, 3, 1, 1); GtkWidget *gem_link = gtk_link_button_new_with_label("https://aistudio.google.com/app/apikey", "Get Gemini Key"); gtk_grid_attach(GTK_GRID(grid), gem_link, 1, 4, 1, 1); // Send Button GtkWidget *send_button = gtk_button_new_with_label("Analyze & Send Report"); g_signal_connect(send_button, "clicked", G_CALLBACK(on_send_clicked), app_data); gtk_grid_attach(GTK_GRID(grid), send_button, 0, 5, 2, 1); // Status Label app_data->status_label = gtk_label_new(""); gtk_grid_attach(GTK_GRID(grid), app_data->status_label, 0, 6, 2, 1); gtk_widget_show_all(dialog); gtk_dialog_run(GTK_DIALOG(dialog)); // Cleanup free(app_data->traceback); free(app_data->sys_info); free(app_data->app_path); free(app_data); gtk_widget_destroy(dialog); }