From 24815d68944a69268adbdf04da7841d7c656b087 Mon Sep 17 00:00:00 2001 From: simos Date: Tue, 12 Aug 2025 15:23:07 +0300 Subject: [PATCH] feat: Update version to 1.7.0 and enhance usage limit message formatting in ChatInterface --- package.json | 2 +- src/components/ChatInterface.jsx | 75 +++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index ea084d1..43ad596 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "claude-code-ui", - "version": "1.6.1", + "version": "1.7.0", "description": "A web-based UI for Claude Code CLI", "type": "module", "main": "server/index.js", diff --git a/src/components/ChatInterface.jsx b/src/components/ChatInterface.jsx index e8cec93..7dd87ed 100644 --- a/src/components/ChatInterface.jsx +++ b/src/components/ChatInterface.jsx @@ -28,6 +28,49 @@ import { MicButton } from './MicButton.jsx'; import { api, authenticatedFetch } from '../utils/api'; +// Format "Claude AI usage limit reached|" 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 const safeLocalStorage = { setItem: (key, value) => { @@ -1053,12 +1096,12 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile ) }} > - {String(message.content || '')} + {formatUsageLimitText(String(message.content || ''))} ) : (
- {message.content} + {formatUsageLimitText(String(message.content || ''))}
)} @@ -2040,18 +2083,8 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess toolResult: null // Will be updated when result comes in }]); } else if (part.type === 'text' && part.text?.trim()) { - // Check for usage limit message and format it user-friendly - let content = 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()}.`; - } - } - } + // Normalize usage limit message to local time + let content = formatUsageLimitText(part.text); // Add regular text message setChatMessages(prev => [...prev, { @@ -2062,18 +2095,8 @@ function ChatInterface({ selectedProject, selectedSession, ws, sendMessage, mess } } } else if (typeof messageData.content === 'string' && messageData.content.trim()) { - // Check for usage limit message and format it user-friendly - let content = 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()}.`; - } - } - } + // Normalize usage limit message to local time + let content = formatUsageLimitText(messageData.content); // Add regular text message setChatMessages(prev => [...prev, {