feat: 重设计私信页并优化开源展柜体验
私信改为飞书风布局,支持缩略图表情/图片、按会话草稿与用户搜索发起会话;主页发私信直达消息页。开源展柜修复空列表粘滞并改版目录式 UI。
This commit is contained in:
@@ -9,7 +9,6 @@ import { useAuth } from '../hooks/useAuth';
|
||||
import { loginPath } from '../utils/authRedirect';
|
||||
import { formatTime } from '../utils/content';
|
||||
import { userPath } from '../utils/userPath';
|
||||
import ComposeMessageDialog from './ComposeMessageDialog';
|
||||
import UserLink from './UserLink';
|
||||
|
||||
interface Props {
|
||||
@@ -28,7 +27,6 @@ export default function PostAuthorCard({
|
||||
const { user: me } = useAuth();
|
||||
const [profile, setProfile] = useState<UserPublic | null>(null);
|
||||
const [stats, setStats] = useState<UserActivityStats | null>(null);
|
||||
const [msgOpen, setMsgOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!author?.id) {
|
||||
@@ -78,7 +76,7 @@ export default function PostAuthorCard({
|
||||
nav(loginPath(profileHref));
|
||||
return;
|
||||
}
|
||||
setMsgOpen(true);
|
||||
nav(`/messages?peer=${author.id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -159,16 +157,6 @@ export default function PostAuthorCard({
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{!isSelf && (
|
||||
<ComposeMessageDialog
|
||||
open={msgOpen}
|
||||
onOpenChange={setMsgOpen}
|
||||
toUserId={author.id}
|
||||
toNickname={nick}
|
||||
onSent={() => nav(`/messages?peer=${author.id}`)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ function pickScrollEl(): HTMLElement | null {
|
||||
const page = document.querySelector<HTMLElement>('.page-wrap:not(.page-wrap--feed)');
|
||||
if (page) return page;
|
||||
|
||||
const showcase = document.querySelector<HTMLElement>('.showcase-page');
|
||||
const showcase = document.querySelector<HTMLElement>('.showcase-panel');
|
||||
if (showcase) return showcase.closest<HTMLElement>('.main-content') ?? showcase;
|
||||
|
||||
const admin = document.querySelector<HTMLElement>('.admin-main');
|
||||
|
||||
@@ -19,12 +19,14 @@ export default function ShowcaseAsideWidget() {
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const hit = getSessionSnapshot<CommunityShowcaseItem[]>(SHOWCASE_KEY);
|
||||
if (hit !== undefined) {
|
||||
// 非空快照直接用;空数组可能是启动竞态假空,仍再拉
|
||||
if (hit !== undefined && hit.length > 0) {
|
||||
setItems(hit);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
if (hit !== undefined) setItems(hit);
|
||||
setLoading(hit === undefined);
|
||||
api.communityShowcase()
|
||||
.then((r) => {
|
||||
if (cancelled) return;
|
||||
@@ -33,10 +35,8 @@ export default function ShowcaseAsideWidget() {
|
||||
setItems(next);
|
||||
})
|
||||
.catch(() => {
|
||||
if (!cancelled) {
|
||||
setSessionSnapshot(SHOWCASE_KEY, []);
|
||||
setItems([]);
|
||||
}
|
||||
// 失败不写空快照,避免假空粘死
|
||||
if (!cancelled && hit === undefined) setItems([]);
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) setLoading(false);
|
||||
@@ -54,17 +54,13 @@ export default function ShowcaseAsideWidget() {
|
||||
setItems(next);
|
||||
})
|
||||
.catch(() => {
|
||||
if (opts.showLoading) {
|
||||
setSessionSnapshot(SHOWCASE_KEY, []);
|
||||
setItems([]);
|
||||
}
|
||||
// 软刷新失败:保持旧 UI
|
||||
// 软刷新 / 强刷失败:保持旧 UI,不写空快照
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
const applyHitOrReload = (showLoading: boolean) => {
|
||||
const hit = getSessionSnapshot<CommunityShowcaseItem[]>(SHOWCASE_KEY);
|
||||
if (hit !== undefined) {
|
||||
if (hit !== undefined && hit.length > 0) {
|
||||
setItems(hit);
|
||||
setLoading(false);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user