@memberjunction/ng-conversations 5.49.0 → 5.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +64 -3
  2. package/dist/lib/components/collection/collections-full-view.component.d.ts +10 -0
  3. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  4. package/dist/lib/components/collection/collections-full-view.component.js +74 -14
  5. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  6. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +31 -5
  7. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  8. package/dist/lib/components/conversation/conversation-chat-area.component.js +169 -101
  9. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  10. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts +5 -1
  11. package/dist/lib/components/conversation/conversation-empty-state.component.d.ts.map +1 -1
  12. package/dist/lib/components/conversation/conversation-empty-state.component.js +13 -3
  13. package/dist/lib/components/conversation/conversation-empty-state.component.js.map +1 -1
  14. package/dist/lib/components/conversation/conversation-list.component.d.ts +16 -1
  15. package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
  16. package/dist/lib/components/conversation/conversation-list.component.js +439 -351
  17. package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
  18. package/dist/lib/components/export/export-modal.component.d.ts +25 -3
  19. package/dist/lib/components/export/export-modal.component.d.ts.map +1 -1
  20. package/dist/lib/components/export/export-modal.component.js +172 -34
  21. package/dist/lib/components/export/export-modal.component.js.map +1 -1
  22. package/dist/lib/components/message/message-input.component.d.ts +4 -1
  23. package/dist/lib/components/message/message-input.component.d.ts.map +1 -1
  24. package/dist/lib/components/message/message-input.component.js +15 -3
  25. package/dist/lib/components/message/message-input.component.js.map +1 -1
  26. package/dist/lib/components/message/message-item.component.d.ts +46 -1
  27. package/dist/lib/components/message/message-item.component.d.ts.map +1 -1
  28. package/dist/lib/components/message/message-item.component.js +295 -201
  29. package/dist/lib/components/message/message-item.component.js.map +1 -1
  30. package/dist/lib/components/message/message-list.component.d.ts +19 -1
  31. package/dist/lib/components/message/message-list.component.d.ts.map +1 -1
  32. package/dist/lib/components/message/message-list.component.js +55 -1
  33. package/dist/lib/components/message/message-list.component.js.map +1 -1
  34. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts +14 -1
  35. package/dist/lib/components/sidebar/conversation-sidebar.component.d.ts.map +1 -1
  36. package/dist/lib/components/sidebar/conversation-sidebar.component.js +38 -5
  37. package/dist/lib/components/sidebar/conversation-sidebar.component.js.map +1 -1
  38. package/dist/lib/components/slots/slot-interfaces.d.ts +23 -1
  39. package/dist/lib/components/slots/slot-interfaces.d.ts.map +1 -1
  40. package/dist/lib/components/slots/slot-interfaces.js.map +1 -1
  41. package/dist/lib/directives/chat-slot.directive.d.ts +10 -2
  42. package/dist/lib/directives/chat-slot.directive.d.ts.map +1 -1
  43. package/dist/lib/directives/chat-slot.directive.js.map +1 -1
  44. package/dist/lib/models/lazy-artifact-info.d.ts +8 -7
  45. package/dist/lib/models/lazy-artifact-info.d.ts.map +1 -1
  46. package/dist/lib/models/lazy-artifact-info.js +12 -11
  47. package/dist/lib/models/lazy-artifact-info.js.map +1 -1
  48. package/dist/lib/services/export.service.d.ts +149 -0
  49. package/dist/lib/services/export.service.d.ts.map +1 -1
  50. package/dist/lib/services/export.service.js +270 -36
  51. package/dist/lib/services/export.service.js.map +1 -1
  52. package/package.json +29 -29
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-list.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, HostListener, ChangeDetectorRef } from '@angular/core';\nimport { UserInfo } from '@memberjunction/core';\nimport { MJConversationEntity, MJProjectEntity, ConversationEngine, UserInfoEngine } from '@memberjunction/core-entities';\nimport { MJDialogService } from '@memberjunction/ng-ui-components';\nimport { DialogService } from '../../services/dialog.service';\nimport { NotificationService } from '../../services/notification.service';\nimport { ActiveTasksService } from '../../services/active-tasks.service';\nimport { ProjectFormModalComponent } from '../project/project-form-modal.component';\nimport { ConversationGroupBy } from '../../models/conversation-state.model';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';\n\n/**\n * A node in the conversation folder tree. Each node holds its project (folder),\n * the conversations directly assigned to it, and its nested child folders.\n */\ninterface FolderNode {\n project: MJProjectEntity;\n depth: number;\n /** Conversations directly in this folder (unpinned only — pinned live in the Pinned section). */\n conversations: MJConversationEntity[];\n children: FolderNode[];\n /** Total conversations in this folder and all descendants. */\n totalCount: number;\n /** True when this folder or any descendant has at least one (filtered) conversation. */\n hasContent: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-list',\n template: `\n <div class=\"conversation-list\">\n <div class=\"list-header\">\n <div class=\"header-top\">\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search conversations...\"\n [(ngModel)]=\"searchQuery\">\n @if (!isSelectionMode) {\n <div class=\"header-menu-container\">\n <button class=\"btn-menu\" (click)=\"toggleHeaderMenu($event)\" title=\"Options\">\n <i class=\"fas fa-ellipsis-v\"></i>\n </button>\n @if (isHeaderMenuOpen) {\n <div class=\"header-dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"onRefreshConversationsClick($event)\" [disabled]=\"isRefreshing\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"isRefreshing\"></i>\n <span>{{ isRefreshing ? 'Refreshing...' : 'Refresh' }}</span>\n </button>\n <button class=\"dropdown-item\" (click)=\"onSelectConversationsClick($event)\">\n <i class=\"fas fa-check-square\"></i>\n <span>Select Conversations</span>\n </button>\n <button class=\"dropdown-item\" (click)=\"onToggleGroupByClick($event)\">\n <i class=\"fas\" [class.fa-folder-tree]=\"groupBy !== 'project'\" [class.fa-list]=\"groupBy === 'project'\"></i>\n <span>{{ groupBy === 'project' ? 'Show as flat list' : 'Group by folder' }}</span>\n </button>\n @if (!isMobileView) {\n <button class=\"dropdown-item\" (click)=\"onUnpinSidebarClick($event)\">\n <i class=\"fas fa-table-columns\"></i>\n <span>Hide Sidebar</span>\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n <button class=\"btn-new-conversation\" (click)=\"createNewConversation()\" title=\"New Conversation\">\n <i class=\"fas fa-plus\"></i>\n <span>New Conversation</span>\n </button>\n <div class=\"list-content\">\n <!-- Pinned Section (only show if there are pinned conversations) -->\n @if (pinnedConversations.length > 0) {\n <div class=\"sidebar-section pinned-section\">\n <div class=\"section-header\" [class.expanded]=\"pinnedExpanded\" (click)=\"togglePinned()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <i class=\"fas fa-thumbtack section-icon\"></i>\n <span>Pinned</span>\n </div>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"pinnedExpanded\">\n @for (conversation of pinnedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n }\n\n @if (groupBy === 'project') {\n <!-- Folders Section -->\n <div class=\"sidebar-section folders-section\">\n <div class=\"section-header\" [class.expanded]=\"foldersExpanded\"\n [class.drag-over]=\"dragOverTargetId === 'folders-root'\"\n (click)=\"toggleFolders()\"\n (dragover)=\"onFoldersRootDragOver($event)\"\n (dragleave)=\"onDragLeave('folders-root')\"\n (drop)=\"onFoldersRootDrop($event)\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>Folders</span>\n </div>\n <button class=\"section-action-btn\" (click)=\"createFolder(null, $event)\" title=\"New Folder\">\n <i class=\"fas fa-folder-plus\"></i>\n </button>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"foldersExpanded\">\n @for (node of folderTree; track node.project.ID) {\n @if (!isSearching || node.hasContent) {\n <ng-container [ngTemplateOutlet]=\"folderNode\" [ngTemplateOutletContext]=\"{ $implicit: node }\"></ng-container>\n }\n }\n @if (folderTree.length === 0) {\n <div class=\"folder-empty-hint\">No folders yet — create one to organize conversations.</div>\n }\n </div>\n </div>\n\n <!-- Ungrouped Section (drop target to remove from folder) -->\n <div class=\"sidebar-section ungrouped-section\"\n [class.drag-over]=\"dragOverTargetId === 'ungrouped'\"\n (dragover)=\"onUngroupedDragOver($event)\"\n (dragleave)=\"onDragLeave('ungrouped')\"\n (drop)=\"onUngroupedDrop($event)\">\n <div class=\"section-header\" [class.expanded]=\"ungroupedExpanded\" (click)=\"toggleUngrouped()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>{{ folderTree.length > 0 ? 'Ungrouped' : 'Messages' }}</span>\n </div>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"ungroupedExpanded\">\n @for (conversation of ungroupedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n } @else {\n <!-- Flat Messages Section -->\n <div class=\"sidebar-section\">\n <div class=\"section-header\" [class.expanded]=\"directMessagesExpanded\" (click)=\"toggleDirectMessages()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>Messages</span>\n </div>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"directMessagesExpanded\">\n @for (conversation of unpinnedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Selection Action Bar -->\n @if (isSelectionMode) {\n <div class=\"selection-action-bar\">\n <div class=\"selection-info\">\n <span class=\"selection-count\">{{ selectedConversationIds.size }} selected</span>\n @if (selectedConversationIds.size < filteredConversations.length) {\n <button class=\"link-btn\" (click)=\"selectAll()\">Select All</button>\n } @else {\n <button class=\"link-btn\" (click)=\"deselectAll()\">Deselect All</button>\n }\n </div>\n <div class=\"selection-actions\">\n <button class=\"btn-delete-bulk\"\n (click)=\"bulkDeleteConversations()\"\n [disabled]=\"selectedConversationIds.size === 0\">\n <i class=\"fas fa-trash\"></i>\n Delete ({{ selectedConversationIds.size }})\n </button>\n <button class=\"btn-cancel\" (click)=\"toggleSelectionMode()\">\n Cancel\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Recursive folder node: header + nested children + direct conversations -->\n <ng-template #folderNode let-node>\n <div class=\"folder-row\"\n [class.drag-over]=\"dragOverTargetId === node.project.ID\"\n [class.dragging]=\"draggedFolderId === node.project.ID\"\n [style.paddingLeft.px]=\"12 + node.depth * 14\"\n [draggable]=\"true\"\n (dragstart)=\"onFolderDragStart(node, $event)\"\n (dragend)=\"onFolderDragEnd()\"\n (click)=\"toggleFolder(node.project.ID)\"\n (dragover)=\"onFolderDragOver(node.project.ID, $event)\"\n (dragleave)=\"onDragLeave(node.project.ID)\"\n (drop)=\"onFolderDrop(node.project, $event)\"\n [title]=\"node.project.Name\">\n <i class=\"fas fa-chevron-right folder-chevron\" [class.expanded]=\"isFolderExpanded(node.project.ID)\"></i>\n <i class=\"fas {{ node.project.Icon || 'fa-folder' }} folder-icon\" [style.color]=\"node.project.Color || null\"></i>\n <span class=\"folder-name\">{{ node.project.Name }}</span>\n <span class=\"folder-count\">{{ node.totalCount }}</span>\n <div class=\"folder-actions\" (click)=\"$event.stopPropagation()\">\n <button class=\"folder-action-btn\" (click)=\"createFolder(node.project.ID, $event)\" title=\"New Subfolder\">\n <i class=\"fas fa-folder-plus\"></i>\n </button>\n <button class=\"folder-action-btn\" (click)=\"editFolder(node.project, $event)\" title=\"Edit Folder\">\n <i class=\"fas fa-pen\"></i>\n </button>\n <button class=\"folder-action-btn danger\" (click)=\"deleteFolder(node.project, $event)\" title=\"Delete Folder\">\n <i class=\"fas fa-trash\"></i>\n </button>\n </div>\n </div>\n @if (isFolderExpanded(node.project.ID)) {\n <div class=\"folder-children\">\n @for (child of node.children; track child.project.ID) {\n @if (!isSearching || child.hasContent) {\n <ng-container [ngTemplateOutlet]=\"folderNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\n }\n }\n @for (conversation of node.conversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation, depth: node.depth + 1 }\"></ng-container>\n }\n @if (node.totalCount === 0 && !isSearching) {\n <div class=\"folder-empty-hint\" [style.paddingLeft.px]=\"26 + node.depth * 14\">Empty — drop a conversation here</div>\n }\n </div>\n }\n </ng-template>\n\n <!-- Shared conversation row used by Pinned, folders, and Ungrouped/Messages -->\n <ng-template #conversationItem let-conversation let-depth=\"depth\">\n <div class=\"conversation-item\"\n [class.active]=\"IsConversationActive(conversation)\"\n [class.renamed]=\"IsConversationRenamed(conversation)\"\n [class.dragging]=\"IsConversationDragging(conversation)\"\n [style.paddingLeft.px]=\"depth ? 16 + depth * 14 : 16\"\n [draggable]=\"!isSelectionMode\"\n (dragstart)=\"onConversationDragStart(conversation, $event)\"\n (dragend)=\"onConversationDragEnd()\"\n (click)=\"handleConversationClick(conversation)\">\n @if (isSelectionMode) {\n <div class=\"conversation-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"selectedConversationIds.has(conversation.ID)\"\n (click)=\"$event.stopPropagation(); toggleConversationSelection(conversation.ID)\">\n </div>\n }\n <div class=\"conversation-icon-wrapper\">\n @if (hasActiveTasks(conversation.ID)) {\n <div class=\"conversation-icon has-tasks\">\n <i class=\"fas fa-spinner fa-pulse\"></i>\n </div>\n }\n <div class=\"badge-overlay\">\n <mj-notification-badge [conversationId]=\"conversation.ID\"></mj-notification-badge>\n </div>\n </div>\n <div class=\"conversation-info\" [title]=\"conversation.Name + (conversation.Description ? '\\n' + conversation.Description : '')\">\n <div class=\"conversation-name\">\n {{ conversation.Name }}\n @if (isSharedWithMe(conversation)) {\n <i class=\"fas fa-share-nodes shared-indicator\"\n [title]=\"sharedWithMeTooltip(conversation)\"></i>\n }\n </div>\n <div class=\"conversation-preview\">{{ conversation.Description }}</div>\n </div>\n @if (!isSelectionMode) {\n <div class=\"conversation-actions\">\n <button class=\"menu-btn\" (click)=\"toggleMenu(conversation.ID, $event)\" title=\"More options\">\n <i class=\"fas fa-ellipsis\"></i>\n </button>\n @if (IsMenuOpen(conversation)) {\n <div class=\"context-menu\" (click)=\"$event.stopPropagation()\">\n @if (IsMoveSubmenuOpen(conversation)) {\n <button class=\"menu-item back\" (click)=\"closeMoveSubmenu($event)\">\n <i class=\"fas fa-chevron-left\"></i>\n <span>Move to folder</span>\n </button>\n <div class=\"menu-divider\"></div>\n <div class=\"move-folder-list\">\n <button class=\"menu-item\" [class.current]=\"!conversation.ProjectID\" (click)=\"selectMoveTarget(conversation, null)\">\n <i class=\"fas fa-inbox\"></i>\n <span>No folder</span>\n </button>\n @for (f of flatFolders; track f.project.ID) {\n <button class=\"menu-item\" [class.current]=\"IsInFolder(conversation, f.project.ID)\"\n [style.paddingLeft.px]=\"14 + f.depth * 12\"\n (click)=\"selectMoveTarget(conversation, f.project.ID)\">\n <i class=\"fas {{ f.project.Icon || 'fa-folder' }}\" [style.color]=\"f.project.Color || null\"></i>\n <span>{{ f.project.Name }}</span>\n </button>\n }\n </div>\n <div class=\"menu-divider\"></div>\n <button class=\"menu-item\" (click)=\"createFolderForConversation(conversation, $event)\">\n <i class=\"fas fa-folder-plus\"></i>\n <span>New folder…</span>\n </button>\n } @else {\n <button class=\"menu-item\" (click)=\"togglePin(conversation, $event)\">\n <i class=\"fas fa-thumbtack\"></i>\n <span>{{ conversation.IsPinned ? 'Unpin' : 'Pin' }}</span>\n </button>\n <button class=\"menu-item\" (click)=\"openMoveSubmenu(conversation.ID, $event)\">\n <i class=\"fas fa-folder-tree\"></i>\n <span>Move to folder</span>\n <i class=\"fas fa-chevron-right submenu-arrow\"></i>\n </button>\n <button class=\"menu-item\" (click)=\"renameConversation(conversation); closeMenu()\">\n <i class=\"fas fa-edit\"></i>\n <span>Rename</span>\n </button>\n <div class=\"menu-divider\"></div>\n <button class=\"menu-item danger\" (click)=\"deleteConversation(conversation); closeMenu()\">\n <i class=\"fas fa-trash\"></i>\n <span>Delete</span>\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n `,\n styles: [`\n :host { display: block; height: 100%; }\n .conversation-list { display: flex; flex-direction: column; height: 100%; background: var(--mj-brand-secondary); }\n .list-header { padding: 8px; border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent); }\n .search-input {\n width: 100%;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 20%, transparent);\n border-radius: 6px;\n color: var(--mj-brand-on-secondary);\n font-size: 13px;\n transition: all 0.2s;\n }\n .search-input::placeholder { color: color-mix(in srgb, var(--mj-brand-on-secondary) 50%, transparent); }\n .search-input:focus { outline: none; background: color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent); border-color: var(--mj-brand-primary); }\n .btn-new-conversation {\n width: calc(100% - 16px);\n margin: 8px;\n padding: 10px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: background 0.2s;\n flex-shrink: 0;\n }\n .btn-new-conversation:hover { background: var(--mj-brand-primary-hover); }\n .btn-new-conversation i { font-size: 14px; }\n .list-content { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0; }\n\n /* Collapsible Sections */\n .sidebar-section { margin-bottom: 20px; }\n .pinned-section .section-title .section-icon {\n color: var(--mj-status-warning);\n font-size: 11px;\n margin-left: 2px;\n }\n .section-header {\n padding: 4px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n color: var(--mj-brand-on-secondary);\n font-size: 13px;\n font-weight: 500;\n transition: background 0.2s;\n user-select: none;\n }\n .section-header:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); }\n .section-title {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .section-title i {\n font-size: 10px;\n }\n .section-title i:not(.section-icon) {\n transition: transform 0.2s;\n }\n .section-header.expanded .section-title i:not(.section-icon) { transform: rotate(90deg); }\n .chat-list {\n padding: 4px 0;\n display: none;\n }\n .chat-list.expanded { display: block; }\n\n .conversation-item {\n padding: 6px 5px 6px 16px;\n cursor: pointer;\n display: flex;\n gap: 8px;\n align-items: center;\n transition: all 0.2s;\n position: relative;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 70%, transparent);\n font-size: 14px;\n min-height: 45px;\n }\n .conversation-item:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); color: var(--mj-brand-on-secondary); }\n .conversation-item:hover .conversation-actions { opacity: 1; }\n .conversation-item.active { background: var(--mj-brand-primary); color: var(--mj-brand-on-secondary); }\n .conversation-icon-wrapper { position: relative; flex-shrink: 0; }\n .conversation-icon { font-size: 12px; width: 16px; text-align: center; }\n .conversation-icon.has-tasks { color: var(--mj-status-warning); }\n .badge-overlay { position: absolute; top: -4px; right: -4px; }\n .conversation-info { flex: 1; min-width: 0; }\n .conversation-name { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }\n .shared-indicator { font-size: 10px; color: color-mix(in srgb, var(--mj-brand-on-secondary) 55%, transparent); flex-shrink: 0; }\n .conversation-item.active .shared-indicator { color: color-mix(in srgb, var(--mj-brand-on-secondary) 85%, transparent); }\n .conversation-preview { font-size: 12px; color: color-mix(in srgb, var(--mj-brand-on-secondary) 50%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .conversation-item.active .conversation-preview { color: color-mix(in srgb, var(--mj-brand-on-secondary) 80%, transparent); }\n .conversation-meta { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }\n\n /* Project Badge */\n .project-badge {\n display: inline-block;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n margin-left: auto;\n background-color: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 60%, transparent);\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .conversation-item:hover .project-badge {\n background-color: color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent);\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 80%, transparent);\n }\n .conversation-item.active .project-badge {\n background-color: color-mix(in srgb, var(--mj-brand-on-secondary) 20%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n\n .conversation-actions {\n position: absolute;\n right: 5px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n z-index: 10;\n }\n .conversation-item:hover .conversation-actions { opacity: 1; pointer-events: auto; }\n .conversation-item.active .conversation-actions { opacity: 1; pointer-events: auto; }\n .conversation-actions > * { pointer-events: auto; }\n .pinned-icon { color: var(--mj-brand-accent); font-size: 12px; }\n\n /* Task Indicator */\n .task-indicator {\n color: var(--mj-status-warning);\n font-size: 12px;\n margin-right: 8px;\n flex-shrink: 0;\n animation: pulse-glow 2s ease-in-out infinite;\n }\n @keyframes pulse-glow {\n 0%, 100% {\n opacity: 1;\n filter: drop-shadow(0 0 2px var(--mj-status-warning));\n }\n 50% {\n opacity: 0.6;\n filter: drop-shadow(0 0 4px var(--mj-status-warning));\n }\n }\n .conversation-item.active .task-indicator {\n color: var(--mj-status-warning);\n }\n\n .menu-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 70%, transparent);\n background: var(--mj-brand-secondary) !important;\n border: none;\n cursor: pointer;\n transition: all 0.2s;\n }\n .menu-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent) !important;\n color: var(--mj-brand-on-secondary);\n }\n .conversation-item.active .menu-btn {\n background: var(--mj-brand-primary-hover) !important;\n color: var(--mj-brand-on-secondary);\n }\n .menu-btn i { font-size: 14px; }\n\n .context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 160px;\n background: var(--mj-brand-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n overflow: hidden;\n pointer-events: auto;\n }\n\n .menu-item {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 14px;\n background: transparent;\n border: none;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 85%, transparent);\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .menu-item:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n\n .menu-item i {\n width: 16px;\n font-size: 13px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 60%, transparent);\n }\n\n .menu-item:hover i {\n color: var(--mj-brand-on-secondary);\n }\n\n .menu-item.danger {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 15%, transparent);\n color: var(--mj-status-error);\n }\n\n .menu-item.danger i {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger:hover i {\n color: var(--mj-status-error);\n }\n\n .menu-divider {\n height: 1px;\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n margin: 4px 0;\n }\n\n /* Rename Animation */\n .conversation-item.renamed {\n animation: renameHighlight 1500ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes renameHighlight {\n 0% {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.4), rgba(147, 51, 234, 0.4));\n transform: scale(1.03);\n box-shadow: 0 0 20px rgba(59, 130, 246, 0.5);\n }\n 25% {\n background: linear-gradient(90deg, rgba(59, 130, 246, 0.35), rgba(147, 51, 234, 0.35));\n box-shadow: 0 0 15px rgba(59, 130, 246, 0.4);\n }\n 50% {\n background: linear-gradient(90deg, rgba(16, 185, 129, 0.3), rgba(59, 130, 246, 0.3));\n transform: scale(1.02);\n box-shadow: 0 0 10px rgba(16, 185, 129, 0.3);\n }\n 75% {\n background: linear-gradient(90deg, rgba(16, 185, 129, 0.2), rgba(59, 130, 246, 0.2));\n box-shadow: 0 0 5px rgba(16, 185, 129, 0.2);\n }\n 100% {\n background: transparent;\n transform: scale(1);\n box-shadow: none;\n }\n }\n\n /* Selection Mode Styles */\n .header-top {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n /* Header menu button and dropdown */\n .header-menu-container {\n position: relative;\n flex-shrink: 0;\n }\n\n .btn-menu {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 70%, transparent);\n cursor: pointer;\n transition: all 0.2s;\n }\n\n .btn-menu:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: var(--mj-brand-on-secondary);\n border-color: color-mix(in srgb, var(--mj-brand-on-secondary) 30%, transparent);\n }\n\n .header-dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--mj-brand-secondary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n overflow: hidden;\n padding: 4px 0;\n }\n\n .header-dropdown-menu .dropdown-item {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n background: transparent;\n border: none;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 85%, transparent);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .header-dropdown-menu .dropdown-item:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n\n .header-dropdown-menu .dropdown-item i {\n width: 16px;\n font-size: 13px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 60%, transparent);\n }\n\n .header-dropdown-menu .dropdown-item:hover i {\n color: var(--mj-brand-on-secondary);\n }\n\n .header-dropdown-menu .dropdown-item .shortcut {\n margin-left: auto;\n font-size: 11px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 40%, transparent);\n font-family: system-ui, -apple-system, sans-serif;\n }\n\n .btn-select {\n padding: 8px 12px;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 70%, transparent);\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .btn-select:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: var(--mj-brand-on-secondary);\n border-color: color-mix(in srgb, var(--mj-brand-on-secondary) 30%, transparent);\n }\n\n .conversation-checkbox {\n display: flex;\n align-items: center;\n margin-right: 8px;\n flex-shrink: 0;\n }\n\n .conversation-checkbox input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n }\n\n .selection-action-bar {\n position: sticky;\n bottom: 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--mj-brand-secondary);\n border-top: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent);\n gap: 12px;\n flex-wrap: wrap;\n flex-shrink: 0;\n }\n\n .selection-info {\n display: flex;\n align-items: center;\n gap: 12px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 90%, transparent);\n font-size: 14px;\n font-weight: 500;\n flex: 1 1 auto;\n min-width: 150px;\n }\n\n .selection-count {\n color: var(--mj-brand-on-secondary);\n }\n\n .link-btn {\n background: none;\n border: none;\n color: var(--mj-brand-accent);\n cursor: pointer;\n font-size: 13px;\n text-decoration: underline;\n padding: 0;\n transition: color 0.2s;\n }\n\n .link-btn:hover {\n color: var(--mj-brand-on-secondary);\n }\n\n .selection-actions {\n display: flex;\n gap: 8px;\n flex: 0 0 auto;\n }\n\n .btn-cancel {\n padding: 8px 16px;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 70%, transparent);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: all 0.2s;\n }\n\n .btn-cancel:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n\n .btn-delete-bulk {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 6px;\n color: var(--mj-brand-on-secondary);\n cursor: pointer;\n font-size: 13px;\n font-weight: 600;\n transition: all 0.2s;\n }\n\n .btn-delete-bulk:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 80%, black);\n }\n\n .btn-delete-bulk:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-delete-bulk i {\n font-size: 12px;\n }\n\n /* Folders */\n .section-action-btn {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 60%, transparent);\n cursor: pointer;\n transition: all 0.2s;\n }\n .section-action-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 15%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n .section-action-btn i { font-size: 12px; }\n\n .folder-row {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 8px 5px 12px;\n cursor: pointer;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 80%, transparent);\n font-size: 13px;\n transition: background 0.15s;\n user-select: none;\n position: relative;\n }\n .folder-row:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); }\n .folder-row.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n }\n .folder-row.dragging { opacity: 0.4; }\n .section-header.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 18%, transparent);\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n border-radius: 6px;\n }\n .folder-chevron {\n font-size: 9px;\n width: 10px;\n flex-shrink: 0;\n transition: transform 0.2s;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 55%, transparent);\n }\n .folder-chevron.expanded { transform: rotate(90deg); }\n .folder-icon { font-size: 12px; width: 16px; text-align: center; flex-shrink: 0; }\n .folder-name {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-weight: 600;\n }\n .folder-count {\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 50%, transparent);\n flex-shrink: 0;\n margin-left: auto;\n padding-left: 6px;\n text-align: right;\n }\n .folder-actions {\n position: absolute;\n right: 6px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n gap: 2px;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n z-index: 5;\n }\n .folder-row:hover .folder-actions { opacity: 1; pointer-events: auto; }\n .folder-row:hover .folder-count { opacity: 0; }\n .folder-action-btn {\n width: 22px;\n height: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 60%, transparent);\n cursor: pointer;\n transition: all 0.15s;\n }\n .folder-action-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 18%, transparent);\n color: var(--mj-brand-on-secondary);\n }\n .folder-action-btn.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 18%, transparent);\n color: var(--mj-status-error);\n }\n .folder-action-btn i { font-size: 11px; }\n .folder-children { display: block; }\n .folder-empty-hint {\n padding: 6px 16px;\n font-size: 11px;\n font-style: italic;\n color: color-mix(in srgb, var(--mj-brand-on-secondary) 45%, transparent);\n }\n .ungrouped-section.drag-over {\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);\n box-shadow: inset 0 0 0 1px var(--mj-brand-primary);\n border-radius: 6px;\n }\n\n /* Dragging state */\n .conversation-item { user-select: none; }\n .conversation-item.dragging { opacity: 0.4; }\n\n /* Move-to-folder submenu */\n .menu-item.back { font-weight: 600; }\n .menu-item .submenu-arrow { margin-left: auto; font-size: 10px; }\n .menu-item.current { background: color-mix(in srgb, var(--mj-brand-primary) 18%, transparent); }\n .move-folder-list { max-height: 240px; overflow-y: auto; }\n `]\n})\nexport class ConversationListComponent implements OnInit, OnDestroy {\n @Input() environmentId!: string;\n @Input() currentUser!: UserInfo;\n @Input() selectedConversationId: string | null = null;\n @Input() renamedConversationId: string | null = null;\n @Input() isSidebarPinned: boolean = true; // Whether sidebar is pinned (stays open after selection)\n @Input() isMobileView: boolean = false; // Whether we're on mobile (no pin options)\n\n @Output() conversationSelected = new EventEmitter<string>();\n @Output() conversationDeleted = new EventEmitter<string>(); // Emits the deleted conversation ID\n @Output() newConversationRequested = new EventEmitter<void>();\n @Output() pinSidebarRequested = new EventEmitter<void>(); // Request to pin sidebar\n @Output() unpinSidebarRequested = new EventEmitter<void>(); // Request to unpin (collapse) sidebar\n @Output() refreshRequested = new EventEmitter<void>(); // Emitted after list refresh so chat area can also reload\n\n public directMessagesExpanded: boolean = true;\n public pinnedExpanded: boolean = true;\n public foldersExpanded: boolean = true;\n public ungroupedExpanded: boolean = true;\n public openMenuConversationId: string | null = null;\n public conversationIdsWithTasks = new Set<string>();\n public isSelectionMode: boolean = false;\n public selectedConversationIds = new Set<string>();\n public isHeaderMenuOpen: boolean = false;\n public isRefreshing: boolean = false;\n\n /** UserInfoEngine key for persisting folder collapse state + group-by mode. */\n private static readonly FolderPrefsKey = 'mj.conversations.folderPrefs.v1';\n\n /** How the conversation list is grouped. 'project' = folders, 'none' = flat list. */\n public groupBy: ConversationGroupBy = 'project';\n\n /** Precomputed groupings, rebuilt whenever conversations/projects/search change. */\n public pinnedConversations: MJConversationEntity[] = [];\n public unpinnedConversations: MJConversationEntity[] = [];\n public ungroupedConversations: MJConversationEntity[] = [];\n public folderTree: FolderNode[] = [];\n /** Flattened folder list (depth-ordered) for the \"Move to folder\" menu. */\n public flatFolders: FolderNode[] = [];\n\n /** Folder IDs (normalized) whose children are collapsed. Absent = expanded. */\n private collapsedFolderIds = new Set<string>();\n\n /** Drag-and-drop state. */\n public draggedConversationId: string | null = null;\n public draggedFolderId: string | null = null;\n public dragOverTargetId: string | null = null;\n\n /** When set, the open conversation menu is showing its \"Move to folder\" picker. */\n public moveSubmenuConversationId: string | null = null;\n\n private _searchQuery: string = '';\n\n private destroy$ = new Subject<void>();\n\n private engine = ConversationEngine.Instance;\n\n // Local UI state for loading/refreshing\n public IsLoading: boolean = false;\n\n constructor(\n private dialogService: DialogService,\n private notificationService: NotificationService,\n private activeTasksService: ActiveTasksService,\n private mjDialogService: MJDialogService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get searchQuery(): string {\n return this._searchQuery;\n }\n set searchQuery(value: string) {\n this._searchQuery = value ?? '';\n this.rebuildGroups();\n }\n\n /** True when a search filter is active. */\n get isSearching(): boolean {\n return this._searchQuery.trim().length > 0;\n }\n\n /** Conversations matching the current search (used by selection-mode helpers). */\n get filteredConversations(): MJConversationEntity[] {\n return this.filterConversations(this.engine.Conversations);\n }\n\n private filterConversations(conversations: MJConversationEntity[]): MJConversationEntity[] {\n if (!this.isSearching) {\n return conversations;\n }\n const lowerQuery = this._searchQuery.toLowerCase();\n return conversations.filter(c =>\n (c.Name?.toLowerCase().includes(lowerQuery)) ||\n (c.Description?.toLowerCase().includes(lowerQuery))\n );\n }\n\n ngOnInit() {\n // Restore persisted folder collapse state + group-by preference\n this.loadFolderPrefs();\n\n // Load conversations (and folders) on init\n this.engine.LoadConversations(this.environmentId, this.currentUser, false);\n\n // Rebuild the precomputed groupings whenever conversations OR projects change\n // (pin, archive, rename, move-to-folder, folder create/rename/delete, etc.).\n this.engine.Conversations$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.rebuildGroups();\n this.cdr.detectChanges();\n });\n\n this.engine.Projects$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.rebuildGroups();\n this.cdr.detectChanges();\n });\n\n // Subscribe to conversation IDs with active tasks (hot set)\n this.activeTasksService.conversationIdsWithTasks$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(conversationIds => {\n this.conversationIdsWithTasks = conversationIds;\n this.cdr.detectChanges(); // Force change detection to ensure spinner icons update reliably\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n @HostListener('document:click')\n onDocumentClick(): void {\n // Close menus when clicking outside\n if (this.openMenuConversationId) {\n this.closeMenu();\n }\n if (this.isHeaderMenuOpen) {\n this.closeHeaderMenu();\n }\n }\n\n public toggleHeaderMenu(event: Event): void {\n event.stopPropagation();\n this.isHeaderMenuOpen = !this.isHeaderMenuOpen;\n }\n\n public closeHeaderMenu(): void {\n this.isHeaderMenuOpen = false;\n }\n\n public onSelectConversationsClick(event: Event): void {\n event.stopPropagation();\n this.toggleSelectionMode();\n this.closeHeaderMenu();\n }\n\n public onToggleGroupByClick(event: Event): void {\n event.stopPropagation();\n this.toggleGroupBy();\n this.closeHeaderMenu();\n }\n\n public async onRefreshConversationsClick(event: Event): Promise<void> {\n event.stopPropagation();\n if (this.isRefreshing) return;\n\n this.isRefreshing = true;\n try {\n await this.engine.LoadConversations(this.environmentId, this.currentUser, true);\n // Signal parent to also reload messages in the active conversation\n this.refreshRequested.emit();\n } catch (error) {\n console.error('Error refreshing conversations:', error);\n await this.dialogService.alert('Error', 'Failed to refresh conversations. Please try again.');\n } finally {\n this.isRefreshing = false;\n this.cdr.detectChanges();\n this.closeHeaderMenu();\n }\n }\n\n public onPinSidebarClick(event: Event): void {\n event.stopPropagation();\n this.closeHeaderMenu();\n this.pinSidebarRequested.emit();\n }\n\n public onUnpinSidebarClick(event: Event): void {\n event.stopPropagation();\n this.closeHeaderMenu();\n this.unpinSidebarRequested.emit();\n }\n\n public toggleDirectMessages(): void {\n this.directMessagesExpanded = !this.directMessagesExpanded;\n }\n\n public togglePinned(): void {\n this.pinnedExpanded = !this.pinnedExpanded;\n }\n\n public toggleFolders(): void {\n this.foldersExpanded = !this.foldersExpanded;\n }\n\n public toggleUngrouped(): void {\n this.ungroupedExpanded = !this.ungroupedExpanded;\n }\n\n // ========================================================================\n // FOLDER GROUPING\n // ========================================================================\n\n /**\n * Recomputes pinned/unpinned/ungrouped lists and the folder tree from the\n * engine's conversation + project caches and the current search filter.\n */\n private rebuildGroups(): void {\n const matching = this.filterConversations(this.engine.Conversations);\n this.pinnedConversations = matching.filter(c => c.IsPinned);\n this.unpinnedConversations = matching.filter(c => !c.IsPinned);\n\n const projects = this.engine.Projects;\n const projectIds = new Set(projects.map(p => NormalizeUUID(p.ID)));\n\n // Bucket unpinned conversations by their folder (pinned ones live in the\n // Pinned section). Conversations with no/unknown folder are \"ungrouped\".\n const conversationsByProject = new Map<string, MJConversationEntity[]>();\n const ungrouped: MJConversationEntity[] = [];\n for (const c of this.unpinnedConversations) {\n const pid = c.ProjectID ? NormalizeUUID(c.ProjectID) : null;\n if (pid && projectIds.has(pid)) {\n const arr = conversationsByProject.get(pid) ?? [];\n arr.push(c);\n conversationsByProject.set(pid, arr);\n } else {\n ungrouped.push(c);\n }\n }\n this.ungroupedConversations = ungrouped;\n\n // Index projects by parent. A project whose parent isn't loaded is treated\n // as a root so it never disappears from the tree.\n const childrenByParent = new Map<string | null, MJProjectEntity[]>();\n for (const p of projects) {\n const parentId = p.ParentID ? NormalizeUUID(p.ParentID) : null;\n const key = parentId && projectIds.has(parentId) ? parentId : null;\n const arr = childrenByParent.get(key) ?? [];\n arr.push(p);\n childrenByParent.set(key, arr);\n }\n\n const build = (parentKey: string | null, depth: number): FolderNode[] => {\n const projectsAtLevel = childrenByParent.get(parentKey) ?? [];\n return projectsAtLevel.map(p => {\n const children = build(NormalizeUUID(p.ID), depth + 1);\n const conversations = conversationsByProject.get(NormalizeUUID(p.ID)) ?? [];\n const totalCount = conversations.length + children.reduce((sum, ch) => sum + ch.totalCount, 0);\n const hasContent = conversations.length > 0 || children.some(ch => ch.hasContent);\n return { project: p, depth, conversations, children, totalCount, hasContent };\n });\n };\n this.folderTree = build(null, 0);\n this.flatFolders = this.flattenFolders(this.folderTree);\n }\n\n private flattenFolders(nodes: FolderNode[]): FolderNode[] {\n const out: FolderNode[] = [];\n for (const node of nodes) {\n out.push(node);\n out.push(...this.flattenFolders(node.children));\n }\n return out;\n }\n\n private findFolderNode(nodes: FolderNode[], projectId: string): FolderNode | null {\n for (const node of nodes) {\n if (UUIDsEqual(node.project.ID, projectId)) return node;\n const found = this.findFolderNode(node.children, projectId);\n if (found) return found;\n }\n return null;\n }\n\n public isFolderExpanded(projectId: string): boolean {\n return !this.collapsedFolderIds.has(NormalizeUUID(projectId));\n }\n\n public toggleFolder(projectId: string): void {\n const key = NormalizeUUID(projectId);\n if (this.collapsedFolderIds.has(key)) {\n this.collapsedFolderIds.delete(key);\n } else {\n this.collapsedFolderIds.add(key);\n }\n this.saveFolderPrefs();\n }\n\n public toggleGroupBy(): void {\n this.groupBy = this.groupBy === 'project' ? 'none' : 'project';\n this.saveFolderPrefs();\n this.rebuildGroups();\n }\n\n private loadFolderPrefs(): void {\n try {\n const raw = UserInfoEngine.Instance.GetSetting(ConversationListComponent.FolderPrefsKey);\n if (!raw) return;\n const parsed = JSON.parse(raw) as { collapsed?: string[]; groupBy?: ConversationGroupBy };\n this.collapsedFolderIds = new Set((parsed.collapsed ?? []).map(id => NormalizeUUID(id)));\n if (parsed.groupBy === 'none' || parsed.groupBy === 'project') {\n this.groupBy = parsed.groupBy;\n }\n } catch {\n // Corrupt/legacy value — ignore and use defaults\n }\n }\n\n private saveFolderPrefs(): void {\n const payload = JSON.stringify({\n collapsed: Array.from(this.collapsedFolderIds),\n groupBy: this.groupBy\n });\n UserInfoEngine.Instance.SetSettingDebounced(ConversationListComponent.FolderPrefsKey, payload);\n }\n\n // ========================================================================\n // DRAG & DROP (move conversation into/out of a folder)\n // ========================================================================\n\n public onConversationDragStart(conversation: MJConversationEntity, event: DragEvent): void {\n if (this.isSelectionMode) return;\n this.draggedFolderId = null;\n this.draggedConversationId = conversation.ID;\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', conversation.ID);\n }\n }\n\n public onConversationDragEnd(): void {\n this.draggedConversationId = null;\n this.dragOverTargetId = null;\n }\n\n public onFolderDragStart(node: FolderNode, event: DragEvent): void {\n event.stopPropagation();\n this.draggedConversationId = null;\n this.draggedFolderId = node.project.ID;\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', node.project.ID);\n }\n }\n\n public onFolderDragEnd(): void {\n this.draggedFolderId = null;\n this.dragOverTargetId = null;\n }\n\n public onFolderDragOver(projectId: string, event: DragEvent): void {\n // A conversation can drop onto any folder; a folder can drop onto any folder\n // that isn't itself or one of its own descendants (which would create a cycle).\n const accepts = this.draggedConversationId\n ? true\n : this.draggedFolderId\n ? this.isValidFolderDropTarget(projectId)\n : false;\n if (!accepts) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = projectId;\n }\n\n public onUngroupedDragOver(event: DragEvent): void {\n if (!this.draggedConversationId) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = 'ungrouped';\n }\n\n /** The Folders section header accepts a dragged folder to move it back to the top level. */\n public onFoldersRootDragOver(event: DragEvent): void {\n if (!this.draggedFolderId) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = 'folders-root';\n }\n\n public onDragLeave(targetId: string): void {\n if (this.dragOverTargetId === targetId) {\n this.dragOverTargetId = null;\n }\n }\n\n public onFolderDrop(project: MJProjectEntity, event: DragEvent): void {\n event.preventDefault();\n const conversationId = this.draggedConversationId;\n const folderId = this.draggedFolderId;\n this.dragOverTargetId = null;\n this.draggedConversationId = null;\n this.draggedFolderId = null;\n if (conversationId) {\n this.moveConversation(conversationId, project.ID);\n } else if (folderId && this.isValidFolderDropTarget(project.ID, folderId)) {\n this.moveFolder(folderId, project.ID);\n }\n }\n\n public onUngroupedDrop(event: DragEvent): void {\n event.preventDefault();\n const conversationId = this.draggedConversationId;\n this.dragOverTargetId = null;\n this.draggedConversationId = null;\n if (conversationId) {\n this.moveConversation(conversationId, null);\n }\n }\n\n public onFoldersRootDrop(event: DragEvent): void {\n event.preventDefault();\n const folderId = this.draggedFolderId;\n this.dragOverTargetId = null;\n this.draggedFolderId = null;\n if (folderId) {\n this.moveFolder(folderId, null);\n }\n }\n\n /**\n * A folder can be dropped onto a target folder only if the target isn't the dragged\n * folder itself and isn't one of its descendants (otherwise we'd create a cycle).\n */\n private isValidFolderDropTarget(targetId: string, draggedId: string | null = this.draggedFolderId): boolean {\n if (!draggedId) return false;\n if (UUIDsEqual(targetId, draggedId)) return false;\n return !this.isDescendantOf(targetId, draggedId);\n }\n\n /** True when `nodeId` is a descendant of `ancestorId` in the folder tree. */\n private isDescendantOf(nodeId: string, ancestorId: string): boolean {\n const byId = new Map(this.engine.Projects.map(p => [NormalizeUUID(p.ID), p]));\n const visited = new Set<string>();\n let current = byId.get(NormalizeUUID(nodeId));\n while (current?.ParentID) {\n const parentKey = NormalizeUUID(current.ParentID);\n if (visited.has(parentKey)) break; // guard against malformed cycles\n visited.add(parentKey);\n if (UUIDsEqual(parentKey, ancestorId)) return true;\n current = byId.get(parentKey);\n }\n return false;\n }\n\n /** Assigns a conversation to a folder (or null to ungroup) and refreshes the view. */\n private async moveConversation(conversationId: string, projectId: string | null): Promise<void> {\n try {\n await this.engine.MoveConversationToProject(conversationId, projectId, this.currentUser);\n // Reveal the destination folder so the user sees where it landed\n if (projectId) {\n this.collapsedFolderIds.delete(NormalizeUUID(projectId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error moving conversation:', error);\n await this.dialogService.alert('Error', 'Failed to move conversation. Please try again.');\n }\n }\n\n /** Reparents a folder under another folder (or to the top level when projectId is null). */\n private async moveFolder(folderId: string, parentId: string | null): Promise<void> {\n // No-op if it's already under that parent\n const folder = this.engine.Projects.find(p => UUIDsEqual(p.ID, folderId));\n const currentParent = folder?.ParentID ?? null;\n const sameParent = (currentParent === null && parentId === null) ||\n (!!currentParent && !!parentId && UUIDsEqual(currentParent, parentId));\n if (sameParent) return;\n\n try {\n await this.engine.MoveProjectToParent(folderId, parentId, this.currentUser);\n // Reveal the new parent so the moved folder is visible\n if (parentId) {\n this.collapsedFolderIds.delete(NormalizeUUID(parentId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error moving folder:', error);\n await this.dialogService.alert('Error', 'Failed to move folder. Please try again.');\n }\n }\n\n // ========================================================================\n // MOVE-TO-FOLDER MENU\n // ========================================================================\n\n public openMoveSubmenu(conversationId: string, event: Event): void {\n event.stopPropagation();\n this.moveSubmenuConversationId = conversationId;\n }\n\n public closeMoveSubmenu(event: Event): void {\n event.stopPropagation();\n this.moveSubmenuConversationId = null;\n }\n\n public IsInFolder(conversation: MJConversationEntity, projectId: string): boolean {\n return !!conversation.ProjectID && UUIDsEqual(conversation.ProjectID, projectId);\n }\n\n public selectMoveTarget(conversation: MJConversationEntity, projectId: string | null): void {\n this.moveConversation(conversation.ID, projectId);\n this.closeMenu();\n }\n\n // ========================================================================\n // FOLDER CRUD (reuses the existing project form modal)\n // ========================================================================\n\n public createFolder(parentId: string | null, event?: Event): void {\n if (event) event.stopPropagation();\n this.openFolderModal(null, parentId);\n }\n\n public editFolder(project: MJProjectEntity, event?: Event): void {\n if (event) event.stopPropagation();\n this.openFolderModal(project, null);\n }\n\n public createFolderForConversation(conversation: MJConversationEntity, event: Event): void {\n event.stopPropagation();\n const conversationId = conversation.ID;\n this.closeMenu();\n this.openFolderModal(null, null, (created) => this.moveConversation(conversationId, created.ID));\n }\n\n private openFolderModal(\n project: MJProjectEntity | null,\n parentId: string | null,\n onCreated?: (project: MJProjectEntity) => void\n ): void {\n const dialogRef = this.mjDialogService.open({\n content: ProjectFormModalComponent,\n width: 600,\n minWidth: 400\n });\n\n const instance = dialogRef.Content!.instance as unknown as ProjectFormModalComponent;\n instance.dialogRef = dialogRef;\n instance.environmentId = this.environmentId;\n instance.currentUser = this.currentUser;\n if (project) instance.project = project;\n if (parentId) instance.parentId = parentId;\n\n instance.projectSaved.subscribe((saved: MJProjectEntity) => {\n // The engine's entity-event handler keeps the projects cache in sync; we\n // just reveal the parent and refresh, then run any post-create action.\n if (parentId) {\n this.collapsedFolderIds.delete(NormalizeUUID(parentId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n if (onCreated) onCreated(saved);\n });\n }\n\n public async deleteFolder(project: MJProjectEntity, event?: Event): Promise<void> {\n if (event) event.stopPropagation();\n\n const node = this.findFolderNode(this.folderTree, project.ID);\n const total = node?.totalCount ?? 0;\n const childCount = node?.children.length ?? 0;\n\n let message = `Are you sure you want to delete the folder \"${project.Name}\"?`;\n if (total > 0 || childCount > 0) {\n message += `\\n\\nConversations inside will be moved out of the folder`;\n message += childCount > 0 ? ` and subfolders will move up one level.` : `.`;\n message += ` Nothing is deleted.`;\n }\n\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Folder',\n message,\n okText: 'Delete',\n cancelText: 'Cancel',\n dangerous: true\n });\n if (!confirmed) return;\n\n try {\n await this.engine.DeleteProject(project.ID, this.currentUser);\n this.collapsedFolderIds.delete(NormalizeUUID(project.ID));\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error deleting folder:', error);\n await this.dialogService.alert(\n 'Error',\n error instanceof Error ? error.message : 'Failed to delete folder. Please try again.'\n );\n }\n }\n\n IsConversationActive(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(conversation.ID, this.selectedConversationId);\n }\n\n IsConversationRenamed(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(conversation.ID, this.renamedConversationId);\n }\n\n IsMenuOpen(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.openMenuConversationId, conversation.ID);\n }\n\n IsConversationDragging(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.draggedConversationId, conversation.ID);\n }\n\n IsMoveSubmenuOpen(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.moveSubmenuConversationId, conversation.ID);\n }\n\n selectConversation(conversation: MJConversationEntity): void {\n this.conversationSelected.emit(conversation.ID);\n // Clear unread notifications when conversation is opened\n this.notificationService.markConversationAsRead(conversation.ID);\n }\n\n async createNewConversation(): Promise<void> {\n // Don't create DB record yet - just show the welcome screen\n // Conversation will be created when user sends first message\n this.newConversationRequested.emit();\n }\n\n async renameConversation(conversation: MJConversationEntity): Promise<void> {\n try {\n const result = await this.dialogService.input({\n title: 'Edit Conversation',\n message: 'Update the name and description for this conversation',\n inputLabel: 'Conversation Name',\n inputValue: conversation.Name || '',\n placeholder: 'My Conversation',\n required: true,\n secondInputLabel: 'Description',\n secondInputValue: conversation.Description || '',\n secondInputPlaceholder: 'Optional description',\n secondInputRequired: false,\n okText: 'Save',\n cancelText: 'Cancel'\n });\n\n if (result) {\n const newName = typeof result === 'string' ? result : result.value;\n const newDescription = typeof result === 'string' ? conversation.Description : result.secondValue;\n\n if (newName !== conversation.Name || newDescription !== conversation.Description) {\n await this.engine.SaveConversation(\n conversation.ID,\n { Name: newName, Description: newDescription || '' },\n this.currentUser\n );\n }\n }\n } catch (error) {\n console.error('Error renaming conversation:', error);\n await this.dialogService.alert('Error', 'Failed to update conversation. Please try again.');\n }\n }\n\n async deleteConversation(conversation: MJConversationEntity): Promise<void> {\n try {\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Conversation',\n message: `Are you sure you want to delete \"${conversation.Name}\"? This action cannot be undone.`,\n okText: 'Delete',\n cancelText: 'Cancel'\n });\n\n if (confirmed) {\n const deletedId = conversation.ID;\n await this.engine.DeleteConversation(deletedId, this.currentUser);\n this.cdr.detectChanges();\n this.conversationDeleted.emit(deletedId);\n }\n } catch (error) {\n console.error('Error deleting conversation:', error);\n await this.dialogService.alert('Error', 'Failed to delete conversation. Please try again.');\n }\n }\n\n toggleMenu(conversationId: string, event: Event): void {\n event.stopPropagation();\n this.openMenuConversationId = this.openMenuConversationId === conversationId ? null : conversationId;\n }\n\n closeMenu(): void {\n this.openMenuConversationId = null;\n this.moveSubmenuConversationId = null;\n }\n\n async togglePin(conversation: MJConversationEntity, event?: Event): Promise<void> {\n if (event) event.stopPropagation();\n this.closeMenu(); // Close immediately on user action — don't wait for the async op\n try {\n await this.engine.PinConversation(conversation.ID, !conversation.IsPinned, this.currentUser);\n } catch (error) {\n console.error('Error toggling pin:', error);\n await this.dialogService.alert('Error', 'Failed to pin/unpin conversation. Please try again.');\n }\n }\n\n hasActiveTasks(conversationId: string): boolean {\n return this.conversationIdsWithTasks.has(conversationId);\n }\n\n /** True when this conversation was shared with the current user by someone else. */\n isSharedWithMe(conversation: MJConversationEntity): boolean {\n return this.engine.GetSharedByInfo(conversation.ID) !== null;\n }\n\n /** Tooltip for the sidebar share icon: \"Shared by {email or name}\". */\n sharedWithMeTooltip(conversation: MJConversationEntity): string {\n const info = this.engine.GetSharedByInfo(conversation.ID);\n if (!info) return 'Shared with you';\n return `Shared by ${info.Email ?? info.Name ?? 'another user'}`;\n }\n\n toggleSelectionMode(): void {\n this.isSelectionMode = !this.isSelectionMode;\n if (!this.isSelectionMode) {\n this.selectedConversationIds.clear();\n }\n }\n\n toggleConversationSelection(conversationId: string): void {\n if (this.selectedConversationIds.has(conversationId)) {\n this.selectedConversationIds.delete(conversationId);\n } else {\n this.selectedConversationIds.add(conversationId);\n }\n }\n\n selectAll(): void {\n this.filteredConversations.forEach(c => {\n this.selectedConversationIds.add(c.ID);\n });\n }\n\n deselectAll(): void {\n this.selectedConversationIds.clear();\n }\n\n async bulkDeleteConversations(): Promise<void> {\n const count = this.selectedConversationIds.size;\n\n if (count === 0) return;\n\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Conversations',\n message: `Are you sure you want to delete ${count} conversation${count > 1 ? 's' : ''}? This action cannot be undone.`,\n okText: 'Delete',\n cancelText: 'Cancel'\n });\n\n if (confirmed) {\n try {\n const result = await this.engine.DeleteMultipleConversations(\n Array.from(this.selectedConversationIds),\n this.currentUser\n );\n\n if (result.Failed.length > 0 && result.Successful.length > 0) {\n // Partial success\n const failedNames = result.Failed.map(f => `\"${f.Name}\"`).join(', ');\n await this.dialogService.alert(\n 'Partial Success',\n `Deleted ${result.Successful.length} of ${count} conversations.\\n\\n` +\n `${result.Failed.length} could not be deleted: ${failedNames}`\n );\n } else if (result.Failed.length > 0 && result.Successful.length === 0) {\n // All failed\n await this.dialogService.alert(\n 'Delete Failed',\n `None of the ${count} conversations could be deleted. They may have already been removed.`\n );\n }\n\n // Emit deleted events for successful deletions\n for (const id of result.Successful) {\n this.conversationDeleted.emit(id);\n }\n\n } catch (error) {\n console.error('Error deleting conversations:', error);\n await this.dialogService.alert('Error', 'Failed to delete conversations. Please try again.');\n } finally {\n // Always exit selection mode after an attempt, whether success or failure\n this.selectedConversationIds.clear();\n this.isSelectionMode = false;\n this.cdr.detectChanges();\n }\n }\n }\n\n handleConversationClick(conversation: MJConversationEntity): void {\n if (this.isSelectionMode) {\n this.toggleConversationSelection(conversation.ID);\n } else {\n this.selectConversation(conversation);\n }\n }\n}"]}
1
+ {"version":3,"file":"conversation-list.component.js","sourceRoot":"","sources":["../../../../src/lib/components/conversation/conversation-list.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, HostListener, ChangeDetectorRef } from '@angular/core';\nimport { UserInfo } from '@memberjunction/core';\nimport { MJConversationEntity, MJProjectEntity, ConversationEngine, UserInfoEngine } from '@memberjunction/core-entities';\nimport { MJDialogService } from '@memberjunction/ng-ui-components';\nimport { DialogService } from '../../services/dialog.service';\nimport { NotificationService } from '../../services/notification.service';\nimport { ActiveTasksService } from '../../services/active-tasks.service';\nimport { ProjectFormModalComponent } from '../project/project-form-modal.component';\nimport { ConversationGroupBy } from '../../models/conversation-state.model';\nimport { Subject } from 'rxjs';\nimport { takeUntil } from 'rxjs/operators';\nimport { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';\n\n/**\n * A node in the conversation folder tree. Each node holds its project (folder),\n * the conversations directly assigned to it, and its nested child folders.\n */\ninterface FolderNode {\n project: MJProjectEntity;\n depth: number;\n /** Conversations directly in this folder (unpinned only — pinned live in the Pinned section). */\n conversations: MJConversationEntity[];\n children: FolderNode[];\n /** Total conversations in this folder and all descendants. */\n totalCount: number;\n /** True when this folder or any descendant has at least one (filtered) conversation. */\n hasContent: boolean;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-conversation-list',\n template: `\n <div class=\"conversation-list\">\n <!-- Header strip gated as a whole so an empty bordered band never renders:\n the ⋯ menu also hides during selection mode, so it only counts toward\n the strip when actually visible. -->\n @if (showSearch || (showHeaderMenu && !isSelectionMode)) {\n <div class=\"list-header\">\n <div class=\"header-top\">\n @if (showSearch) {\n <input\n type=\"text\"\n class=\"search-input\"\n placeholder=\"Search conversations...\"\n [(ngModel)]=\"searchQuery\">\n }\n @if (showHeaderMenu && !isSelectionMode) {\n <div class=\"header-menu-container\">\n <button class=\"btn-menu\" (click)=\"toggleHeaderMenu($event)\" title=\"Options\">\n <i class=\"fas fa-ellipsis-v\"></i>\n </button>\n @if (isHeaderMenuOpen) {\n <div class=\"header-dropdown-menu\">\n <button class=\"dropdown-item\" (click)=\"onRefreshConversationsClick($event)\" [disabled]=\"isRefreshing\">\n <i class=\"fas fa-sync-alt\" [class.fa-spin]=\"isRefreshing\"></i>\n <span>{{ isRefreshing ? 'Refreshing...' : 'Refresh' }}</span>\n </button>\n <button class=\"dropdown-item\" (click)=\"onSelectConversationsClick($event)\">\n <i class=\"fas fa-check-square\"></i>\n <span>Select Conversations</span>\n </button>\n <button class=\"dropdown-item\" (click)=\"onToggleGroupByClick($event)\">\n <i class=\"fas\" [class.fa-folder-tree]=\"groupBy !== 'project'\" [class.fa-list]=\"groupBy === 'project'\"></i>\n <span>{{ groupBy === 'project' ? 'Show as flat list' : 'Group by folder' }}</span>\n </button>\n @if (!isMobileView) {\n <button class=\"dropdown-item\" (click)=\"onUnpinSidebarClick($event)\">\n <i class=\"fas fa-table-columns\"></i>\n <span>Hide Sidebar</span>\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n @if (showNewConversationButton) {\n <button class=\"btn-new-conversation\" (click)=\"createNewConversation()\" title=\"New Conversation\">\n <i class=\"fas fa-plus\"></i>\n <span>New Conversation</span>\n </button>\n }\n <div class=\"list-content\">\n <!-- Pinned Section (only show if there are pinned conversations) -->\n @if (pinnedConversations.length > 0) {\n <div class=\"sidebar-section pinned-section\">\n @if (showSectionHeaders) {\n <div class=\"section-header\" [class.expanded]=\"pinnedExpanded\" (click)=\"togglePinned()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <i class=\"fas fa-thumbtack section-icon\"></i>\n <span>Pinned</span>\n </div>\n </div>\n }\n <div class=\"chat-list\" [class.expanded]=\"!showSectionHeaders || pinnedExpanded\">\n @for (conversation of pinnedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n }\n\n <!-- showSectionHeaders=false forces the FLAT branch even in project\n grouping: the folder tree's root drop-zone and New Folder action\n live in the section header, so rendering the tree without headers\n would let a user drag a folder INTO another folder with no way to\n ever drag it back out (a one-way door). Flat + headerless is the\n coherent chrome-less rendering. -->\n @if (showSectionHeaders && groupBy === 'project') {\n <!-- Folders Section. NOTE: this whole branch is already gated on\n showSectionHeaders above, so the header + collapse state here are\n unconditional — a headerless folder tree never renders. -->\n <div class=\"sidebar-section folders-section\">\n <div class=\"section-header\" [class.expanded]=\"foldersExpanded\"\n [class.drag-over]=\"dragOverTargetId === 'folders-root'\"\n (click)=\"toggleFolders()\"\n (dragover)=\"onFoldersRootDragOver($event)\"\n (dragleave)=\"onDragLeave('folders-root')\"\n (drop)=\"onFoldersRootDrop($event)\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>Folders</span>\n </div>\n <button class=\"section-action-btn\" (click)=\"createFolder(null, $event)\" title=\"New Folder\">\n <i class=\"fas fa-folder-plus\"></i>\n </button>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"foldersExpanded\">\n @for (node of folderTree; track node.project.ID) {\n @if (!isSearching || node.hasContent) {\n <ng-container [ngTemplateOutlet]=\"folderNode\" [ngTemplateOutletContext]=\"{ $implicit: node }\"></ng-container>\n }\n }\n @if (folderTree.length === 0) {\n <div class=\"folder-empty-hint\">No folders yet — create one to organize conversations.</div>\n }\n </div>\n </div>\n\n <!-- Ungrouped Section (drop target to remove from folder) -->\n <div class=\"sidebar-section ungrouped-section\"\n [class.drag-over]=\"dragOverTargetId === 'ungrouped'\"\n (dragover)=\"onUngroupedDragOver($event)\"\n (dragleave)=\"onDragLeave('ungrouped')\"\n (drop)=\"onUngroupedDrop($event)\">\n <!-- Same as Folders above: reached only when showSectionHeaders is true. -->\n <div class=\"section-header\" [class.expanded]=\"ungroupedExpanded\" (click)=\"toggleUngrouped()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>{{ folderTree.length > 0 ? 'Ungrouped' : 'Messages' }}</span>\n </div>\n </div>\n <div class=\"chat-list\" [class.expanded]=\"ungroupedExpanded\">\n @for (conversation of ungroupedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n } @else {\n <!-- Flat Messages Section -->\n <div class=\"sidebar-section\">\n @if (showSectionHeaders) {\n <div class=\"section-header\" [class.expanded]=\"directMessagesExpanded\" (click)=\"toggleDirectMessages()\">\n <div class=\"section-title\">\n <i class=\"fas fa-chevron-right\"></i>\n <span>Messages</span>\n </div>\n </div>\n }\n <div class=\"chat-list\" [class.expanded]=\"!showSectionHeaders || directMessagesExpanded\">\n @for (conversation of unpinnedConversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation }\"></ng-container>\n }\n </div>\n </div>\n }\n </div>\n\n <!-- Selection Action Bar -->\n @if (isSelectionMode) {\n <div class=\"selection-action-bar\">\n <div class=\"selection-info\">\n <span class=\"selection-count\">{{ selectedConversationIds.size }} selected</span>\n @if (selectedConversationIds.size < filteredConversations.length) {\n <button class=\"link-btn\" (click)=\"selectAll()\">Select All</button>\n } @else {\n <button class=\"link-btn\" (click)=\"deselectAll()\">Deselect All</button>\n }\n </div>\n <div class=\"selection-actions\">\n <button class=\"btn-delete-bulk\"\n (click)=\"bulkDeleteConversations()\"\n [disabled]=\"selectedConversationIds.size === 0\">\n <i class=\"fas fa-trash\"></i>\n Delete ({{ selectedConversationIds.size }})\n </button>\n <button class=\"btn-cancel\" (click)=\"toggleSelectionMode()\">\n Cancel\n </button>\n </div>\n </div>\n }\n </div>\n\n <!-- Recursive folder node: header + nested children + direct conversations -->\n <ng-template #folderNode let-node>\n <div class=\"folder-row\"\n [class.drag-over]=\"dragOverTargetId === node.project.ID\"\n [class.dragging]=\"draggedFolderId === node.project.ID\"\n [style.paddingLeft.px]=\"12 + node.depth * 14\"\n [draggable]=\"true\"\n (dragstart)=\"onFolderDragStart(node, $event)\"\n (dragend)=\"onFolderDragEnd()\"\n (click)=\"toggleFolder(node.project.ID)\"\n (dragover)=\"onFolderDragOver(node.project.ID, $event)\"\n (dragleave)=\"onDragLeave(node.project.ID)\"\n (drop)=\"onFolderDrop(node.project, $event)\"\n [title]=\"node.project.Name\">\n <i class=\"fas fa-chevron-right folder-chevron\" [class.expanded]=\"isFolderExpanded(node.project.ID)\"></i>\n <i class=\"fas {{ node.project.Icon || 'fa-folder' }} folder-icon\" [style.color]=\"node.project.Color || null\"></i>\n <span class=\"folder-name\">{{ node.project.Name }}</span>\n <span class=\"folder-count\">{{ node.totalCount }}</span>\n <div class=\"folder-actions\" (click)=\"$event.stopPropagation()\">\n <button class=\"folder-action-btn\" (click)=\"createFolder(node.project.ID, $event)\" title=\"New Subfolder\">\n <i class=\"fas fa-folder-plus\"></i>\n </button>\n <button class=\"folder-action-btn\" (click)=\"editFolder(node.project, $event)\" title=\"Edit Folder\">\n <i class=\"fas fa-pen\"></i>\n </button>\n <button class=\"folder-action-btn danger\" (click)=\"deleteFolder(node.project, $event)\" title=\"Delete Folder\">\n <i class=\"fas fa-trash\"></i>\n </button>\n </div>\n </div>\n @if (isFolderExpanded(node.project.ID)) {\n <div class=\"folder-children\">\n @for (child of node.children; track child.project.ID) {\n @if (!isSearching || child.hasContent) {\n <ng-container [ngTemplateOutlet]=\"folderNode\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\n }\n }\n @for (conversation of node.conversations; track conversation.ID) {\n <ng-container [ngTemplateOutlet]=\"conversationItem\" [ngTemplateOutletContext]=\"{ $implicit: conversation, depth: node.depth + 1 }\"></ng-container>\n }\n @if (node.totalCount === 0 && !isSearching) {\n <div class=\"folder-empty-hint\" [style.paddingLeft.px]=\"26 + node.depth * 14\">Empty — drop a conversation here</div>\n }\n </div>\n }\n </ng-template>\n\n <!-- Shared conversation row used by Pinned, folders, and Ungrouped/Messages -->\n <ng-template #conversationItem let-conversation let-depth=\"depth\">\n <div class=\"conversation-item\"\n [class.active]=\"IsConversationActive(conversation)\"\n [class.renamed]=\"IsConversationRenamed(conversation)\"\n [class.dragging]=\"IsConversationDragging(conversation)\"\n [style.paddingLeft.px]=\"depth ? 16 + depth * 14 : 16\"\n [draggable]=\"!isSelectionMode\"\n (dragstart)=\"onConversationDragStart(conversation, $event)\"\n (dragend)=\"onConversationDragEnd()\"\n (click)=\"handleConversationClick(conversation)\">\n @if (isSelectionMode) {\n <div class=\"conversation-checkbox\">\n <input type=\"checkbox\"\n [checked]=\"selectedConversationIds.has(conversation.ID)\"\n (click)=\"$event.stopPropagation(); toggleConversationSelection(conversation.ID)\">\n </div>\n }\n <div class=\"conversation-icon-wrapper\">\n @if (hasActiveTasks(conversation.ID)) {\n <div class=\"conversation-icon has-tasks\">\n <i class=\"fas fa-spinner fa-pulse\"></i>\n </div>\n }\n <div class=\"badge-overlay\">\n <mj-notification-badge [conversationId]=\"conversation.ID\"></mj-notification-badge>\n </div>\n </div>\n <div class=\"conversation-info\" [title]=\"conversation.Name + (conversation.Description ? '\\n' + conversation.Description : '')\">\n <div class=\"conversation-name\">\n {{ conversation.Name }}\n @if (isSharedWithMe(conversation)) {\n <i class=\"fas fa-share-nodes shared-indicator\"\n [title]=\"sharedWithMeTooltip(conversation)\"></i>\n }\n </div>\n <div class=\"conversation-preview\">{{ conversation.Description }}</div>\n </div>\n @if (!isSelectionMode) {\n <div class=\"conversation-actions\">\n <button class=\"menu-btn\" (click)=\"toggleMenu(conversation.ID, $event)\" title=\"More options\">\n <i class=\"fas fa-ellipsis\"></i>\n </button>\n @if (IsMenuOpen(conversation)) {\n <div class=\"context-menu\" (click)=\"$event.stopPropagation()\">\n @if (IsMoveSubmenuOpen(conversation)) {\n <button class=\"menu-item back\" (click)=\"closeMoveSubmenu($event)\">\n <i class=\"fas fa-chevron-left\"></i>\n <span>Move to folder</span>\n </button>\n <div class=\"menu-divider\"></div>\n <div class=\"move-folder-list\">\n <button class=\"menu-item\" [class.current]=\"!conversation.ProjectID\" (click)=\"selectMoveTarget(conversation, null)\">\n <i class=\"fas fa-inbox\"></i>\n <span>No folder</span>\n </button>\n @for (f of flatFolders; track f.project.ID) {\n <button class=\"menu-item\" [class.current]=\"IsInFolder(conversation, f.project.ID)\"\n [style.paddingLeft.px]=\"14 + f.depth * 12\"\n (click)=\"selectMoveTarget(conversation, f.project.ID)\">\n <i class=\"fas {{ f.project.Icon || 'fa-folder' }}\" [style.color]=\"f.project.Color || null\"></i>\n <span>{{ f.project.Name }}</span>\n </button>\n }\n </div>\n <div class=\"menu-divider\"></div>\n <button class=\"menu-item\" (click)=\"createFolderForConversation(conversation, $event)\">\n <i class=\"fas fa-folder-plus\"></i>\n <span>New folder…</span>\n </button>\n } @else {\n <button class=\"menu-item\" (click)=\"togglePin(conversation, $event)\">\n <i class=\"fas fa-thumbtack\"></i>\n <span>{{ conversation.IsPinned ? 'Unpin' : 'Pin' }}</span>\n </button>\n <button class=\"menu-item\" (click)=\"openMoveSubmenu(conversation.ID, $event)\">\n <i class=\"fas fa-folder-tree\"></i>\n <span>Move to folder</span>\n <i class=\"fas fa-chevron-right submenu-arrow\"></i>\n </button>\n <button class=\"menu-item\" (click)=\"renameConversation(conversation); closeMenu()\">\n <i class=\"fas fa-edit\"></i>\n <span>Rename</span>\n </button>\n <div class=\"menu-divider\"></div>\n <button class=\"menu-item danger\" (click)=\"deleteConversation(conversation); closeMenu()\">\n <i class=\"fas fa-trash\"></i>\n <span>Delete</span>\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n </ng-template>\n `,\n styles: [`\n :host {\n display: block;\n height: 100%;\n /* White-label theming tokens for the list panel. The public\n --mj-chat-list-* custom properties are host-overridable (set\n them at :root or on any ancestor); the private --conv-list-* names\n resolve the fallback ONCE here so the 70+ usages below stay simple.\n (A self-referential var() fallback would be a custom-property cycle,\n so the two-name indirection is required, not stylistic.) Defaults\n preserve the stock look exactly: a brand-secondary panel with\n on-secondary ink. Hover/border/divider states derive from the ink via\n color-mix, so they follow automatically when the ink is remapped.\n The accent trio drives the panel's ACTION surfaces (New Conversation\n button, search-focus ring, checkbox tick, drag-over highlights) —\n independent of the active-row pair so a host can tint actions on their\n own; defaults to the brand-primary action color, unchanged.\n --conv-list-hover-bg is the row-hover wash: it defaults to the same\n ink-derived tint as before (so a bg/ink remap still gives a neutral\n hover), but a host can point it at a brand tint to make hover an accent\n cue while keeping the panel itself on a neutral surface. */\n --conv-list-bg: var(--mj-chat-list-bg, var(--mj-brand-secondary));\n --conv-list-ink: var(--mj-chat-list-ink, var(--mj-brand-on-secondary));\n --conv-list-active-bg: var(--mj-chat-list-active-bg, var(--mj-brand-primary));\n --conv-list-active-ink: var(--mj-chat-list-active-ink, var(--mj-brand-on-secondary));\n --conv-list-active-hover-bg: var(--mj-chat-list-active-hover-bg, var(--mj-brand-primary-hover));\n --conv-list-accent: var(--mj-chat-list-accent, var(--mj-brand-primary));\n --conv-list-accent-ink: var(--mj-chat-list-accent-ink, var(--mj-text-inverse));\n --conv-list-accent-hover: var(--mj-chat-list-accent-hover, var(--mj-brand-primary-hover));\n --conv-list-hover-bg: var(--mj-chat-list-hover-bg, color-mix(in srgb, var(--conv-list-ink) 8%, transparent));\n }\n .conversation-list { display: flex; flex-direction: column; height: 100%; background: var(--conv-list-bg); }\n .list-header { padding: 8px; border-bottom: 1px solid color-mix(in srgb, var(--conv-list-ink) 10%, transparent); }\n .search-input {\n width: 100%;\n padding: 8px 12px;\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 20%, transparent);\n border-radius: 6px;\n color: var(--conv-list-ink);\n font-size: 13px;\n transition: all 0.2s;\n }\n .search-input::placeholder { color: color-mix(in srgb, var(--conv-list-ink) 50%, transparent); }\n .search-input:focus { outline: none; background: color-mix(in srgb, var(--conv-list-ink) 15%, transparent); border-color: var(--conv-list-accent); }\n .btn-new-conversation {\n width: calc(100% - 16px);\n margin: 8px;\n padding: 10px;\n background: var(--conv-list-accent);\n color: var(--conv-list-accent-ink);\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n transition: background 0.2s;\n flex-shrink: 0;\n }\n .btn-new-conversation:hover { background: var(--conv-list-accent-hover); }\n .btn-new-conversation i { font-size: 14px; }\n .list-content { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0; }\n\n /* Collapsible Sections */\n .sidebar-section { margin-bottom: 20px; }\n .pinned-section .section-title .section-icon {\n color: var(--mj-status-warning);\n font-size: 11px;\n margin-left: 2px;\n }\n .section-header {\n padding: 4px 16px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n cursor: pointer;\n color: var(--conv-list-ink);\n font-size: 13px;\n font-weight: 500;\n transition: background 0.2s;\n user-select: none;\n }\n .section-header:hover { background: color-mix(in srgb, var(--conv-list-ink) 8%, transparent); }\n .section-title {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .section-title i {\n font-size: 10px;\n }\n .section-title i:not(.section-icon) {\n transition: transform 0.2s;\n }\n .section-header.expanded .section-title i:not(.section-icon) { transform: rotate(90deg); }\n .chat-list {\n padding: 4px 0;\n display: none;\n }\n .chat-list.expanded { display: block; }\n\n .conversation-item {\n padding: 6px 5px 6px 16px;\n cursor: pointer;\n display: flex;\n gap: 8px;\n align-items: center;\n transition: all 0.2s;\n position: relative;\n color: color-mix(in srgb, var(--conv-list-ink) 70%, transparent);\n font-size: 14px;\n min-height: 45px;\n }\n .conversation-item:hover { background: var(--conv-list-hover-bg); color: var(--conv-list-ink); }\n .conversation-item:hover .conversation-actions { opacity: 1; }\n .conversation-item.active { background: var(--conv-list-active-bg); color: var(--conv-list-active-ink); }\n .conversation-icon-wrapper { position: relative; flex-shrink: 0; }\n .conversation-icon { font-size: 12px; width: 16px; text-align: center; }\n .conversation-icon.has-tasks { color: var(--mj-status-warning); }\n .badge-overlay { position: absolute; top: -4px; right: -4px; }\n .conversation-info { flex: 1; min-width: 0; }\n .conversation-name { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }\n .shared-indicator { font-size: 10px; color: color-mix(in srgb, var(--conv-list-ink) 55%, transparent); flex-shrink: 0; }\n .conversation-item.active .shared-indicator { color: color-mix(in srgb, var(--conv-list-active-ink) 85%, transparent); }\n .conversation-preview { font-size: 12px; color: color-mix(in srgb, var(--conv-list-ink) 50%, transparent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n .conversation-item.active .conversation-preview { color: color-mix(in srgb, var(--conv-list-active-ink) 80%, transparent); }\n .conversation-meta { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }\n\n /* Project Badge */\n .project-badge {\n display: inline-block;\n padding: 2px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 600;\n margin-left: auto;\n background-color: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: color-mix(in srgb, var(--conv-list-ink) 60%, transparent);\n white-space: nowrap;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .conversation-item:hover .project-badge {\n background-color: color-mix(in srgb, var(--conv-list-ink) 15%, transparent);\n color: color-mix(in srgb, var(--conv-list-ink) 80%, transparent);\n }\n .conversation-item.active .project-badge {\n background-color: color-mix(in srgb, var(--conv-list-active-ink) 20%, transparent);\n color: var(--conv-list-active-ink);\n }\n\n .conversation-actions {\n position: absolute;\n right: 5px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n z-index: 10;\n }\n .conversation-item:hover .conversation-actions { opacity: 1; pointer-events: auto; }\n .conversation-item.active .conversation-actions { opacity: 1; pointer-events: auto; }\n .conversation-actions > * { pointer-events: auto; }\n .pinned-icon { color: var(--mj-brand-accent); font-size: 12px; }\n\n /* Task Indicator */\n .task-indicator {\n color: var(--mj-status-warning);\n font-size: 12px;\n margin-right: 8px;\n flex-shrink: 0;\n animation: pulse-glow 2s ease-in-out infinite;\n }\n @keyframes pulse-glow {\n 0%, 100% {\n opacity: 1;\n filter: drop-shadow(0 0 2px var(--mj-status-warning));\n }\n 50% {\n opacity: 0.6;\n filter: drop-shadow(0 0 4px var(--mj-status-warning));\n }\n }\n .conversation-item.active .task-indicator {\n color: var(--mj-status-warning);\n }\n\n .menu-btn {\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: color-mix(in srgb, var(--conv-list-ink) 70%, transparent);\n background: var(--conv-list-bg) !important;\n border: none;\n cursor: pointer;\n transition: all 0.2s;\n }\n .menu-btn:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 15%, transparent) !important;\n color: var(--conv-list-ink);\n }\n .conversation-item.active .menu-btn {\n background: var(--conv-list-active-hover-bg) !important;\n color: var(--conv-list-active-ink);\n }\n .menu-btn i { font-size: 14px; }\n\n .context-menu {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 4px;\n min-width: 160px;\n background: var(--conv-list-bg);\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 15%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n overflow: hidden;\n pointer-events: auto;\n }\n\n .menu-item {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 14px;\n background: transparent;\n border: none;\n color: color-mix(in srgb, var(--conv-list-ink) 85%, transparent);\n font-size: 14px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .menu-item:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: var(--conv-list-ink);\n }\n\n .menu-item i {\n width: 16px;\n font-size: 13px;\n color: color-mix(in srgb, var(--conv-list-ink) 60%, transparent);\n }\n\n .menu-item:hover i {\n color: var(--conv-list-ink);\n }\n\n .menu-item.danger {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 15%, transparent);\n color: var(--mj-status-error);\n }\n\n .menu-item.danger i {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger:hover i {\n color: var(--mj-status-error);\n }\n\n .menu-divider {\n height: 1px;\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n margin: 4px 0;\n }\n\n /* Rename Animation */\n .conversation-item.renamed {\n animation: renameHighlight 1500ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n /* Brand-token ramp (was hardcoded tailwind blue/purple/emerald rgba values,\n which ignored theming): primary/accent open the flash, success/primary\n carry the fade, at the original alpha ramp (40/35/30/20; glows 50-20). */\n @keyframes renameHighlight {\n 0% {\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-brand-primary) 40%, transparent),\n color-mix(in srgb, var(--mj-brand-accent) 40%, transparent));\n transform: scale(1.03);\n box-shadow: 0 0 20px color-mix(in srgb, var(--mj-brand-primary) 50%, transparent);\n }\n 25% {\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-brand-primary) 35%, transparent),\n color-mix(in srgb, var(--mj-brand-accent) 35%, transparent));\n box-shadow: 0 0 15px color-mix(in srgb, var(--mj-brand-primary) 40%, transparent);\n }\n 50% {\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-status-success) 30%, transparent),\n color-mix(in srgb, var(--mj-brand-primary) 30%, transparent));\n transform: scale(1.02);\n box-shadow: 0 0 10px color-mix(in srgb, var(--mj-status-success) 30%, transparent);\n }\n 75% {\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-status-success) 20%, transparent),\n color-mix(in srgb, var(--mj-brand-primary) 20%, transparent));\n box-shadow: 0 0 5px color-mix(in srgb, var(--mj-status-success) 20%, transparent);\n }\n 100% {\n background: transparent;\n transform: scale(1);\n box-shadow: none;\n }\n }\n\n /* Selection Mode Styles */\n .header-top {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n /* Header menu button and dropdown */\n .header-menu-container {\n position: relative;\n flex-shrink: 0;\n }\n\n .btn-menu {\n width: 32px;\n height: 32px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--conv-list-ink) 70%, transparent);\n cursor: pointer;\n transition: all 0.2s;\n }\n\n .btn-menu:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: var(--conv-list-ink);\n border-color: color-mix(in srgb, var(--conv-list-ink) 30%, transparent);\n }\n\n .header-dropdown-menu {\n position: absolute;\n top: calc(100% + 4px);\n right: 0;\n min-width: 200px;\n background: var(--conv-list-bg);\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 15%, transparent);\n border-radius: 8px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n overflow: hidden;\n padding: 4px 0;\n }\n\n .header-dropdown-menu .dropdown-item {\n width: 100%;\n display: flex;\n align-items: center;\n gap: 10px;\n padding: 10px 14px;\n background: transparent;\n border: none;\n color: color-mix(in srgb, var(--conv-list-ink) 85%, transparent);\n font-size: 13px;\n text-align: left;\n cursor: pointer;\n transition: all 0.15s;\n }\n\n .header-dropdown-menu .dropdown-item:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: var(--conv-list-ink);\n }\n\n .header-dropdown-menu .dropdown-item i {\n width: 16px;\n font-size: 13px;\n color: color-mix(in srgb, var(--conv-list-ink) 60%, transparent);\n }\n\n .header-dropdown-menu .dropdown-item:hover i {\n color: var(--conv-list-ink);\n }\n\n .header-dropdown-menu .dropdown-item .shortcut {\n margin-left: auto;\n font-size: 11px;\n color: color-mix(in srgb, var(--conv-list-ink) 40%, transparent);\n font-family: system-ui, -apple-system, sans-serif;\n }\n\n .btn-select {\n padding: 8px 12px;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--conv-list-ink) 70%, transparent);\n font-size: 13px;\n font-weight: 500;\n display: flex;\n align-items: center;\n gap: 6px;\n cursor: pointer;\n transition: all 0.2s;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .btn-select:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: var(--conv-list-ink);\n border-color: color-mix(in srgb, var(--conv-list-ink) 30%, transparent);\n }\n\n .conversation-checkbox {\n display: flex;\n align-items: center;\n margin-right: 8px;\n flex-shrink: 0;\n }\n\n .conversation-checkbox input[type=\"checkbox\"] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--conv-list-accent);\n }\n\n .selection-action-bar {\n position: sticky;\n bottom: 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 12px 16px;\n background: var(--conv-list-bg);\n border-top: 1px solid color-mix(in srgb, var(--conv-list-ink) 15%, transparent);\n gap: 12px;\n flex-wrap: wrap;\n flex-shrink: 0;\n }\n\n .selection-info {\n display: flex;\n align-items: center;\n gap: 12px;\n color: color-mix(in srgb, var(--conv-list-ink) 90%, transparent);\n font-size: 14px;\n font-weight: 500;\n flex: 1 1 auto;\n min-width: 150px;\n }\n\n .selection-count {\n color: var(--conv-list-ink);\n }\n\n .link-btn {\n background: none;\n border: none;\n color: var(--mj-brand-accent);\n cursor: pointer;\n font-size: 13px;\n text-decoration: underline;\n padding: 0;\n transition: color 0.2s;\n }\n\n .link-btn:hover {\n color: var(--conv-list-ink);\n }\n\n .selection-actions {\n display: flex;\n gap: 8px;\n flex: 0 0 auto;\n }\n\n .btn-cancel {\n padding: 8px 16px;\n background: transparent;\n border: 1px solid color-mix(in srgb, var(--conv-list-ink) 20%, transparent);\n border-radius: 6px;\n color: color-mix(in srgb, var(--conv-list-ink) 70%, transparent);\n cursor: pointer;\n font-size: 13px;\n font-weight: 500;\n transition: all 0.2s;\n }\n\n .btn-cancel:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 10%, transparent);\n color: var(--conv-list-ink);\n }\n\n .btn-delete-bulk {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 16px;\n background: var(--mj-status-error);\n border: none;\n border-radius: 6px;\n /* Deliberately NOT --conv-list-ink: this ink sits on the error-red button,\n not the panel, so it must not follow a panel remap. (brand-on-secondary\n stays light in both modes; text-inverse flips dark in dark mode.) */\n color: var(--mj-brand-on-secondary);\n cursor: pointer;\n font-size: 13px;\n font-weight: 600;\n transition: all 0.2s;\n }\n\n .btn-delete-bulk:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 80%, black);\n }\n\n .btn-delete-bulk:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-delete-bulk i {\n font-size: 12px;\n }\n\n /* Folders */\n .section-action-btn {\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: color-mix(in srgb, var(--conv-list-ink) 60%, transparent);\n cursor: pointer;\n transition: all 0.2s;\n }\n .section-action-btn:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 15%, transparent);\n color: var(--conv-list-ink);\n }\n .section-action-btn i { font-size: 12px; }\n\n .folder-row {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 5px 8px 5px 12px;\n cursor: pointer;\n color: color-mix(in srgb, var(--conv-list-ink) 80%, transparent);\n font-size: 13px;\n transition: background 0.15s;\n user-select: none;\n position: relative;\n }\n .folder-row:hover { background: color-mix(in srgb, var(--conv-list-ink) 8%, transparent); }\n .folder-row.drag-over {\n background: color-mix(in srgb, var(--conv-list-accent) 25%, transparent);\n box-shadow: inset 0 0 0 1px var(--conv-list-accent);\n }\n .folder-row.dragging { opacity: 0.4; }\n .section-header.drag-over {\n background: color-mix(in srgb, var(--conv-list-accent) 18%, transparent);\n box-shadow: inset 0 0 0 1px var(--conv-list-accent);\n border-radius: 6px;\n }\n .folder-chevron {\n font-size: 9px;\n width: 10px;\n flex-shrink: 0;\n transition: transform 0.2s;\n color: color-mix(in srgb, var(--conv-list-ink) 55%, transparent);\n }\n .folder-chevron.expanded { transform: rotate(90deg); }\n .folder-icon { font-size: 12px; width: 16px; text-align: center; flex-shrink: 0; }\n .folder-name {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n font-weight: 600;\n }\n .folder-count {\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--conv-list-ink) 50%, transparent);\n flex-shrink: 0;\n margin-left: auto;\n padding-left: 6px;\n text-align: right;\n }\n .folder-actions {\n position: absolute;\n right: 6px;\n top: 50%;\n transform: translateY(-50%);\n display: flex;\n gap: 2px;\n opacity: 0;\n pointer-events: none;\n transition: opacity 0.2s;\n z-index: 5;\n }\n .folder-row:hover .folder-actions { opacity: 1; pointer-events: auto; }\n .folder-row:hover .folder-count { opacity: 0; }\n .folder-action-btn {\n width: 22px;\n height: 22px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n border: none;\n border-radius: 4px;\n color: color-mix(in srgb, var(--conv-list-ink) 60%, transparent);\n cursor: pointer;\n transition: all 0.15s;\n }\n .folder-action-btn:hover {\n background: color-mix(in srgb, var(--conv-list-ink) 18%, transparent);\n color: var(--conv-list-ink);\n }\n .folder-action-btn.danger:hover {\n background: color-mix(in srgb, var(--mj-status-error) 18%, transparent);\n color: var(--mj-status-error);\n }\n .folder-action-btn i { font-size: 11px; }\n .folder-children { display: block; }\n .folder-empty-hint {\n padding: 6px 16px;\n font-size: 11px;\n font-style: italic;\n color: color-mix(in srgb, var(--conv-list-ink) 45%, transparent);\n }\n .ungrouped-section.drag-over {\n background: color-mix(in srgb, var(--conv-list-accent) 12%, transparent);\n box-shadow: inset 0 0 0 1px var(--conv-list-accent);\n border-radius: 6px;\n }\n\n /* Dragging state */\n .conversation-item { user-select: none; }\n .conversation-item.dragging { opacity: 0.4; }\n\n /* Move-to-folder submenu */\n .menu-item.back { font-weight: 600; }\n .menu-item .submenu-arrow { margin-left: auto; font-size: 10px; }\n .menu-item.current { background: color-mix(in srgb, var(--conv-list-accent) 18%, transparent); }\n .move-folder-list { max-height: 240px; overflow-y: auto; }\n `]\n})\nexport class ConversationListComponent implements OnInit, OnDestroy {\n @Input() environmentId!: string;\n @Input() currentUser!: UserInfo;\n @Input() selectedConversationId: string | null = null;\n @Input() renamedConversationId: string | null = null;\n @Input() isSidebarPinned: boolean = true; // Whether sidebar is pinned (stays open after selection)\n @Input() isMobileView: boolean = false; // Whether we're on mobile (no pin options)\n\n // ── White-label chrome toggles (all default true = stock rendering) ──\n /** Show the search box in the list header. Flipping to false clears any active\n * search so a hidden filter can't keep silently narrowing the list. */\n @Input()\n set showSearch(value: boolean) {\n if (!value && this._searchQuery) {\n this.searchQuery = ''; // setter rebuilds the groupings\n }\n this._showSearch = value;\n }\n get showSearch(): boolean {\n return this._showSearch;\n }\n private _showSearch = true;\n /** Show the \"New Conversation\" button. */\n @Input() showNewConversationButton: boolean = true;\n /** Show the ⋯ header options menu (refresh / select / group-by / hide sidebar). */\n @Input() showHeaderMenu: boolean = true;\n /** Show the collapsible Pinned / Folders / Messages section headers. When false,\n * the list renders FLAT and fully expanded: folder grouping is bypassed (the\n * folder tree's root drop-zone and New Folder action live in the section\n * header, so a headerless tree would allow one-way folder nesting) — the\n * chrome-less rendering for embedded hosts. */\n @Input() showSectionHeaders: boolean = true;\n\n @Output() conversationSelected = new EventEmitter<string>();\n @Output() conversationDeleted = new EventEmitter<string>(); // Emits the deleted conversation ID\n @Output() newConversationRequested = new EventEmitter<void>();\n @Output() pinSidebarRequested = new EventEmitter<void>(); // Request to pin sidebar\n @Output() unpinSidebarRequested = new EventEmitter<void>(); // Request to unpin (collapse) sidebar\n @Output() refreshRequested = new EventEmitter<void>(); // Emitted after list refresh so chat area can also reload\n\n public directMessagesExpanded: boolean = true;\n public pinnedExpanded: boolean = true;\n public foldersExpanded: boolean = true;\n public ungroupedExpanded: boolean = true;\n public openMenuConversationId: string | null = null;\n public conversationIdsWithTasks = new Set<string>();\n public isSelectionMode: boolean = false;\n public selectedConversationIds = new Set<string>();\n public isHeaderMenuOpen: boolean = false;\n public isRefreshing: boolean = false;\n\n /** UserInfoEngine key for persisting folder collapse state + group-by mode. */\n private static readonly FolderPrefsKey = 'mj.conversations.folderPrefs.v1';\n\n /** How the conversation list is grouped. 'project' = folders, 'none' = flat list. */\n public groupBy: ConversationGroupBy = 'project';\n\n /** Precomputed groupings, rebuilt whenever conversations/projects/search change. */\n public pinnedConversations: MJConversationEntity[] = [];\n public unpinnedConversations: MJConversationEntity[] = [];\n public ungroupedConversations: MJConversationEntity[] = [];\n public folderTree: FolderNode[] = [];\n /** Flattened folder list (depth-ordered) for the \"Move to folder\" menu. */\n public flatFolders: FolderNode[] = [];\n\n /** Folder IDs (normalized) whose children are collapsed. Absent = expanded. */\n private collapsedFolderIds = new Set<string>();\n\n /** Drag-and-drop state. */\n public draggedConversationId: string | null = null;\n public draggedFolderId: string | null = null;\n public dragOverTargetId: string | null = null;\n\n /** When set, the open conversation menu is showing its \"Move to folder\" picker. */\n public moveSubmenuConversationId: string | null = null;\n\n private _searchQuery: string = '';\n\n private destroy$ = new Subject<void>();\n\n private engine = ConversationEngine.Instance;\n\n // Local UI state for loading/refreshing\n public IsLoading: boolean = false;\n\n constructor(\n private dialogService: DialogService,\n private notificationService: NotificationService,\n private activeTasksService: ActiveTasksService,\n private mjDialogService: MJDialogService,\n private cdr: ChangeDetectorRef\n ) {}\n\n get searchQuery(): string {\n return this._searchQuery;\n }\n set searchQuery(value: string) {\n this._searchQuery = value ?? '';\n this.rebuildGroups();\n }\n\n /** True when a search filter is active. */\n get isSearching(): boolean {\n return this._searchQuery.trim().length > 0;\n }\n\n /** Conversations matching the current search (used by selection-mode helpers). */\n get filteredConversations(): MJConversationEntity[] {\n return this.filterConversations(this.engine.Conversations);\n }\n\n private filterConversations(conversations: MJConversationEntity[]): MJConversationEntity[] {\n if (!this.isSearching) {\n return conversations;\n }\n const lowerQuery = this._searchQuery.toLowerCase();\n return conversations.filter(c =>\n (c.Name?.toLowerCase().includes(lowerQuery)) ||\n (c.Description?.toLowerCase().includes(lowerQuery))\n );\n }\n\n ngOnInit() {\n // Restore persisted folder collapse state + group-by preference\n this.loadFolderPrefs();\n\n // Load conversations (and folders) on init\n this.engine.LoadConversations(this.environmentId, this.currentUser, false);\n\n // Rebuild the precomputed groupings whenever conversations OR projects change\n // (pin, archive, rename, move-to-folder, folder create/rename/delete, etc.).\n this.engine.Conversations$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.rebuildGroups();\n this.cdr.detectChanges();\n });\n\n this.engine.Projects$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(() => {\n this.rebuildGroups();\n this.cdr.detectChanges();\n });\n\n // Subscribe to conversation IDs with active tasks (hot set)\n this.activeTasksService.conversationIdsWithTasks$.pipe(\n takeUntil(this.destroy$)\n ).subscribe(conversationIds => {\n this.conversationIdsWithTasks = conversationIds;\n this.cdr.detectChanges(); // Force change detection to ensure spinner icons update reliably\n });\n }\n\n ngOnDestroy() {\n this.destroy$.next();\n this.destroy$.complete();\n }\n\n @HostListener('document:click')\n onDocumentClick(): void {\n // Close menus when clicking outside\n if (this.openMenuConversationId) {\n this.closeMenu();\n }\n if (this.isHeaderMenuOpen) {\n this.closeHeaderMenu();\n }\n }\n\n public toggleHeaderMenu(event: Event): void {\n event.stopPropagation();\n this.isHeaderMenuOpen = !this.isHeaderMenuOpen;\n }\n\n public closeHeaderMenu(): void {\n this.isHeaderMenuOpen = false;\n }\n\n public onSelectConversationsClick(event: Event): void {\n event.stopPropagation();\n this.toggleSelectionMode();\n this.closeHeaderMenu();\n }\n\n public onToggleGroupByClick(event: Event): void {\n event.stopPropagation();\n this.toggleGroupBy();\n this.closeHeaderMenu();\n }\n\n public async onRefreshConversationsClick(event: Event): Promise<void> {\n event.stopPropagation();\n if (this.isRefreshing) return;\n\n this.isRefreshing = true;\n try {\n await this.engine.LoadConversations(this.environmentId, this.currentUser, true);\n // Signal parent to also reload messages in the active conversation\n this.refreshRequested.emit();\n } catch (error) {\n console.error('Error refreshing conversations:', error);\n await this.dialogService.alert('Error', 'Failed to refresh conversations. Please try again.');\n } finally {\n this.isRefreshing = false;\n this.cdr.detectChanges();\n this.closeHeaderMenu();\n }\n }\n\n public onPinSidebarClick(event: Event): void {\n event.stopPropagation();\n this.closeHeaderMenu();\n this.pinSidebarRequested.emit();\n }\n\n public onUnpinSidebarClick(event: Event): void {\n event.stopPropagation();\n this.closeHeaderMenu();\n this.unpinSidebarRequested.emit();\n }\n\n public toggleDirectMessages(): void {\n this.directMessagesExpanded = !this.directMessagesExpanded;\n }\n\n public togglePinned(): void {\n this.pinnedExpanded = !this.pinnedExpanded;\n }\n\n public toggleFolders(): void {\n this.foldersExpanded = !this.foldersExpanded;\n }\n\n public toggleUngrouped(): void {\n this.ungroupedExpanded = !this.ungroupedExpanded;\n }\n\n // ========================================================================\n // FOLDER GROUPING\n // ========================================================================\n\n /**\n * Recomputes pinned/unpinned/ungrouped lists and the folder tree from the\n * engine's conversation + project caches and the current search filter.\n */\n private rebuildGroups(): void {\n const matching = this.filterConversations(this.engine.Conversations);\n this.pinnedConversations = matching.filter(c => c.IsPinned);\n this.unpinnedConversations = matching.filter(c => !c.IsPinned);\n\n const projects = this.engine.Projects;\n const projectIds = new Set(projects.map(p => NormalizeUUID(p.ID)));\n\n // Bucket unpinned conversations by their folder (pinned ones live in the\n // Pinned section). Conversations with no/unknown folder are \"ungrouped\".\n const conversationsByProject = new Map<string, MJConversationEntity[]>();\n const ungrouped: MJConversationEntity[] = [];\n for (const c of this.unpinnedConversations) {\n const pid = c.ProjectID ? NormalizeUUID(c.ProjectID) : null;\n if (pid && projectIds.has(pid)) {\n const arr = conversationsByProject.get(pid) ?? [];\n arr.push(c);\n conversationsByProject.set(pid, arr);\n } else {\n ungrouped.push(c);\n }\n }\n this.ungroupedConversations = ungrouped;\n\n // Index projects by parent. A project whose parent isn't loaded is treated\n // as a root so it never disappears from the tree.\n const childrenByParent = new Map<string | null, MJProjectEntity[]>();\n for (const p of projects) {\n const parentId = p.ParentID ? NormalizeUUID(p.ParentID) : null;\n const key = parentId && projectIds.has(parentId) ? parentId : null;\n const arr = childrenByParent.get(key) ?? [];\n arr.push(p);\n childrenByParent.set(key, arr);\n }\n\n const build = (parentKey: string | null, depth: number): FolderNode[] => {\n const projectsAtLevel = childrenByParent.get(parentKey) ?? [];\n return projectsAtLevel.map(p => {\n const children = build(NormalizeUUID(p.ID), depth + 1);\n const conversations = conversationsByProject.get(NormalizeUUID(p.ID)) ?? [];\n const totalCount = conversations.length + children.reduce((sum, ch) => sum + ch.totalCount, 0);\n const hasContent = conversations.length > 0 || children.some(ch => ch.hasContent);\n return { project: p, depth, conversations, children, totalCount, hasContent };\n });\n };\n this.folderTree = build(null, 0);\n this.flatFolders = this.flattenFolders(this.folderTree);\n }\n\n private flattenFolders(nodes: FolderNode[]): FolderNode[] {\n const out: FolderNode[] = [];\n for (const node of nodes) {\n out.push(node);\n out.push(...this.flattenFolders(node.children));\n }\n return out;\n }\n\n private findFolderNode(nodes: FolderNode[], projectId: string): FolderNode | null {\n for (const node of nodes) {\n if (UUIDsEqual(node.project.ID, projectId)) return node;\n const found = this.findFolderNode(node.children, projectId);\n if (found) return found;\n }\n return null;\n }\n\n public isFolderExpanded(projectId: string): boolean {\n return !this.collapsedFolderIds.has(NormalizeUUID(projectId));\n }\n\n public toggleFolder(projectId: string): void {\n const key = NormalizeUUID(projectId);\n if (this.collapsedFolderIds.has(key)) {\n this.collapsedFolderIds.delete(key);\n } else {\n this.collapsedFolderIds.add(key);\n }\n this.saveFolderPrefs();\n }\n\n public toggleGroupBy(): void {\n this.groupBy = this.groupBy === 'project' ? 'none' : 'project';\n this.saveFolderPrefs();\n this.rebuildGroups();\n }\n\n private loadFolderPrefs(): void {\n try {\n const raw = UserInfoEngine.Instance.GetSetting(ConversationListComponent.FolderPrefsKey);\n if (!raw) return;\n const parsed = JSON.parse(raw) as { collapsed?: string[]; groupBy?: ConversationGroupBy };\n this.collapsedFolderIds = new Set((parsed.collapsed ?? []).map(id => NormalizeUUID(id)));\n if (parsed.groupBy === 'none' || parsed.groupBy === 'project') {\n this.groupBy = parsed.groupBy;\n }\n } catch {\n // Corrupt/legacy value — ignore and use defaults\n }\n }\n\n private saveFolderPrefs(): void {\n const payload = JSON.stringify({\n collapsed: Array.from(this.collapsedFolderIds),\n groupBy: this.groupBy\n });\n UserInfoEngine.Instance.SetSettingDebounced(ConversationListComponent.FolderPrefsKey, payload);\n }\n\n // ========================================================================\n // DRAG & DROP (move conversation into/out of a folder)\n // ========================================================================\n\n public onConversationDragStart(conversation: MJConversationEntity, event: DragEvent): void {\n if (this.isSelectionMode) return;\n this.draggedFolderId = null;\n this.draggedConversationId = conversation.ID;\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', conversation.ID);\n }\n }\n\n public onConversationDragEnd(): void {\n this.draggedConversationId = null;\n this.dragOverTargetId = null;\n }\n\n public onFolderDragStart(node: FolderNode, event: DragEvent): void {\n event.stopPropagation();\n this.draggedConversationId = null;\n this.draggedFolderId = node.project.ID;\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', node.project.ID);\n }\n }\n\n public onFolderDragEnd(): void {\n this.draggedFolderId = null;\n this.dragOverTargetId = null;\n }\n\n public onFolderDragOver(projectId: string, event: DragEvent): void {\n // A conversation can drop onto any folder; a folder can drop onto any folder\n // that isn't itself or one of its own descendants (which would create a cycle).\n const accepts = this.draggedConversationId\n ? true\n : this.draggedFolderId\n ? this.isValidFolderDropTarget(projectId)\n : false;\n if (!accepts) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = projectId;\n }\n\n public onUngroupedDragOver(event: DragEvent): void {\n if (!this.draggedConversationId) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = 'ungrouped';\n }\n\n /** The Folders section header accepts a dragged folder to move it back to the top level. */\n public onFoldersRootDragOver(event: DragEvent): void {\n if (!this.draggedFolderId) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';\n this.dragOverTargetId = 'folders-root';\n }\n\n public onDragLeave(targetId: string): void {\n if (this.dragOverTargetId === targetId) {\n this.dragOverTargetId = null;\n }\n }\n\n public onFolderDrop(project: MJProjectEntity, event: DragEvent): void {\n event.preventDefault();\n const conversationId = this.draggedConversationId;\n const folderId = this.draggedFolderId;\n this.dragOverTargetId = null;\n this.draggedConversationId = null;\n this.draggedFolderId = null;\n if (conversationId) {\n this.moveConversation(conversationId, project.ID);\n } else if (folderId && this.isValidFolderDropTarget(project.ID, folderId)) {\n this.moveFolder(folderId, project.ID);\n }\n }\n\n public onUngroupedDrop(event: DragEvent): void {\n event.preventDefault();\n const conversationId = this.draggedConversationId;\n this.dragOverTargetId = null;\n this.draggedConversationId = null;\n if (conversationId) {\n this.moveConversation(conversationId, null);\n }\n }\n\n public onFoldersRootDrop(event: DragEvent): void {\n event.preventDefault();\n const folderId = this.draggedFolderId;\n this.dragOverTargetId = null;\n this.draggedFolderId = null;\n if (folderId) {\n this.moveFolder(folderId, null);\n }\n }\n\n /**\n * A folder can be dropped onto a target folder only if the target isn't the dragged\n * folder itself and isn't one of its descendants (otherwise we'd create a cycle).\n */\n private isValidFolderDropTarget(targetId: string, draggedId: string | null = this.draggedFolderId): boolean {\n if (!draggedId) return false;\n if (UUIDsEqual(targetId, draggedId)) return false;\n return !this.isDescendantOf(targetId, draggedId);\n }\n\n /** True when `nodeId` is a descendant of `ancestorId` in the folder tree. */\n private isDescendantOf(nodeId: string, ancestorId: string): boolean {\n const byId = new Map(this.engine.Projects.map(p => [NormalizeUUID(p.ID), p]));\n const visited = new Set<string>();\n let current = byId.get(NormalizeUUID(nodeId));\n while (current?.ParentID) {\n const parentKey = NormalizeUUID(current.ParentID);\n if (visited.has(parentKey)) break; // guard against malformed cycles\n visited.add(parentKey);\n if (UUIDsEqual(parentKey, ancestorId)) return true;\n current = byId.get(parentKey);\n }\n return false;\n }\n\n /** Assigns a conversation to a folder (or null to ungroup) and refreshes the view. */\n private async moveConversation(conversationId: string, projectId: string | null): Promise<void> {\n try {\n await this.engine.MoveConversationToProject(conversationId, projectId, this.currentUser);\n // Reveal the destination folder so the user sees where it landed\n if (projectId) {\n this.collapsedFolderIds.delete(NormalizeUUID(projectId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error moving conversation:', error);\n await this.dialogService.alert('Error', 'Failed to move conversation. Please try again.');\n }\n }\n\n /** Reparents a folder under another folder (or to the top level when projectId is null). */\n private async moveFolder(folderId: string, parentId: string | null): Promise<void> {\n // No-op if it's already under that parent\n const folder = this.engine.Projects.find(p => UUIDsEqual(p.ID, folderId));\n const currentParent = folder?.ParentID ?? null;\n const sameParent = (currentParent === null && parentId === null) ||\n (!!currentParent && !!parentId && UUIDsEqual(currentParent, parentId));\n if (sameParent) return;\n\n try {\n await this.engine.MoveProjectToParent(folderId, parentId, this.currentUser);\n // Reveal the new parent so the moved folder is visible\n if (parentId) {\n this.collapsedFolderIds.delete(NormalizeUUID(parentId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error moving folder:', error);\n await this.dialogService.alert('Error', 'Failed to move folder. Please try again.');\n }\n }\n\n // ========================================================================\n // MOVE-TO-FOLDER MENU\n // ========================================================================\n\n public openMoveSubmenu(conversationId: string, event: Event): void {\n event.stopPropagation();\n this.moveSubmenuConversationId = conversationId;\n }\n\n public closeMoveSubmenu(event: Event): void {\n event.stopPropagation();\n this.moveSubmenuConversationId = null;\n }\n\n public IsInFolder(conversation: MJConversationEntity, projectId: string): boolean {\n return !!conversation.ProjectID && UUIDsEqual(conversation.ProjectID, projectId);\n }\n\n public selectMoveTarget(conversation: MJConversationEntity, projectId: string | null): void {\n this.moveConversation(conversation.ID, projectId);\n this.closeMenu();\n }\n\n // ========================================================================\n // FOLDER CRUD (reuses the existing project form modal)\n // ========================================================================\n\n public createFolder(parentId: string | null, event?: Event): void {\n if (event) event.stopPropagation();\n this.openFolderModal(null, parentId);\n }\n\n public editFolder(project: MJProjectEntity, event?: Event): void {\n if (event) event.stopPropagation();\n this.openFolderModal(project, null);\n }\n\n public createFolderForConversation(conversation: MJConversationEntity, event: Event): void {\n event.stopPropagation();\n const conversationId = conversation.ID;\n this.closeMenu();\n this.openFolderModal(null, null, (created) => this.moveConversation(conversationId, created.ID));\n }\n\n private openFolderModal(\n project: MJProjectEntity | null,\n parentId: string | null,\n onCreated?: (project: MJProjectEntity) => void\n ): void {\n const dialogRef = this.mjDialogService.open({\n content: ProjectFormModalComponent,\n width: 600,\n minWidth: 400\n });\n\n const instance = dialogRef.Content!.instance as unknown as ProjectFormModalComponent;\n instance.dialogRef = dialogRef;\n instance.environmentId = this.environmentId;\n instance.currentUser = this.currentUser;\n if (project) instance.project = project;\n if (parentId) instance.parentId = parentId;\n\n instance.projectSaved.subscribe((saved: MJProjectEntity) => {\n // The engine's entity-event handler keeps the projects cache in sync; we\n // just reveal the parent and refresh, then run any post-create action.\n if (parentId) {\n this.collapsedFolderIds.delete(NormalizeUUID(parentId));\n }\n this.rebuildGroups();\n this.cdr.detectChanges();\n if (onCreated) onCreated(saved);\n });\n }\n\n public async deleteFolder(project: MJProjectEntity, event?: Event): Promise<void> {\n if (event) event.stopPropagation();\n\n const node = this.findFolderNode(this.folderTree, project.ID);\n const total = node?.totalCount ?? 0;\n const childCount = node?.children.length ?? 0;\n\n let message = `Are you sure you want to delete the folder \"${project.Name}\"?`;\n if (total > 0 || childCount > 0) {\n message += `\\n\\nConversations inside will be moved out of the folder`;\n message += childCount > 0 ? ` and subfolders will move up one level.` : `.`;\n message += ` Nothing is deleted.`;\n }\n\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Folder',\n message,\n okText: 'Delete',\n cancelText: 'Cancel',\n dangerous: true\n });\n if (!confirmed) return;\n\n try {\n await this.engine.DeleteProject(project.ID, this.currentUser);\n this.collapsedFolderIds.delete(NormalizeUUID(project.ID));\n this.rebuildGroups();\n this.cdr.detectChanges();\n } catch (error) {\n console.error('Error deleting folder:', error);\n await this.dialogService.alert(\n 'Error',\n error instanceof Error ? error.message : 'Failed to delete folder. Please try again.'\n );\n }\n }\n\n IsConversationActive(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(conversation.ID, this.selectedConversationId);\n }\n\n IsConversationRenamed(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(conversation.ID, this.renamedConversationId);\n }\n\n IsMenuOpen(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.openMenuConversationId, conversation.ID);\n }\n\n IsConversationDragging(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.draggedConversationId, conversation.ID);\n }\n\n IsMoveSubmenuOpen(conversation: MJConversationEntity): boolean {\n return UUIDsEqual(this.moveSubmenuConversationId, conversation.ID);\n }\n\n selectConversation(conversation: MJConversationEntity): void {\n this.conversationSelected.emit(conversation.ID);\n // Clear unread notifications when conversation is opened\n this.notificationService.markConversationAsRead(conversation.ID);\n }\n\n async createNewConversation(): Promise<void> {\n // Don't create DB record yet - just show the welcome screen\n // Conversation will be created when user sends first message\n this.newConversationRequested.emit();\n }\n\n async renameConversation(conversation: MJConversationEntity): Promise<void> {\n try {\n const result = await this.dialogService.input({\n title: 'Edit Conversation',\n message: 'Update the name and description for this conversation',\n inputLabel: 'Conversation Name',\n inputValue: conversation.Name || '',\n placeholder: 'My Conversation',\n required: true,\n secondInputLabel: 'Description',\n secondInputValue: conversation.Description || '',\n secondInputPlaceholder: 'Optional description',\n secondInputRequired: false,\n okText: 'Save',\n cancelText: 'Cancel'\n });\n\n if (result) {\n const newName = typeof result === 'string' ? result : result.value;\n const newDescription = typeof result === 'string' ? conversation.Description : result.secondValue;\n\n if (newName !== conversation.Name || newDescription !== conversation.Description) {\n await this.engine.SaveConversation(\n conversation.ID,\n { Name: newName, Description: newDescription || '' },\n this.currentUser\n );\n }\n }\n } catch (error) {\n console.error('Error renaming conversation:', error);\n await this.dialogService.alert('Error', 'Failed to update conversation. Please try again.');\n }\n }\n\n async deleteConversation(conversation: MJConversationEntity): Promise<void> {\n try {\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Conversation',\n message: `Are you sure you want to delete \"${conversation.Name}\"? This action cannot be undone.`,\n okText: 'Delete',\n cancelText: 'Cancel'\n });\n\n if (confirmed) {\n const deletedId = conversation.ID;\n await this.engine.DeleteConversation(deletedId, this.currentUser);\n this.cdr.detectChanges();\n this.conversationDeleted.emit(deletedId);\n }\n } catch (error) {\n console.error('Error deleting conversation:', error);\n await this.dialogService.alert('Error', 'Failed to delete conversation. Please try again.');\n }\n }\n\n toggleMenu(conversationId: string, event: Event): void {\n event.stopPropagation();\n this.openMenuConversationId = this.openMenuConversationId === conversationId ? null : conversationId;\n }\n\n closeMenu(): void {\n this.openMenuConversationId = null;\n this.moveSubmenuConversationId = null;\n }\n\n async togglePin(conversation: MJConversationEntity, event?: Event): Promise<void> {\n if (event) event.stopPropagation();\n this.closeMenu(); // Close immediately on user action — don't wait for the async op\n try {\n await this.engine.PinConversation(conversation.ID, !conversation.IsPinned, this.currentUser);\n } catch (error) {\n console.error('Error toggling pin:', error);\n await this.dialogService.alert('Error', 'Failed to pin/unpin conversation. Please try again.');\n }\n }\n\n hasActiveTasks(conversationId: string): boolean {\n return this.conversationIdsWithTasks.has(conversationId);\n }\n\n /** True when this conversation was shared with the current user by someone else. */\n isSharedWithMe(conversation: MJConversationEntity): boolean {\n return this.engine.GetSharedByInfo(conversation.ID) !== null;\n }\n\n /** Tooltip for the sidebar share icon: \"Shared by {email or name}\". */\n sharedWithMeTooltip(conversation: MJConversationEntity): string {\n const info = this.engine.GetSharedByInfo(conversation.ID);\n if (!info) return 'Shared with you';\n return `Shared by ${info.Email ?? info.Name ?? 'another user'}`;\n }\n\n toggleSelectionMode(): void {\n this.isSelectionMode = !this.isSelectionMode;\n if (!this.isSelectionMode) {\n this.selectedConversationIds.clear();\n }\n }\n\n toggleConversationSelection(conversationId: string): void {\n if (this.selectedConversationIds.has(conversationId)) {\n this.selectedConversationIds.delete(conversationId);\n } else {\n this.selectedConversationIds.add(conversationId);\n }\n }\n\n selectAll(): void {\n this.filteredConversations.forEach(c => {\n this.selectedConversationIds.add(c.ID);\n });\n }\n\n deselectAll(): void {\n this.selectedConversationIds.clear();\n }\n\n async bulkDeleteConversations(): Promise<void> {\n const count = this.selectedConversationIds.size;\n\n if (count === 0) return;\n\n const confirmed = await this.dialogService.confirm({\n title: 'Delete Conversations',\n message: `Are you sure you want to delete ${count} conversation${count > 1 ? 's' : ''}? This action cannot be undone.`,\n okText: 'Delete',\n cancelText: 'Cancel'\n });\n\n if (confirmed) {\n try {\n const result = await this.engine.DeleteMultipleConversations(\n Array.from(this.selectedConversationIds),\n this.currentUser\n );\n\n if (result.Failed.length > 0 && result.Successful.length > 0) {\n // Partial success\n const failedNames = result.Failed.map(f => `\"${f.Name}\"`).join(', ');\n await this.dialogService.alert(\n 'Partial Success',\n `Deleted ${result.Successful.length} of ${count} conversations.\\n\\n` +\n `${result.Failed.length} could not be deleted: ${failedNames}`\n );\n } else if (result.Failed.length > 0 && result.Successful.length === 0) {\n // All failed\n await this.dialogService.alert(\n 'Delete Failed',\n `None of the ${count} conversations could be deleted. They may have already been removed.`\n );\n }\n\n // Emit deleted events for successful deletions\n for (const id of result.Successful) {\n this.conversationDeleted.emit(id);\n }\n\n } catch (error) {\n console.error('Error deleting conversations:', error);\n await this.dialogService.alert('Error', 'Failed to delete conversations. Please try again.');\n } finally {\n // Always exit selection mode after an attempt, whether success or failure\n this.selectedConversationIds.clear();\n this.isSelectionMode = false;\n this.cdr.detectChanges();\n }\n }\n }\n\n handleConversationClick(conversation: MJConversationEntity): void {\n if (this.isSelectionMode) {\n this.toggleConversationSelection(conversation.ID);\n } else {\n this.selectConversation(conversation);\n }\n }\n}"]}
@@ -1,7 +1,7 @@
1
1
  import { EventEmitter } from '@angular/core';
2
2
  import { MJConversationEntity } from '@memberjunction/core-entities';
3
3
  import { UserInfo } from '@memberjunction/core';
4
- import { ExportService, ExportFormat, ExportOptions } from '../../services/export.service';
4
+ import { ExportService, ExportFormat, ExportOptions, ExportBranding } from '../../services/export.service';
5
5
  import { DialogService } from '../../services/dialog.service';
6
6
  import { ToastService } from '../../services/toast.service';
7
7
  import * as i0 from "@angular/core";
@@ -9,15 +9,37 @@ export declare class ExportModalComponent {
9
9
  private exportService;
10
10
  private dialogService;
11
11
  private toastService;
12
- isVisible: boolean;
12
+ private _isVisible;
13
+ set isVisible(value: boolean);
14
+ get isVisible(): boolean;
13
15
  conversation?: MJConversationEntity;
14
16
  currentUser: UserInfo;
17
+ /**
18
+ * Host-supplied export branding (theme tokens / logo / title). When set, the
19
+ * HTML format's "Include branding" checkbox defaults on and the branding is
20
+ * passed to {@link ExportService} on export. See `ExportBranding`.
21
+ */
22
+ branding: ExportBranding | null;
15
23
  cancelled: EventEmitter<void>;
16
24
  exported: EventEmitter<void>;
17
25
  selectedFormat: ExportFormat | null;
18
26
  isExporting: boolean;
19
27
  errorMessage: string;
20
28
  exportOptions: ExportOptions;
29
+ /** Format-aware hint under the "Include branding" checkbox. */
30
+ get brandingHint(): string;
31
+ /**
32
+ * The options actually handed to the service. `includeTheme` is the user's INTENT;
33
+ * this resolves it against the selected format:
34
+ *
35
+ * - HTML with the stylesheet off cannot carry branding (a full-size unstyled logo and
36
+ * an unstyled footer would leak), so it drops.
37
+ * - `includeCSS` is an HTML-only concern and must NOT decide anything for
38
+ * markdown / text / JSON — resolving here rather than mutating `includeTheme` is
39
+ * what keeps an HTML-format toggle from silently following the user into another
40
+ * format.
41
+ */
42
+ private resolveExportOptions;
21
43
  get exportTitle(): string;
22
44
  get canExport(): boolean;
23
45
  formats: {
@@ -32,6 +54,6 @@ export declare class ExportModalComponent {
32
54
  onCancel(): void;
33
55
  private resetForm;
34
56
  static ɵfac: i0.ɵɵFactoryDeclaration<ExportModalComponent, never>;
35
- static ɵcmp: i0.ɵɵComponentDeclaration<ExportModalComponent, "mj-export-modal", never, { "isVisible": { "alias": "isVisible"; "required": false; }; "conversation": { "alias": "conversation"; "required": false; }; "currentUser": { "alias": "currentUser"; "required": false; }; }, { "cancelled": "cancelled"; "exported": "exported"; }, never, never, false, never>;
57
+ static ɵcmp: i0.ɵɵComponentDeclaration<ExportModalComponent, "mj-export-modal", never, { "isVisible": { "alias": "isVisible"; "required": false; }; "conversation": { "alias": "conversation"; "required": false; }; "currentUser": { "alias": "currentUser"; "required": false; }; "branding": { "alias": "branding"; "required": false; }; }, { "cancelled": "cancelled"; "exported": "exported"; }, never, never, false, never>;
36
58
  }
37
59
  //# sourceMappingURL=export-modal.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"export-modal.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/export/export-modal.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;;AAE5D,qBAySa,oBAAoB;IAwD7B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,YAAY;IAzDb,SAAS,UAAS;IAClB,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,WAAW,EAAG,QAAQ,CAAC;IACtB,SAAS,qBAA4B;IACrC,QAAQ,qBAA4B;IAE9C,cAAc,EAAE,YAAY,GAAG,IAAI,CAAc;IACjD,WAAW,UAAS;IACpB,YAAY,SAAM;IAElB,aAAa,EAAE,aAAa,CAK1B;IAEF,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAIvB;IAED,OAAO;eAEkB,YAAY;;;;QAuBnC;gBAGQ,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,YAAY;IAGpC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAMlC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC/B,QAAQ,IAAI,IAAI;IAKhB,OAAO,CAAC,SAAS;yCAzGN,oBAAoB;2CAApB,oBAAoB;CAoHhC"}
1
+ {"version":3,"file":"export-modal.component.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/export/export-modal.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;;AAE5D,qBA6Ua,oBAAoB;IAmH7B,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,YAAY;IApHtB,OAAO,CAAC,UAAU,CAAS;IAC3B,IACI,SAAS,CAAC,KAAK,EAAE,OAAO,EAY3B;IACD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEQ,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,WAAW,EAAG,QAAQ,CAAC;IAChC;;;;OAIG;IACM,QAAQ,EAAE,cAAc,GAAG,IAAI,CAAQ;IACtC,SAAS,qBAA4B;IACrC,QAAQ,qBAA4B;IAE9C,cAAc,EAAE,YAAY,GAAG,IAAI,CAAc;IACjD,WAAW,UAAS;IACpB,YAAY,SAAM;IAElB,aAAa,EAAE,aAAa,CAO1B;IAEF,+DAA+D;IAC/D,IAAI,YAAY,IAAI,MAAM,CASzB;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,oBAAoB;IAU5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,IAAI,SAAS,IAAI,OAAO,CAIvB;IAED,OAAO;eAEkB,YAAY;;;;QAuBnC;gBAGQ,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,YAAY;IAGpC,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAMlC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC/B,QAAQ,IAAI,IAAI;IAKhB,OAAO,CAAC,SAAS;yCApKN,oBAAoB;2CAApB,oBAAoB;CAiLhC"}