-
Notifications
You must be signed in to change notification settings - Fork 699
Feat/rtl support #271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/rtl support #271
Changes from all commits
19190f9
bbd5d4a
2ff37c4
ed653ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,243 @@ | ||||||||||
| #!/bin/bash | ||||||||||
|
|
||||||||||
| # Claude Code UI Control Script | ||||||||||
| # Usage: ccui.sh [start|stop] | ||||||||||
|
|
||||||||||
| PROJECT_DIR="/Users/alexsuprun/Documents/my-code/claudecodeui" | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hardcoded path prevents portability. The 🔎 Proposed fix: Use script location for portability-PROJECT_DIR="/Users/alexsuprun/Documents/my-code/claudecodeui"
+# Resolve project directory from script location
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PROJECT_DIR="$SCRIPT_DIR"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||
| SERVER_PORT=3001 | ||||||||||
| CLIENT_PORT=5173 | ||||||||||
| LOG_FILE="$PROJECT_DIR/ccui.log" | ||||||||||
| PID_FILE="$PROJECT_DIR/ccui.pid" | ||||||||||
|
|
||||||||||
| start() { | ||||||||||
| echo "🚀 Starting Claude Code UI..." | ||||||||||
|
|
||||||||||
| # Check if already running | ||||||||||
| if [ -f "$PID_FILE" ]; then | ||||||||||
| PID=$(cat "$PID_FILE") | ||||||||||
| if ps -p "$PID" > /dev/null 2>&1; then | ||||||||||
| echo "⚠️ Claude Code UI is already running (PID: $PID)" | ||||||||||
| echo "💡 Use 'ccui stop' to stop it first" | ||||||||||
| return 1 | ||||||||||
| else | ||||||||||
| # PID file exists but process is dead, clean it up | ||||||||||
| rm "$PID_FILE" | ||||||||||
| fi | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Check and kill processes on both ports | ||||||||||
| for PORT in $SERVER_PORT $CLIENT_PORT; do | ||||||||||
| PORT_PIDS=$(lsof -ti:$PORT 2>/dev/null) | ||||||||||
| if [ ! -z "$PORT_PIDS" ]; then | ||||||||||
| echo "⚠️ Port $PORT is in use by processes: $PORT_PIDS" | ||||||||||
| echo "🔧 Killing processes on port $PORT..." | ||||||||||
| kill -9 $PORT_PIDS 2>/dev/null | ||||||||||
| sleep 1 | ||||||||||
| fi | ||||||||||
| done | ||||||||||
|
|
||||||||||
| # Ensure .env exists | ||||||||||
| if [ ! -f "$PROJECT_DIR/.env" ]; then | ||||||||||
| echo "📝 Creating .env from .env.example..." | ||||||||||
| cp "$PROJECT_DIR/.env.example" "$PROJECT_DIR/.env" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Start the dev server (both backend and frontend) in background | ||||||||||
| cd "$PROJECT_DIR" | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle If the directory doesn't exist or is inaccessible, the script will continue running 🔎 Proposed fix- cd "$PROJECT_DIR"
+ cd "$PROJECT_DIR" || { echo "❌ Failed to change to project directory: $PROJECT_DIR"; exit 1; }📝 Committable suggestion
Suggested change
🧰 Tools🪛 Shellcheck (0.11.0)[warning] 46-46: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. (SC2164) 🤖 Prompt for AI Agents |
||||||||||
| echo "📦 Starting development servers (backend + frontend)..." | ||||||||||
| nohup npm run dev > "$LOG_FILE" 2>&1 & | ||||||||||
|
|
||||||||||
| # Save PID | ||||||||||
| echo $! > "$PID_FILE" | ||||||||||
|
|
||||||||||
| echo "" | ||||||||||
| echo "⏳ Waiting for servers to start..." | ||||||||||
|
|
||||||||||
| # Wait for both server and client to be ready | ||||||||||
| MAX_WAIT=30 | ||||||||||
| WAIT_COUNT=0 | ||||||||||
| SERVER_READY=false | ||||||||||
| CLIENT_READY=false | ||||||||||
|
|
||||||||||
| while [ $WAIT_COUNT -lt $MAX_WAIT ]; do | ||||||||||
| # Check server port | ||||||||||
| if ! $SERVER_READY && lsof -ti:$SERVER_PORT > /dev/null 2>&1; then | ||||||||||
| echo "✅ Backend server ready on port $SERVER_PORT" | ||||||||||
| SERVER_READY=true | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Check client port | ||||||||||
| if ! $CLIENT_READY && lsof -ti:$CLIENT_PORT > /dev/null 2>&1; then | ||||||||||
| echo "✅ Frontend client ready on port $CLIENT_PORT" | ||||||||||
| CLIENT_READY=true | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Break if both are ready | ||||||||||
| if $SERVER_READY && $CLIENT_READY; then | ||||||||||
| break | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| sleep 1 | ||||||||||
| WAIT_COUNT=$((WAIT_COUNT + 1)) | ||||||||||
| done | ||||||||||
|
|
||||||||||
| echo "" | ||||||||||
| if $SERVER_READY && $CLIENT_READY; then | ||||||||||
| echo "✅ Claude Code UI started successfully!" | ||||||||||
| echo "🌐 Server: http://localhost:$SERVER_PORT" | ||||||||||
| echo "🎨 Client: http://localhost:$CLIENT_PORT" | ||||||||||
| echo "📝 Logs: $LOG_FILE" | ||||||||||
| echo "💡 Use 'ccui stop' to stop all servers" | ||||||||||
| echo "" | ||||||||||
|
|
||||||||||
| # Open browser | ||||||||||
| echo "🌐 Opening browser..." | ||||||||||
| if command -v open > /dev/null 2>&1; then | ||||||||||
| open "http://localhost:$CLIENT_PORT" | ||||||||||
| elif command -v xdg-open > /dev/null 2>&1; then | ||||||||||
| xdg-open "http://localhost:$CLIENT_PORT" | ||||||||||
| else | ||||||||||
| echo "⚠️ Could not auto-open browser. Please open http://localhost:$CLIENT_PORT manually" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| echo "" | ||||||||||
| echo "📊 Recent logs:" | ||||||||||
| tail -n 10 "$LOG_FILE" | ||||||||||
| else | ||||||||||
| echo "⚠️ Servers may not have started properly within $MAX_WAIT seconds" | ||||||||||
| echo "📝 Check logs for details: $LOG_FILE" | ||||||||||
| echo "💡 Or run: ccui logs" | ||||||||||
| fi | ||||||||||
| } | ||||||||||
|
|
||||||||||
| stop() { | ||||||||||
| echo "🛑 Stopping Claude Code UI..." | ||||||||||
|
|
||||||||||
| if [ ! -f "$PID_FILE" ]; then | ||||||||||
| echo "⚠️ No PID file found" | ||||||||||
|
|
||||||||||
| # Try to kill by ports | ||||||||||
| for PORT in $SERVER_PORT $CLIENT_PORT; do | ||||||||||
| PORT_PIDS=$(lsof -ti:$PORT 2>/dev/null) | ||||||||||
| if [ ! -z "$PORT_PIDS" ]; then | ||||||||||
| echo "🔧 Found processes on port $PORT: $PORT_PIDS" | ||||||||||
| kill -9 $PORT_PIDS 2>/dev/null | ||||||||||
| echo "✅ Killed processes on port $PORT" | ||||||||||
| fi | ||||||||||
| done | ||||||||||
| return 0 | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| PID=$(cat "$PID_FILE") | ||||||||||
|
|
||||||||||
| # Kill the main process and its children | ||||||||||
| if ps -p "$PID" > /dev/null 2>&1; then | ||||||||||
| echo "🔧 Killing process tree for PID $PID..." | ||||||||||
|
|
||||||||||
| # Kill child processes first | ||||||||||
| pkill -P "$PID" 2>/dev/null | ||||||||||
|
|
||||||||||
| # Kill main process | ||||||||||
| kill "$PID" 2>/dev/null | ||||||||||
| sleep 1 | ||||||||||
|
|
||||||||||
| # Force kill if still running | ||||||||||
| if ps -p "$PID" > /dev/null 2>&1; then | ||||||||||
| echo "⚡ Force killing process $PID..." | ||||||||||
| kill -9 "$PID" 2>/dev/null | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| echo "✅ Process stopped" | ||||||||||
| else | ||||||||||
| echo "ℹ️ Process $PID is not running" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Clean up any remaining processes on both ports | ||||||||||
| for PORT in $SERVER_PORT $CLIENT_PORT; do | ||||||||||
| PORT_PIDS=$(lsof -ti:$PORT 2>/dev/null) | ||||||||||
| if [ ! -z "$PORT_PIDS" ]; then | ||||||||||
| echo "🔧 Cleaning up remaining processes on port $PORT..." | ||||||||||
| kill -9 $PORT_PIDS 2>/dev/null | ||||||||||
| fi | ||||||||||
| done | ||||||||||
|
|
||||||||||
| # Remove PID file | ||||||||||
| rm -f "$PID_FILE" | ||||||||||
| echo "🧹 Cleaned up PID file" | ||||||||||
| } | ||||||||||
|
|
||||||||||
| status() { | ||||||||||
| echo "📊 Claude Code UI Status" | ||||||||||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||||||||||
|
|
||||||||||
| if [ -f "$PID_FILE" ]; then | ||||||||||
| PID=$(cat "$PID_FILE") | ||||||||||
| if ps -p "$PID" > /dev/null 2>&1; then | ||||||||||
| echo "✅ Running (PID: $PID)" | ||||||||||
| echo "🌐 Server: http://localhost:$SERVER_PORT" | ||||||||||
| echo "🎨 Client: http://localhost:$CLIENT_PORT" | ||||||||||
| echo "📝 Logs: $LOG_FILE" | ||||||||||
| else | ||||||||||
| echo "❌ Not running (stale PID file)" | ||||||||||
| fi | ||||||||||
| else | ||||||||||
| echo "❌ Not running" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| echo "" | ||||||||||
| echo "Port Status:" | ||||||||||
|
|
||||||||||
| # Check server port | ||||||||||
| SERVER_PIDS=$(lsof -ti:$SERVER_PORT 2>/dev/null) | ||||||||||
| if [ ! -z "$SERVER_PIDS" ]; then | ||||||||||
| echo "🔌 Server port $SERVER_PORT in use by: $SERVER_PIDS" | ||||||||||
| else | ||||||||||
| echo "🔌 Server port $SERVER_PORT is free" | ||||||||||
| fi | ||||||||||
|
|
||||||||||
| # Check client port | ||||||||||
| CLIENT_PIDS=$(lsof -ti:$CLIENT_PORT 2>/dev/null) | ||||||||||
| if [ ! -z "$CLIENT_PIDS" ]; then | ||||||||||
| echo "🔌 Client port $CLIENT_PORT in use by: $CLIENT_PIDS" | ||||||||||
| else | ||||||||||
| echo "🔌 Client port $CLIENT_PORT is free" | ||||||||||
| fi | ||||||||||
| } | ||||||||||
|
|
||||||||||
| # Main command handler | ||||||||||
| COMMAND=${1:-start} | ||||||||||
|
|
||||||||||
| case "$COMMAND" in | ||||||||||
| start) | ||||||||||
| start | ||||||||||
| ;; | ||||||||||
| stop) | ||||||||||
| stop | ||||||||||
| ;; | ||||||||||
| restart) | ||||||||||
| stop | ||||||||||
| sleep 2 | ||||||||||
| start | ||||||||||
| ;; | ||||||||||
| status) | ||||||||||
| status | ||||||||||
| ;; | ||||||||||
| logs) | ||||||||||
| if [ -f "$LOG_FILE" ]; then | ||||||||||
| tail -f "$LOG_FILE" | ||||||||||
| else | ||||||||||
| echo "❌ No log file found at $LOG_FILE" | ||||||||||
| fi | ||||||||||
| ;; | ||||||||||
| *) | ||||||||||
| echo "Usage: ccui.sh [start|stop|restart|status|logs]" | ||||||||||
| echo "" | ||||||||||
| echo "Commands:" | ||||||||||
| echo " start - Start the server (default)" | ||||||||||
| echo " stop - Stop the server" | ||||||||||
| echo " restart - Restart the server" | ||||||||||
| echo " status - Check server status" | ||||||||||
| echo " logs - Follow server logs" | ||||||||||
| exit 1 | ||||||||||
| ;; | ||||||||||
| esac | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /** | ||
| * Detects if text contains at least one RTL (right-to-left) character | ||
| * Checks for Arabic, Hebrew, and other RTL script characters | ||
| * | ||
| * @param {string} text - The text to analyze | ||
| * @returns {boolean} - True if at least one RTL character is found | ||
| */ | ||
| export function hasRTLCharacters(text) { | ||
| if (!text || typeof text !== 'string') { | ||
| return false; | ||
| } | ||
|
|
||
| // RTL Unicode ranges: | ||
| // Arabic: U+0600-U+06FF | ||
| // Hebrew: U+0590-U+05FF | ||
| // Arabic Supplement: U+0750-U+077F | ||
| // Arabic Extended-A: U+08A0-U+08FF | ||
| // Arabic Presentation Forms-A: U+FB50-U+FDFF | ||
| // Arabic Presentation Forms-B: U+FE70-U+FEFF | ||
| // Hebrew Presentation Forms: U+FB1D-U+FB4F | ||
| const rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB1D-\uFB4F\uFB50-\uFDFF\uFE70-\uFEFF]/; | ||
|
|
||
| return rtlRegex.test(text); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usage comment is incomplete.
The usage comment only mentions
start|stopbut the script supportsstart|stop|restart|status|logs.🔎 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents