Initial commit
diff --git a/loop/webui/src/timeline/commits.ts b/loop/webui/src/timeline/commits.ts
new file mode 100644
index 0000000..f4303f2
--- /dev/null
+++ b/loop/webui/src/timeline/commits.ts
@@ -0,0 +1,90 @@
+/**
+ * Utility functions for rendering commit messages in the timeline
+ */
+
+import { escapeHTML } from "./utils";
+
+interface Commit {
+ hash: string;
+ subject: string;
+ body: string;
+ pushed_branch?: string;
+}
+
+/**
+ * Create HTML elements to display commits in the timeline
+ * @param commits List of commit information to display
+ * @param diffViewerCallback Callback function to show commit diff when requested
+ * @returns The created HTML container element with commit information
+ */
+export function createCommitsContainer(
+ commits: Commit[],
+ diffViewerCallback: (commitHash: string) => void
+): HTMLElement {
+ const commitsContainer = document.createElement("div");
+ commitsContainer.className = "commits-container";
+
+ // Create a header for commits
+ const commitsHeaderRow = document.createElement("div");
+ commitsHeaderRow.className = "commits-header";
+ commitsHeaderRow.textContent = `${commits.length} new commit${commits.length > 1 ? "s" : ""} detected`;
+ commitsContainer.appendChild(commitsHeaderRow);
+
+ // Create a row for commit boxes
+ const commitBoxesRow = document.createElement("div");
+ commitBoxesRow.className = "commit-boxes-row";
+
+ // Add each commit as a box
+ commits.forEach((commit) => {
+ // Create the commit box
+ const commitBox = document.createElement("div");
+ commitBox.className = "commit-box";
+
+ // Show commit hash and subject line as the preview
+ const commitPreview = document.createElement("div");
+ commitPreview.className = "commit-preview";
+
+ // Include pushed branch information if available
+ let previewHTML = `<span class="commit-hash">${commit.hash.substring(0, 8)}</span> ${escapeHTML(commit.subject)}`;
+ if (commit.pushed_branch) {
+ previewHTML += ` <span class="pushed-branch">→ pushed to ${escapeHTML(commit.pushed_branch)}</span>`;
+ }
+
+ commitPreview.innerHTML = previewHTML;
+ commitBox.appendChild(commitPreview);
+
+ // Create expandable view for commit details
+ const expandedView = document.createElement("div");
+ expandedView.className = "commit-details is-hidden";
+ expandedView.innerHTML = `<pre>${escapeHTML(commit.body)}</pre>`;
+ commitBox.appendChild(expandedView);
+
+ // Toggle visibility of expanded view when clicking the preview
+ commitPreview.addEventListener("click", (event) => {
+ // If holding Ctrl/Cmd key, show diff for this commit
+ if (event.ctrlKey || event.metaKey) {
+ // Call the diff viewer callback with the commit hash
+ diffViewerCallback(commit.hash);
+ } else {
+ // Normal behavior - toggle expanded view
+ expandedView.classList.toggle("is-hidden");
+ }
+ });
+
+ // Add a diff button to view commit changes
+ const diffButton = document.createElement("button");
+ diffButton.className = "commit-diff-button";
+ diffButton.textContent = "View Changes";
+ diffButton.addEventListener("click", (event) => {
+ event.stopPropagation(); // Prevent triggering the parent click event
+ diffViewerCallback(commit.hash);
+ });
+ // Add the button directly to the commit box
+ commitBox.appendChild(diffButton);
+
+ commitBoxesRow.appendChild(commitBox);
+ });
+
+ commitsContainer.appendChild(commitBoxesRow);
+ return commitsContainer;
+}