chore: test deploy snapshot
This commit is contained in:
@@ -2371,6 +2371,29 @@ export async function createChatShareRoom(
|
||||
} satisfies ChatShareRoomSummary;
|
||||
}
|
||||
|
||||
export async function deleteChatShareRoom(token: string, sessionId: string) {
|
||||
const response = await requestChatApi<{
|
||||
ok: boolean;
|
||||
deleted: boolean;
|
||||
deletedSessionId: string;
|
||||
nextRoomSessionId?: string | null;
|
||||
}>(
|
||||
`/shares/${encodeURIComponent(token)}/rooms/${encodeURIComponent(sessionId)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
},
|
||||
{
|
||||
allowUnauthenticated: true,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
deleted: response.deleted === true,
|
||||
deletedSessionId: normalizeRequiredText(response.deletedSessionId),
|
||||
nextRoomSessionId: normalizeOptionalText(response.nextRoomSessionId),
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteChatConversationRequest(sessionId: string, requestId: string) {
|
||||
const response = await requestChatApi<{ ok: boolean; deleted: boolean; sessionId: string; requestId: string }>(
|
||||
`/conversations/${encodeURIComponent(sessionId)}/requests/${encodeURIComponent(requestId)}`,
|
||||
|
||||
@@ -211,21 +211,75 @@
|
||||
}
|
||||
|
||||
.chat-share-page__room-list-panel {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 10px;
|
||||
border-radius: 14px;
|
||||
background: rgba(248, 250, 252, 0.94);
|
||||
box-shadow: inset 0 0 0 1px rgba(219, 226, 236, 0.82);
|
||||
}
|
||||
|
||||
.chat-share-page__room-filter-input.ant-input-affix-wrapper {
|
||||
width: 100%;
|
||||
border-radius: 12px;
|
||||
border-color: rgba(191, 204, 220, 0.9);
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: inset 0 0 0 1px rgba(241, 245, 249, 0.78);
|
||||
}
|
||||
|
||||
.chat-share-page__room-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.chat-share-page__room-swipe {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
border-radius: 14px;
|
||||
isolation: isolate;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.chat-share-page__room-delete-action {
|
||||
position: absolute;
|
||||
inset: 0 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 96px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(180deg, #ef4444 0%, #dc2626 100%);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
.chat-share-page__room-swipe.is-swiped .chat-share-page__room-delete-action,
|
||||
.chat-share-page__room-swipe.is-dragging .chat-share-page__room-delete-action {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.chat-share-page__room-swipe.is-delete-locked .chat-share-page__room-delete-action {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding: 12px;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
@@ -235,6 +289,11 @@
|
||||
0 6px 18px rgba(148, 163, 184, 0.08);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.2s ease, background 0.2s ease, transform 0.16s ease;
|
||||
touch-action: pan-y;
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.chat-share-page__room-card--active {
|
||||
@@ -244,6 +303,26 @@
|
||||
0 10px 24px rgba(59, 130, 246, 0.16);
|
||||
}
|
||||
|
||||
.chat-share-page__room-swipe.is-dragging .chat-share-page__room-card {
|
||||
transition: box-shadow 0.2s ease, background 0.2s ease;
|
||||
}
|
||||
|
||||
.chat-share-page__room-card--default {
|
||||
background:
|
||||
linear-gradient(180deg, #f4fbff 0%, #e3f4ff 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(34, 211, 238, 0.22),
|
||||
0 8px 20px rgba(14, 165, 233, 0.1);
|
||||
}
|
||||
|
||||
.chat-share-page__room-card--default.chat-share-page__room-card--active {
|
||||
background:
|
||||
linear-gradient(180deg, #dff7ff 0%, #d2f0ff 100%);
|
||||
box-shadow:
|
||||
inset 0 0 0 1px rgba(8, 145, 178, 0.34),
|
||||
0 10px 24px rgba(14, 165, 233, 0.14);
|
||||
}
|
||||
|
||||
.chat-share-page__room-card-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -265,6 +344,17 @@
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.chat-share-page__room-list-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 84px;
|
||||
padding: 12px;
|
||||
border-radius: 14px;
|
||||
background: rgba(255, 255, 255, 0.72);
|
||||
box-shadow: inset 0 0 0 1px rgba(226, 232, 240, 0.9);
|
||||
}
|
||||
|
||||
.chat-share-page__create-room-form {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
@@ -1515,6 +1605,10 @@
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.chat-share-page__room-list-panel {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.chat-share-page__program-app-shell--system-chat-room {
|
||||
padding: 0;
|
||||
}
|
||||
@@ -2258,12 +2352,38 @@
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-dialog {
|
||||
top: max(72px, calc(env(safe-area-inset-top, 0px) + 56px));
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-dialog .ant-modal-content {
|
||||
max-height: min(
|
||||
calc(100dvh - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px) - 96px),
|
||||
720px
|
||||
);
|
||||
border-radius: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-dialog .ant-modal-body {
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-section {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.chat-share-page__previous-question-modal-section + .chat-share-page__previous-question-modal-section {
|
||||
border-top: 1px solid #e5eaf1;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
clearChatShareConversationRoom,
|
||||
completeChatShareManualBadge,
|
||||
createChatShareRoom,
|
||||
deleteChatShareRoom,
|
||||
fetchChatShareRuntimeSnapshot,
|
||||
fetchChatShareSnapshot,
|
||||
getStoredChatShareAccessPin,
|
||||
@@ -97,6 +98,12 @@ const SHARE_TOKEN_USAGE_CLOCK_INTERVAL_MS = 1000;
|
||||
const SHARE_EXPIRY_CLOCK_INTERVAL_MS = 60 * 1000;
|
||||
const SHARE_IMMEDIATE_SEND_PINNED_STORAGE_KEY = 'codex-live-share-immediate-send-pinned-by-token';
|
||||
const SHARE_IMMEDIATE_SEND_TOGGLE_HOLD_MS = 1000;
|
||||
const SHARE_ROOM_SWIPE_DELETE_LIMIT_PX = 108;
|
||||
const SHARE_ROOM_SWIPE_DELETE_THRESHOLD_PX = 72;
|
||||
const SHARE_ROOM_TOUCH_TAP_SLOP_PX = 14;
|
||||
const SHARE_ROOM_TOUCH_SCROLL_CANCEL_PX = 18;
|
||||
const SHARE_ROOM_SWIPE_ACTIVATION_PX = 18;
|
||||
const SHARE_ROOM_SWIPE_START_EDGE_PX = 56;
|
||||
const SHARE_ACCESS_PIN_PROMPT_TTL_OPTIONS = [
|
||||
{ value: 'always', label: '매번 묻기', minutes: 0 },
|
||||
{ value: '5', label: '5분 유지', minutes: 5 },
|
||||
@@ -249,6 +256,14 @@ function parseAccessPinPromptTtlOptionValue(value: string) {
|
||||
return matchedOption?.minutes ?? null;
|
||||
}
|
||||
|
||||
function canDeleteShareRoom(room: ChatShareRoomSummary, rooms: ChatShareRoomSummary[]) {
|
||||
if (room.isDefault) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return rooms.length > 1;
|
||||
}
|
||||
|
||||
function readStoredShareImmediateSendPinnedByToken() {
|
||||
if (typeof window === 'undefined') {
|
||||
return {} as Record<string, boolean>;
|
||||
@@ -1551,6 +1566,18 @@ function buildRequestAnswerText(
|
||||
return stripHiddenPreviewTags(String(request.responseText ?? '').replace(DIFF_CODE_BLOCK_PATTERN, '')).trim();
|
||||
}
|
||||
|
||||
function resolveShareRequestFallbackAnswerText(request: ChatConversationRequest) {
|
||||
if (request.status === 'queued') {
|
||||
return '요청 대기 등록 하였습니다.';
|
||||
}
|
||||
|
||||
if (request.status === 'accepted' || request.status === 'started') {
|
||||
return '요청 처리 중 입니다.';
|
||||
}
|
||||
|
||||
return request.statusMessage?.trim() || '아직 답변이 없습니다.';
|
||||
}
|
||||
|
||||
function replaceChatShareSnapshotRequest(snapshot: ChatShareSnapshot, nextRequest: ChatConversationRequest): ChatShareSnapshot {
|
||||
return {
|
||||
...snapshot,
|
||||
@@ -1580,6 +1607,41 @@ function resolveShareConversationParentRequest(
|
||||
return parentRequestId ? requestById.get(parentRequestId) ?? null : null;
|
||||
}
|
||||
|
||||
function resolveShareRequestLineage(
|
||||
request: ChatConversationRequest | null | undefined,
|
||||
requestById: ReadonlyMap<string, ChatConversationRequest>,
|
||||
) {
|
||||
const directParentRequest = resolveShareConversationParentRequest(request, requestById);
|
||||
|
||||
if (!directParentRequest) {
|
||||
return {
|
||||
directParentRequest: null,
|
||||
topParentRequest: null,
|
||||
};
|
||||
}
|
||||
|
||||
let currentRequest: ChatConversationRequest | null = directParentRequest;
|
||||
let topParentRequest: ChatConversationRequest | null = directParentRequest;
|
||||
const visitedRequestIds = new Set<string>();
|
||||
|
||||
while (currentRequest) {
|
||||
const currentRequestId = currentRequest.requestId.trim();
|
||||
|
||||
if (!currentRequestId || visitedRequestIds.has(currentRequestId)) {
|
||||
break;
|
||||
}
|
||||
|
||||
visitedRequestIds.add(currentRequestId);
|
||||
topParentRequest = currentRequest;
|
||||
currentRequest = resolveShareConversationParentRequest(currentRequest, requestById);
|
||||
}
|
||||
|
||||
return {
|
||||
directParentRequest,
|
||||
topParentRequest,
|
||||
};
|
||||
}
|
||||
|
||||
function buildSharePreviewItemsFromText(text: string, shareToken: string) {
|
||||
if (!shareToken) {
|
||||
return [];
|
||||
@@ -2936,7 +2998,11 @@ function ShareRequestCard({
|
||||
() => buildSharePreviewItemsFromText(request.userText, shareToken),
|
||||
[request.userText, shareToken],
|
||||
);
|
||||
const resolvedAnswerText = answerText.trim() || request.statusMessage?.trim() || '아직 답변이 없습니다.';
|
||||
const { directParentRequest, topParentRequest } = useMemo(
|
||||
() => resolveShareRequestLineage(request, requestById),
|
||||
[request, requestById],
|
||||
);
|
||||
const resolvedAnswerText = answerText.trim() || resolveShareRequestFallbackAnswerText(request);
|
||||
const shouldRenderQuestion = mode !== 'answer-only';
|
||||
const shouldRenderFullAnswer = mode === 'full' || mode === 'answer-only';
|
||||
const isRequestStillRunning = isRequestInFlight(request.status);
|
||||
@@ -2975,8 +3041,22 @@ function ShareRequestCard({
|
||||
&& !request.hasResponse
|
||||
&& request.status === 'queued';
|
||||
const retryCount = Math.max(0, Number(request.retryCount ?? 0) || 0);
|
||||
const hasQuestionLineage = Boolean(directParentRequest || topParentRequest);
|
||||
const questionActions = (
|
||||
<>
|
||||
{hasQuestionLineage && onOpenPreviousQuestion ? (
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="chat-share-page__message-action-button"
|
||||
icon={<CommentOutlined />}
|
||||
aria-label="부모 질의 보기"
|
||||
title="부모 질의 보기"
|
||||
onClick={() => {
|
||||
onOpenPreviousQuestion(request.requestId);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{canCancelDisconnectedRequest ? (
|
||||
<Button
|
||||
type="text"
|
||||
@@ -3239,7 +3319,7 @@ export function ChatSharePage() {
|
||||
const [pendingVerificationCompletionRequestIds, setPendingVerificationCompletionRequestIds] = useState<string[]>([]);
|
||||
const [pendingRequestCancellationIds, setPendingRequestCancellationIds] = useState<string[]>([]);
|
||||
const [pendingRequestRetryIds, setPendingRequestRetryIds] = useState<string[]>([]);
|
||||
const [isShareRoomListVisible, setIsShareRoomListVisible] = useState(true);
|
||||
const [isShareRoomListVisible, setIsShareRoomListVisible] = useState(false);
|
||||
const [isRoomSwitching, setIsRoomSwitching] = useState(false);
|
||||
const [replyReferenceRequestId, setReplyReferenceRequestId] = useState('');
|
||||
const [previousQuestionModalRequestId, setPreviousQuestionModalRequestId] = useState('');
|
||||
@@ -3283,6 +3363,12 @@ export function ChatSharePage() {
|
||||
const [optimisticShareRooms, setOptimisticShareRooms] = useState<ChatShareRoomSummary[]>([]);
|
||||
const [isRefreshingRoomNotificationStatus, setIsRefreshingRoomNotificationStatus] = useState(false);
|
||||
const [isSendingRoomNotificationTest, setIsSendingRoomNotificationTest] = useState(false);
|
||||
const [isDeletingRoom, setIsDeletingRoom] = useState(false);
|
||||
const [pendingDeleteRoomSessionId, setPendingDeleteRoomSessionId] = useState('');
|
||||
const [swipedRoomSessionId, setSwipedRoomSessionId] = useState('');
|
||||
const [draggingRoomSessionId, setDraggingRoomSessionId] = useState('');
|
||||
const [draggingRoomOffsetX, setDraggingRoomOffsetX] = useState(0);
|
||||
const [shareRoomFilterKeyword, setShareRoomFilterKeyword] = useState('');
|
||||
const [searchKeyword, setSearchKeyword] = useState('');
|
||||
const [searchPanelMode, setSearchPanelMode] = useState<ShareSearchPanelMode>('all');
|
||||
const [selectedAppEnvironment, setSelectedAppEnvironment] = useState<ShareAppEnvironment>(() =>
|
||||
@@ -3291,6 +3377,7 @@ export function ChatSharePage() {
|
||||
const [programTarget, setProgramTarget] = useState<ShareProgramTarget | null>(null);
|
||||
const [programMinimizedTarget, setProgramMinimizedTarget] = useState<ShareProgramTarget | null>(null);
|
||||
const [isProgramMinimized, setIsProgramMinimized] = useState(false);
|
||||
const [programReloadKey, setProgramReloadKey] = useState(0);
|
||||
const programMinimizedCardRef = useRef<HTMLDivElement | null>(null);
|
||||
const programMinimizedDragStateRef = useRef<{
|
||||
pointerId: number;
|
||||
@@ -3299,6 +3386,14 @@ export function ChatSharePage() {
|
||||
captureTarget: HTMLDivElement;
|
||||
} | null>(null);
|
||||
const programMinimizedMovedRef = useRef(false);
|
||||
const roomSwipeStartXRef = useRef<number | null>(null);
|
||||
const roomSwipeStartYRef = useRef<number | null>(null);
|
||||
const roomSwipeLockedSessionIdRef = useRef('');
|
||||
const roomSwipeStartEligibleRef = useRef(false);
|
||||
const roomSwipeMovedRef = useRef(false);
|
||||
const roomTouchScrollDetectedRef = useRef(false);
|
||||
const suppressRoomClickRef = useRef(false);
|
||||
const skipNextRoomClickSessionIdRef = useRef('');
|
||||
const programMinimizedPositionRef = useRef(getDefaultProgramMinimizedPosition());
|
||||
const [programMinimizedPosition, setProgramMinimizedPosition] = useState(() => programMinimizedPositionRef.current);
|
||||
const composerRef = useRef<TextAreaRef | null>(null);
|
||||
@@ -3348,6 +3443,30 @@ export function ChatSharePage() {
|
||||
() => shareRooms.find((item) => item.sessionId === selectedShareRoomSessionId) ?? null,
|
||||
[selectedShareRoomSessionId, shareRooms],
|
||||
);
|
||||
const filteredShareRooms = useMemo(() => {
|
||||
const keyword = shareRoomFilterKeyword.trim().toLowerCase();
|
||||
if (!keyword) {
|
||||
return shareRooms;
|
||||
}
|
||||
|
||||
return shareRooms.filter((room) => {
|
||||
const searchIndex = [
|
||||
room.title,
|
||||
room.contextLabel,
|
||||
room.requestBadgeLabel,
|
||||
room.sessionId,
|
||||
]
|
||||
.map((value) => value?.trim().toLowerCase() ?? '')
|
||||
.filter(Boolean)
|
||||
.join(' ');
|
||||
|
||||
return searchIndex.includes(keyword);
|
||||
});
|
||||
}, [shareRoomFilterKeyword, shareRooms]);
|
||||
const pendingDeleteRoom = useMemo(
|
||||
() => shareRooms.find((item) => item.sessionId === pendingDeleteRoomSessionId) ?? null,
|
||||
[pendingDeleteRoomSessionId, shareRooms],
|
||||
);
|
||||
useEffect(() => {
|
||||
if (optimisticShareRooms.length === 0 || !snapshot?.rooms?.length) {
|
||||
return;
|
||||
@@ -3831,6 +3950,111 @@ export function ChatSharePage() {
|
||||
setCreatingRoomSeedMessage('이 방에서 이어갈 작업 내용을 남겨 주세요. 필요한 파일이나 참고 문맥이 있으면 함께 적어 주세요.');
|
||||
setIsCreateRoomOpen(true);
|
||||
}, [currentSharedChatTypeId, enabledChatTypes]);
|
||||
const resetRoomSwipeState = useCallback(() => {
|
||||
roomSwipeStartXRef.current = null;
|
||||
roomSwipeStartYRef.current = null;
|
||||
roomSwipeLockedSessionIdRef.current = '';
|
||||
roomSwipeStartEligibleRef.current = false;
|
||||
roomSwipeMovedRef.current = false;
|
||||
roomTouchScrollDetectedRef.current = false;
|
||||
setDraggingRoomSessionId('');
|
||||
setDraggingRoomOffsetX(0);
|
||||
}, []);
|
||||
const handleRoomSwipeStart = useCallback((
|
||||
sessionId: string,
|
||||
clientX: number,
|
||||
clientY: number,
|
||||
swipeStartAllowed: boolean,
|
||||
) => {
|
||||
const targetRoom = shareRooms.find((room) => room.sessionId === sessionId);
|
||||
|
||||
if (isDeletingRoom || !targetRoom || !canDeleteShareRoom(targetRoom, shareRooms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
roomSwipeStartXRef.current = clientX;
|
||||
roomSwipeStartYRef.current = clientY;
|
||||
roomSwipeLockedSessionIdRef.current = sessionId;
|
||||
roomSwipeStartEligibleRef.current = swipeStartAllowed;
|
||||
roomSwipeMovedRef.current = false;
|
||||
roomTouchScrollDetectedRef.current = false;
|
||||
setDraggingRoomSessionId(sessionId);
|
||||
setDraggingRoomOffsetX(0);
|
||||
setSwipedRoomSessionId((current) => (current === sessionId ? sessionId : ''));
|
||||
}, [isDeletingRoom, shareRooms]);
|
||||
const handleRoomSwipeMove = useCallback((sessionId: string, clientX: number, clientY: number) => {
|
||||
if (
|
||||
roomSwipeLockedSessionIdRef.current !== sessionId
|
||||
|| roomSwipeStartXRef.current == null
|
||||
|| roomSwipeStartYRef.current == null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const deltaX = clientX - roomSwipeStartXRef.current;
|
||||
const deltaY = clientY - roomSwipeStartYRef.current;
|
||||
const absDeltaX = Math.abs(deltaX);
|
||||
const absDeltaY = Math.abs(deltaY);
|
||||
|
||||
if (absDeltaY <= SHARE_ROOM_TOUCH_TAP_SLOP_PX && absDeltaX <= SHARE_ROOM_TOUCH_TAP_SLOP_PX) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (absDeltaY >= SHARE_ROOM_TOUCH_SCROLL_CANCEL_PX && absDeltaY > absDeltaX) {
|
||||
roomTouchScrollDetectedRef.current = true;
|
||||
setSwipedRoomSessionId('');
|
||||
setDraggingRoomSessionId('');
|
||||
setDraggingRoomOffsetX(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (absDeltaX < SHARE_ROOM_SWIPE_ACTIVATION_PX || absDeltaX <= absDeltaY) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!roomSwipeStartEligibleRef.current) {
|
||||
setDraggingRoomSessionId(sessionId);
|
||||
setDraggingRoomOffsetX(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (deltaX >= 0) {
|
||||
setDraggingRoomSessionId(sessionId);
|
||||
setDraggingRoomOffsetX(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const nextOffset = Math.max(deltaX, -SHARE_ROOM_SWIPE_DELETE_LIMIT_PX);
|
||||
if (Math.abs(nextOffset) >= SHARE_ROOM_SWIPE_ACTIVATION_PX) {
|
||||
roomSwipeMovedRef.current = true;
|
||||
suppressRoomClickRef.current = true;
|
||||
}
|
||||
setDraggingRoomSessionId(sessionId);
|
||||
setDraggingRoomOffsetX(nextOffset);
|
||||
}, []);
|
||||
const handleRoomSwipeEnd = useCallback((sessionId: string) => {
|
||||
if (roomSwipeLockedSessionIdRef.current !== sessionId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (roomTouchScrollDetectedRef.current) {
|
||||
resetRoomSwipeState();
|
||||
setSwipedRoomSessionId('');
|
||||
window.setTimeout(() => {
|
||||
suppressRoomClickRef.current = false;
|
||||
}, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
const shouldRevealDelete = draggingRoomOffsetX <= -SHARE_ROOM_SWIPE_DELETE_THRESHOLD_PX;
|
||||
const wasSwipeGesture = roomSwipeMovedRef.current;
|
||||
resetRoomSwipeState();
|
||||
setSwipedRoomSessionId(shouldRevealDelete ? sessionId : '');
|
||||
window.setTimeout(() => {
|
||||
suppressRoomClickRef.current = false;
|
||||
}, 0);
|
||||
return !wasSwipeGesture && !shouldRevealDelete;
|
||||
}, [draggingRoomOffsetX, resetRoomSwipeState]);
|
||||
const refreshShareRuntime = useCallback(async (options?: { silent?: boolean }) => {
|
||||
if (!normalizedToken || !selectedShareRoomSessionId) {
|
||||
setShareRuntimeSnapshot(null);
|
||||
@@ -3957,6 +4181,74 @@ export function ChatSharePage() {
|
||||
snapshotRefreshPromiseRef.current = refreshTask;
|
||||
return refreshTask;
|
||||
}, [normalizedToken]);
|
||||
const handleDeleteShareRoom = useCallback(async (room: ChatShareRoomSummary) => {
|
||||
if (!normalizedToken || !room.sessionId || isDeletingRoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canDeleteShareRoom(room, shareRooms)) {
|
||||
message.warning(room.isDefault ? '기본 채팅방은 삭제할 수 없습니다.' : '마지막 채팅방은 삭제할 수 없습니다.');
|
||||
return;
|
||||
}
|
||||
|
||||
setIsDeletingRoom(true);
|
||||
|
||||
try {
|
||||
const result = await deleteChatShareRoom(normalizedToken, room.sessionId);
|
||||
const fallbackSessionId =
|
||||
result.nextRoomSessionId
|
||||
|| shareRooms.find((item) => item.sessionId !== room.sessionId)?.sessionId
|
||||
|| '';
|
||||
|
||||
setOptimisticShareRooms((current) => current.filter((item) => item.sessionId !== room.sessionId));
|
||||
setSnapshot((current) => {
|
||||
if (!current) {
|
||||
return current;
|
||||
}
|
||||
|
||||
const nextRooms = current.rooms.filter((item) => item.sessionId !== room.sessionId);
|
||||
const nextActiveSessionId =
|
||||
current.activeSessionId === room.sessionId
|
||||
? (result.nextRoomSessionId || nextRooms.find((item) => item.isDefault)?.sessionId || nextRooms[0]?.sessionId || '')
|
||||
: current.activeSessionId;
|
||||
|
||||
return {
|
||||
...current,
|
||||
rooms: nextRooms,
|
||||
activeSessionId: nextActiveSessionId,
|
||||
};
|
||||
});
|
||||
setPendingDeleteRoomSessionId('');
|
||||
setSwipedRoomSessionId('');
|
||||
requestedRoomSessionIdRef.current =
|
||||
requestedRoomSessionIdRef.current === room.sessionId ? fallbackSessionId : requestedRoomSessionIdRef.current;
|
||||
setRequestedRoomSessionId((current) => (current === room.sessionId ? fallbackSessionId : current));
|
||||
|
||||
if (selectedShareRoomSessionId === room.sessionId) {
|
||||
setDraftText('');
|
||||
setComposerAttachments([]);
|
||||
setReplyReferenceRequestId('');
|
||||
setLatestRequestId('');
|
||||
setExpandMode('pending');
|
||||
}
|
||||
|
||||
await refreshSnapshot({ silent: true });
|
||||
message.success(`"${room.title}" 채팅방을 삭제했습니다.`);
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '공유 채팅방 삭제 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
resetRoomSwipeState();
|
||||
setIsDeletingRoom(false);
|
||||
}
|
||||
}, [
|
||||
isDeletingRoom,
|
||||
message,
|
||||
normalizedToken,
|
||||
refreshSnapshot,
|
||||
resetRoomSwipeState,
|
||||
selectedShareRoomSessionId,
|
||||
shareRooms,
|
||||
]);
|
||||
const handleCancelShareRuntimeRequest = useCallback((item: ChatRuntimeJobItem) => {
|
||||
const actionLabel = item.status === 'queued' ? '대기 요청' : '실행 중 요청';
|
||||
|
||||
@@ -4448,6 +4740,10 @@ export function ChatSharePage() {
|
||||
window.location.reload();
|
||||
}, []);
|
||||
|
||||
const handleReloadProgram = useCallback(() => {
|
||||
setProgramReloadKey((current) => current + 1);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setAccessPinInput('');
|
||||
setAccessPinSubmitError('');
|
||||
@@ -4743,6 +5039,16 @@ export function ChatSharePage() {
|
||||
|
||||
setRequestedRoomSessionId('');
|
||||
}, [requestedRoomSessionId, shareRooms]);
|
||||
useEffect(() => {
|
||||
if (isDeletingRoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shareRooms.some((room) => room.sessionId === swipedRoomSessionId)) {
|
||||
setSwipedRoomSessionId('');
|
||||
resetRoomSwipeState();
|
||||
}
|
||||
}, [isDeletingRoom, resetRoomSwipeState, shareRooms, swipedRoomSessionId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') {
|
||||
@@ -5228,13 +5534,30 @@ export function ChatSharePage() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectShareRoom = useCallback((sessionId: string) => {
|
||||
const handleSelectShareRoom = useCallback((sessionId: string, options?: { bypassSuppression?: boolean }) => {
|
||||
const normalizedSessionId = sessionId.trim();
|
||||
const shouldBypassSuppression = options?.bypassSuppression === true;
|
||||
|
||||
if (!shouldBypassSuppression && skipNextRoomClickSessionIdRef.current === normalizedSessionId) {
|
||||
skipNextRoomClickSessionIdRef.current = '';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!shouldBypassSuppression && (suppressRoomClickRef.current || roomSwipeMovedRef.current)) {
|
||||
suppressRoomClickRef.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!normalizedSessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (swipedRoomSessionId === normalizedSessionId || draggingRoomSessionId === normalizedSessionId) {
|
||||
setSwipedRoomSessionId('');
|
||||
resetRoomSwipeState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (normalizedSessionId === selectedShareRoomSessionId) {
|
||||
setIsShareRoomListVisible(false);
|
||||
return;
|
||||
@@ -5244,7 +5567,7 @@ export function ChatSharePage() {
|
||||
setIsRoomSwitching(true);
|
||||
setRequestedRoomSessionId(normalizedSessionId);
|
||||
setIsShareRoomListVisible(false);
|
||||
}, [selectedShareRoomSessionId]);
|
||||
}, [draggingRoomSessionId, resetRoomSwipeState, selectedShareRoomSessionId, swipedRoomSessionId]);
|
||||
|
||||
const handleCreateShareRoom = useCallback(async () => {
|
||||
if (!normalizedToken || isCreatingRoom) {
|
||||
@@ -6013,17 +6336,35 @@ export function ChatSharePage() {
|
||||
|
||||
return summarizeShareReplyReferenceText(answerText || replyReferenceRequest.userText || '선택한 답변');
|
||||
}, [replyReferenceRequest, requestAnswerTextById]);
|
||||
const previousQuestionModalRequest = useMemo(
|
||||
const previousQuestionModalTargetRequest = useMemo(
|
||||
() => (previousQuestionModalRequestId.trim() ? requestById.get(previousQuestionModalRequestId.trim()) ?? null : null),
|
||||
[previousQuestionModalRequestId, requestById],
|
||||
);
|
||||
const previousQuestionModalText = useMemo(
|
||||
() => resolveShareRequestQuestionText(previousQuestionModalRequest),
|
||||
[previousQuestionModalRequest],
|
||||
const previousQuestionModalLineage = useMemo(
|
||||
() => resolveShareRequestLineage(previousQuestionModalTargetRequest, requestById),
|
||||
[previousQuestionModalTargetRequest, requestById],
|
||||
);
|
||||
const previousQuestionModalPreviewItems = useMemo(
|
||||
() => buildSharePreviewItemsFromText(previousQuestionModalRequest?.userText ?? '', normalizedToken),
|
||||
[normalizedToken, previousQuestionModalRequest?.userText],
|
||||
const previousQuestionModalDirectParent = previousQuestionModalLineage.directParentRequest;
|
||||
const previousQuestionModalTopParent =
|
||||
previousQuestionModalLineage.topParentRequest
|
||||
&& previousQuestionModalLineage.topParentRequest.requestId.trim() !== previousQuestionModalLineage.directParentRequest?.requestId.trim()
|
||||
? previousQuestionModalLineage.topParentRequest
|
||||
: null;
|
||||
const previousQuestionModalDirectParentText = useMemo(
|
||||
() => resolveShareRequestQuestionText(previousQuestionModalDirectParent),
|
||||
[previousQuestionModalDirectParent],
|
||||
);
|
||||
const previousQuestionModalTopParentText = useMemo(
|
||||
() => resolveShareRequestQuestionText(previousQuestionModalTopParent),
|
||||
[previousQuestionModalTopParent],
|
||||
);
|
||||
const previousQuestionModalDirectParentPreviewItems = useMemo(
|
||||
() => buildSharePreviewItemsFromText(previousQuestionModalDirectParent?.userText ?? '', normalizedToken),
|
||||
[normalizedToken, previousQuestionModalDirectParent?.userText],
|
||||
);
|
||||
const previousQuestionModalTopParentPreviewItems = useMemo(
|
||||
() => buildSharePreviewItemsFromText(previousQuestionModalTopParent?.userText ?? '', normalizedToken),
|
||||
[normalizedToken, previousQuestionModalTopParent?.userText],
|
||||
);
|
||||
const activityLogByRequestId = useMemo(
|
||||
() => new Map((snapshot?.activityLogs ?? []).map((item) => [item.requestId.trim(), item])),
|
||||
@@ -6164,6 +6505,7 @@ export function ChatSharePage() {
|
||||
}
|
||||
|
||||
recordShareAppLaunch(target.appId);
|
||||
setProgramReloadKey(0);
|
||||
setProgramTarget(target);
|
||||
setProgramMinimizedTarget(target);
|
||||
setIsProgramMinimized(false);
|
||||
@@ -7206,6 +7548,17 @@ export function ChatSharePage() {
|
||||
<div className={contentLayoutClassName}>
|
||||
{canToggleShareRoomList && isShareRoomListVisible ? (
|
||||
<section className="chat-share-page__panel chat-share-page__room-list-panel">
|
||||
<Input
|
||||
allowClear
|
||||
value={shareRoomFilterKeyword}
|
||||
onChange={(event) => {
|
||||
setShareRoomFilterKeyword(event.target.value);
|
||||
}}
|
||||
className="chat-share-page__room-filter-input"
|
||||
placeholder="채팅방 필터"
|
||||
prefix={<SearchOutlined />}
|
||||
aria-label="공유채팅 채팅방 필터"
|
||||
/>
|
||||
<div className="chat-share-page__section-head chat-share-page__section-head--compact">
|
||||
<div className="chat-share-page__section-copy">
|
||||
<Title level={5}>채팅방</Title>
|
||||
@@ -7220,28 +7573,97 @@ export function ChatSharePage() {
|
||||
) : null}
|
||||
</div>
|
||||
<div className="chat-share-page__room-list">
|
||||
{shareRooms.map((room) => {
|
||||
{filteredShareRooms.map((room) => {
|
||||
const isActive = room.sessionId === selectedShareRoomSessionId;
|
||||
const canDeleteRoom = canDeleteShareRoom(room, shareRooms);
|
||||
const isDeletingTarget = isDeletingRoom && pendingDeleteRoomSessionId === room.sessionId;
|
||||
|
||||
return (
|
||||
<button
|
||||
<div
|
||||
key={room.sessionId}
|
||||
type="button"
|
||||
className={`chat-share-page__room-card${isActive ? ' chat-share-page__room-card--active' : ''}`}
|
||||
onClick={() => {
|
||||
handleSelectShareRoom(room.sessionId);
|
||||
}}
|
||||
className={`chat-share-page__room-swipe ${
|
||||
swipedRoomSessionId === room.sessionId ? 'is-swiped' : ''
|
||||
} ${draggingRoomSessionId === room.sessionId ? 'is-dragging' : ''} ${
|
||||
canDeleteRoom ? '' : 'is-delete-locked'
|
||||
}`}
|
||||
>
|
||||
<span className="chat-share-page__room-card-head">
|
||||
<span className="chat-share-page__room-card-title">{room.title}</span>
|
||||
{room.isDefault ? <Tag color="blue">기본</Tag> : null}
|
||||
</span>
|
||||
<span className="chat-share-page__room-card-meta">
|
||||
{room.contextLabel?.trim() || room.requestBadgeLabel?.trim() || '공유 채팅방'}
|
||||
</span>
|
||||
</button>
|
||||
{canDeleteRoom ? (
|
||||
<button
|
||||
type="button"
|
||||
className="chat-share-page__room-delete-action"
|
||||
aria-label={`${room.title} 채팅방 삭제`}
|
||||
title={`${room.title} 채팅방 삭제`}
|
||||
disabled={isDeletingTarget}
|
||||
onClick={() => {
|
||||
setPendingDeleteRoomSessionId(room.sessionId);
|
||||
}}
|
||||
>
|
||||
<DeleteOutlined />
|
||||
</button>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className={`chat-share-page__room-card${isActive ? ' chat-share-page__room-card--active' : ''}${
|
||||
room.isDefault ? ' chat-share-page__room-card--default' : ''
|
||||
}`}
|
||||
style={{
|
||||
transform:
|
||||
draggingRoomSessionId === room.sessionId
|
||||
? `translate3d(${draggingRoomOffsetX}px, 0, 0)`
|
||||
: canDeleteRoom && swipedRoomSessionId === room.sessionId
|
||||
? `translate3d(-${SHARE_ROOM_SWIPE_DELETE_THRESHOLD_PX}px, 0, 0)`
|
||||
: undefined,
|
||||
}}
|
||||
onTouchStart={(event) => {
|
||||
const touch = event.changedTouches[0];
|
||||
const rect = event.currentTarget.getBoundingClientRect();
|
||||
handleRoomSwipeStart(
|
||||
room.sessionId,
|
||||
touch?.clientX ?? 0,
|
||||
touch?.clientY ?? 0,
|
||||
(touch?.clientX ?? 0) >= rect.right - SHARE_ROOM_SWIPE_START_EDGE_PX,
|
||||
);
|
||||
}}
|
||||
onTouchMove={(event) => {
|
||||
handleRoomSwipeMove(
|
||||
room.sessionId,
|
||||
event.changedTouches[0]?.clientX ?? 0,
|
||||
event.changedTouches[0]?.clientY ?? 0,
|
||||
);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
const shouldSelect = handleRoomSwipeEnd(room.sessionId);
|
||||
|
||||
if (shouldSelect) {
|
||||
skipNextRoomClickSessionIdRef.current = room.sessionId;
|
||||
handleSelectShareRoom(room.sessionId, { bypassSuppression: true });
|
||||
}
|
||||
}}
|
||||
onTouchCancel={() => {
|
||||
handleRoomSwipeEnd(room.sessionId);
|
||||
}}
|
||||
onClick={() => {
|
||||
handleSelectShareRoom(room.sessionId);
|
||||
}}
|
||||
>
|
||||
<span className="chat-share-page__room-card-head">
|
||||
<span className="chat-share-page__room-card-title">{room.title}</span>
|
||||
{room.isDefault ? <Tag color="cyan">기본 채팅</Tag> : null}
|
||||
</span>
|
||||
<span className="chat-share-page__room-card-meta">
|
||||
{room.isDefault
|
||||
? (room.contextLabel?.trim() || room.requestBadgeLabel?.trim() || '삭제할 수 없는 기본 채팅방')
|
||||
: (room.contextLabel?.trim() || room.requestBadgeLabel?.trim() || '공유 채팅방')}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{filteredShareRooms.length === 0 ? (
|
||||
<div className="chat-share-page__room-list-empty">
|
||||
<Text type="secondary">조건에 맞는 채팅방이 없습니다.</Text>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
@@ -7644,36 +8066,96 @@ export function ChatSharePage() {
|
||||
</div>
|
||||
) : null}
|
||||
<Modal
|
||||
open={Boolean(previousQuestionModalRequest)}
|
||||
title="부모 요청"
|
||||
footer={null}
|
||||
open={Boolean(pendingDeleteRoom)}
|
||||
title="공유 채팅방을 삭제할까요?"
|
||||
okText="삭제"
|
||||
cancelText="취소"
|
||||
okButtonProps={{ danger: true }}
|
||||
centered
|
||||
onCancel={() => {
|
||||
setPendingDeleteRoomSessionId('');
|
||||
}}
|
||||
onOk={async () => {
|
||||
if (!pendingDeleteRoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
await handleDeleteShareRoom(pendingDeleteRoom);
|
||||
}}
|
||||
>
|
||||
<Text>
|
||||
{pendingDeleteRoom
|
||||
? `"${pendingDeleteRoom.title}" 채팅방과 이 방의 요청·메시지 기록이 삭제됩니다.`
|
||||
: '선택한 공유 채팅방과 이 방의 요청·메시지 기록이 삭제됩니다.'}
|
||||
</Text>
|
||||
</Modal>
|
||||
<Modal
|
||||
open={Boolean(previousQuestionModalDirectParent || previousQuestionModalTopParent)}
|
||||
title="부모 질의"
|
||||
footer={null}
|
||||
className="chat-share-page__previous-question-modal-dialog"
|
||||
onCancel={() => {
|
||||
setPreviousQuestionModalRequestId('');
|
||||
}}
|
||||
>
|
||||
<div className="chat-share-page__previous-question-modal">
|
||||
<div className="chat-share-page__previous-question-modal-section">
|
||||
<Text strong>부모 요청</Text>
|
||||
<Text type="secondary">
|
||||
{previousQuestionModalRequest ? formatTimeLabel(previousQuestionModalRequest.createdAt) || '요청 시각 없음' : ''}
|
||||
</Text>
|
||||
<Paragraph className="chat-share-page__previous-question-modal-text">
|
||||
{previousQuestionModalText || '부모 요청 내용을 찾지 못했습니다.'}
|
||||
</Paragraph>
|
||||
{previousQuestionModalPreviewItems.length > 0 ? (
|
||||
<div className="chat-share-page__resource-list">
|
||||
{previousQuestionModalPreviewItems.map((item) => (
|
||||
<ShareResourcePreviewCard
|
||||
key={`previous-question-${item.id}`}
|
||||
item={item}
|
||||
shareToken={normalizedToken}
|
||||
onOpenProgram={openProgramTarget}
|
||||
/>
|
||||
))}
|
||||
{previousQuestionModalDirectParent ? (
|
||||
<div className="chat-share-page__previous-question-modal-section">
|
||||
<div className="chat-share-page__previous-question-modal-head">
|
||||
<Text strong>바로 상위 부모</Text>
|
||||
<Text type="secondary">
|
||||
{formatTimeLabel(previousQuestionModalDirectParent.createdAt) || '요청 시각 없음'}
|
||||
</Text>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<Paragraph className="chat-share-page__previous-question-modal-text">
|
||||
{previousQuestionModalDirectParentText || '부모 질의 내용을 찾지 못했습니다.'}
|
||||
</Paragraph>
|
||||
{previousQuestionModalDirectParentPreviewItems.length > 0 ? (
|
||||
<div className="chat-share-page__resource-list">
|
||||
{previousQuestionModalDirectParentPreviewItems.map((item) => (
|
||||
<ShareResourcePreviewCard
|
||||
key={`previous-question-direct-${item.id}`}
|
||||
item={item}
|
||||
shareToken={normalizedToken}
|
||||
onOpenProgram={openProgramTarget}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{previousQuestionModalTopParent ? (
|
||||
<div className="chat-share-page__previous-question-modal-section">
|
||||
<div className="chat-share-page__previous-question-modal-head">
|
||||
<Text strong>연결된 최상위 부모</Text>
|
||||
<Text type="secondary">
|
||||
{formatTimeLabel(previousQuestionModalTopParent.createdAt) || '요청 시각 없음'}
|
||||
</Text>
|
||||
</div>
|
||||
<Paragraph className="chat-share-page__previous-question-modal-text">
|
||||
{previousQuestionModalTopParentText || '최상위 부모 질의 내용을 찾지 못했습니다.'}
|
||||
</Paragraph>
|
||||
{previousQuestionModalTopParentPreviewItems.length > 0 ? (
|
||||
<div className="chat-share-page__resource-list">
|
||||
{previousQuestionModalTopParentPreviewItems.map((item) => (
|
||||
<ShareResourcePreviewCard
|
||||
key={`previous-question-top-${item.id}`}
|
||||
item={item}
|
||||
shareToken={normalizedToken}
|
||||
onOpenProgram={openProgramTarget}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
{!previousQuestionModalDirectParent && !previousQuestionModalTopParent ? (
|
||||
<div className="chat-share-page__previous-question-modal-section">
|
||||
<Paragraph className="chat-share-page__previous-question-modal-text">
|
||||
부모 질의 내용을 찾지 못했습니다.
|
||||
</Paragraph>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal
|
||||
@@ -8400,6 +8882,18 @@ export function ChatSharePage() {
|
||||
open={Boolean(programTarget) && !isProgramMinimized}
|
||||
title={programTarget?.label ?? '공유 프로그램'}
|
||||
meta={programTarget?.meta ?? '공유 토큰 실행'}
|
||||
actions={
|
||||
programTarget ? (
|
||||
<Button
|
||||
type="text"
|
||||
className="fullscreen-preview-modal__icon-button"
|
||||
aria-label="앱 새로고침"
|
||||
title="앱 새로고침"
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={handleReloadProgram}
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
zIndex={SHARE_PROGRAM_MODAL_Z_INDEX}
|
||||
maskClosable={false}
|
||||
hideHeader={false}
|
||||
@@ -8413,23 +8907,28 @@ export function ChatSharePage() {
|
||||
>
|
||||
{programTarget ? (
|
||||
embeddedPlayAppContent ? (
|
||||
<div className="chat-share-page__program-app-shell">
|
||||
<div key={`${programTarget.key}:${programReloadKey}`} className="chat-share-page__program-app-shell">
|
||||
{embeddedPlayAppContent}
|
||||
</div>
|
||||
) : programTarget.appId && findReadyPlayAppEntryById(programTarget.appId) ? (
|
||||
<iframe
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
title={programTarget.label}
|
||||
src={programTarget.url}
|
||||
className="app-chat-panel__preview-frame"
|
||||
/>
|
||||
) : programTarget.appId === SHARE_CURRENT_CHAT_APP_ID ? (
|
||||
<iframe
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
title={programTarget.label}
|
||||
src={programTarget.url}
|
||||
className="app-chat-panel__preview-frame"
|
||||
/>
|
||||
) : programTarget.appId === 'text-memo-widget' ? (
|
||||
<div className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface">
|
||||
<div
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface"
|
||||
>
|
||||
<Suspense
|
||||
fallback={(
|
||||
<div className="chat-share-page__program-app-loading" role="status" aria-live="polite">
|
||||
@@ -8441,7 +8940,10 @@ export function ChatSharePage() {
|
||||
</Suspense>
|
||||
</div>
|
||||
) : programTarget.appId === 'token-setting' ? (
|
||||
<div className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface">
|
||||
<div
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface"
|
||||
>
|
||||
<TokenSettingManagementPage
|
||||
sharedPreviewTokenSetting={shareTokenSetting}
|
||||
sharedAccess={
|
||||
@@ -8455,7 +8957,10 @@ export function ChatSharePage() {
|
||||
/>
|
||||
</div>
|
||||
) : programTarget.appId === 'shared-resource' ? (
|
||||
<div className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface">
|
||||
<div
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface"
|
||||
>
|
||||
<SharedResourceManagementPage
|
||||
disableInstallMetadata
|
||||
sharedPreview={{
|
||||
@@ -8475,26 +8980,34 @@ export function ChatSharePage() {
|
||||
/>
|
||||
</div>
|
||||
) : programTarget.appId === 'app-settings' ? (
|
||||
<div className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface">
|
||||
<div
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface"
|
||||
>
|
||||
<SharedAppSettingsPage shareToken={normalizedToken} />
|
||||
</div>
|
||||
) : programTarget.appId === 'server-command' ? (
|
||||
<div className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface">
|
||||
<div
|
||||
key={`${programTarget.key}:${programReloadKey}`}
|
||||
className="chat-share-page__program-app-shell chat-share-page__program-app-shell--surface"
|
||||
>
|
||||
<ServerCommandPage sharedAccess={sharedServerCommandAccess} />
|
||||
</div>
|
||||
) : (
|
||||
<ChatPreviewBody
|
||||
target={{
|
||||
label: programTarget.label,
|
||||
url: programTarget.url,
|
||||
kind: programTarget.kind,
|
||||
}}
|
||||
previewText=""
|
||||
isPreviewLoading={false}
|
||||
previewError=""
|
||||
renderHtmlAsFrame
|
||||
fullscreen
|
||||
/>
|
||||
<div key={`${programTarget.key}:${programReloadKey}`} className="chat-share-page__program-app-shell">
|
||||
<ChatPreviewBody
|
||||
target={{
|
||||
label: programTarget.label,
|
||||
url: programTarget.url,
|
||||
kind: programTarget.kind,
|
||||
}}
|
||||
previewText=""
|
||||
isPreviewLoading={false}
|
||||
previewError=""
|
||||
renderHtmlAsFrame
|
||||
fullscreen
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
) : null}
|
||||
</FullscreenPreviewModal>
|
||||
|
||||
Reference in New Issue
Block a user