feat: Update version to 1.7.0 and enhance usage limit message formatting in ChatInterface

This commit is contained in:
simos
2025-08-12 15:23:07 +03:00
parent 2603b8aaf1
commit 24815d6894
2 changed files with 50 additions and 27 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "claude-code-ui", "name": "claude-code-ui",
"version": "1.6.1", "version": "1.7.0",
"description": "A web-based UI for Claude Code CLI", "description": "A web-based UI for Claude Code CLI",
"type": "module", "type": "module",
"main": "server/index.js", "main": "server/index.js",

View File

@@ -28,6 +28,49 @@ import { MicButton } from './MicButton.jsx';
import { api, authenticatedFetch } from '../utils/api'; import { api, authenticatedFetch } from '../utils/api';
// Format "Claude AI usage limit reached|<epoch>" into a local time string
function formatUsageLimitText(text) {
try {
if (typeof text !== 'string') return text;
return text.replace(/Claude AI usage limit reached\|(\d{10,13})/g, (match, ts) => {
let timestampMs = parseInt(ts, 10);
if (!Number.isFinite(timestampMs)) return match;
if (timestampMs < 1e12) timestampMs *= 1000; // seconds → ms
const reset = new Date(timestampMs);
// Time HH:mm in local time
const timeStr = new Intl.DateTimeFormat(undefined, {
hour: '2-digit',
minute: '2-digit',
hour12: false
}).format(reset);
// Human-readable timezone: GMT±HH[:MM] (City)
const offsetMinutesLocal = -reset.getTimezoneOffset();
const sign = offsetMinutesLocal >= 0 ? '+' : '-';
const abs = Math.abs(offsetMinutesLocal);
const offH = Math.floor(abs / 60);
const offM = abs % 60;
const gmt = `GMT${sign}${offH}${offM ? ':' + String(offM).padStart(2, '0') : ''}`;
const tzId = Intl.DateTimeFormat().resolvedOptions().timeZone || '';
const cityRaw = tzId.split('/').pop() || '';
const city = cityRaw
.replace(/_/g, ' ')
.toLowerCase()
.replace(/\b\w/g, c => c.toUpperCase());
const tzHuman = city ? `${gmt} (${city})` : gmt;
// Readable date like "8 Jun 2025"
const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const dateReadable = `${reset.getDate()} ${months[reset.getMonth()]} ${reset.getFullYear()}`;
return `Claude usage limit reached. Your limit will reset at **${timeStr} ${tzHuman}** - ${dateReadable}`;
});
} catch {
return text;
}
}
// Safe localStorage utility to handle quota exceeded errors // Safe localStorage utility to handle quota exceeded errors
const safeLocalStorage = { const safeLocalStorage = {
setItem: (key, value) => { setItem: (key, value) => {
@@ -1053,12 +1096,12 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile
) )
}} }}
> >
{String(message.content || '')} {formatUsageLimitText(String(message.content || ''))}
</ReactMarkdown> </ReactMarkdown>
</div> </div>
) : ( ) : (
<div className="whitespace-pre-wrap"> <div className="whitespace-pre-wrap">
{message.content} {formatUsageLimitText(String(message.content || ''))}
</div> </div>
)} )}
</div> </div>
@@ -2040,18 +2083,8 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess
toolResult: null // Will be updated when result comes in toolResult: null // Will be updated when result comes in
}]); }]);
} else if (part.type === 'text' && part.text?.trim()) { } else if (part.type === 'text' && part.text?.trim()) {
// Check for usage limit message and format it user-friendly // Normalize usage limit message to local time
let content = part.text; let content = formatUsageLimitText(part.text);
if (content.includes('Claude AI usage limit reached|')) {
const parts = content.split('|');
if (parts.length === 2) {
const timestamp = parseInt(parts[1]);
if (!isNaN(timestamp)) {
const resetTime = new Date(timestamp * 1000);
content = `Claude AI usage limit reached. The limit will reset on ${resetTime.toLocaleDateString()} at ${resetTime.toLocaleTimeString()}.`;
}
}
}
// Add regular text message // Add regular text message
setChatMessages(prev => [...prev, { setChatMessages(prev => [...prev, {
@@ -2062,18 +2095,8 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess
} }
} }
} else if (typeof messageData.content === 'string' && messageData.content.trim()) { } else if (typeof messageData.content === 'string' && messageData.content.trim()) {
// Check for usage limit message and format it user-friendly // Normalize usage limit message to local time
let content = messageData.content; let content = formatUsageLimitText(messageData.content);
if (content.includes('Claude AI usage limit reached|')) {
const parts = content.split('|');
if (parts.length === 2) {
const timestamp = parseInt(parts[1]);
if (!isNaN(timestamp)) {
const resetTime = new Date(timestamp * 1000);
content = `Claude AI usage limit reached. The limit will reset on ${resetTime.toLocaleDateString()} at ${resetTime.toLocaleTimeString()}.`;
}
}
}
// Add regular text message // Add regular text message
setChatMessages(prev => [...prev, { setChatMessages(prev => [...prev, {