Commit c9009a549fa3a201c4d0e6c5ca17dec64270260a
1 parent
c9834ccb
Move nickname UI above the chat input, trigger on input focus
- "昵称 X ✎" button (next to the "聊天" title) replaced with a row directly above the chat input: hidden until a nickname is set, then shows "<nickname> change name" — matches infiniteslop.ai's own placement/label - Nickname prompt now triggers on focusing the chat input itself, not just on hitting send — so a first-time visitor sees it the moment they click in Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Showing
3 changed files
with
81 additions
and
56 deletions
library.json
| 1 | 1 | [ |
| 2 | 2 | { |
| 3 | + "id": "8024972d6019", | |
| 4 | + "source": "h3console", | |
| 5 | + "prompt": "蛤蟆文太跳出来了打架", | |
| 6 | + "fullPrompt": "蛤蟆文太跳出来了打架", | |
| 7 | + "edited": false, | |
| 8 | + "width": 832, | |
| 9 | + "height": 480, | |
| 10 | + "duration": 5, | |
| 11 | + "partition": "text", | |
| 12 | + "likes": 0, | |
| 13 | + "createdAt": 1788249485816 | |
| 14 | + }, | |
| 15 | + { | |
| 3 | 16 | "id": "0ade3648412f", |
| 4 | 17 | "source": "h3console", |
| 5 | 18 | "prompt": "来一只猫在草地上玩耍", |
| ... | ... | @@ -53,7 +66,7 @@ |
| 53 | 66 | "likes": 0, |
| 54 | 67 | "createdAt": 1788192915845, |
| 55 | 68 | "promptEn": "scholar watches the room warily", |
| 56 | - "lastPlayedAt": 1788246004885 | |
| 69 | + "lastPlayedAt": 1788249895446 | |
| 57 | 70 | }, |
| 58 | 71 | { |
| 59 | 72 | "id": "e8cbb73560ef", |
| ... | ... | @@ -307,7 +320,7 @@ |
| 307 | 320 | "partition": "ref2va", |
| 308 | 321 | "likes": 0, |
| 309 | 322 | "createdAt": 1788187365789, |
| 310 | - "lastPlayedAt": 1788247402036, | |
| 323 | + "lastPlayedAt": 1788249805778, | |
| 311 | 324 | "promptEn": "woman in white being gentle and comforting" |
| 312 | 325 | }, |
| 313 | 326 | { |
| ... | ... | @@ -488,7 +501,7 @@ |
| 488 | 501 | "likes": 0, |
| 489 | 502 | "createdAt": 1788138492364, |
| 490 | 503 | "promptEn": "astronaut on a Martian canyon, helmet reflecting an alien ruined city", |
| 491 | - "lastPlayedAt": 1788247866434 | |
| 504 | + "lastPlayedAt": 1788250133927 | |
| 492 | 505 | }, |
| 493 | 506 | { |
| 494 | 507 | "id": "f84b8f044ec5", |
| ... | ... | @@ -503,7 +516,7 @@ |
| 503 | 516 | "likes": 0, |
| 504 | 517 | "createdAt": 1788120171725, |
| 505 | 518 | "promptEn": "constable bursts in and blocks the door, talks to a pale woman behind the screen", |
| 506 | - "lastPlayedAt": 1788248607084 | |
| 519 | + "lastPlayedAt": 1788249899449 | |
| 507 | 520 | }, |
| 508 | 521 | { |
| 509 | 522 | "id": "5c364152e54c", |
| ... | ... | @@ -563,7 +576,7 @@ |
| 563 | 576 | "likes": 0, |
| 564 | 577 | "createdAt": 1788071067702, |
| 565 | 578 | "promptEn": "constable stands still, quietly says he won't make a sound, woman stays silent behind the screen", |
| 566 | - "lastPlayedAt": 1788247289944 | |
| 579 | + "lastPlayedAt": 1788249939841 | |
| 567 | 580 | }, |
| 568 | 581 | { |
| 569 | 582 | "id": "2e09fcd3d42c", |
| ... | ... | @@ -638,7 +651,7 @@ |
| 638 | 651 | "likes": 0, |
| 639 | 652 | "createdAt": 1788026877547, |
| 640 | 653 | "promptEn": "a deity in gold crown and red veil, quietly judging you in a moonlit bridal chamber", |
| 641 | - "lastPlayedAt": 1788248094627 | |
| 654 | + "lastPlayedAt": 1788249765707 | |
| 642 | 655 | }, |
| 643 | 656 | { |
| 644 | 657 | "id": "d5f811737e95", |
| ... | ... | @@ -683,7 +696,7 @@ |
| 683 | 696 | "likes": 0, |
| 684 | 697 | "createdAt": 1788026569123, |
| 685 | 698 | "promptEn": "pale dream demon in a suit, reaching out a hand inside a dream train car", |
| 686 | - "lastPlayedAt": 1788248166697 | |
| 699 | + "lastPlayedAt": 1788250129929 | |
| 687 | 700 | }, |
| 688 | 701 | { |
| 689 | 702 | "id": "bd6e2b264243", |
| ... | ... | @@ -743,7 +756,7 @@ |
| 743 | 756 | "likes": 0, |
| 744 | 757 | "createdAt": 1788026068497, |
| 745 | 758 | "promptEn": "black-haired prince in a red cloak, pressing down an execution order in the trial hall", |
| 746 | - "lastPlayedAt": 1788247147812 | |
| 759 | + "lastPlayedAt": 1788249833797 | |
| 747 | 760 | }, |
| 748 | 761 | { |
| 749 | 762 | "id": "0a5e37bb328c", |
| ... | ... | @@ -758,7 +771,7 @@ |
| 758 | 771 | "likes": 0, |
| 759 | 772 | "createdAt": 1788025642732, |
| 760 | 773 | "promptEn": "Vecna reaching out a claw in his lair in the Upside Down, red lightning", |
| 761 | - "lastPlayedAt": 1788246201053 | |
| 774 | + "lastPlayedAt": 1788249929837 | |
| 762 | 775 | }, |
| 763 | 776 | { |
| 764 | 777 | "id": "00862f966c3f", |
| ... | ... | @@ -1133,7 +1146,7 @@ |
| 1133 | 1146 | "likes": 0, |
| 1134 | 1147 | "createdAt": 1788014099497, |
| 1135 | 1148 | "promptEn": "glass bridge game, exploiting a flaw to push back player 101", |
| 1136 | - "lastPlayedAt": 1788248180707 | |
| 1149 | + "lastPlayedAt": 1788249885816 | |
| 1137 | 1150 | }, |
| 1138 | 1151 | { |
| 1139 | 1152 | "id": "24576c264a25", |
| ... | ... | @@ -1148,7 +1161,7 @@ |
| 1148 | 1161 | "likes": 0, |
| 1149 | 1162 | "createdAt": 1788013870849, |
| 1150 | 1163 | "promptEn": "glass bridge game, exploiting a flaw to push back player 101", |
| 1151 | - "lastPlayedAt": 1788244557694 | |
| 1164 | + "lastPlayedAt": 1788249963847 | |
| 1152 | 1165 | }, |
| 1153 | 1166 | { |
| 1154 | 1167 | "id": "dd12bbb55060", |
| ... | ... | @@ -1178,7 +1191,7 @@ |
| 1178 | 1191 | "likes": 0, |
| 1179 | 1192 | "createdAt": 1788013632065, |
| 1180 | 1193 | "promptEn": "glass bridge game, held the goal but paid a price", |
| 1181 | - "lastPlayedAt": 1788247840412 | |
| 1194 | + "lastPlayedAt": 1788249933837 | |
| 1182 | 1195 | }, |
| 1183 | 1196 | { |
| 1184 | 1197 | "id": "892b923eed29", |
| ... | ... | @@ -1193,7 +1206,7 @@ |
| 1193 | 1206 | "likes": 0, |
| 1194 | 1207 | "createdAt": 1788013393463, |
| 1195 | 1208 | "promptEn": "guessed wrong in a survival game, got countered", |
| 1196 | - "lastPlayedAt": 1788248362870 | |
| 1209 | + "lastPlayedAt": 1788250071902 | |
| 1197 | 1210 | }, |
| 1198 | 1211 | { |
| 1199 | 1212 | "id": "7880a91928c6", |
| ... | ... | @@ -1253,7 +1266,7 @@ |
| 1253 | 1266 | "likes": 0, |
| 1254 | 1267 | "createdAt": 1788012679740, |
| 1255 | 1268 | "promptEn": "in the mental lair, exploiting a flaw to counter Vecna", |
| 1256 | - "lastPlayedAt": 1788245658603 | |
| 1269 | + "lastPlayedAt": 1788250124975 | |
| 1257 | 1270 | }, |
| 1258 | 1271 | { |
| 1259 | 1272 | "id": "3913752bbe3a", |
| ... | ... | @@ -1403,7 +1416,7 @@ |
| 1403 | 1416 | "likes": 0, |
| 1404 | 1417 | "createdAt": 1788010775613, |
| 1405 | 1418 | "promptEn": "facing Voldemort, stayed passive and got cornered", |
| 1406 | - "lastPlayedAt": 1788241054655 | |
| 1419 | + "lastPlayedAt": 1788249909833 | |
| 1407 | 1420 | }, |
| 1408 | 1421 | { |
| 1409 | 1422 | "id": "795842efa4a1", |
| ... | ... | @@ -1583,7 +1596,7 @@ |
| 1583 | 1596 | "likes": 0, |
| 1584 | 1597 | "createdAt": 1788007915610, |
| 1585 | 1598 | "promptEn": "in the ruined city, exploiting a flaw to counter Tomura", |
| 1586 | - "lastPlayedAt": 1788244427575 | |
| 1599 | + "lastPlayedAt": 1788249919450 | |
| 1587 | 1600 | }, |
| 1588 | 1601 | { |
| 1589 | 1602 | "id": "f67685cd6862", |
| ... | ... | @@ -1628,7 +1641,7 @@ |
| 1628 | 1641 | "likes": 0, |
| 1629 | 1642 | "createdAt": 1788007201908, |
| 1630 | 1643 | "promptEn": "breaking into the palace, Neferpitou stalling to protect the king", |
| 1631 | - "lastPlayedAt": 1788248014560 | |
| 1644 | + "lastPlayedAt": 1788249889814 | |
| 1632 | 1645 | }, |
| 1633 | 1646 | { |
| 1634 | 1647 | "id": "628026375795", |
| ... | ... | @@ -1718,7 +1731,7 @@ |
| 1718 | 1731 | "likes": 0, |
| 1719 | 1732 | "createdAt": 1788005778588, |
| 1720 | 1733 | "promptEn": "facing Frieza, held the goal but paid a price", |
| 1721 | - "lastPlayedAt": 1788247462098 | |
| 1734 | + "lastPlayedAt": 1788249925828 | |
| 1722 | 1735 | }, |
| 1723 | 1736 | { |
| 1724 | 1737 | "id": "b96cc9762cf6", |
| ... | ... | @@ -1808,7 +1821,7 @@ |
| 1808 | 1821 | "likes": 0, |
| 1809 | 1822 | "createdAt": 1788004353928, |
| 1810 | 1823 | "promptEn": "facing Mahito, went in head-on and got seen through", |
| 1811 | - "lastPlayedAt": 1788244924008 | |
| 1824 | + "lastPlayedAt": 1788250119920 | |
| 1812 | 1825 | }, |
| 1813 | 1826 | { |
| 1814 | 1827 | "id": "971d80ec087c", |
| ... | ... | @@ -1928,7 +1941,7 @@ |
| 1928 | 1941 | "likes": 0, |
| 1929 | 1942 | "createdAt": 1788002691822, |
| 1930 | 1943 | "promptEn": "facing Reiner, held the goal but paid a price", |
| 1931 | - "lastPlayedAt": 1788244299472 | |
| 1944 | + "lastPlayedAt": 1788249915447 | |
| 1932 | 1945 | }, |
| 1933 | 1946 | { |
| 1934 | 1947 | "id": "f65b15d67966", |
| ... | ... | @@ -2258,7 +2271,7 @@ |
| 2258 | 2271 | "likes": 0, |
| 2259 | 2272 | "createdAt": 1787762342686, |
| 2260 | 2273 | "promptEn": "woman tells him from behind the screen to go check outside, he steps out warily", |
| 2261 | - "lastPlayedAt": 1788248000548 | |
| 2274 | + "lastPlayedAt": 1788250091902 | |
| 2262 | 2275 | }, |
| 2263 | 2276 | { |
| 2264 | 2277 | "id": "47a6de809c61", |
| ... | ... | @@ -2288,7 +2301,7 @@ |
| 2288 | 2301 | "likes": 0, |
| 2289 | 2302 | "createdAt": 1787762311804, |
| 2290 | 2303 | "promptEn": "constable sits with a cup of water, slowly looking up at the woman behind the screen", |
| 2291 | - "lastPlayedAt": 1788246833570 | |
| 2304 | + "lastPlayedAt": 1788250038963 | |
| 2292 | 2305 | }, |
| 2293 | 2306 | { |
| 2294 | 2307 | "id": "850f13881576", |
| ... | ... | @@ -2393,7 +2406,7 @@ |
| 2393 | 2406 | "likes": 0, |
| 2394 | 2407 | "createdAt": 1787724313620, |
| 2395 | 2408 | "promptEn": "first-person view bursting into the room, glancing back in fear, the woman startled", |
| 2396 | - "lastPlayedAt": 1788247658274 | |
| 2409 | + "lastPlayedAt": 1788249869811 | |
| 2397 | 2410 | }, |
| 2398 | 2411 | { |
| 2399 | 2412 | "id": "81b6c3789111", |
| ... | ... | @@ -2498,7 +2511,7 @@ |
| 2498 | 2511 | "likes": 0, |
| 2499 | 2512 | "createdAt": 1787708653181, |
| 2500 | 2513 | "promptEn": "constable holds her gaze, quietly says \"go on\", then waits in silence", |
| 2501 | - "lastPlayedAt": 1788244341508 | |
| 2514 | + "lastPlayedAt": 1788249737695 | |
| 2502 | 2515 | }, |
| 2503 | 2516 | { |
| 2504 | 2517 | "id": "55f98ceec9e4", |
| ... | ... | @@ -2663,7 +2676,7 @@ |
| 2663 | 2676 | "likes": 0, |
| 2664 | 2677 | "createdAt": 1787674737743, |
| 2665 | 2678 | "promptEn": "constable slowly looks around the room, discovers her watching him motionlessly through the screen", |
| 2666 | - "lastPlayedAt": 1788248444942 | |
| 2679 | + "lastPlayedAt": 1788249837798 | |
| 2667 | 2680 | }, |
| 2668 | 2681 | { |
| 2669 | 2682 | "id": "c74118d0413f", |
| ... | ... | @@ -2708,7 +2721,7 @@ |
| 2708 | 2721 | "likes": 0, |
| 2709 | 2722 | "createdAt": 1787674695703, |
| 2710 | 2723 | "promptEn": "constable stops, faces the screen, quietly promises to keep his voice down", |
| 2711 | - "lastPlayedAt": 1788247540173 | |
| 2724 | + "lastPlayedAt": 1788250023879 | |
| 2712 | 2725 | }, |
| 2713 | 2726 | { |
| 2714 | 2727 | "id": "94dc455e26bf", |
| ... | ... | @@ -2753,7 +2766,7 @@ |
| 2753 | 2766 | "likes": 0, |
| 2754 | 2767 | "createdAt": 1787674642139, |
| 2755 | 2768 | "promptEn": "constable forms hand seals and summons a giant toad out of smoke", |
| 2756 | - "lastPlayedAt": 1788247129805 | |
| 2769 | + "lastPlayedAt": 1788250076972 | |
| 2757 | 2770 | }, |
| 2758 | 2771 | { |
| 2759 | 2772 | "id": "e9a6320e18a9", |
| ... | ... | @@ -2783,7 +2796,7 @@ |
| 2783 | 2796 | "likes": 0, |
| 2784 | 2797 | "createdAt": 1787674639055, |
| 2785 | 2798 | "promptEn": "constable checks his reflection in the mirror, sees her behind his shoulder in it, turns around to find the screen empty", |
| 2786 | - "lastPlayedAt": 1788246273115 | |
| 2799 | + "lastPlayedAt": 1788249777714 | |
| 2787 | 2800 | }, |
| 2788 | 2801 | { |
| 2789 | 2802 | "id": "ebaf0dde3d9f", |
| ... | ... | @@ -3023,7 +3036,7 @@ |
| 3023 | 3036 | "likes": 0, |
| 3024 | 3037 | "createdAt": 1787615243753, |
| 3025 | 3038 | "promptEn": "robot arm picks up a red block and puts it down", |
| 3026 | - "lastPlayedAt": 1788246909631 | |
| 3039 | + "lastPlayedAt": 1788249857808 | |
| 3027 | 3040 | }, |
| 3028 | 3041 | { |
| 3029 | 3042 | "id": "d040eec16a88", |
| ... | ... | @@ -3038,7 +3051,7 @@ |
| 3038 | 3051 | "likes": 0, |
| 3039 | 3052 | "createdAt": 1787615242602, |
| 3040 | 3053 | "promptEn": "otome game male lead showcase PV", |
| 3041 | - "lastPlayedAt": 1788247347993 | |
| 3054 | + "lastPlayedAt": 1788249753702 | |
| 3042 | 3055 | }, |
| 3043 | 3056 | { |
| 3044 | 3057 | "id": "423a20afba5a", |
| ... | ... | @@ -3068,7 +3081,7 @@ |
| 3068 | 3081 | "likes": 0, |
| 3069 | 3082 | "createdAt": 1787615240988, |
| 3070 | 3083 | "promptEn": "clay fox sprints off a cliff, slow-mo leap over the canyon", |
| 3071 | - "lastPlayedAt": 1788247880445 | |
| 3084 | + "lastPlayedAt": 1788249951846 | |
| 3072 | 3085 | }, |
| 3073 | 3086 | { |
| 3074 | 3087 | "id": "db125dc6a831", |
| ... | ... | @@ -3128,7 +3141,7 @@ |
| 3128 | 3141 | "likes": 0, |
| 3129 | 3142 | "createdAt": 1787588545243, |
| 3130 | 3143 | "promptEn": "ergonomic office chair 360 showcase ad", |
| 3131 | - "lastPlayedAt": 1788248711178 | |
| 3144 | + "lastPlayedAt": 1788250058966 | |
| 3132 | 3145 | }, |
| 3133 | 3146 | { |
| 3134 | 3147 | "id": "b0d258352c3c", |
| ... | ... | @@ -3218,7 +3231,7 @@ |
| 3218 | 3231 | "likes": 0, |
| 3219 | 3232 | "createdAt": 1787588541726, |
| 3220 | 3233 | "promptEn": "woman opens the trunk on a desert road, takes out a bag", |
| 3221 | - "lastPlayedAt": 1788245330307 | |
| 3234 | + "lastPlayedAt": 1788250107920 | |
| 3222 | 3235 | }, |
| 3223 | 3236 | { |
| 3224 | 3237 | "id": "97846542ab09", |
| ... | ... | @@ -3397,7 +3410,7 @@ |
| 3397 | 3410 | "partition": "text", |
| 3398 | 3411 | "likes": 0, |
| 3399 | 3412 | "createdAt": 1787576506447, |
| 3400 | - "lastPlayedAt": 1788247534166, | |
| 3413 | + "lastPlayedAt": 1788250053889, | |
| 3401 | 3414 | "promptEn": "man does as she says but stays on guard" |
| 3402 | 3415 | }, |
| 3403 | 3416 | { |
| ... | ... | @@ -3548,7 +3561,7 @@ |
| 3548 | 3561 | "likes": 0, |
| 3549 | 3562 | "createdAt": 1787542770522, |
| 3550 | 3563 | "promptEn": "clip cut to match a reference video's editing rhythm", |
| 3551 | - "lastPlayedAt": 1788248438939 | |
| 3564 | + "lastPlayedAt": 1788249969849 | |
| 3552 | 3565 | }, |
| 3553 | 3566 | { |
| 3554 | 3567 | "id": "f9286d694bad", |
| ... | ... | @@ -3608,7 +3621,7 @@ |
| 3608 | 3621 | "likes": 0, |
| 3609 | 3622 | "createdAt": 1787470101960, |
| 3610 | 3623 | "promptEn": "cute hand-drawn beagle dog making faces, game screen", |
| 3611 | - "lastPlayedAt": 1788248134665 | |
| 3624 | + "lastPlayedAt": 1788249793727 | |
| 3612 | 3625 | }, |
| 3613 | 3626 | { |
| 3614 | 3627 | "id": "4067993ff824", |
| ... | ... | @@ -3833,7 +3846,7 @@ |
| 3833 | 3846 | "likes": 0, |
| 3834 | 3847 | "createdAt": 1787450754171, |
| 3835 | 3848 | "promptEn": "protagonist leaps across rooftops fleeing pursuers", |
| 3836 | - "lastPlayedAt": 1788246511317 | |
| 3849 | + "lastPlayedAt": 1788249973852 | |
| 3837 | 3850 | }, |
| 3838 | 3851 | { |
| 3839 | 3852 | "id": "fd0183c54763", |
| ... | ... | @@ -3878,7 +3891,7 @@ |
| 3878 | 3891 | "likes": 0, |
| 3879 | 3892 | "createdAt": 1787442174982, |
| 3880 | 3893 | "promptEn": "protagonist leaps across rooftops fleeing pursuers", |
| 3881 | - "lastPlayedAt": 1788248334845 | |
| 3894 | + "lastPlayedAt": 1788249819782 | |
| 3882 | 3895 | }, |
| 3883 | 3896 | { |
| 3884 | 3897 | "id": "18105bc2900b", |
| ... | ... | @@ -4058,7 +4071,7 @@ |
| 4058 | 4071 | "likes": 0, |
| 4059 | 4072 | "createdAt": 1787412606465, |
| 4060 | 4073 | "promptEn": "protagonist leaps across rooftops fleeing pursuers", |
| 4061 | - "lastPlayedAt": 1788246453270 | |
| 4074 | + "lastPlayedAt": 1788249769708 | |
| 4062 | 4075 | }, |
| 4063 | 4076 | { |
| 4064 | 4077 | "id": "29a99dc412b2", |
| ... | ... | @@ -4358,7 +4371,7 @@ |
| 4358 | 4371 | "likes": 0, |
| 4359 | 4372 | "createdAt": 1787326019290, |
| 4360 | 4373 | "promptEn": "misty Jiangnan old town at dawn, woman walking with an oil-paper umbrella", |
| 4361 | - "lastPlayedAt": 1788247508139 | |
| 4374 | + "lastPlayedAt": 1788249851805 | |
| 4362 | 4375 | }, |
| 4363 | 4376 | { |
| 4364 | 4377 | "id": "fd8534ce588c", | ... | ... |
live.css
| ... | ... | @@ -176,21 +176,26 @@ body { |
| 176 | 176 | color: var(--muted); |
| 177 | 177 | padding: 12px 14px 6px; |
| 178 | 178 | } |
| 179 | -.chat-title-row { display: flex; align-items: center; justify-content: space-between; } | |
| 180 | -.nickname-edit-btn { | |
| 179 | +.chat-identity-row { | |
| 180 | + display: flex; | |
| 181 | + align-items: center; | |
| 182 | + gap: 8px; | |
| 183 | + padding: 0 14px 6px; | |
| 184 | + font-size: 11.5px; | |
| 185 | + font-weight: 700; | |
| 186 | +} | |
| 187 | +.chat-identity-row #currentNickname { color: var(--accent); } | |
| 188 | +.chat-identity-row #changeNameBtn { | |
| 181 | 189 | background: transparent; |
| 182 | - border: 1px solid var(--border); | |
| 190 | + border: none; | |
| 183 | 191 | color: var(--muted); |
| 184 | 192 | font-size: 11px; |
| 185 | 193 | font-weight: 700; |
| 186 | - text-transform: none; | |
| 187 | - letter-spacing: normal; | |
| 188 | - border-radius: 999px; | |
| 189 | - padding: 3px 10px; | |
| 194 | + text-decoration: underline; | |
| 190 | 195 | cursor: pointer; |
| 196 | + padding: 0; | |
| 191 | 197 | } |
| 192 | -.nickname-edit-btn:hover { color: #fff; border-color: var(--muted); } | |
| 193 | -.nickname-edit-btn #currentNickname { color: var(--accent); } | |
| 198 | +.chat-identity-row #changeNameBtn:hover { color: #fff; } | |
| 194 | 199 | .chat-list { |
| 195 | 200 | flex: 1; |
| 196 | 201 | overflow-y: auto; | ... | ... |
live.html
| ... | ... | @@ -40,11 +40,12 @@ |
| 40 | 40 | </div> |
| 41 | 41 | |
| 42 | 42 | <aside class="right-col" id="rightCol" hidden> |
| 43 | - <div class="section-title chat-title-row"> | |
| 44 | - <span>聊天</span> | |
| 45 | - <button class="nickname-edit-btn" id="nicknameEditBtn">昵称 <span id="currentNickname">未设置</span> ✎</button> | |
| 46 | - </div> | |
| 43 | + <div class="section-title">聊天</div> | |
| 47 | 44 | <div class="chat-list" id="chatList"></div> |
| 45 | + <div class="chat-identity-row" id="chatIdentityRow" hidden> | |
| 46 | + <span id="currentNickname"></span> | |
| 47 | + <button id="changeNameBtn">change name</button> | |
| 48 | + </div> | |
| 48 | 49 | <div class="chat-input-row"> |
| 49 | 50 | <input type="text" id="chatInput" placeholder="说点什么,或者想看什么…" maxlength="300" /> |
| 50 | 51 | <button id="chatSendBtn">发送</button> |
| ... | ... | @@ -97,7 +98,8 @@ const muteBtn = document.getElementById("muteBtn"); |
| 97 | 98 | const nicknameModal = document.getElementById("nicknameModal"); |
| 98 | 99 | const nicknameInput = document.getElementById("nicknameInput"); |
| 99 | 100 | const nicknameConfirmBtn = document.getElementById("nicknameConfirmBtn"); |
| 100 | -const nicknameEditBtn = document.getElementById("nicknameEditBtn"); | |
| 101 | +const chatIdentityRow = document.getElementById("chatIdentityRow"); | |
| 102 | +const changeNameBtn = document.getElementById("changeNameBtn"); | |
| 101 | 103 | const currentNickname = document.getElementById("currentNickname"); |
| 102 | 104 | const clientId = Math.random().toString(36).slice(2); |
| 103 | 105 | |
| ... | ... | @@ -130,7 +132,8 @@ function getIdentity() { |
| 130 | 132 | } |
| 131 | 133 | function updateNicknameLabel() { |
| 132 | 134 | const existing = getIdentity(); |
| 133 | - currentNickname.textContent = existing ? existing.nickname : "未设置"; | |
| 135 | + chatIdentityRow.hidden = !existing; | |
| 136 | + if (existing) currentNickname.textContent = existing.nickname; | |
| 134 | 137 | } |
| 135 | 138 | |
| 136 | 139 | // Shared by first-time setup and the always-visible "昵称 ✎" edit button. |
| ... | ... | @@ -167,7 +170,7 @@ function ensureIdentity() { |
| 167 | 170 | }); |
| 168 | 171 | } |
| 169 | 172 | |
| 170 | -nicknameEditBtn.addEventListener("click", async () => { | |
| 173 | +changeNameBtn.addEventListener("click", async () => { | |
| 171 | 174 | const existing = getIdentity(); |
| 172 | 175 | const nickname = await openNicknameModal(existing ? existing.nickname : ""); |
| 173 | 176 | const uid = existing ? existing.uid : crypto.randomUUID ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).slice(2)}`; |
| ... | ... | @@ -176,6 +179,10 @@ nicknameEditBtn.addEventListener("click", async () => { |
| 176 | 179 | updateNicknameLabel(); |
| 177 | 180 | }); |
| 178 | 181 | |
| 182 | +// First click into the chat box is what prompts for a nickname — not just | |
| 183 | +// hitting send — so the identity row above the input appears right away. | |
| 184 | +chatInput.addEventListener("focus", () => ensureIdentity()); | |
| 185 | + | |
| 179 | 186 | updateNicknameLabel(); |
| 180 | 187 | |
| 181 | 188 | function renderBrowseList() { | ... | ... |