6ede33ccdb
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-24.04-arm, linux/arm64, arm64, , runner, false, cpu) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_web, cpu, ./surfsense_web/Dockerfile, web, surfsense-web, ubuntu-latest, linux/amd64, amd64, , runner, false, cpu) (push) Blocked by required conditions
Build and Push Docker Images / compute_version (push) Waiting to run
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, , production, false, cpu) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda126, production, true, cuda126) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, cu126, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda126, production, true, cuda126) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, -cuda, production, true, cuda) (push) Blocked by required conditions
Build and Push Docker Images / verify_digests (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend, , cpu) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, cpu, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-latest, linux/amd64, amd64, , production, false, cpu) (push) Blocked by required conditions
Build and Push Docker Images / build (./surfsense_backend, cu128, ./surfsense_backend/Dockerfile, backend, surfsense-backend, ubuntu-24.04-arm, linux/arm64, arm64, -cuda, production, true, cuda) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda, cuda) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (backend, surfsense-backend, -cuda126, cuda126) (push) Blocked by required conditions
Build and Push Docker Images / create_manifest (web, surfsense-web, , cpu) (push) Blocked by required conditions
Build and Push Docker Images / finalize_release (push) Blocked by required conditions
Obsidian Plugin Lint / lint (push) Waiting to run
71 lines
2.3 KiB
TypeScript
71 lines
2.3 KiB
TypeScript
import {
|
|
differenceInDays,
|
|
differenceInMinutes,
|
|
format,
|
|
isThisYear,
|
|
isToday,
|
|
isTomorrow,
|
|
isYesterday,
|
|
} from "date-fns";
|
|
|
|
/**
|
|
* Format a date string as a human-readable relative time
|
|
* - < 1 min: "Just now"
|
|
* - < 60 min: "15m ago"
|
|
* - Today: "Today, 2:30 PM"
|
|
* - Yesterday: "Yesterday, 2:30 PM"
|
|
* - < 7 days: "3d ago"
|
|
* - Older: "Jan 15, 2026"
|
|
*/
|
|
export function formatRelativeDate(dateString: string): string {
|
|
const date = new Date(dateString);
|
|
const now = new Date();
|
|
const minutesAgo = differenceInMinutes(now, date);
|
|
const daysAgo = differenceInDays(now, date);
|
|
|
|
if (minutesAgo < 1) return "Just now";
|
|
if (minutesAgo < 60) return `${minutesAgo}m ago`;
|
|
if (isToday(date)) return `Today, ${format(date, "h:mm a")}`;
|
|
if (isYesterday(date)) return `Yesterday, ${format(date, "h:mm a")}`;
|
|
if (daysAgo < 7) return `${daysAgo}d ago`;
|
|
return format(date, "MMM d, yyyy");
|
|
}
|
|
|
|
/**
|
|
* Format a future date string as a human-readable countdown.
|
|
* - < 1 min: "Any moment"
|
|
* - < 60 min: "in 15m"
|
|
* - Today: "Today, 2:30 PM"
|
|
* - Tomorrow: "Tomorrow, 2:30 PM"
|
|
* - < 7 days: "in 3d"
|
|
* - This year: "May 30, 2:30 PM"
|
|
* - Older: "Jan 15, 2027"
|
|
*
|
|
* Mirrors {@link formatRelativeDate} but for moments strictly after now.
|
|
* Falls back to the past-relative formatter if the timestamp is not in
|
|
* the future (defensive — guards against stale "next_fire_at" values).
|
|
*/
|
|
export function formatRelativeFutureDate(dateString: string): string {
|
|
const date = new Date(dateString);
|
|
const now = new Date();
|
|
const minutesAhead = differenceInMinutes(date, now);
|
|
const daysAhead = differenceInDays(date, now);
|
|
|
|
if (minutesAhead <= 0) return formatRelativeDate(dateString);
|
|
if (minutesAhead < 1) return "Any moment";
|
|
if (minutesAhead < 60) return `in ${minutesAhead}m`;
|
|
if (isToday(date)) return `Today, ${format(date, "h:mm a")}`;
|
|
if (isTomorrow(date)) return `Tomorrow, ${format(date, "h:mm a")}`;
|
|
if (daysAhead < 7) return `in ${daysAhead}d`;
|
|
if (isThisYear(date)) return format(date, "MMM d, h:mm a");
|
|
return format(date, "MMM d, yyyy");
|
|
}
|
|
|
|
/**
|
|
* Format a thread's last-updated timestamp for the chats sidebars.
|
|
* Example: "Mar 23, 2026 at 4:30 PM"
|
|
*/
|
|
export function formatThreadTimestamp(dateString: string): string {
|
|
return format(new Date(dateString), "MMM d, yyyy 'at' h:mm a");
|
|
}
|