@liguoshuai/pi-web-chat 1.10.1 → 1.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/CHANGELOG.md +17 -0
- package/package.json +1 -1
- package/public/app.js +19 -3
- package/public/index.html +2 -2
- package/public/style.css +104 -32
package/docs/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.10.2] - 2026-08-30
|
|
11
|
+
|
|
12
|
+
### Fixed & Improved
|
|
13
|
+
- **移动端顶栏排版与信息密度重构 (Mobile Topbar UX)**:
|
|
14
|
+
- 在移动端隐藏多余的会话名截断占位,隐藏导出按钮文字标签仅保留操作图标,为工作目录与模型选择胶囊腾出充足显示空间。
|
|
15
|
+
- 优化移动端触控胶囊布局与间距,杜绝文字极端挤压和残缺问题。
|
|
16
|
+
- **欢迎区与模型卡片响应式布局优化 (Empty State & Model Banner)**:
|
|
17
|
+
- 优化欢迎引导文案,兼容移动端抽屉式侧边栏交互。
|
|
18
|
+
- 为 `★ 默认模型` 徽标增加专用样式并强制单行禁止折行,彻底消除断词分行问题。
|
|
19
|
+
- 修复模型卡片在移动端下的左右对齐与视觉比例,“切换模型”按钮平滑对齐。
|
|
20
|
+
- 优化快捷推荐指令标签(Suggestions Chips),支持移动端优雅折行排版。
|
|
21
|
+
- **移动端输入框与占位提示适配 (Composer Mobile Adaptation)**:
|
|
22
|
+
- 移动端自动使用精简的 Placeholder 提示文案,彻底解决长提示在窄屏单行输入框下文字被腰斩截断的问题。
|
|
23
|
+
- 增强底部操作区全面屏手势安全区(`safe-area-inset-bottom`)适配。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
10
27
|
## [1.10.1] - 2026-08-30
|
|
11
28
|
|
|
12
29
|
### Improved
|
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -2335,6 +2335,21 @@ function baseName(p) {
|
|
|
2335
2335
|
}
|
|
2336
2336
|
|
|
2337
2337
|
// ---- Composer ----
|
|
2338
|
+
function getComposerPlaceholder() {
|
|
2339
|
+
const isMobile = window.innerWidth <= 768;
|
|
2340
|
+
if (state.aborting) {
|
|
2341
|
+
return isMobile ? "正在中止…" : "正在中止当前任务…";
|
|
2342
|
+
}
|
|
2343
|
+
if (state.streaming) {
|
|
2344
|
+
return isMobile
|
|
2345
|
+
? "AI 运行中… 可输入补充指令"
|
|
2346
|
+
: "AI 正在运行中… 可在此输入补充/指导指令,按 Enter 或点击【插入指令】实时调整";
|
|
2347
|
+
}
|
|
2348
|
+
return isMobile
|
|
2349
|
+
? "给 pi 发消息…"
|
|
2350
|
+
: "给 pi 发消息… (Enter 发送,Shift+Enter 换行)";
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2338
2353
|
function updateComposerUI() {
|
|
2339
2354
|
const ta = $("#composer");
|
|
2340
2355
|
const text = ta ? ta.value.trim() : "";
|
|
@@ -2356,7 +2371,7 @@ function updateComposerUI() {
|
|
|
2356
2371
|
if (steerBtn) {
|
|
2357
2372
|
steerBtn.style.display = "none";
|
|
2358
2373
|
}
|
|
2359
|
-
if (ta) ta.placeholder =
|
|
2374
|
+
if (ta) ta.placeholder = getComposerPlaceholder();
|
|
2360
2375
|
} else if (state.streaming) {
|
|
2361
2376
|
if (sendBtn) {
|
|
2362
2377
|
sendBtn.classList.add("stop");
|
|
@@ -2372,7 +2387,7 @@ function updateComposerUI() {
|
|
|
2372
2387
|
steerBtn.style.display = "none";
|
|
2373
2388
|
}
|
|
2374
2389
|
}
|
|
2375
|
-
if (ta) ta.placeholder =
|
|
2390
|
+
if (ta) ta.placeholder = getComposerPlaceholder();
|
|
2376
2391
|
} else {
|
|
2377
2392
|
if (sendBtn) {
|
|
2378
2393
|
sendBtn.classList.remove("stop");
|
|
@@ -2383,7 +2398,7 @@ function updateComposerUI() {
|
|
|
2383
2398
|
if (steerBtn) {
|
|
2384
2399
|
steerBtn.style.display = "none";
|
|
2385
2400
|
}
|
|
2386
|
-
if (ta) ta.placeholder =
|
|
2401
|
+
if (ta) ta.placeholder = getComposerPlaceholder();
|
|
2387
2402
|
}
|
|
2388
2403
|
}
|
|
2389
2404
|
|
|
@@ -2824,6 +2839,7 @@ async function init() {
|
|
|
2824
2839
|
lastIsMobile = isMobile;
|
|
2825
2840
|
// Crossing the breakpoint: always close the drawer to reach a known state.
|
|
2826
2841
|
$(".app").classList.remove("sidebar-open");
|
|
2842
|
+
updateComposerUI();
|
|
2827
2843
|
}
|
|
2828
2844
|
});
|
|
2829
2845
|
|
package/public/index.html
CHANGED
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
<div id="emptyState" class="empty-state" style="display:flex;">
|
|
80
80
|
<div class="logo">π</div>
|
|
81
81
|
<h1>有什么可以帮你?</h1>
|
|
82
|
-
<p>我是 <strong>pi</strong>
|
|
82
|
+
<p>我是 <strong>pi</strong> 编程助手,可以读写文件、运行命令、改代码。在下方输入你的需求开始,或打开历史会话继续。</p>
|
|
83
83
|
<div class="empty-model-banner" id="emptyModelBanner">
|
|
84
84
|
<div class="empty-model-left">
|
|
85
85
|
<span class="empty-model-icon">🤖</span>
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
<path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"></path>
|
|
113
113
|
</svg>
|
|
114
114
|
</button>
|
|
115
|
-
<textarea id="composer" rows="1" placeholder="给 pi 发消息…
|
|
115
|
+
<textarea id="composer" rows="1" placeholder="给 pi 发消息…"></textarea>
|
|
116
116
|
<button class="steer-btn" id="steerBtn" title="在 AI 运行过程中插入指导指令" style="display:none;">
|
|
117
117
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg>
|
|
118
118
|
<span>插入指令</span>
|
package/public/style.css
CHANGED
|
@@ -812,6 +812,7 @@ body {
|
|
|
812
812
|
gap: 6px;
|
|
813
813
|
font-size: 13px;
|
|
814
814
|
color: var(--text);
|
|
815
|
+
flex-wrap: wrap;
|
|
815
816
|
}
|
|
816
817
|
.empty-model-label {
|
|
817
818
|
color: var(--text-muted);
|
|
@@ -824,6 +825,20 @@ body {
|
|
|
824
825
|
text-overflow: ellipsis;
|
|
825
826
|
white-space: nowrap;
|
|
826
827
|
}
|
|
828
|
+
.badge-default {
|
|
829
|
+
display: inline-flex;
|
|
830
|
+
align-items: center;
|
|
831
|
+
font-size: 11px;
|
|
832
|
+
font-weight: 500;
|
|
833
|
+
color: #f59e0b;
|
|
834
|
+
background: rgba(245, 158, 11, 0.12);
|
|
835
|
+
border: 1px solid rgba(245, 158, 11, 0.25);
|
|
836
|
+
border-radius: 4px;
|
|
837
|
+
padding: 1px 6px;
|
|
838
|
+
white-space: nowrap !important;
|
|
839
|
+
flex-shrink: 0;
|
|
840
|
+
line-height: 1.3;
|
|
841
|
+
}
|
|
827
842
|
.btn-topbar-action {
|
|
828
843
|
display: inline-flex;
|
|
829
844
|
align-items: center;
|
|
@@ -1504,7 +1519,7 @@ body {
|
|
|
1504
1519
|
|
|
1505
1520
|
/* Topbar Mobile Adjustments — fixed, taller, shadowed so it is always findable */
|
|
1506
1521
|
.topbar {
|
|
1507
|
-
height:
|
|
1522
|
+
height: 50px;
|
|
1508
1523
|
padding: 0 8px;
|
|
1509
1524
|
gap: 6px;
|
|
1510
1525
|
position: fixed;
|
|
@@ -1515,21 +1530,16 @@ body {
|
|
|
1515
1530
|
background: var(--bg);
|
|
1516
1531
|
border-bottom: 1px solid var(--border);
|
|
1517
1532
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
|
|
1533
|
+
display: flex;
|
|
1534
|
+
align-items: center;
|
|
1518
1535
|
}
|
|
1519
1536
|
|
|
1520
1537
|
.main {
|
|
1521
|
-
padding-top:
|
|
1538
|
+
padding-top: 50px;
|
|
1522
1539
|
}
|
|
1523
1540
|
|
|
1524
1541
|
.topbar .session-name {
|
|
1525
|
-
|
|
1526
|
-
font-weight: 500;
|
|
1527
|
-
min-width: 0;
|
|
1528
|
-
flex: 1;
|
|
1529
|
-
overflow: hidden;
|
|
1530
|
-
text-overflow: ellipsis;
|
|
1531
|
-
white-space: nowrap;
|
|
1532
|
-
padding: 0 2px;
|
|
1542
|
+
display: none !important;
|
|
1533
1543
|
}
|
|
1534
1544
|
|
|
1535
1545
|
.btn-toggle-sidebar {
|
|
@@ -1548,7 +1558,7 @@ body {
|
|
|
1548
1558
|
#cwdPillWrap {
|
|
1549
1559
|
padding: 4px 7px;
|
|
1550
1560
|
font-size: 11px;
|
|
1551
|
-
max-width:
|
|
1561
|
+
max-width: 80px;
|
|
1552
1562
|
overflow: hidden;
|
|
1553
1563
|
text-overflow: ellipsis;
|
|
1554
1564
|
white-space: nowrap;
|
|
@@ -1559,22 +1569,26 @@ body {
|
|
|
1559
1569
|
display: flex;
|
|
1560
1570
|
align-items: center;
|
|
1561
1571
|
gap: 4px;
|
|
1562
|
-
flex
|
|
1563
|
-
|
|
1572
|
+
flex: 1;
|
|
1573
|
+
min-width: 0;
|
|
1564
1574
|
}
|
|
1565
1575
|
|
|
1566
1576
|
.model-pill {
|
|
1567
1577
|
padding: 4px 8px;
|
|
1568
1578
|
font-size: 11px;
|
|
1569
|
-
max-width:
|
|
1579
|
+
max-width: 125px;
|
|
1570
1580
|
overflow: hidden;
|
|
1571
1581
|
text-overflow: ellipsis;
|
|
1572
1582
|
white-space: nowrap;
|
|
1573
|
-
flex-shrink:
|
|
1583
|
+
flex-shrink: 1;
|
|
1584
|
+
min-width: 0;
|
|
1574
1585
|
gap: 4px;
|
|
1575
1586
|
}
|
|
1576
1587
|
.model-pill-name {
|
|
1577
|
-
max-width:
|
|
1588
|
+
max-width: 100%;
|
|
1589
|
+
overflow: hidden;
|
|
1590
|
+
text-overflow: ellipsis;
|
|
1591
|
+
white-space: nowrap;
|
|
1578
1592
|
}
|
|
1579
1593
|
.model-pill-badge {
|
|
1580
1594
|
display: none !important;
|
|
@@ -1597,20 +1611,30 @@ body {
|
|
|
1597
1611
|
font-weight: 500;
|
|
1598
1612
|
}
|
|
1599
1613
|
|
|
1614
|
+
.btn-topbar-action {
|
|
1615
|
+
width: 32px;
|
|
1616
|
+
height: 32px;
|
|
1617
|
+
padding: 0;
|
|
1618
|
+
display: inline-flex;
|
|
1619
|
+
align-items: center;
|
|
1620
|
+
justify-content: center;
|
|
1621
|
+
flex-shrink: 0;
|
|
1622
|
+
}
|
|
1623
|
+
.topbar-action-label {
|
|
1624
|
+
display: none !important;
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1600
1627
|
@media (max-width: 360px) {
|
|
1601
1628
|
.topbar {
|
|
1602
1629
|
padding: 0 4px;
|
|
1603
1630
|
gap: 4px;
|
|
1604
1631
|
}
|
|
1605
1632
|
#cwdPillWrap {
|
|
1606
|
-
max-width:
|
|
1633
|
+
max-width: 60px;
|
|
1607
1634
|
padding: 4px 5px;
|
|
1608
1635
|
}
|
|
1609
1636
|
.model-pill {
|
|
1610
|
-
max-width:
|
|
1611
|
-
}
|
|
1612
|
-
.model-pill-name {
|
|
1613
|
-
max-width: 50px;
|
|
1637
|
+
max-width: 95px;
|
|
1614
1638
|
}
|
|
1615
1639
|
.thinking-pill {
|
|
1616
1640
|
padding: 4px 5px;
|
|
@@ -1637,13 +1661,48 @@ body {
|
|
|
1637
1661
|
}
|
|
1638
1662
|
|
|
1639
1663
|
.empty-model-banner {
|
|
1640
|
-
padding:
|
|
1641
|
-
flex-direction:
|
|
1664
|
+
padding: 12px 14px;
|
|
1665
|
+
flex-direction: row;
|
|
1666
|
+
align-items: center;
|
|
1667
|
+
justify-content: space-between;
|
|
1668
|
+
gap: 10px;
|
|
1669
|
+
width: 100%;
|
|
1670
|
+
max-width: 100%;
|
|
1671
|
+
box-sizing: border-box;
|
|
1672
|
+
}
|
|
1673
|
+
.empty-model-left {
|
|
1674
|
+
display: flex;
|
|
1642
1675
|
align-items: flex-start;
|
|
1643
|
-
gap:
|
|
1676
|
+
gap: 10px;
|
|
1677
|
+
flex: 1;
|
|
1678
|
+
min-width: 0;
|
|
1679
|
+
}
|
|
1680
|
+
.empty-model-icon {
|
|
1681
|
+
font-size: 22px;
|
|
1682
|
+
margin-top: 1px;
|
|
1683
|
+
flex-shrink: 0;
|
|
1684
|
+
}
|
|
1685
|
+
.empty-model-info {
|
|
1686
|
+
flex: 1;
|
|
1687
|
+
min-width: 0;
|
|
1688
|
+
gap: 4px;
|
|
1689
|
+
}
|
|
1690
|
+
.empty-model-title-row {
|
|
1691
|
+
flex-wrap: wrap;
|
|
1692
|
+
gap: 4px 6px;
|
|
1693
|
+
font-size: 12.5px;
|
|
1694
|
+
line-height: 1.4;
|
|
1695
|
+
}
|
|
1696
|
+
.empty-model-name {
|
|
1697
|
+
font-weight: 600;
|
|
1698
|
+
word-break: break-all;
|
|
1699
|
+
white-space: normal;
|
|
1644
1700
|
}
|
|
1645
1701
|
.btn-change-model {
|
|
1646
|
-
align-self:
|
|
1702
|
+
align-self: center;
|
|
1703
|
+
padding: 6px 10px;
|
|
1704
|
+
font-size: 11.5px;
|
|
1705
|
+
flex-shrink: 0;
|
|
1647
1706
|
}
|
|
1648
1707
|
|
|
1649
1708
|
.mobile-toolbar-fab {
|
|
@@ -1691,7 +1750,7 @@ body {
|
|
|
1691
1750
|
|
|
1692
1751
|
/* Empty state mobile adjustments */
|
|
1693
1752
|
.empty-state {
|
|
1694
|
-
padding:
|
|
1753
|
+
padding: 20px 14px;
|
|
1695
1754
|
gap: 12px;
|
|
1696
1755
|
}
|
|
1697
1756
|
|
|
@@ -1709,31 +1768,44 @@ body {
|
|
|
1709
1768
|
}
|
|
1710
1769
|
|
|
1711
1770
|
.suggestions {
|
|
1771
|
+
display: flex;
|
|
1712
1772
|
gap: 8px;
|
|
1713
|
-
margin-top:
|
|
1773
|
+
margin-top: 10px;
|
|
1774
|
+
flex-wrap: wrap;
|
|
1775
|
+
justify-content: center;
|
|
1776
|
+
width: 100%;
|
|
1777
|
+
max-width: 100%;
|
|
1778
|
+
box-sizing: border-box;
|
|
1714
1779
|
}
|
|
1715
1780
|
|
|
1716
1781
|
.suggestions .chip {
|
|
1717
|
-
padding:
|
|
1782
|
+
padding: 8px 12px;
|
|
1718
1783
|
font-size: 12px;
|
|
1784
|
+
line-height: 1.35;
|
|
1785
|
+
text-align: center;
|
|
1786
|
+
border-radius: 18px;
|
|
1787
|
+
max-width: 100%;
|
|
1788
|
+
box-sizing: border-box;
|
|
1789
|
+
white-space: normal;
|
|
1719
1790
|
}
|
|
1720
1791
|
|
|
1721
1792
|
/* Composer input mobile adjustments */
|
|
1722
1793
|
.composer {
|
|
1723
|
-
padding: 8px 12px
|
|
1794
|
+
padding: 8px 12px;
|
|
1795
|
+
padding-bottom: max(12px, calc(8px + env(safe-area-inset-bottom, 0px)));
|
|
1724
1796
|
}
|
|
1725
1797
|
|
|
1726
1798
|
.composer-inner {
|
|
1727
|
-
padding:
|
|
1799
|
+
padding: 5px 8px 5px 12px;
|
|
1728
1800
|
border-radius: 22px;
|
|
1729
1801
|
gap: 6px;
|
|
1730
1802
|
}
|
|
1731
1803
|
|
|
1732
1804
|
.composer textarea {
|
|
1733
1805
|
padding: 6px 0;
|
|
1734
|
-
font-size:
|
|
1806
|
+
font-size: 15px;
|
|
1735
1807
|
line-height: 20px;
|
|
1736
|
-
min-height:
|
|
1808
|
+
min-height: 28px;
|
|
1737
1809
|
max-height: 160px;
|
|
1738
1810
|
}
|
|
1739
1811
|
|