156 lines
5.7 KiB
TypeScript
156 lines
5.7 KiB
TypeScript
export const ISOLATED_CHAT_ROOM_SESSION_PREFIX = 'chat-room-menu-';
|
|
export const MANAGED_CHAT_SHARE_SESSION_PREFIX = 'chat-share-room-';
|
|
|
|
export type IsolatedChatRoomScope = {
|
|
topMenu: string;
|
|
menuTitle: string;
|
|
featureTitle: string;
|
|
focusedComponentId: string | null;
|
|
pageUrl: string;
|
|
selectionSummary?: string | null;
|
|
selectionIds?: string[];
|
|
errorSummary?: string | null;
|
|
sourceAppId?: string | null;
|
|
launchedAt: string;
|
|
};
|
|
|
|
export type MainChatPanelMode = 'live' | 'rooms';
|
|
|
|
export function isIsolatedChatRoomSessionId(sessionId: string | null | undefined) {
|
|
return String(sessionId ?? '').trim().startsWith(ISOLATED_CHAT_ROOM_SESSION_PREFIX);
|
|
}
|
|
|
|
export function isManagedChatShareSessionId(sessionId: string | null | undefined) {
|
|
return String(sessionId ?? '').trim().startsWith(MANAGED_CHAT_SHARE_SESSION_PREFIX);
|
|
}
|
|
|
|
export function createIsolatedChatRoomSessionId() {
|
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
return `${ISOLATED_CHAT_ROOM_SESSION_PREFIX}${crypto.randomUUID()}`;
|
|
}
|
|
|
|
return `${ISOLATED_CHAT_ROOM_SESSION_PREFIX}${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
}
|
|
|
|
export function shouldShowConversationForMode(sessionId: string, mode: MainChatPanelMode) {
|
|
const isIsolatedRoom = isIsolatedChatRoomSessionId(sessionId);
|
|
const isManagedShareRoom = isManagedChatShareSessionId(sessionId);
|
|
return mode === 'rooms' ? isIsolatedRoom || isManagedShareRoom : !isIsolatedRoom && !isManagedShareRoom;
|
|
}
|
|
|
|
export function resolveChatPathForSession(sessionId: string) {
|
|
return isIsolatedChatRoomSessionId(sessionId) || isManagedChatShareSessionId(sessionId) ? '/chat/rooms' : '/chat/live';
|
|
}
|
|
|
|
export function normalizeIsolatedChatRoomScope(
|
|
scope: Partial<IsolatedChatRoomScope> | null | undefined,
|
|
): IsolatedChatRoomScope | null {
|
|
if (!scope) {
|
|
return null;
|
|
}
|
|
|
|
const menuTitle = String(scope.menuTitle ?? '').trim();
|
|
const featureTitle = String(scope.featureTitle ?? '').trim();
|
|
const pageUrl = String(scope.pageUrl ?? '').trim();
|
|
|
|
if (!menuTitle && !featureTitle && !pageUrl) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
topMenu: String(scope.topMenu ?? '').trim() || 'unknown',
|
|
menuTitle: menuTitle || '현재 메뉴',
|
|
featureTitle: featureTitle || menuTitle || '현재 기능',
|
|
focusedComponentId: String(scope.focusedComponentId ?? '').trim() || null,
|
|
pageUrl,
|
|
selectionSummary: String(scope.selectionSummary ?? '').trim() || null,
|
|
selectionIds: Array.isArray(scope.selectionIds)
|
|
? scope.selectionIds.map((item) => String(item).trim()).filter(Boolean)
|
|
: [],
|
|
errorSummary: String(scope.errorSummary ?? '').trim() || null,
|
|
sourceAppId: String(scope.sourceAppId ?? '').trim() || null,
|
|
launchedAt: String(scope.launchedAt ?? '').trim() || new Date().toISOString(),
|
|
};
|
|
}
|
|
|
|
export function buildIsolatedChatRoomTitle(scope: IsolatedChatRoomScope | null | undefined) {
|
|
if (!scope) {
|
|
return '격리 채팅방';
|
|
}
|
|
|
|
return `${scope.menuTitle} · ${scope.featureTitle}`.trim();
|
|
}
|
|
|
|
export function buildIsolatedChatRoomRequestBadgeLabel(scope: IsolatedChatRoomScope | null | undefined) {
|
|
if (!scope) {
|
|
return '격리 요청';
|
|
}
|
|
|
|
return scope.focusedComponentId?.trim() || scope.featureTitle || scope.menuTitle || '격리 요청';
|
|
}
|
|
|
|
export function buildIsolatedChatRoomContextSupplement(scope: IsolatedChatRoomScope | null | undefined) {
|
|
if (!scope) {
|
|
return '';
|
|
}
|
|
|
|
const lines = [
|
|
'## 격리 채팅방 범위',
|
|
`- 현재 활성 메뉴: ${scope.menuTitle}`,
|
|
`- 현재 기능: ${scope.featureTitle}`,
|
|
`- topMenu: ${scope.topMenu || '없음'}`,
|
|
`- focusedComponentId: ${scope.focusedComponentId || '없음'}`,
|
|
`- pageUrl: ${scope.pageUrl || '없음'}`,
|
|
];
|
|
|
|
if (scope.selectionSummary) {
|
|
lines.push(`- 현재 선택: ${scope.selectionSummary}`);
|
|
}
|
|
|
|
if (scope.selectionIds && scope.selectionIds.length > 0) {
|
|
lines.push(`- 선택 ID: ${scope.selectionIds.join(', ')}`);
|
|
}
|
|
|
|
if (scope.errorSummary) {
|
|
lines.push('');
|
|
lines.push('## 최근 참조 에러');
|
|
lines.push(scope.errorSummary);
|
|
}
|
|
|
|
return lines.join('\n').trim();
|
|
}
|
|
|
|
function normalizeScopeCompareValue(value: string | null | undefined) {
|
|
return String(value ?? '').trim();
|
|
}
|
|
|
|
function normalizeScopeSelectionIds(value: string[] | null | undefined) {
|
|
return (value ?? []).map((item) => String(item).trim()).filter(Boolean).sort();
|
|
}
|
|
|
|
export function doesIsolatedChatRoomScopeMatch(
|
|
left: IsolatedChatRoomScope | null | undefined,
|
|
right: IsolatedChatRoomScope | null | undefined,
|
|
) {
|
|
const normalizedLeft = normalizeIsolatedChatRoomScope(left);
|
|
const normalizedRight = normalizeIsolatedChatRoomScope(right);
|
|
|
|
if (!normalizedLeft || !normalizedRight) {
|
|
return false;
|
|
}
|
|
|
|
const leftSelectionIds = normalizeScopeSelectionIds(normalizedLeft.selectionIds);
|
|
const rightSelectionIds = normalizeScopeSelectionIds(normalizedRight.selectionIds);
|
|
|
|
return (
|
|
normalizeScopeCompareValue(normalizedLeft.sourceAppId) === normalizeScopeCompareValue(normalizedRight.sourceAppId) &&
|
|
normalizeScopeCompareValue(normalizedLeft.topMenu) === normalizeScopeCompareValue(normalizedRight.topMenu) &&
|
|
normalizeScopeCompareValue(normalizedLeft.menuTitle) === normalizeScopeCompareValue(normalizedRight.menuTitle) &&
|
|
normalizeScopeCompareValue(normalizedLeft.featureTitle) === normalizeScopeCompareValue(normalizedRight.featureTitle) &&
|
|
normalizeScopeCompareValue(normalizedLeft.focusedComponentId) === normalizeScopeCompareValue(normalizedRight.focusedComponentId) &&
|
|
normalizeScopeCompareValue(normalizedLeft.pageUrl) === normalizeScopeCompareValue(normalizedRight.pageUrl) &&
|
|
leftSelectionIds.length === rightSelectionIds.length &&
|
|
leftSelectionIds.every((item, index) => item === rightSelectionIds[index])
|
|
);
|
|
}
|