Forráskód Böngészése

Fix job search results visibility and simplify assistant response.

Render the listings scroll section in the main layout so result cards appear after search, and replace verbose row/JSON chat output with a concise card-focused summary.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 2 hónapja
szülő
commit
a57976258d
1 módosított fájl, 8 hozzáadás és 32 törlés
  1. 8 32
      App for Indeed/Views/DashboardView.swift

+ 8 - 32
App for Indeed/Views/DashboardView.swift

@@ -259,6 +259,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         mainOverlay.addArrangedSubview(chatStatusStack)
         mainOverlay.addArrangedSubview(listingsTopSpacer)
         mainOverlay.addArrangedSubview(chatScrollView)
+        mainOverlay.addArrangedSubview(jobListingsScrollView)
         mainOverlay.addArrangedSubview(searchBarShadowHost)
 
         contentStack.addArrangedSubview(sidebar)
@@ -291,10 +292,12 @@ final class DashboardView: NSView, NSTextFieldDelegate {
             searchBarShadowHost.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
             chatStatusStack.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
             chatScrollView.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
+            jobListingsScrollView.widthAnchor.constraint(equalTo: mainOverlay.widthAnchor, multiplier: 0.92),
 
             jobListingsContainer.topAnchor.constraint(equalTo: jobListingsScrollView.contentView.topAnchor),
             jobListingsContainer.leadingAnchor.constraint(equalTo: jobListingsScrollView.contentView.leadingAnchor),
             jobListingsContainer.widthAnchor.constraint(equalTo: jobListingsScrollView.contentView.widthAnchor),
+            jobListingsScrollView.heightAnchor.constraint(greaterThanOrEqualToConstant: 200),
 
             greetingLabel.leadingAnchor.constraint(equalTo: mainOverlay.leadingAnchor, constant: 16),
             greetingLabel.trailingAnchor.constraint(equalTo: mainOverlay.trailingAnchor, constant: -16),
@@ -1209,7 +1212,7 @@ final class DashboardView: NSView, NSTextFieldDelegate {
                 case .success(let output):
                     let normalizedJobs = self.normalizedJobs(output.jobs)
                     self.configureJobListings(normalizedJobs, noResultsForQuery: prompt)
-                    let reply = self.makeAssistantSearchReply(query: prompt, jobs: normalizedJobs, jsonResult: output.rawJSON)
+                    let reply = self.makeAssistantSearchReply(query: prompt, jobs: normalizedJobs)
                     self.chatMessages.append(ChatMessage(role: "assistant", content: reply))
                     self.appendChatBubble(text: reply, isUser: false)
                     self.chatStatusLabel.stringValue = "Ask for another job, company, or skill match"
@@ -1234,42 +1237,16 @@ final class DashboardView: NSView, NSTextFieldDelegate {
         return trimmed.filter { !$0.title.isEmpty && !$0.description.isEmpty }
     }
 
-    private func makeAssistantSearchReply(query: String, jobs: [JobListing], jsonResult: String) -> String {
+    private func makeAssistantSearchReply(query: String, jobs: [JobListing]) -> String {
         if jobs.isEmpty {
-            return """
-            No jobs were found for "\(query)".
-
-            JSON result:
-            \(jsonResult)
-            """
-        }
-        let rows = jobs.prefix(8).enumerated().map { index, job in
-            let fallback = "https://www.indeed.com/jobs?q=\(job.title.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "")"
-            let link = (job.url?.isEmpty == false) ? job.url! : fallback
-            let compactDescription = compactSingleLine(job.description, maxCharacters: 110)
-            return "\(index + 1)) \(job.title) | \(compactDescription) | \(link)"
+            return "No jobs were found for \"\(query)\". Try another title, skill, company, or location."
         }
         return """
         Found \(jobs.count) job result(s) for "\(query)".
-
-        Row-wise results:
-        \(rows.joined(separator: "\n"))
-
-        JSON result:
-        \(jsonResult)
+        Each result is shown as a card with the role, job description, and an Apply button that opens the job link.
         """
     }
 
-    private func compactSingleLine(_ text: String, maxCharacters: Int) -> String {
-        let single = text
-            .replacingOccurrences(of: "\n", with: " ")
-            .replacingOccurrences(of: "\\s+", with: " ", options: .regularExpression)
-            .trimmingCharacters(in: .whitespacesAndNewlines)
-        guard single.count > maxCharacters, maxCharacters > 1 else { return single }
-        let end = single.index(single.startIndex, offsetBy: maxCharacters - 1)
-        return String(single[..<end]) + "…"
-    }
-
     func controlTextDidBeginEditing(_ obj: Notification) {
         applySearchFieldInsertionPoint(obj.object)
         if (obj.object as? NSTextField) === jobKeywordsField {
@@ -1665,7 +1642,7 @@ private final class OpenAIJobSearchService {
                 let cleanedText = Self.extractJSONObject(from: text)
                 let jsonData = Data(cleanedText.utf8)
                 let jobsPayload = try JSONDecoder().decode(JobSearchResultsPayload.self, from: jsonData)
-                completion(.success(JobSearchOutput(jobs: jobsPayload.jobs, rawJSON: cleanedText)))
+                completion(.success(JobSearchOutput(jobs: jobsPayload.jobs)))
             } catch {
                 let rawBody = String(data: data, encoding: .utf8) ?? "<non-utf8 response>"
                 let message = "The API response could not be parsed as job JSON. Raw response: \(rawBody.prefix(600))"
@@ -1772,7 +1749,6 @@ private struct JobSearchResultsPayload: Codable {
 
 private struct JobSearchOutput {
     let jobs: [JobListing]
-    let rawJSON: String
 }
 
 private struct OpenAIAPIErrorResponse: Codable {