chore: test deploy snapshot

This commit is contained in:
2026-05-28 16:11:33 +09:00
parent b1bec9cb6f
commit a97d933cff
2 changed files with 163 additions and 128 deletions

View File

@@ -2463,11 +2463,57 @@
.app-chat-preview-card--prompt .app-chat-preview-card__actions {
flex: 0 0 auto;
min-width: fit-content;
min-width: 0;
max-width: 100%;
flex-wrap: nowrap;
margin-left: auto;
}
@media (max-width: 720px) {
.app-chat-preview-card--prompt .app-chat-preview-card__header {
align-items: flex-start;
flex-wrap: wrap;
}
.app-chat-preview-card--prompt .app-chat-preview-card__actions {
width: 100%;
flex: 1 1 100%;
justify-content: flex-start;
flex-wrap: wrap;
gap: 6px;
margin-left: 0;
}
.app-chat-prompt-card__submitted {
max-width: 100%;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.app-chat-prompt-card__selection-pill {
max-width: 100%;
white-space: normal;
overflow-wrap: anywhere;
word-break: break-word;
}
.app-chat-prompt-card__step-header {
flex-wrap: wrap;
}
.app-chat-prompt-card__preview-toolbar {
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
min-height: 0;
}
.app-chat-prompt-card__preview-title.ant-typography {
flex: 1 1 100%;
}
}
.app-chat-prompt-card__preview-modal.ant-modal {
background:
linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(226, 232, 240, 0.98)),

View File

@@ -173,6 +173,9 @@ type ShareSearchResult = {
value: string;
};
};
type ShareSearchIndexedResult = ShareSearchResult & {
searchText: string;
};
type ShareSearchPanelMode = 'all' | 'apps';
type ShareWorkServerVersionStatus = 'latest' | 'unknown' | 'update-available' | 'build-required';
type ClientNotificationPermissionState = 'unsupported' | 'default' | 'granted' | 'denied';
@@ -1923,6 +1926,10 @@ function matchesSearchKeyword(keyword: string, ...values: Array<string | null |
return values.some((value) => normalizeSearchKeyword(value ?? '').includes(keyword));
}
function buildSearchKeywordText(...values: Array<string | null | undefined>) {
return normalizeSearchKeyword(values.filter(Boolean).join(' '));
}
function buildSharePromptSelectionKey(parentRequestId: string, sourceMessageId: number, promptIndex: number, promptTitle: string, promptSignature: string) {
return [parentRequestId.trim(), sourceMessageId, promptIndex, promptTitle.trim(), promptSignature.trim()].join('::');
}
@@ -8379,110 +8386,26 @@ export function ChatSharePage() {
? renderEmbeddedSharePlayApp(programTarget.appId, closeProgramTarget, normalizedToken)
: null;
const isServerCommandDrawerOpen = programTarget?.appId === 'server-command';
const searchResults = useMemo<ShareSearchResult[]>(() => {
const keyword = normalizeSearchKeyword(searchKeyword);
const results: ShareSearchResult[] = [];
if (searchPanelMode === 'apps') {
const photoprismLauncher = buildPhotoPrismProgramTarget();
if (
matchesSearchKeyword(
keyword,
currentShareChatTarget.label,
currentShareChatTarget.appId,
'공유채팅',
'현재 토큰',
'현재 공유토큰 열기',
...APPS_LAUNCHER_SEARCH_TERMS,
)
) {
results.push({
key: `management-app:${SHARE_CURRENT_CHAT_APP_ID}`,
title: currentShareChatTarget.label,
description: `현재 공유토큰을 ${selectedAppEnvironment} 환경에서 다시 엽니다.`,
category: 'resource',
icon: <CommentOutlined />,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[SHARE_CURRENT_CHAT_APP_ID]),
resource: currentShareChatTarget,
});
}
sortedAllowedManagementApps.forEach((item) => {
if (!matchesSearchKeyword(keyword, item.value, item.label, item.description, ...APPS_LAUNCHER_SEARCH_TERMS)) {
return;
}
results.push({
key: `management-app:${item.value}`,
title: item.label,
description: item.description,
category: 'resource',
icon: item.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[item.value]),
resource: buildShareManagementProgramTarget(item.value, item.label),
});
});
sortedAllowedPlayAppEntries.forEach((entry) => {
if (
!matchesSearchKeyword(
keyword,
entry.id,
entry.name,
entry.searchDescription,
...APPS_LAUNCHER_SEARCH_TERMS,
...(entry.searchKeywords ?? []),
)
) {
return;
}
results.push({
key: `app:${entry.id}`,
title: entry.name,
description: resolveSupportedEnvironmentSummary(entry),
category: 'resource',
icon: entry.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[entry.id]),
appEntry: entry,
resource:
entry.id === 'photoprism'
? photoprismLauncher
: buildPlayAppProgramTarget(entry.id, entry.name),
});
});
return results;
}
if (!keyword) {
return results;
}
const indexedContentSearchResults = useMemo<ShareSearchIndexedResult[]>(() => {
const results: ShareSearchIndexedResult[] = [];
sortedRequests.forEach((request) => {
const requestText = buildShareVisibleText(request.userText);
if (matchesSearchKeyword(keyword, requestText, request.statusMessage, request.requestId)) {
results.push({
key: `request:${request.requestId}`,
title: requestText || '질문',
description: `질문 · ${formatTimeLabel(request.createdAt)}`,
category: 'request',
requestId: request.requestId,
scrollTarget: {
type: 'request',
value: request.requestId,
},
});
}
results.push({
key: `request:${request.requestId}`,
title: requestText || '질문',
description: `질문 · ${formatTimeLabel(request.createdAt)}`,
category: 'request',
requestId: request.requestId,
scrollTarget: {
type: 'request',
value: request.requestId,
},
searchText: buildSearchKeywordText(requestText, request.statusMessage, request.requestId),
});
buildSharePreviewItemsFromText(request.userText, normalizedToken).forEach((item) => {
if (!matchesSearchKeyword(keyword, item.label, item.url, item.kind)) {
return;
}
const scopedUrl = resolveShareScopedResourceUrl(item.url, normalizedToken);
results.push({
key: `request-resource:${request.requestId}:${item.id}`,
title: item.label,
@@ -8492,7 +8415,7 @@ export function ChatSharePage() {
resource: {
key: `request-resource:${request.requestId}:${item.id}`,
label: item.label,
url: scopedUrl,
url: item.url,
kind: item.kind,
meta: `${item.kind} resource`,
},
@@ -8500,6 +8423,7 @@ export function ChatSharePage() {
type: 'request',
value: request.requestId,
},
searchText: buildSearchKeywordText(item.label, item.url, item.kind),
});
});
});
@@ -8509,25 +8433,20 @@ export function ChatSharePage() {
const visibleText = buildVisibleMessageText(entry, payload);
const requestId = entry.clientRequestId?.trim() || snapshot?.rootRequestId?.trim() || '';
if (matchesSearchKeyword(keyword, visibleText, entry.author, requestId)) {
results.push({
key: `response:${entry.id}`,
title: visibleText || '응답',
description: `${entry.author === 'user' ? '질문 메시지' : '응답'} · ${formatTimeLabel(entry.timestamp)}`,
category: 'response',
requestId: requestId || undefined,
scrollTarget: {
type: 'response',
value: String(entry.id),
},
});
}
results.push({
key: `response:${entry.id}`,
title: visibleText || '응답',
description: `${entry.author === 'user' ? '질문 메시지' : '응답'} · ${formatTimeLabel(entry.timestamp)}`,
category: 'response',
requestId: requestId || undefined,
scrollTarget: {
type: 'response',
value: String(entry.id),
},
searchText: buildSearchKeywordText(visibleText, entry.author, requestId),
});
(payload?.promptParts ?? []).forEach((prompt, promptIndex) => {
if (!matchesSearchKeyword(keyword, buildSharePromptSearchText(prompt), requestId, entry.id)) {
return;
}
results.push({
key: `prompt:${entry.id}:${promptIndex}`,
title: prompt.title || 'prompt',
@@ -8538,15 +8457,15 @@ export function ChatSharePage() {
type: 'prompt',
value: buildSharePromptAnchorKey(entry.id, promptIndex),
},
searchText: buildSearchKeywordText(buildSharePromptSearchText(prompt), requestId, String(entry.id)),
});
});
(payload?.previewItems ?? []).forEach((item) => {
if (!requestId || !matchesSearchKeyword(keyword, item.label, item.url, item.kind)) {
if (!requestId) {
return;
}
const scopedUrl = resolveShareScopedResourceUrl(item.url, normalizedToken);
results.push({
key: `response-resource:${entry.id}:${item.id}`,
title: item.label,
@@ -8556,7 +8475,7 @@ export function ChatSharePage() {
resource: {
key: `response-resource:${entry.id}:${item.id}`,
label: item.label,
url: scopedUrl,
url: resolveShareScopedResourceUrl(item.url, normalizedToken),
kind: item.kind,
meta: `${item.kind} resource`,
},
@@ -8564,6 +8483,7 @@ export function ChatSharePage() {
type: 'response',
value: String(entry.id),
},
searchText: buildSearchKeywordText(item.label, item.url, item.kind),
});
});
});
@@ -8571,10 +8491,6 @@ export function ChatSharePage() {
(snapshot?.activityLogs ?? []).forEach((activity, index) => {
const summary = summarizeActivityLogLines(activity.lines ?? []).join(' ');
if (!matchesSearchKeyword(keyword, activity.requestId, summary)) {
return;
}
results.push({
key: `activity:${activity.requestId}:${index}`,
title: summary || `활동 로그 ${index + 1}`,
@@ -8585,13 +8501,86 @@ export function ChatSharePage() {
type: 'activity',
value: 'chat-share-activity-panel',
},
searchText: buildSearchKeywordText(activity.requestId, summary),
});
});
return results
.filter((item) => !item.scrollTarget || item.scrollTarget.value.trim())
.slice(0, 40);
}, [appLaunchUsage, currentShareChatTarget, messageRenderPayloadById, normalizedToken, searchKeyword, searchPanelMode, selectedAppEnvironment, snapshot?.activityLogs, snapshot?.rootRequestId, sortedAllowedManagementApps, sortedAllowedPlayAppEntries, sortedMessages, sortedRequests]);
return results.filter((item) => !item.scrollTarget || item.scrollTarget.value.trim());
}, [messageRenderPayloadById, normalizedToken, snapshot?.activityLogs, snapshot?.rootRequestId, sortedMessages, sortedRequests]);
const indexedAppSearchResults = useMemo<ShareSearchIndexedResult[]>(() => {
const results: ShareSearchIndexedResult[] = [];
const photoprismLauncher = buildPhotoPrismProgramTarget();
results.push({
key: `management-app:${SHARE_CURRENT_CHAT_APP_ID}`,
title: currentShareChatTarget.label,
description: `현재 공유토큰을 ${selectedAppEnvironment} 환경에서 다시 엽니다.`,
category: 'resource',
icon: <CommentOutlined />,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[SHARE_CURRENT_CHAT_APP_ID]),
resource: currentShareChatTarget,
searchText: buildSearchKeywordText(
currentShareChatTarget.label,
currentShareChatTarget.appId,
'공유채팅',
'현재 토큰',
'현재 공유토큰 열기',
...APPS_LAUNCHER_SEARCH_TERMS,
),
});
sortedAllowedManagementApps.forEach((item) => {
results.push({
key: `management-app:${item.value}`,
title: item.label,
description: item.description,
category: 'resource',
icon: item.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[item.value]),
resource: buildShareManagementProgramTarget(item.value, item.label),
searchText: buildSearchKeywordText(item.value, item.label, item.description, ...APPS_LAUNCHER_SEARCH_TERMS),
});
});
sortedAllowedPlayAppEntries.forEach((entry) => {
results.push({
key: `app:${entry.id}`,
title: entry.name,
description: resolveSupportedEnvironmentSummary(entry),
category: 'resource',
icon: entry.icon,
usageBadge: resolveShareAppUsageBadge(appLaunchUsage[entry.id]),
appEntry: entry,
resource:
entry.id === 'photoprism'
? photoprismLauncher
: buildPlayAppProgramTarget(entry.id, entry.name),
searchText: buildSearchKeywordText(
entry.id,
entry.name,
entry.searchDescription,
...APPS_LAUNCHER_SEARCH_TERMS,
...(entry.searchKeywords ?? []),
),
});
});
return results;
}, [appLaunchUsage, currentShareChatTarget, selectedAppEnvironment, sortedAllowedManagementApps, sortedAllowedPlayAppEntries]);
const searchResults = useMemo<ShareSearchResult[]>(() => {
const keyword = normalizeSearchKeyword(searchKeyword);
const source = searchPanelMode === 'apps' ? indexedAppSearchResults : indexedContentSearchResults;
if (searchPanelMode !== 'apps' && !keyword) {
return [];
}
const filtered = keyword
? source.filter((item) => item.searchText.includes(keyword))
: source;
return filtered.slice(0, 40).map(({ searchText: _searchText, ...result }) => result);
}, [indexedAppSearchResults, indexedContentSearchResults, searchKeyword, searchPanelMode]);
const selectedTokenUsageSetting = shareTokenSetting;
const tokenUsageSummaryByPeriod = useMemo(
() =>