|
23 | 23 | import { isMobileFullscreenOpen } from '$lib/stores/drawerStore'; |
24 | 24 | import { setHoveredSession } from '$lib/stores/hoveredSession'; |
25 | 25 | import type { SessionState } from '$lib/config/statusColors'; |
26 | | - import { getIssueTypeVisual } from '$lib/config/statusColors'; |
| 26 | + import { getIssueTypeVisual, getSessionStateVisual } from '$lib/config/statusColors'; |
| 27 | +
|
| 28 | + /** Split an agent name on camelCase boundaries: "GentleCoast" → ["Gentle", "Coast"]. */ |
| 29 | + function splitAgentName(name: string): string[] { |
| 30 | + if (!name) return []; |
| 31 | + return name.replace(/([a-z])([A-Z])/g, '$1\u0000$2').split('\u0000'); |
| 32 | + } |
27 | 33 |
|
28 | 34 | interface AgentTask { |
29 | 35 | id: string; |
|
725 | 731 | > |
726 | 732 | <!-- Page 0: Terminal / SessionCard --> |
727 | 733 | <div class="pager-page"> |
728 | | - <!-- Custom mobile header matching TasksActive mobile layout --> |
| 734 | + <!-- Custom mobile header — same swipe-card design as TasksActive standalone tasks --> |
729 | 735 | {#if task} |
730 | 736 | {@const typeVisual = getIssueTypeVisual(task.issue_type)} |
| 737 | + {@const stateVisual = getSessionStateVisual(sseState || 'idle')} |
731 | 738 | <div class="mobile-task-header"> |
732 | | - <div class="mobile-task-title">{task.title || task.id}</div> |
733 | | - {#if task.description} |
734 | | - <div class="mobile-task-desc">{task.description}</div> |
735 | | - {/if} |
736 | | - <div class="mobile-task-meta"> |
737 | | - <span class="mobile-task-id-badge" style="color: oklch(0.65 0.15 200);">{task.id}</span> |
738 | | - {#if elapsed} |
739 | | - <span class="meta-sep">·</span> |
740 | | - <span class="mobile-elapsed">{#if elapsed.showHours}{elapsed.hours}:{/if}{elapsed.minutes}:{elapsed.seconds}</span> |
741 | | - {/if} |
742 | | - <span class="meta-sep">·</span> |
743 | | - <AgentAvatar name={agentName} size={16} showRing={true} sessionState={sseState || 'idle'} /> |
744 | | - <span class="mobile-agent">{agentName}</span> |
745 | | - {#if task.issue_type} |
746 | | - <span class="meta-sep">·</span> |
747 | | - <span class="mobile-type" title={typeVisual.label}>{typeVisual.icon}</span> |
748 | | - {/if} |
749 | | - {#if task.priority != null && task.priority <= 2} |
750 | | - <span class="meta-sep">·</span> |
751 | | - <span class="mobile-priority-badge mobile-priority-{task.priority}">P{task.priority}</span> |
752 | | - {/if} |
| 739 | + <div class="mobile-card-inner"> |
| 740 | + <!-- Left strip: large avatar + split agent name (matches TasksActive swipe card) --> |
| 741 | + <div class="mobile-state-strip mobile-state-strip-agent" style="background: {stateVisual.bgTint}; border-right: 2px solid {stateVisual.accent};"> |
| 742 | + <AgentAvatar name={agentName} size={36} showRing={true} sessionState={sseState || 'idle'} /> |
| 743 | + <div class="mobile-strip-agent-label" title={agentName}> |
| 744 | + {#each splitAgentName(agentName) as part} |
| 745 | + <span>{part}</span> |
| 746 | + {/each} |
| 747 | + </div> |
| 748 | + </div> |
| 749 | + <!-- Right body: title, description, badges row --> |
| 750 | + <div class="mobile-card-body"> |
| 751 | + <div class="mobile-title" title={task.title}>{task.title || task.id}</div> |
| 752 | + {#if task.description} |
| 753 | + <div class="mobile-description">{task.description}</div> |
| 754 | + {/if} |
| 755 | + <div class="mobile-card-row2"> |
| 756 | + <span class="mobile-task-id" style="color: {stateVisual.accent};">{task.id}</span> |
| 757 | + {#if elapsed} |
| 758 | + <span class="mobile-separator">·</span> |
| 759 | + <span class="mobile-elapsed">{#if elapsed.showHours}{elapsed.hours}:{/if}{elapsed.minutes}:{elapsed.seconds}</span> |
| 760 | + {/if} |
| 761 | + {#if task.issue_type} |
| 762 | + <span class="mobile-separator">·</span> |
| 763 | + <span class="mobile-type-icon" title={typeVisual.label}>{typeVisual.icon}</span> |
| 764 | + {/if} |
| 765 | + {#if task.priority != null && task.priority <= 2} |
| 766 | + <span class="mobile-separator">·</span> |
| 767 | + <span class="mobile-priority mobile-priority-{task.priority}">P{task.priority}</span> |
| 768 | + {/if} |
| 769 | + </div> |
| 770 | + </div> |
753 | 771 | </div> |
754 | 772 | </div> |
755 | 773 | {/if} |
|
1483 | 1501 | white-space: nowrap; |
1484 | 1502 | } |
1485 | 1503 |
|
1486 | | - /* Custom mobile header (matches TasksActive mobile layout) */ |
| 1504 | + /* Custom mobile header — same swipe-card design as TasksActive standalone tasks */ |
1487 | 1505 | .mobile-task-header { |
1488 | | - padding: 0.5rem 0.75rem; |
1489 | 1506 | border-bottom: 1px solid oklch(0.22 0.02 250); |
1490 | 1507 | flex-shrink: 0; |
1491 | 1508 | } |
1492 | 1509 |
|
1493 | | - .mobile-task-title { |
1494 | | - font-size: 0.8125rem; |
| 1510 | + /* Inner flex row: left strip + right body */ |
| 1511 | + .mobile-card-inner { |
| 1512 | + display: flex; |
| 1513 | + align-items: stretch; |
| 1514 | + min-height: 0; |
| 1515 | + } |
| 1516 | +
|
| 1517 | + /* Left strip: avatar + split agent name */ |
| 1518 | + .mobile-state-strip { |
| 1519 | + width: 28px; |
| 1520 | + flex-shrink: 0; |
| 1521 | + display: flex; |
| 1522 | + align-items: center; |
| 1523 | + justify-content: center; |
| 1524 | + } |
| 1525 | +
|
| 1526 | + .mobile-state-strip-agent { |
| 1527 | + width: 62px; |
| 1528 | + padding: 8px 4px; |
| 1529 | + flex-direction: column; |
| 1530 | + gap: 4px; |
| 1531 | + } |
| 1532 | +
|
| 1533 | + /* CamelCase-split agent name below avatar */ |
| 1534 | + .mobile-strip-agent-label { |
| 1535 | + display: flex; |
| 1536 | + flex-direction: column; |
| 1537 | + align-items: center; |
| 1538 | + line-height: 1.1; |
| 1539 | + font-size: 0.5rem; |
| 1540 | + font-weight: 500; |
| 1541 | + letter-spacing: 0.02em; |
| 1542 | + text-transform: uppercase; |
| 1543 | + color: oklch(0.60 0.015 250); |
| 1544 | + font-family: system-ui, -apple-system, sans-serif; |
| 1545 | + text-align: center; |
| 1546 | + max-width: 100%; |
| 1547 | + overflow: hidden; |
| 1548 | + opacity: 0.85; |
| 1549 | + } |
| 1550 | +
|
| 1551 | + .mobile-strip-agent-label span { |
| 1552 | + max-width: 100%; |
| 1553 | + overflow: hidden; |
| 1554 | + text-overflow: ellipsis; |
| 1555 | + white-space: nowrap; |
| 1556 | + } |
| 1557 | +
|
| 1558 | + /* Right content area */ |
| 1559 | + .mobile-card-body { |
| 1560 | + flex: 1; |
| 1561 | + min-width: 0; |
| 1562 | + padding: 0.625rem 0.75rem; |
| 1563 | + display: flex; |
| 1564 | + flex-direction: column; |
| 1565 | + gap: 0.2rem; |
| 1566 | + } |
| 1567 | +
|
| 1568 | + .mobile-title { |
| 1569 | + min-width: 0; |
| 1570 | + font-size: 0.9375rem; |
1495 | 1571 | font-weight: 600; |
1496 | | - color: oklch(0.90 0.02 250); |
1497 | | - line-height: 1.3; |
| 1572 | + color: oklch(0.88 0.02 250); |
| 1573 | + font-family: system-ui, -apple-system, sans-serif; |
| 1574 | + overflow: hidden; |
| 1575 | + text-overflow: ellipsis; |
| 1576 | + white-space: nowrap; |
1498 | 1577 | } |
1499 | 1578 |
|
1500 | | - .mobile-task-desc { |
| 1579 | + .mobile-description { |
| 1580 | + min-width: 0; |
1501 | 1581 | font-size: 0.6875rem; |
1502 | | - color: oklch(0.55 0.02 250); |
1503 | | - margin-top: 0.125rem; |
| 1582 | + color: oklch(0.60 0.02 250); |
1504 | 1583 | overflow: hidden; |
1505 | 1584 | text-overflow: ellipsis; |
1506 | 1585 | white-space: nowrap; |
| 1586 | + line-height: 1.4; |
1507 | 1587 | } |
1508 | 1588 |
|
1509 | | - .mobile-task-meta { |
| 1589 | + .mobile-card-row2 { |
1510 | 1590 | display: flex; |
1511 | 1591 | align-items: center; |
1512 | 1592 | gap: 0.25rem; |
1513 | | - margin-top: 0.375rem; |
1514 | | - font-size: 0.6875rem; |
1515 | | - color: oklch(0.55 0.02 250); |
| 1593 | + font-size: 0.625rem; |
| 1594 | + color: oklch(0.50 0.02 250); |
1516 | 1595 | flex-wrap: wrap; |
| 1596 | + margin-top: 0.125rem; |
1517 | 1597 | } |
1518 | 1598 |
|
1519 | | - .mobile-task-id-badge { |
| 1599 | + .mobile-task-id { |
1520 | 1600 | font-family: monospace; |
1521 | 1601 | font-size: 0.625rem; |
1522 | 1602 | } |
|
1527 | 1607 | color: oklch(0.50 0.02 250); |
1528 | 1608 | } |
1529 | 1609 |
|
1530 | | - .meta-sep { |
| 1610 | + .mobile-separator { |
1531 | 1611 | color: oklch(0.35 0.02 250); |
1532 | 1612 | } |
1533 | 1613 |
|
1534 | | - .mobile-agent { |
1535 | | - font-size: 0.625rem; |
1536 | | - font-weight: 600; |
1537 | | - color: oklch(0.70 0.02 250); |
1538 | | - text-transform: uppercase; |
1539 | | - letter-spacing: 0.03em; |
1540 | | - } |
1541 | | -
|
1542 | | - .mobile-type { |
1543 | | - font-size: 0.75rem; |
| 1614 | + .mobile-type-icon { |
| 1615 | + font-size: 0.6875rem; |
1544 | 1616 | } |
1545 | 1617 |
|
1546 | | - .mobile-priority-badge { |
| 1618 | + .mobile-priority { |
1547 | 1619 | font-size: 0.5625rem; |
1548 | 1620 | font-weight: 700; |
1549 | 1621 | padding: 0.0625rem 0.25rem; |
|
0 commit comments