chore: sweep em dashes from our own source and README (#13)
This commit was merged in pull request #13.
This commit is contained in:
@@ -35,7 +35,7 @@ import { recencyGroup, truncate } from "../utils";
|
||||
*
|
||||
* - The search bar is the composer. It is the only always-focused text input in
|
||||
* a `List`, which is what makes "hit a hotkey, then just start typing" work.
|
||||
* - `filtering` is off, because the left column is a conversation switcher — the
|
||||
* - `filtering` is off, because the left column is a conversation switcher. The
|
||||
* builtin fuzzy filter would hide rows as the user types their question.
|
||||
* - `Detail` accepts no typed input (`onSearchTextChange` exists only on `List`,
|
||||
* `Grid`, `Form` and `Dropdown`), so the left column cannot be dropped: it is
|
||||
@@ -87,7 +87,7 @@ export function ChatView({ initialSession, initialPrompt }: ChatViewProps) {
|
||||
/**
|
||||
* Reopening the command continues the most recent conversation, but only if it
|
||||
* was used recently. Past the configured idle window it starts a fresh chat
|
||||
* instead — the previous conversation is never removed, it just drops down the
|
||||
* instead. The previous conversation is never removed, it just drops down the
|
||||
* sidebar. Setting the preference to "Never" keeps the last chat open forever.
|
||||
*/
|
||||
useEffect(() => {
|
||||
@@ -218,7 +218,7 @@ export function ChatView({ initialSession, initialPrompt }: ChatViewProps) {
|
||||
|
||||
/**
|
||||
* The primary action adapts to the search bar. With text in it, Return sends;
|
||||
* with it empty — where sending would be a no-op anyway — Return opens the
|
||||
* with it empty (where sending would be a no-op anyway), Return opens the
|
||||
* highlighted conversation instead.
|
||||
*/
|
||||
const rowActions = (row: SessionRow) => {
|
||||
@@ -249,8 +249,8 @@ export function ChatView({ initialSession, initialPrompt }: ChatViewProps) {
|
||||
}
|
||||
|
||||
const placeholder = chat.status
|
||||
? `${chat.status} — press ⏎ to stop`
|
||||
: "Lam is thinking — press ⏎ to stop";
|
||||
? `${chat.status}. Press ⏎ to stop`
|
||||
: "Lam is thinking. Press ⏎ to stop";
|
||||
|
||||
return (
|
||||
<List
|
||||
|
||||
+5
-5
@@ -15,8 +15,8 @@ import type { ChatTurn, ThreadMessage } from "./types";
|
||||
* and a `**Lam**` header on each exchange gave both speakers the same visual
|
||||
* weight and made the reader scan past chrome to reach the answer.
|
||||
*
|
||||
* Raycast solves the same problem with alignment — right-aligned bubbles for
|
||||
* the user — but markdown offers no alignment control, so styling is the only
|
||||
* Raycast solves the same problem by aligning messages: right-aligned bubbles
|
||||
* for the user. Markdown offers no alignment control, so styling is the only
|
||||
* lever available.
|
||||
*/
|
||||
|
||||
@@ -66,7 +66,7 @@ function renderMessage(message: ThreadMessage, options: TranscriptOptions): stri
|
||||
|
||||
// The one thing allowed to break the plain-text rule, because it means
|
||||
// something went wrong and should not be skimmed past.
|
||||
if (message.error) sections.push("", `**Error** — ${message.error}`);
|
||||
if (message.error) sections.push("", `**Error:** ${message.error}`);
|
||||
|
||||
if (options.showToolCalls && message.toolCalls.length > 0) {
|
||||
sections.push("", renderTools(message));
|
||||
@@ -129,8 +129,8 @@ export function buildThreadMarkdown(
|
||||
* Unlike the transcript this reads oldest-first: as a standalone document, a
|
||||
* conversation is easier to read in the order it happened.
|
||||
*
|
||||
* This needs labels because the transcript's styling — blockquotes and dimmed
|
||||
* text — is gone by the time it reaches a clipboard.
|
||||
* This needs labels because the transcript's styling (blockquotes and dimmed
|
||||
* text) is gone by the time it reaches a clipboard.
|
||||
*/
|
||||
export function sessionToPlainText(turns: ChatTurn[]): string {
|
||||
if (turns.length === 0) return "";
|
||||
|
||||
@@ -58,7 +58,7 @@ export function resolveResumeTimeout(value: string | undefined): number | undefi
|
||||
|
||||
/** Human-readable form of {@link ResolvedPreferences.resumeTimeoutMs}, for the setup screen. */
|
||||
export function describeResumeTimeout(milliseconds: number | undefined): string {
|
||||
if (milliseconds === undefined) return "Never — always reopen the last chat";
|
||||
if (milliseconds === undefined) return "Never (always reopen the last chat)";
|
||||
|
||||
const minutes = Math.round(milliseconds / MINUTE);
|
||||
if (minutes < 60) return `After ${minutes} minutes`;
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ export function buildThread(turns: ChatTurn[], live: LiveState): ThreadMessage[]
|
||||
const messages: ThreadMessage[] = [];
|
||||
|
||||
// Strictly newest message first. The search bar sits at the top of the window,
|
||||
// so the most recent thing — an answer, once one has been written — should be
|
||||
// so the most recent thing, an answer once one has been written, should be
|
||||
// the first line under it. A consequence is that within an exchange the answer
|
||||
// comes before its question, which is the intended reading order here.
|
||||
for (let index = turns.length - 1; index >= 0; index--) {
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ export type RecencyGroup = "Today" | "Yesterday" | "This week" | "Older";
|
||||
* Buckets a timestamp for the conversation sidebar.
|
||||
*
|
||||
* Raycast groups its sidebar this way, and it buys the grouping that per-row
|
||||
* timestamps were trying to convey — without putting a timestamp on every row.
|
||||
* timestamps were trying to convey, without putting a timestamp on every row.
|
||||
*/
|
||||
export function recencyGroup(timestamp: number, now: number = Date.now()): RecencyGroup {
|
||||
const startOfToday = new Date(now);
|
||||
|
||||
Reference in New Issue
Block a user