@memberjunction/ng-conversations 5.41.0 → 5.42.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 (53) hide show
  1. package/dist/__tests__/remote-browser-channel.test.js +163 -1
  2. package/dist/__tests__/remote-browser-channel.test.js.map +1 -1
  3. package/dist/lib/components/collection/collections-full-view.component.d.ts +105 -2
  4. package/dist/lib/components/collection/collections-full-view.component.d.ts.map +1 -1
  5. package/dist/lib/components/collection/collections-full-view.component.js +1378 -489
  6. package/dist/lib/components/collection/collections-full-view.component.js.map +1 -1
  7. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts +4 -0
  8. package/dist/lib/components/conversation/conversation-chat-area.component.d.ts.map +1 -1
  9. package/dist/lib/components/conversation/conversation-chat-area.component.js +13 -8
  10. package/dist/lib/components/conversation/conversation-chat-area.component.js.map +1 -1
  11. package/dist/lib/components/conversation/conversation-list.component.d.ts +98 -5
  12. package/dist/lib/components/conversation/conversation-list.component.d.ts.map +1 -1
  13. package/dist/lib/components/conversation/conversation-list.component.js +1102 -401
  14. package/dist/lib/components/conversation/conversation-list.component.js.map +1 -1
  15. package/dist/lib/components/message/message-input.component.js +1 -1
  16. package/dist/lib/components/message/message-input.component.js.map +1 -1
  17. package/dist/lib/components/project/project-form-modal.component.d.ts +5 -1
  18. package/dist/lib/components/project/project-form-modal.component.d.ts.map +1 -1
  19. package/dist/lib/components/project/project-form-modal.component.js +104 -85
  20. package/dist/lib/components/project/project-form-modal.component.js.map +1 -1
  21. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts +22 -0
  22. package/dist/lib/components/realtime/channels/base-realtime-channel-client.d.ts.map +1 -1
  23. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js +40 -0
  24. package/dist/lib/components/realtime/channels/base-realtime-channel-client.js.map +1 -1
  25. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +12 -1
  26. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  27. package/dist/lib/components/realtime/realtime-agent-picker.component.js +97 -19
  28. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  29. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts +33 -0
  30. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.d.ts.map +1 -1
  31. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js +164 -7
  32. package/dist/lib/components/realtime/remote-browser/remote-browser-channel.js.map +1 -1
  33. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts +35 -2
  34. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.d.ts.map +1 -1
  35. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js +67 -4
  36. package/dist/lib/components/realtime/remote-browser/remote-browser-surface.component.js.map +1 -1
  37. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts +1 -0
  38. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.d.ts.map +1 -1
  39. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js +13 -0
  40. package/dist/lib/components/realtime/remote-browser/remote-browser-tools.js.map +1 -1
  41. package/dist/lib/components/workspace/conversation-workspace.component.d.ts +4 -0
  42. package/dist/lib/components/workspace/conversation-workspace.component.d.ts.map +1 -1
  43. package/dist/lib/components/workspace/conversation-workspace.component.js +13 -8
  44. package/dist/lib/components/workspace/conversation-workspace.component.js.map +1 -1
  45. package/dist/lib/services/artifact-state.service.d.ts +1 -1
  46. package/dist/lib/services/artifact-state.service.d.ts.map +1 -1
  47. package/dist/lib/services/artifact-state.service.js +7 -2
  48. package/dist/lib/services/artifact-state.service.js.map +1 -1
  49. package/dist/lib/services/realtime-pairing.d.ts +8 -7
  50. package/dist/lib/services/realtime-pairing.d.ts.map +1 -1
  51. package/dist/lib/services/realtime-pairing.js +19 -9
  52. package/dist/lib/services/realtime-pairing.js.map +1 -1
  53. package/package.json +26 -26
@@ -1,332 +1,532 @@
1
1
  import { Component, Input, Output, EventEmitter, HostListener } from '@angular/core';
2
- import { ConversationEngine } from '@memberjunction/core-entities';
2
+ import { ConversationEngine, UserInfoEngine } from '@memberjunction/core-entities';
3
+ import { ProjectFormModalComponent } from '../project/project-form-modal.component';
3
4
  import { Subject } from 'rxjs';
4
5
  import { takeUntil } from 'rxjs/operators';
5
- import { UUIDsEqual } from '@memberjunction/global';
6
+ import { UUIDsEqual, NormalizeUUID } from '@memberjunction/global';
6
7
  import * as i0 from "@angular/core";
7
8
  import * as i1 from "../../services/dialog.service";
8
9
  import * as i2 from "../../services/notification.service";
9
10
  import * as i3 from "../../services/active-tasks.service";
10
- import * as i4 from "@angular/forms";
11
- import * as i5 from "../notification/notification-badge.component";
11
+ import * as i4 from "@memberjunction/ng-ui-components";
12
+ import * as i5 from "@angular/common";
13
+ import * as i6 from "@angular/forms";
14
+ import * as i7 from "../notification/notification-badge.component";
15
+ const _c0 = a0 => ({ $implicit: a0 });
16
+ const _c1 = (a0, a1) => ({ $implicit: a0, depth: a1 });
12
17
  const _forTrack0 = ($index, $item) => $item.ID;
13
- function ConversationListComponent_Conditional_4_Conditional_3_Conditional_9_Template(rf, ctx) { if (rf & 1) {
14
- const _r4 = i0.ɵɵgetCurrentView();
15
- i0.ɵɵelementStart(0, "button", 21);
16
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Conditional_9_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.onUnpinSidebarClick($event)); });
17
- i0.ɵɵelement(1, "i", 24);
18
+ const _forTrack1 = ($index, $item) => $item.project.ID;
19
+ function ConversationListComponent_Conditional_4_Conditional_3_Conditional_13_Template(rf, ctx) { if (rf & 1) {
20
+ const _r5 = i0.ɵɵgetCurrentView();
21
+ i0.ɵɵelementStart(0, "button", 18);
22
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Conditional_13_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r5); const ctx_r2 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r2.onUnpinSidebarClick($event)); });
23
+ i0.ɵɵelement(1, "i", 22);
18
24
  i0.ɵɵelementStart(2, "span");
19
25
  i0.ɵɵtext(3, "Hide Sidebar");
20
26
  i0.ɵɵelementEnd()();
21
27
  } }
22
28
  function ConversationListComponent_Conditional_4_Conditional_3_Template(rf, ctx) { if (rf & 1) {
23
- const _r3 = i0.ɵɵgetCurrentView();
24
- i0.ɵɵelementStart(0, "div", 18)(1, "button", 19);
25
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onRefreshConversationsClick($event)); });
26
- i0.ɵɵelement(2, "i", 20);
29
+ const _r4 = i0.ɵɵgetCurrentView();
30
+ i0.ɵɵelementStart(0, "div", 15)(1, "button", 16);
31
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onRefreshConversationsClick($event)); });
32
+ i0.ɵɵelement(2, "i", 17);
27
33
  i0.ɵɵelementStart(3, "span");
28
34
  i0.ɵɵtext(4);
29
35
  i0.ɵɵelementEnd()();
30
- i0.ɵɵelementStart(5, "button", 21);
31
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Template_button_click_5_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.onSelectConversationsClick($event)); });
32
- i0.ɵɵelement(6, "i", 22);
36
+ i0.ɵɵelementStart(5, "button", 18);
37
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Template_button_click_5_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onSelectConversationsClick($event)); });
38
+ i0.ɵɵelement(6, "i", 19);
33
39
  i0.ɵɵelementStart(7, "span");
34
40
  i0.ɵɵtext(8, "Select Conversations");
35
41
  i0.ɵɵelementEnd()();
36
- i0.ɵɵconditionalCreate(9, ConversationListComponent_Conditional_4_Conditional_3_Conditional_9_Template, 4, 0, "button", 23);
42
+ i0.ɵɵelementStart(9, "button", 18);
43
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Conditional_3_Template_button_click_9_listener($event) { i0.ɵɵrestoreView(_r4); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.onToggleGroupByClick($event)); });
44
+ i0.ɵɵelement(10, "i", 20);
45
+ i0.ɵɵelementStart(11, "span");
46
+ i0.ɵɵtext(12);
47
+ i0.ɵɵelementEnd()();
48
+ i0.ɵɵconditionalCreate(13, ConversationListComponent_Conditional_4_Conditional_3_Conditional_13_Template, 4, 0, "button", 21);
37
49
  i0.ɵɵelementEnd();
38
50
  } if (rf & 2) {
39
- const ctx_r1 = i0.ɵɵnextContext(2);
51
+ const ctx_r2 = i0.ɵɵnextContext(2);
40
52
  i0.ɵɵadvance();
41
- i0.ɵɵproperty("disabled", ctx_r1.isRefreshing);
53
+ i0.ɵɵproperty("disabled", ctx_r2.isRefreshing);
42
54
  i0.ɵɵadvance();
43
- i0.ɵɵclassProp("fa-spin", ctx_r1.isRefreshing);
55
+ i0.ɵɵclassProp("fa-spin", ctx_r2.isRefreshing);
44
56
  i0.ɵɵadvance(2);
45
- i0.ɵɵtextInterpolate(ctx_r1.isRefreshing ? "Refreshing..." : "Refresh");
46
- i0.ɵɵadvance(5);
47
- i0.ɵɵconditional(!ctx_r1.isMobileView ? 9 : -1);
57
+ i0.ɵɵtextInterpolate(ctx_r2.isRefreshing ? "Refreshing..." : "Refresh");
58
+ i0.ɵɵadvance(6);
59
+ i0.ɵɵclassProp("fa-folder-tree", ctx_r2.groupBy !== "project")("fa-list", ctx_r2.groupBy === "project");
60
+ i0.ɵɵadvance(2);
61
+ i0.ɵɵtextInterpolate(ctx_r2.groupBy === "project" ? "Show as flat list" : "Group by folder");
62
+ i0.ɵɵadvance();
63
+ i0.ɵɵconditional(!ctx_r2.isMobileView ? 13 : -1);
48
64
  } }
49
65
  function ConversationListComponent_Conditional_4_Template(rf, ctx) { if (rf & 1) {
50
- const _r1 = i0.ɵɵgetCurrentView();
51
- i0.ɵɵelementStart(0, "div", 4)(1, "button", 16);
52
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleHeaderMenu($event)); });
53
- i0.ɵɵelement(2, "i", 17);
66
+ const _r2 = i0.ɵɵgetCurrentView();
67
+ i0.ɵɵelementStart(0, "div", 6)(1, "button", 13);
68
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_4_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r2); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleHeaderMenu($event)); });
69
+ i0.ɵɵelement(2, "i", 14);
54
70
  i0.ɵɵelementEnd();
55
- i0.ɵɵconditionalCreate(3, ConversationListComponent_Conditional_4_Conditional_3_Template, 10, 5, "div", 18);
71
+ i0.ɵɵconditionalCreate(3, ConversationListComponent_Conditional_4_Conditional_3_Template, 14, 10, "div", 15);
56
72
  i0.ɵɵelementEnd();
57
73
  } if (rf & 2) {
58
- const ctx_r1 = i0.ɵɵnextContext();
74
+ const ctx_r2 = i0.ɵɵnextContext();
59
75
  i0.ɵɵadvance(3);
60
- i0.ɵɵconditional(ctx_r1.isHeaderMenuOpen ? 3 : -1);
76
+ i0.ɵɵconditional(ctx_r2.isHeaderMenuOpen ? 3 : -1);
77
+ } }
78
+ function ConversationListComponent_Conditional_10_For_9_Template(rf, ctx) { if (rf & 1) {
79
+ i0.ɵɵelementContainer(0, 28);
80
+ } if (rf & 2) {
81
+ const conversation_r7 = ctx.$implicit;
82
+ i0.ɵɵnextContext(2);
83
+ const conversationItem_r8 = i0.ɵɵreference(17);
84
+ i0.ɵɵproperty("ngTemplateOutlet", conversationItem_r8)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, conversation_r7));
61
85
  } }
62
- function ConversationListComponent_Conditional_10_For_9_Conditional_1_Template(rf, ctx) { if (rf & 1) {
63
- const _r8 = i0.ɵɵgetCurrentView();
64
- i0.ɵɵelementStart(0, "div", 27)(1, "input", 37);
65
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_1_Template_input_click_1_listener($event) { i0.ɵɵrestoreView(_r8); const conversation_r7 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); $event.stopPropagation(); return i0.ɵɵresetView(ctx_r1.toggleConversationSelection(conversation_r7.ID)); });
86
+ function ConversationListComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
87
+ const _r6 = i0.ɵɵgetCurrentView();
88
+ i0.ɵɵelementStart(0, "div", 10)(1, "div", 23);
89
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r6); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.togglePinned()); });
90
+ i0.ɵɵelementStart(2, "div", 24);
91
+ i0.ɵɵelement(3, "i", 25)(4, "i", 26);
92
+ i0.ɵɵelementStart(5, "span");
93
+ i0.ɵɵtext(6, "Pinned");
94
+ i0.ɵɵelementEnd()()();
95
+ i0.ɵɵelementStart(7, "div", 27);
96
+ i0.ɵɵrepeaterCreate(8, ConversationListComponent_Conditional_10_For_9_Template, 1, 4, "ng-container", 28, _forTrack0);
66
97
  i0.ɵɵelementEnd()();
67
98
  } if (rf & 2) {
68
- const conversation_r7 = i0.ɵɵnextContext().$implicit;
69
- const ctx_r1 = i0.ɵɵnextContext(2);
99
+ const ctx_r2 = i0.ɵɵnextContext();
70
100
  i0.ɵɵadvance();
71
- i0.ɵɵproperty("checked", ctx_r1.selectedConversationIds.has(conversation_r7.ID));
101
+ i0.ɵɵclassProp("expanded", ctx_r2.pinnedExpanded);
102
+ i0.ɵɵadvance(6);
103
+ i0.ɵɵclassProp("expanded", ctx_r2.pinnedExpanded);
104
+ i0.ɵɵadvance();
105
+ i0.ɵɵrepeater(ctx_r2.pinnedConversations);
106
+ } }
107
+ function ConversationListComponent_Conditional_11_For_10_Conditional_0_Template(rf, ctx) { if (rf & 1) {
108
+ i0.ɵɵelementContainer(0, 28);
109
+ } if (rf & 2) {
110
+ const node_r10 = i0.ɵɵnextContext().$implicit;
111
+ i0.ɵɵnextContext(2);
112
+ const folderNode_r11 = i0.ɵɵreference(15);
113
+ i0.ɵɵproperty("ngTemplateOutlet", folderNode_r11)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, node_r10));
114
+ } }
115
+ function ConversationListComponent_Conditional_11_For_10_Template(rf, ctx) { if (rf & 1) {
116
+ i0.ɵɵconditionalCreate(0, ConversationListComponent_Conditional_11_For_10_Conditional_0_Template, 1, 4, "ng-container", 28);
117
+ } if (rf & 2) {
118
+ const node_r10 = ctx.$implicit;
119
+ const ctx_r2 = i0.ɵɵnextContext(2);
120
+ i0.ɵɵconditional(!ctx_r2.isSearching || node_r10.hasContent ? 0 : -1);
72
121
  } }
73
- function ConversationListComponent_Conditional_10_For_9_Conditional_3_Template(rf, ctx) { if (rf & 1) {
74
- i0.ɵɵelementStart(0, "div", 29);
75
- i0.ɵɵelement(1, "i", 38);
122
+ function ConversationListComponent_Conditional_11_Conditional_11_Template(rf, ctx) { if (rf & 1) {
123
+ i0.ɵɵelementStart(0, "div", 33);
124
+ i0.ɵɵtext(1, "No folders yet \u2014 create one to organize conversations.");
76
125
  i0.ɵɵelementEnd();
77
126
  } }
78
- function ConversationListComponent_Conditional_10_For_9_Conditional_9_Template(rf, ctx) { if (rf & 1) {
79
- i0.ɵɵelement(0, "i", 34);
127
+ function ConversationListComponent_Conditional_11_For_20_Template(rf, ctx) { if (rf & 1) {
128
+ i0.ɵɵelementContainer(0, 28);
80
129
  } if (rf & 2) {
81
- const conversation_r7 = i0.ɵɵnextContext().$implicit;
82
- const ctx_r1 = i0.ɵɵnextContext(2);
83
- i0.ɵɵproperty("title", ctx_r1.sharedWithMeTooltip(conversation_r7));
130
+ const conversation_r12 = ctx.$implicit;
131
+ i0.ɵɵnextContext(2);
132
+ const conversationItem_r8 = i0.ɵɵreference(17);
133
+ i0.ɵɵproperty("ngTemplateOutlet", conversationItem_r8)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, conversation_r12));
84
134
  } }
85
- function ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template(rf, ctx) { if (rf & 1) {
86
- const _r10 = i0.ɵɵgetCurrentView();
87
- i0.ɵɵelementStart(0, "div", 42);
88
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r10); return i0.ɵɵresetView($event.stopPropagation()); });
89
- i0.ɵɵelementStart(1, "button", 43);
90
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r10); const conversation_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.togglePin(conversation_r7, $event)); });
91
- i0.ɵɵelement(2, "i", 44);
92
- i0.ɵɵelementStart(3, "span");
93
- i0.ɵɵtext(4, "Unpin");
135
+ function ConversationListComponent_Conditional_11_Template(rf, ctx) { if (rf & 1) {
136
+ const _r9 = i0.ɵɵgetCurrentView();
137
+ i0.ɵɵelementStart(0, "div", 29)(1, "div", 30);
138
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_11_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleFolders()); })("dragover", function ConversationListComponent_Conditional_11_Template_div_dragover_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFoldersRootDragOver($event)); })("dragleave", function ConversationListComponent_Conditional_11_Template_div_dragleave_1_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDragLeave("folders-root")); })("drop", function ConversationListComponent_Conditional_11_Template_div_drop_1_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFoldersRootDrop($event)); });
139
+ i0.ɵɵelementStart(2, "div", 24);
140
+ i0.ɵɵelement(3, "i", 25);
141
+ i0.ɵɵelementStart(4, "span");
142
+ i0.ɵɵtext(5, "Folders");
94
143
  i0.ɵɵelementEnd()();
95
- i0.ɵɵelementStart(5, "button", 43);
96
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r10); const conversation_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.renameConversation(conversation_r7); return i0.ɵɵresetView(ctx_r1.closeMenu()); });
97
- i0.ɵɵelement(6, "i", 45);
98
- i0.ɵɵelementStart(7, "span");
99
- i0.ɵɵtext(8, "Rename");
144
+ i0.ɵɵelementStart(6, "button", 31);
145
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_11_Template_button_click_6_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.createFolder(null, $event)); });
146
+ i0.ɵɵelement(7, "i", 32);
147
+ i0.ɵɵelementEnd()();
148
+ i0.ɵɵelementStart(8, "div", 27);
149
+ i0.ɵɵrepeaterCreate(9, ConversationListComponent_Conditional_11_For_10_Template, 1, 1, null, null, _forTrack1);
150
+ i0.ɵɵconditionalCreate(11, ConversationListComponent_Conditional_11_Conditional_11_Template, 2, 0, "div", 33);
100
151
  i0.ɵɵelementEnd()();
101
- i0.ɵɵelement(9, "div", 46);
102
- i0.ɵɵelementStart(10, "button", 47);
103
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r10); const conversation_r7 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); ctx_r1.deleteConversation(conversation_r7); return i0.ɵɵresetView(ctx_r1.closeMenu()); });
104
- i0.ɵɵelement(11, "i", 48);
105
- i0.ɵɵelementStart(12, "span");
106
- i0.ɵɵtext(13, "Delete");
152
+ i0.ɵɵelementStart(12, "div", 34);
153
+ i0.ɵɵlistener("dragover", function ConversationListComponent_Conditional_11_Template_div_dragover_12_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onUngroupedDragOver($event)); })("dragleave", function ConversationListComponent_Conditional_11_Template_div_dragleave_12_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDragLeave("ungrouped")); })("drop", function ConversationListComponent_Conditional_11_Template_div_drop_12_listener($event) { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onUngroupedDrop($event)); });
154
+ i0.ɵɵelementStart(13, "div", 23);
155
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_11_Template_div_click_13_listener() { i0.ɵɵrestoreView(_r9); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleUngrouped()); });
156
+ i0.ɵɵelementStart(14, "div", 24);
157
+ i0.ɵɵelement(15, "i", 25);
158
+ i0.ɵɵelementStart(16, "span");
159
+ i0.ɵɵtext(17);
107
160
  i0.ɵɵelementEnd()()();
161
+ i0.ɵɵelementStart(18, "div", 27);
162
+ i0.ɵɵrepeaterCreate(19, ConversationListComponent_Conditional_11_For_20_Template, 1, 4, "ng-container", 28, _forTrack0);
163
+ i0.ɵɵelementEnd()();
164
+ } if (rf & 2) {
165
+ const ctx_r2 = i0.ɵɵnextContext();
166
+ i0.ɵɵadvance();
167
+ i0.ɵɵclassProp("expanded", ctx_r2.foldersExpanded)("drag-over", ctx_r2.dragOverTargetId === "folders-root");
168
+ i0.ɵɵadvance(7);
169
+ i0.ɵɵclassProp("expanded", ctx_r2.foldersExpanded);
170
+ i0.ɵɵadvance();
171
+ i0.ɵɵrepeater(ctx_r2.folderTree);
172
+ i0.ɵɵadvance(2);
173
+ i0.ɵɵconditional(ctx_r2.folderTree.length === 0 ? 11 : -1);
174
+ i0.ɵɵadvance();
175
+ i0.ɵɵclassProp("drag-over", ctx_r2.dragOverTargetId === "ungrouped");
176
+ i0.ɵɵadvance();
177
+ i0.ɵɵclassProp("expanded", ctx_r2.ungroupedExpanded);
178
+ i0.ɵɵadvance(4);
179
+ i0.ɵɵtextInterpolate(ctx_r2.folderTree.length > 0 ? "Ungrouped" : "Messages");
180
+ i0.ɵɵadvance();
181
+ i0.ɵɵclassProp("expanded", ctx_r2.ungroupedExpanded);
182
+ i0.ɵɵadvance();
183
+ i0.ɵɵrepeater(ctx_r2.ungroupedConversations);
108
184
  } }
109
- function ConversationListComponent_Conditional_10_For_9_Conditional_12_Template(rf, ctx) { if (rf & 1) {
110
- const _r9 = i0.ɵɵgetCurrentView();
111
- i0.ɵɵelementStart(0, "div", 36)(1, "button", 39);
112
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Conditional_12_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r9); const conversation_r7 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.toggleMenu(conversation_r7.ID, $event)); });
113
- i0.ɵɵelement(2, "i", 40);
185
+ function ConversationListComponent_Conditional_12_For_8_Template(rf, ctx) { if (rf & 1) {
186
+ i0.ɵɵelementContainer(0, 28);
187
+ } if (rf & 2) {
188
+ const conversation_r14 = ctx.$implicit;
189
+ i0.ɵɵnextContext(2);
190
+ const conversationItem_r8 = i0.ɵɵreference(17);
191
+ i0.ɵɵproperty("ngTemplateOutlet", conversationItem_r8)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, conversation_r14));
192
+ } }
193
+ function ConversationListComponent_Conditional_12_Template(rf, ctx) { if (rf & 1) {
194
+ const _r13 = i0.ɵɵgetCurrentView();
195
+ i0.ɵɵelementStart(0, "div", 11)(1, "div", 23);
196
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_12_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r13); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleDirectMessages()); });
197
+ i0.ɵɵelementStart(2, "div", 24);
198
+ i0.ɵɵelement(3, "i", 25);
199
+ i0.ɵɵelementStart(4, "span");
200
+ i0.ɵɵtext(5, "Messages");
201
+ i0.ɵɵelementEnd()()();
202
+ i0.ɵɵelementStart(6, "div", 27);
203
+ i0.ɵɵrepeaterCreate(7, ConversationListComponent_Conditional_12_For_8_Template, 1, 4, "ng-container", 28, _forTrack0);
204
+ i0.ɵɵelementEnd()();
205
+ } if (rf & 2) {
206
+ const ctx_r2 = i0.ɵɵnextContext();
207
+ i0.ɵɵadvance();
208
+ i0.ɵɵclassProp("expanded", ctx_r2.directMessagesExpanded);
209
+ i0.ɵɵadvance(5);
210
+ i0.ɵɵclassProp("expanded", ctx_r2.directMessagesExpanded);
211
+ i0.ɵɵadvance();
212
+ i0.ɵɵrepeater(ctx_r2.unpinnedConversations);
213
+ } }
214
+ function ConversationListComponent_Conditional_13_Conditional_4_Template(rf, ctx) { if (rf & 1) {
215
+ const _r16 = i0.ɵɵgetCurrentView();
216
+ i0.ɵɵelementStart(0, "button", 42);
217
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_13_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r16); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.selectAll()); });
218
+ i0.ɵɵtext(1, "Select All");
219
+ i0.ɵɵelementEnd();
220
+ } }
221
+ function ConversationListComponent_Conditional_13_Conditional_5_Template(rf, ctx) { if (rf & 1) {
222
+ const _r17 = i0.ɵɵgetCurrentView();
223
+ i0.ɵɵelementStart(0, "button", 42);
224
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_13_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r2 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r2.deselectAll()); });
225
+ i0.ɵɵtext(1, "Deselect All");
226
+ i0.ɵɵelementEnd();
227
+ } }
228
+ function ConversationListComponent_Conditional_13_Template(rf, ctx) { if (rf & 1) {
229
+ const _r15 = i0.ɵɵgetCurrentView();
230
+ i0.ɵɵelementStart(0, "div", 12)(1, "div", 35)(2, "span", 36);
231
+ i0.ɵɵtext(3);
114
232
  i0.ɵɵelementEnd();
115
- i0.ɵɵconditionalCreate(3, ConversationListComponent_Conditional_10_For_9_Conditional_12_Conditional_3_Template, 14, 0, "div", 41);
233
+ i0.ɵɵconditionalCreate(4, ConversationListComponent_Conditional_13_Conditional_4_Template, 2, 0, "button", 37)(5, ConversationListComponent_Conditional_13_Conditional_5_Template, 2, 0, "button", 37);
116
234
  i0.ɵɵelementEnd();
235
+ i0.ɵɵelementStart(6, "div", 38)(7, "button", 39);
236
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_13_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.bulkDeleteConversations()); });
237
+ i0.ɵɵelement(8, "i", 40);
238
+ i0.ɵɵtext(9);
239
+ i0.ɵɵelementEnd();
240
+ i0.ɵɵelementStart(10, "button", 41);
241
+ i0.ɵɵlistener("click", function ConversationListComponent_Conditional_13_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r15); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleSelectionMode()); });
242
+ i0.ɵɵtext(11, " Cancel ");
243
+ i0.ɵɵelementEnd()()();
117
244
  } if (rf & 2) {
118
- const conversation_r7 = i0.ɵɵnextContext().$implicit;
119
- const ctx_r1 = i0.ɵɵnextContext(2);
245
+ const ctx_r2 = i0.ɵɵnextContext();
246
+ i0.ɵɵadvance(3);
247
+ i0.ɵɵtextInterpolate1("", ctx_r2.selectedConversationIds.size, " selected");
248
+ i0.ɵɵadvance();
249
+ i0.ɵɵconditional(ctx_r2.selectedConversationIds.size < ctx_r2.filteredConversations.length ? 4 : 5);
120
250
  i0.ɵɵadvance(3);
121
- i0.ɵɵconditional(ctx_r1.IsMenuOpen(conversation_r7) ? 3 : -1);
251
+ i0.ɵɵproperty("disabled", ctx_r2.selectedConversationIds.size === 0);
252
+ i0.ɵɵadvance(2);
253
+ i0.ɵɵtextInterpolate1(" Delete (", ctx_r2.selectedConversationIds.size, ") ");
122
254
  } }
123
- function ConversationListComponent_Conditional_10_For_9_Template(rf, ctx) { if (rf & 1) {
124
- const _r6 = i0.ɵɵgetCurrentView();
125
- i0.ɵɵelementStart(0, "div", 26);
126
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_For_9_Template_div_click_0_listener() { const conversation_r7 = i0.ɵɵrestoreView(_r6).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.handleConversationClick(conversation_r7)); });
127
- i0.ɵɵconditionalCreate(1, ConversationListComponent_Conditional_10_For_9_Conditional_1_Template, 2, 1, "div", 27);
128
- i0.ɵɵelementStart(2, "div", 28);
129
- i0.ɵɵconditionalCreate(3, ConversationListComponent_Conditional_10_For_9_Conditional_3_Template, 2, 0, "div", 29);
130
- i0.ɵɵelementStart(4, "div", 30);
131
- i0.ɵɵelement(5, "mj-notification-badge", 31);
132
- i0.ɵɵelementEnd()();
133
- i0.ɵɵelementStart(6, "div", 32)(7, "div", 33);
134
- i0.ɵɵtext(8);
135
- i0.ɵɵconditionalCreate(9, ConversationListComponent_Conditional_10_For_9_Conditional_9_Template, 1, 1, "i", 34);
255
+ function ConversationListComponent_ng_template_14_Conditional_14_For_2_Conditional_0_Template(rf, ctx) { if (rf & 1) {
256
+ i0.ɵɵelementContainer(0, 28);
257
+ } if (rf & 2) {
258
+ const child_r20 = i0.ɵɵnextContext().$implicit;
259
+ i0.ɵɵnextContext(3);
260
+ const folderNode_r11 = i0.ɵɵreference(15);
261
+ i0.ɵɵproperty("ngTemplateOutlet", folderNode_r11)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c0, child_r20));
262
+ } }
263
+ function ConversationListComponent_ng_template_14_Conditional_14_For_2_Template(rf, ctx) { if (rf & 1) {
264
+ i0.ɵɵconditionalCreate(0, ConversationListComponent_ng_template_14_Conditional_14_For_2_Conditional_0_Template, 1, 4, "ng-container", 28);
265
+ } if (rf & 2) {
266
+ const child_r20 = ctx.$implicit;
267
+ const ctx_r2 = i0.ɵɵnextContext(3);
268
+ i0.ɵɵconditional(!ctx_r2.isSearching || child_r20.hasContent ? 0 : -1);
269
+ } }
270
+ function ConversationListComponent_ng_template_14_Conditional_14_For_4_Template(rf, ctx) { if (rf & 1) {
271
+ i0.ɵɵelementContainer(0, 28);
272
+ } if (rf & 2) {
273
+ const conversation_r21 = ctx.$implicit;
274
+ const node_r19 = i0.ɵɵnextContext(2).$implicit;
275
+ i0.ɵɵnextContext();
276
+ const conversationItem_r8 = i0.ɵɵreference(17);
277
+ i0.ɵɵproperty("ngTemplateOutlet", conversationItem_r8)("ngTemplateOutletContext", i0.ɵɵpureFunction2(2, _c1, conversation_r21, node_r19.depth + 1));
278
+ } }
279
+ function ConversationListComponent_ng_template_14_Conditional_14_Conditional_5_Template(rf, ctx) { if (rf & 1) {
280
+ i0.ɵɵelementStart(0, "div", 33);
281
+ i0.ɵɵtext(1, "Empty \u2014 drop a conversation here");
136
282
  i0.ɵɵelementEnd();
137
- i0.ɵɵelementStart(10, "div", 35);
138
- i0.ɵɵtext(11);
139
- i0.ɵɵelementEnd()();
140
- i0.ɵɵconditionalCreate(12, ConversationListComponent_Conditional_10_For_9_Conditional_12_Template, 4, 1, "div", 36);
283
+ } if (rf & 2) {
284
+ const node_r19 = i0.ɵɵnextContext(2).$implicit;
285
+ i0.ɵɵstyleProp("padding-left", 26 + node_r19.depth * 14, "px");
286
+ } }
287
+ function ConversationListComponent_ng_template_14_Conditional_14_Template(rf, ctx) { if (rf & 1) {
288
+ i0.ɵɵelementStart(0, "div", 52);
289
+ i0.ɵɵrepeaterCreate(1, ConversationListComponent_ng_template_14_Conditional_14_For_2_Template, 1, 1, null, null, _forTrack1);
290
+ i0.ɵɵrepeaterCreate(3, ConversationListComponent_ng_template_14_Conditional_14_For_4_Template, 1, 5, "ng-container", 28, _forTrack0);
291
+ i0.ɵɵconditionalCreate(5, ConversationListComponent_ng_template_14_Conditional_14_Conditional_5_Template, 2, 2, "div", 53);
141
292
  i0.ɵɵelementEnd();
142
293
  } if (rf & 2) {
143
- const conversation_r7 = ctx.$implicit;
144
- const ctx_r1 = i0.ɵɵnextContext(2);
145
- i0.ɵɵclassProp("active", ctx_r1.IsConversationActive(conversation_r7))("renamed", ctx_r1.IsConversationRenamed(conversation_r7));
294
+ const node_r19 = i0.ɵɵnextContext().$implicit;
295
+ const ctx_r2 = i0.ɵɵnextContext();
146
296
  i0.ɵɵadvance();
147
- i0.ɵɵconditional(ctx_r1.isSelectionMode ? 1 : -1);
297
+ i0.ɵɵrepeater(node_r19.children);
148
298
  i0.ɵɵadvance(2);
149
- i0.ɵɵconditional(ctx_r1.hasActiveTasks(conversation_r7.ID) ? 3 : -1);
299
+ i0.ɵɵrepeater(node_r19.conversations);
150
300
  i0.ɵɵadvance(2);
151
- i0.ɵɵproperty("conversationId", conversation_r7.ID);
301
+ i0.ɵɵconditional(node_r19.totalCount === 0 && !ctx_r2.isSearching ? 5 : -1);
302
+ } }
303
+ function ConversationListComponent_ng_template_14_Template(rf, ctx) { if (rf & 1) {
304
+ const _r18 = i0.ɵɵgetCurrentView();
305
+ i0.ɵɵelementStart(0, "div", 43);
306
+ i0.ɵɵlistener("dragstart", function ConversationListComponent_ng_template_14_Template_div_dragstart_0_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFolderDragStart(node_r19, $event)); })("dragend", function ConversationListComponent_ng_template_14_Template_div_dragend_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFolderDragEnd()); })("click", function ConversationListComponent_ng_template_14_Template_div_click_0_listener() { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleFolder(node_r19.project.ID)); })("dragover", function ConversationListComponent_ng_template_14_Template_div_dragover_0_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFolderDragOver(node_r19.project.ID, $event)); })("dragleave", function ConversationListComponent_ng_template_14_Template_div_dragleave_0_listener() { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onDragLeave(node_r19.project.ID)); })("drop", function ConversationListComponent_ng_template_14_Template_div_drop_0_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onFolderDrop(node_r19.project, $event)); });
307
+ i0.ɵɵelement(1, "i", 44)(2, "i");
308
+ i0.ɵɵelementStart(3, "span", 45);
309
+ i0.ɵɵtext(4);
310
+ i0.ɵɵelementEnd();
311
+ i0.ɵɵelementStart(5, "span", 46);
312
+ i0.ɵɵtext(6);
313
+ i0.ɵɵelementEnd();
314
+ i0.ɵɵelementStart(7, "div", 47);
315
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_14_Template_div_click_7_listener($event) { i0.ɵɵrestoreView(_r18); return i0.ɵɵresetView($event.stopPropagation()); });
316
+ i0.ɵɵelementStart(8, "button", 48);
317
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_14_Template_button_click_8_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.createFolder(node_r19.project.ID, $event)); });
318
+ i0.ɵɵelement(9, "i", 32);
319
+ i0.ɵɵelementEnd();
320
+ i0.ɵɵelementStart(10, "button", 49);
321
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_14_Template_button_click_10_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.editFolder(node_r19.project, $event)); });
322
+ i0.ɵɵelement(11, "i", 50);
323
+ i0.ɵɵelementEnd();
324
+ i0.ɵɵelementStart(12, "button", 51);
325
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_14_Template_button_click_12_listener($event) { const node_r19 = i0.ɵɵrestoreView(_r18).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.deleteFolder(node_r19.project, $event)); });
326
+ i0.ɵɵelement(13, "i", 40);
327
+ i0.ɵɵelementEnd()()();
328
+ i0.ɵɵconditionalCreate(14, ConversationListComponent_ng_template_14_Conditional_14_Template, 6, 1, "div", 52);
329
+ } if (rf & 2) {
330
+ const node_r19 = ctx.$implicit;
331
+ const ctx_r2 = i0.ɵɵnextContext();
332
+ i0.ɵɵstyleProp("padding-left", 12 + node_r19.depth * 14, "px");
333
+ i0.ɵɵclassProp("drag-over", ctx_r2.dragOverTargetId === node_r19.project.ID)("dragging", ctx_r2.draggedFolderId === node_r19.project.ID);
334
+ i0.ɵɵproperty("draggable", true)("title", node_r19.project.Name);
152
335
  i0.ɵɵadvance();
153
- i0.ɵɵproperty("title", conversation_r7.Name + (conversation_r7.Description ? "\n" + conversation_r7.Description : ""));
154
- i0.ɵɵadvance(2);
155
- i0.ɵɵtextInterpolate1(" ", conversation_r7.Name, " ");
336
+ i0.ɵɵclassProp("expanded", ctx_r2.isFolderExpanded(node_r19.project.ID));
156
337
  i0.ɵɵadvance();
157
- i0.ɵɵconditional(ctx_r1.isSharedWithMe(conversation_r7) ? 9 : -1);
338
+ i0.ɵɵclassMap(i0.ɵɵinterpolate1("fas ", node_r19.project.Icon || "fa-folder", " folder-icon"));
339
+ i0.ɵɵstyleProp("color", node_r19.project.Color || null);
158
340
  i0.ɵɵadvance(2);
159
- i0.ɵɵtextInterpolate(conversation_r7.Description);
160
- i0.ɵɵadvance();
161
- i0.ɵɵconditional(!ctx_r1.isSelectionMode ? 12 : -1);
341
+ i0.ɵɵtextInterpolate(node_r19.project.Name);
342
+ i0.ɵɵadvance(2);
343
+ i0.ɵɵtextInterpolate(node_r19.totalCount);
344
+ i0.ɵɵadvance(8);
345
+ i0.ɵɵconditional(ctx_r2.isFolderExpanded(node_r19.project.ID) ? 14 : -1);
162
346
  } }
163
- function ConversationListComponent_Conditional_10_Template(rf, ctx) { if (rf & 1) {
164
- const _r5 = i0.ɵɵgetCurrentView();
165
- i0.ɵɵelementStart(0, "div", 8)(1, "div", 10);
166
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_10_Template_div_click_1_listener() { i0.ɵɵrestoreView(_r5); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.togglePinned()); });
167
- i0.ɵɵelementStart(2, "div", 11);
168
- i0.ɵɵelement(3, "i", 12)(4, "i", 25);
169
- i0.ɵɵelementStart(5, "span");
170
- i0.ɵɵtext(6, "Pinned");
171
- i0.ɵɵelementEnd()()();
172
- i0.ɵɵelementStart(7, "div", 13);
173
- i0.ɵɵrepeaterCreate(8, ConversationListComponent_Conditional_10_For_9_Template, 13, 12, "div", 14, _forTrack0);
347
+ function ConversationListComponent_ng_template_16_Conditional_1_Template(rf, ctx) { if (rf & 1) {
348
+ const _r24 = i0.ɵɵgetCurrentView();
349
+ i0.ɵɵelementStart(0, "div", 55)(1, "input", 65);
350
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_1_Template_input_click_1_listener($event) { i0.ɵɵrestoreView(_r24); const conversation_r23 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); $event.stopPropagation(); return i0.ɵɵresetView(ctx_r2.toggleConversationSelection(conversation_r23.ID)); });
174
351
  i0.ɵɵelementEnd()();
175
352
  } if (rf & 2) {
176
- const ctx_r1 = i0.ɵɵnextContext();
177
- i0.ɵɵadvance();
178
- i0.ɵɵclassProp("expanded", ctx_r1.pinnedExpanded);
179
- i0.ɵɵadvance(6);
180
- i0.ɵɵclassProp("expanded", ctx_r1.pinnedExpanded);
353
+ const conversation_r23 = i0.ɵɵnextContext().$implicit;
354
+ const ctx_r2 = i0.ɵɵnextContext();
181
355
  i0.ɵɵadvance();
182
- i0.ɵɵrepeater(ctx_r1.pinnedConversations);
356
+ i0.ɵɵproperty("checked", ctx_r2.selectedConversationIds.has(conversation_r23.ID));
183
357
  } }
184
- function ConversationListComponent_For_19_Conditional_1_Template(rf, ctx) { if (rf & 1) {
185
- const _r13 = i0.ɵɵgetCurrentView();
186
- i0.ɵɵelementStart(0, "div", 27)(1, "input", 37);
187
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_1_Template_input_click_1_listener($event) { i0.ɵɵrestoreView(_r13); const conversation_r12 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); $event.stopPropagation(); return i0.ɵɵresetView(ctx_r1.toggleConversationSelection(conversation_r12.ID)); });
358
+ function ConversationListComponent_ng_template_16_Conditional_3_Template(rf, ctx) { if (rf & 1) {
359
+ i0.ɵɵelementStart(0, "div", 57);
360
+ i0.ɵɵelement(1, "i", 66);
361
+ i0.ɵɵelementEnd();
362
+ } }
363
+ function ConversationListComponent_ng_template_16_Conditional_9_Template(rf, ctx) { if (rf & 1) {
364
+ i0.ɵɵelement(0, "i", 62);
365
+ } if (rf & 2) {
366
+ const conversation_r23 = i0.ɵɵnextContext().$implicit;
367
+ const ctx_r2 = i0.ɵɵnextContext();
368
+ i0.ɵɵproperty("title", ctx_r2.sharedWithMeTooltip(conversation_r23));
369
+ } }
370
+ function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_For_11_Template(rf, ctx) { if (rf & 1) {
371
+ const _r28 = i0.ɵɵgetCurrentView();
372
+ i0.ɵɵelementStart(0, "button", 75);
373
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_For_11_Template_button_click_0_listener() { const f_r29 = i0.ɵɵrestoreView(_r28).$implicit; const conversation_r23 = i0.ɵɵnextContext(4).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectMoveTarget(conversation_r23, f_r29.project.ID)); });
374
+ i0.ɵɵelement(1, "i");
375
+ i0.ɵɵelementStart(2, "span");
376
+ i0.ɵɵtext(3);
188
377
  i0.ɵɵelementEnd()();
189
378
  } if (rf & 2) {
190
- const conversation_r12 = i0.ɵɵnextContext().$implicit;
191
- const ctx_r1 = i0.ɵɵnextContext();
379
+ const f_r29 = ctx.$implicit;
380
+ const conversation_r23 = i0.ɵɵnextContext(4).$implicit;
381
+ const ctx_r2 = i0.ɵɵnextContext();
382
+ i0.ɵɵstyleProp("padding-left", 14 + f_r29.depth * 12, "px");
383
+ i0.ɵɵclassProp("current", ctx_r2.IsInFolder(conversation_r23, f_r29.project.ID));
192
384
  i0.ɵɵadvance();
193
- i0.ɵɵproperty("checked", ctx_r1.selectedConversationIds.has(conversation_r12.ID));
385
+ i0.ɵɵclassMap(i0.ɵɵinterpolate1("fas ", f_r29.project.Icon || "fa-folder"));
386
+ i0.ɵɵstyleProp("color", f_r29.project.Color || null);
387
+ i0.ɵɵadvance(2);
388
+ i0.ɵɵtextInterpolate(f_r29.project.Name);
194
389
  } }
195
- function ConversationListComponent_For_19_Conditional_3_Template(rf, ctx) { if (rf & 1) {
196
- i0.ɵɵelementStart(0, "div", 29);
197
- i0.ɵɵelement(1, "i", 38);
390
+ function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_Template(rf, ctx) { if (rf & 1) {
391
+ const _r27 = i0.ɵɵgetCurrentView();
392
+ i0.ɵɵelementStart(0, "button", 71);
393
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r27); const ctx_r2 = i0.ɵɵnextContext(4); return i0.ɵɵresetView(ctx_r2.closeMoveSubmenu($event)); });
394
+ i0.ɵɵelement(1, "i", 72);
395
+ i0.ɵɵelementStart(2, "span");
396
+ i0.ɵɵtext(3, "Move to folder");
397
+ i0.ɵɵelementEnd()();
398
+ i0.ɵɵelement(4, "div", 73);
399
+ i0.ɵɵelementStart(5, "div", 74)(6, "button", 75);
400
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_Template_button_click_6_listener() { i0.ɵɵrestoreView(_r27); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.selectMoveTarget(conversation_r23, null)); });
401
+ i0.ɵɵelement(7, "i", 76);
402
+ i0.ɵɵelementStart(8, "span");
403
+ i0.ɵɵtext(9, "No folder");
404
+ i0.ɵɵelementEnd()();
405
+ i0.ɵɵrepeaterCreate(10, ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_For_11_Template, 4, 10, "button", 77, _forTrack1);
198
406
  i0.ɵɵelementEnd();
199
- } }
200
- function ConversationListComponent_For_19_Conditional_9_Template(rf, ctx) { if (rf & 1) {
201
- i0.ɵɵelement(0, "i", 34);
407
+ i0.ɵɵelement(12, "div", 73);
408
+ i0.ɵɵelementStart(13, "button", 75);
409
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_Template_button_click_13_listener($event) { i0.ɵɵrestoreView(_r27); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.createFolderForConversation(conversation_r23, $event)); });
410
+ i0.ɵɵelement(14, "i", 32);
411
+ i0.ɵɵelementStart(15, "span");
412
+ i0.ɵɵtext(16, "New folder\u2026");
413
+ i0.ɵɵelementEnd()();
202
414
  } if (rf & 2) {
203
- const conversation_r12 = i0.ɵɵnextContext().$implicit;
204
- const ctx_r1 = i0.ɵɵnextContext();
205
- i0.ɵɵproperty("title", ctx_r1.sharedWithMeTooltip(conversation_r12));
415
+ const conversation_r23 = i0.ɵɵnextContext(3).$implicit;
416
+ const ctx_r2 = i0.ɵɵnextContext();
417
+ i0.ɵɵadvance(6);
418
+ i0.ɵɵclassProp("current", !conversation_r23.ProjectID);
419
+ i0.ɵɵadvance(4);
420
+ i0.ɵɵrepeater(ctx_r2.flatFolders);
206
421
  } }
207
- function ConversationListComponent_For_19_Conditional_12_Conditional_3_Template(rf, ctx) { if (rf & 1) {
208
- const _r15 = i0.ɵɵgetCurrentView();
209
- i0.ɵɵelementStart(0, "div", 42);
210
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_12_Conditional_3_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r15); return i0.ɵɵresetView($event.stopPropagation()); });
211
- i0.ɵɵelementStart(1, "button", 43);
212
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_12_Conditional_3_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r15); const conversation_r12 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.togglePin(conversation_r12, $event)); });
213
- i0.ɵɵelement(2, "i", 44);
214
- i0.ɵɵelementStart(3, "span");
215
- i0.ɵɵtext(4, "Pin");
422
+ function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template(rf, ctx) { if (rf & 1) {
423
+ const _r30 = i0.ɵɵgetCurrentView();
424
+ i0.ɵɵelementStart(0, "button", 75);
425
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r30); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.togglePin(conversation_r23, $event)); });
426
+ i0.ɵɵelement(1, "i", 78);
427
+ i0.ɵɵelementStart(2, "span");
428
+ i0.ɵɵtext(3);
216
429
  i0.ɵɵelementEnd()();
217
- i0.ɵɵelementStart(5, "button", 43);
218
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_12_Conditional_3_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r15); const conversation_r12 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.renameConversation(conversation_r12); return i0.ɵɵresetView(ctx_r1.closeMenu()); });
219
- i0.ɵɵelement(6, "i", 45);
220
- i0.ɵɵelementStart(7, "span");
221
- i0.ɵɵtext(8, "Rename");
430
+ i0.ɵɵelementStart(4, "button", 75);
431
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template_button_click_4_listener($event) { i0.ɵɵrestoreView(_r30); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.openMoveSubmenu(conversation_r23.ID, $event)); });
432
+ i0.ɵɵelement(5, "i", 79);
433
+ i0.ɵɵelementStart(6, "span");
434
+ i0.ɵɵtext(7, "Move to folder");
435
+ i0.ɵɵelementEnd();
436
+ i0.ɵɵelement(8, "i", 80);
437
+ i0.ɵɵelementEnd();
438
+ i0.ɵɵelementStart(9, "button", 75);
439
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template_button_click_9_listener() { i0.ɵɵrestoreView(_r30); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); ctx_r2.renameConversation(conversation_r23); return i0.ɵɵresetView(ctx_r2.closeMenu()); });
440
+ i0.ɵɵelement(10, "i", 81);
441
+ i0.ɵɵelementStart(11, "span");
442
+ i0.ɵɵtext(12, "Rename");
222
443
  i0.ɵɵelementEnd()();
223
- i0.ɵɵelement(9, "div", 46);
224
- i0.ɵɵelementStart(10, "button", 47);
225
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_12_Conditional_3_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r15); const conversation_r12 = i0.ɵɵnextContext(2).$implicit; const ctx_r1 = i0.ɵɵnextContext(); ctx_r1.deleteConversation(conversation_r12); return i0.ɵɵresetView(ctx_r1.closeMenu()); });
226
- i0.ɵɵelement(11, "i", 48);
227
- i0.ɵɵelementStart(12, "span");
228
- i0.ɵɵtext(13, "Delete");
229
- i0.ɵɵelementEnd()()();
444
+ i0.ɵɵelement(13, "div", 73);
445
+ i0.ɵɵelementStart(14, "button", 82);
446
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template_button_click_14_listener() { i0.ɵɵrestoreView(_r30); const conversation_r23 = i0.ɵɵnextContext(3).$implicit; const ctx_r2 = i0.ɵɵnextContext(); ctx_r2.deleteConversation(conversation_r23); return i0.ɵɵresetView(ctx_r2.closeMenu()); });
447
+ i0.ɵɵelement(15, "i", 40);
448
+ i0.ɵɵelementStart(16, "span");
449
+ i0.ɵɵtext(17, "Delete");
450
+ i0.ɵɵelementEnd()();
451
+ } if (rf & 2) {
452
+ const conversation_r23 = i0.ɵɵnextContext(3).$implicit;
453
+ i0.ɵɵadvance(3);
454
+ i0.ɵɵtextInterpolate(conversation_r23.IsPinned ? "Unpin" : "Pin");
455
+ } }
456
+ function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Template(rf, ctx) { if (rf & 1) {
457
+ const _r26 = i0.ɵɵgetCurrentView();
458
+ i0.ɵɵelementStart(0, "div", 70);
459
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r26); return i0.ɵɵresetView($event.stopPropagation()); });
460
+ i0.ɵɵconditionalCreate(1, ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_1_Template, 17, 2)(2, ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Conditional_2_Template, 18, 1);
461
+ i0.ɵɵelementEnd();
462
+ } if (rf & 2) {
463
+ const conversation_r23 = i0.ɵɵnextContext(2).$implicit;
464
+ const ctx_r2 = i0.ɵɵnextContext();
465
+ i0.ɵɵadvance();
466
+ i0.ɵɵconditional(ctx_r2.IsMoveSubmenuOpen(conversation_r23) ? 1 : 2);
230
467
  } }
231
- function ConversationListComponent_For_19_Conditional_12_Template(rf, ctx) { if (rf & 1) {
232
- const _r14 = i0.ɵɵgetCurrentView();
233
- i0.ɵɵelementStart(0, "div", 36)(1, "button", 39);
234
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Conditional_12_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r14); const conversation_r12 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleMenu(conversation_r12.ID, $event)); });
235
- i0.ɵɵelement(2, "i", 40);
468
+ function ConversationListComponent_ng_template_16_Conditional_12_Template(rf, ctx) { if (rf & 1) {
469
+ const _r25 = i0.ɵɵgetCurrentView();
470
+ i0.ɵɵelementStart(0, "div", 64)(1, "button", 67);
471
+ i0.ɵɵlistener("click", function ConversationListComponent_ng_template_16_Conditional_12_Template_button_click_1_listener($event) { i0.ɵɵrestoreView(_r25); const conversation_r23 = i0.ɵɵnextContext().$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.toggleMenu(conversation_r23.ID, $event)); });
472
+ i0.ɵɵelement(2, "i", 68);
236
473
  i0.ɵɵelementEnd();
237
- i0.ɵɵconditionalCreate(3, ConversationListComponent_For_19_Conditional_12_Conditional_3_Template, 14, 0, "div", 41);
474
+ i0.ɵɵconditionalCreate(3, ConversationListComponent_ng_template_16_Conditional_12_Conditional_3_Template, 3, 1, "div", 69);
238
475
  i0.ɵɵelementEnd();
239
476
  } if (rf & 2) {
240
- const conversation_r12 = i0.ɵɵnextContext().$implicit;
241
- const ctx_r1 = i0.ɵɵnextContext();
477
+ const conversation_r23 = i0.ɵɵnextContext().$implicit;
478
+ const ctx_r2 = i0.ɵɵnextContext();
242
479
  i0.ɵɵadvance(3);
243
- i0.ɵɵconditional(ctx_r1.IsMenuOpen(conversation_r12) ? 3 : -1);
480
+ i0.ɵɵconditional(ctx_r2.IsMenuOpen(conversation_r23) ? 3 : -1);
244
481
  } }
245
- function ConversationListComponent_For_19_Template(rf, ctx) { if (rf & 1) {
246
- const _r11 = i0.ɵɵgetCurrentView();
247
- i0.ɵɵelementStart(0, "div", 26);
248
- i0.ɵɵlistener("click", function ConversationListComponent_For_19_Template_div_click_0_listener() { const conversation_r12 = i0.ɵɵrestoreView(_r11).$implicit; const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.handleConversationClick(conversation_r12)); });
249
- i0.ɵɵconditionalCreate(1, ConversationListComponent_For_19_Conditional_1_Template, 2, 1, "div", 27);
250
- i0.ɵɵelementStart(2, "div", 28);
251
- i0.ɵɵconditionalCreate(3, ConversationListComponent_For_19_Conditional_3_Template, 2, 0, "div", 29);
252
- i0.ɵɵelementStart(4, "div", 30);
253
- i0.ɵɵelement(5, "mj-notification-badge", 31);
482
+ function ConversationListComponent_ng_template_16_Template(rf, ctx) { if (rf & 1) {
483
+ const _r22 = i0.ɵɵgetCurrentView();
484
+ i0.ɵɵelementStart(0, "div", 54);
485
+ i0.ɵɵlistener("dragstart", function ConversationListComponent_ng_template_16_Template_div_dragstart_0_listener($event) { const conversation_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onConversationDragStart(conversation_r23, $event)); })("dragend", function ConversationListComponent_ng_template_16_Template_div_dragend_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onConversationDragEnd()); })("click", function ConversationListComponent_ng_template_16_Template_div_click_0_listener() { const conversation_r23 = i0.ɵɵrestoreView(_r22).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.handleConversationClick(conversation_r23)); });
486
+ i0.ɵɵconditionalCreate(1, ConversationListComponent_ng_template_16_Conditional_1_Template, 2, 1, "div", 55);
487
+ i0.ɵɵelementStart(2, "div", 56);
488
+ i0.ɵɵconditionalCreate(3, ConversationListComponent_ng_template_16_Conditional_3_Template, 2, 0, "div", 57);
489
+ i0.ɵɵelementStart(4, "div", 58);
490
+ i0.ɵɵelement(5, "mj-notification-badge", 59);
254
491
  i0.ɵɵelementEnd()();
255
- i0.ɵɵelementStart(6, "div", 32)(7, "div", 33);
492
+ i0.ɵɵelementStart(6, "div", 60)(7, "div", 61);
256
493
  i0.ɵɵtext(8);
257
- i0.ɵɵconditionalCreate(9, ConversationListComponent_For_19_Conditional_9_Template, 1, 1, "i", 34);
494
+ i0.ɵɵconditionalCreate(9, ConversationListComponent_ng_template_16_Conditional_9_Template, 1, 1, "i", 62);
258
495
  i0.ɵɵelementEnd();
259
- i0.ɵɵelementStart(10, "div", 35);
496
+ i0.ɵɵelementStart(10, "div", 63);
260
497
  i0.ɵɵtext(11);
261
498
  i0.ɵɵelementEnd()();
262
- i0.ɵɵconditionalCreate(12, ConversationListComponent_For_19_Conditional_12_Template, 4, 1, "div", 36);
499
+ i0.ɵɵconditionalCreate(12, ConversationListComponent_ng_template_16_Conditional_12_Template, 4, 1, "div", 64);
263
500
  i0.ɵɵelementEnd();
264
501
  } if (rf & 2) {
265
- const conversation_r12 = ctx.$implicit;
266
- const ctx_r1 = i0.ɵɵnextContext();
267
- i0.ɵɵclassProp("active", ctx_r1.IsConversationActive(conversation_r12))("renamed", ctx_r1.IsConversationRenamed(conversation_r12));
502
+ const conversation_r23 = ctx.$implicit;
503
+ const depth_r31 = ctx.depth;
504
+ const ctx_r2 = i0.ɵɵnextContext();
505
+ i0.ɵɵstyleProp("padding-left", depth_r31 ? 16 + depth_r31 * 14 : 16, "px");
506
+ i0.ɵɵclassProp("active", ctx_r2.IsConversationActive(conversation_r23))("renamed", ctx_r2.IsConversationRenamed(conversation_r23))("dragging", ctx_r2.IsConversationDragging(conversation_r23));
507
+ i0.ɵɵproperty("draggable", !ctx_r2.isSelectionMode);
268
508
  i0.ɵɵadvance();
269
- i0.ɵɵconditional(ctx_r1.isSelectionMode ? 1 : -1);
509
+ i0.ɵɵconditional(ctx_r2.isSelectionMode ? 1 : -1);
270
510
  i0.ɵɵadvance(2);
271
- i0.ɵɵconditional(ctx_r1.hasActiveTasks(conversation_r12.ID) ? 3 : -1);
511
+ i0.ɵɵconditional(ctx_r2.hasActiveTasks(conversation_r23.ID) ? 3 : -1);
272
512
  i0.ɵɵadvance(2);
273
- i0.ɵɵproperty("conversationId", conversation_r12.ID);
513
+ i0.ɵɵproperty("conversationId", conversation_r23.ID);
274
514
  i0.ɵɵadvance();
275
- i0.ɵɵproperty("title", conversation_r12.Name + (conversation_r12.Description ? "\n" + conversation_r12.Description : ""));
515
+ i0.ɵɵproperty("title", conversation_r23.Name + (conversation_r23.Description ? "\n" + conversation_r23.Description : ""));
276
516
  i0.ɵɵadvance(2);
277
- i0.ɵɵtextInterpolate1(" ", conversation_r12.Name, " ");
517
+ i0.ɵɵtextInterpolate1(" ", conversation_r23.Name, " ");
278
518
  i0.ɵɵadvance();
279
- i0.ɵɵconditional(ctx_r1.isSharedWithMe(conversation_r12) ? 9 : -1);
519
+ i0.ɵɵconditional(ctx_r2.isSharedWithMe(conversation_r23) ? 9 : -1);
280
520
  i0.ɵɵadvance(2);
281
- i0.ɵɵtextInterpolate(conversation_r12.Description);
521
+ i0.ɵɵtextInterpolate(conversation_r23.Description);
282
522
  i0.ɵɵadvance();
283
- i0.ɵɵconditional(!ctx_r1.isSelectionMode ? 12 : -1);
284
- } }
285
- function ConversationListComponent_Conditional_20_Conditional_4_Template(rf, ctx) { if (rf & 1) {
286
- const _r17 = i0.ɵɵgetCurrentView();
287
- i0.ɵɵelementStart(0, "button", 55);
288
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_20_Conditional_4_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r17); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.selectAll()); });
289
- i0.ɵɵtext(1, "Select All");
290
- i0.ɵɵelementEnd();
291
- } }
292
- function ConversationListComponent_Conditional_20_Conditional_5_Template(rf, ctx) { if (rf & 1) {
293
- const _r18 = i0.ɵɵgetCurrentView();
294
- i0.ɵɵelementStart(0, "button", 55);
295
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_20_Conditional_5_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.deselectAll()); });
296
- i0.ɵɵtext(1, "Deselect All");
297
- i0.ɵɵelementEnd();
298
- } }
299
- function ConversationListComponent_Conditional_20_Template(rf, ctx) { if (rf & 1) {
300
- const _r16 = i0.ɵɵgetCurrentView();
301
- i0.ɵɵelementStart(0, "div", 15)(1, "div", 49)(2, "span", 50);
302
- i0.ɵɵtext(3);
303
- i0.ɵɵelementEnd();
304
- i0.ɵɵconditionalCreate(4, ConversationListComponent_Conditional_20_Conditional_4_Template, 2, 0, "button", 51)(5, ConversationListComponent_Conditional_20_Conditional_5_Template, 2, 0, "button", 51);
305
- i0.ɵɵelementEnd();
306
- i0.ɵɵelementStart(6, "div", 52)(7, "button", 53);
307
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_20_Template_button_click_7_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.bulkDeleteConversations()); });
308
- i0.ɵɵelement(8, "i", 48);
309
- i0.ɵɵtext(9);
310
- i0.ɵɵelementEnd();
311
- i0.ɵɵelementStart(10, "button", 54);
312
- i0.ɵɵlistener("click", function ConversationListComponent_Conditional_20_Template_button_click_10_listener() { i0.ɵɵrestoreView(_r16); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.toggleSelectionMode()); });
313
- i0.ɵɵtext(11, " Cancel ");
314
- i0.ɵɵelementEnd()()();
315
- } if (rf & 2) {
316
- const ctx_r1 = i0.ɵɵnextContext();
317
- i0.ɵɵadvance(3);
318
- i0.ɵɵtextInterpolate1("", ctx_r1.selectedConversationIds.size, " selected");
319
- i0.ɵɵadvance();
320
- i0.ɵɵconditional(ctx_r1.selectedConversationIds.size < ctx_r1.filteredConversations.length ? 4 : 5);
321
- i0.ɵɵadvance(3);
322
- i0.ɵɵproperty("disabled", ctx_r1.selectedConversationIds.size === 0);
323
- i0.ɵɵadvance(2);
324
- i0.ɵɵtextInterpolate1(" Delete (", ctx_r1.selectedConversationIds.size, ") ");
523
+ i0.ɵɵconditional(!ctx_r2.isSelectionMode ? 12 : -1);
325
524
  } }
326
525
  export class ConversationListComponent {
327
526
  dialogService;
328
527
  notificationService;
329
528
  activeTasksService;
529
+ mjDialogService;
330
530
  cdr;
331
531
  environmentId;
332
532
  currentUser;
@@ -342,45 +542,81 @@ export class ConversationListComponent {
342
542
  refreshRequested = new EventEmitter(); // Emitted after list refresh so chat area can also reload
343
543
  directMessagesExpanded = true;
344
544
  pinnedExpanded = true;
545
+ foldersExpanded = true;
546
+ ungroupedExpanded = true;
345
547
  openMenuConversationId = null;
346
548
  conversationIdsWithTasks = new Set();
347
549
  isSelectionMode = false;
348
550
  selectedConversationIds = new Set();
349
- searchQuery = '';
350
551
  isHeaderMenuOpen = false;
351
552
  isRefreshing = false;
553
+ /** UserInfoEngine key for persisting folder collapse state + group-by mode. */
554
+ static FolderPrefsKey = 'mj.conversations.folderPrefs.v1';
555
+ /** How the conversation list is grouped. 'project' = folders, 'none' = flat list. */
556
+ groupBy = 'project';
557
+ /** Precomputed groupings, rebuilt whenever conversations/projects/search change. */
558
+ pinnedConversations = [];
559
+ unpinnedConversations = [];
560
+ ungroupedConversations = [];
561
+ folderTree = [];
562
+ /** Flattened folder list (depth-ordered) for the "Move to folder" menu. */
563
+ flatFolders = [];
564
+ /** Folder IDs (normalized) whose children are collapsed. Absent = expanded. */
565
+ collapsedFolderIds = new Set();
566
+ /** Drag-and-drop state. */
567
+ draggedConversationId = null;
568
+ draggedFolderId = null;
569
+ dragOverTargetId = null;
570
+ /** When set, the open conversation menu is showing its "Move to folder" picker. */
571
+ moveSubmenuConversationId = null;
572
+ _searchQuery = '';
352
573
  destroy$ = new Subject();
353
574
  engine = ConversationEngine.Instance;
354
575
  // Local UI state for loading/refreshing
355
576
  IsLoading = false;
356
- constructor(dialogService, notificationService, activeTasksService, cdr) {
577
+ constructor(dialogService, notificationService, activeTasksService, mjDialogService, cdr) {
357
578
  this.dialogService = dialogService;
358
579
  this.notificationService = notificationService;
359
580
  this.activeTasksService = activeTasksService;
581
+ this.mjDialogService = mjDialogService;
360
582
  this.cdr = cdr;
361
583
  }
584
+ get searchQuery() {
585
+ return this._searchQuery;
586
+ }
587
+ set searchQuery(value) {
588
+ this._searchQuery = value ?? '';
589
+ this.rebuildGroups();
590
+ }
591
+ /** True when a search filter is active. */
592
+ get isSearching() {
593
+ return this._searchQuery.trim().length > 0;
594
+ }
595
+ /** Conversations matching the current search (used by selection-mode helpers). */
362
596
  get filteredConversations() {
363
- if (!this.searchQuery || this.searchQuery.trim() === '') {
364
- return this.engine.Conversations;
597
+ return this.filterConversations(this.engine.Conversations);
598
+ }
599
+ filterConversations(conversations) {
600
+ if (!this.isSearching) {
601
+ return conversations;
365
602
  }
366
- const lowerQuery = this.searchQuery.toLowerCase();
367
- return this.engine.Conversations.filter(c => (c.Name?.toLowerCase().includes(lowerQuery)) ||
603
+ const lowerQuery = this._searchQuery.toLowerCase();
604
+ return conversations.filter(c => (c.Name?.toLowerCase().includes(lowerQuery)) ||
368
605
  (c.Description?.toLowerCase().includes(lowerQuery)));
369
606
  }
370
- get pinnedConversations() {
371
- return this.filteredConversations.filter(c => c.IsPinned);
372
- }
373
- get unpinnedConversations() {
374
- return this.filteredConversations.filter(c => !c.IsPinned);
375
- }
376
607
  ngOnInit() {
377
- // Load conversations on init
608
+ // Restore persisted folder collapse state + group-by preference
609
+ this.loadFolderPrefs();
610
+ // Load conversations (and folders) on init
378
611
  this.engine.LoadConversations(this.environmentId, this.currentUser, false);
379
- // Re-run change detection whenever the conversations list changes (pin, archive, rename, etc.).
380
- // filteredConversations/pinnedConversations/unpinnedConversations are pure getters that read
381
- // engine.Conversations directly, so Angular doesn't know to re-evaluate them unless
382
- // we explicitly trigger a check here.
612
+ // Rebuild the precomputed groupings whenever conversations OR projects change
613
+ // (pin, archive, rename, move-to-folder, folder create/rename/delete, etc.).
383
614
  this.engine.Conversations$.pipe(takeUntil(this.destroy$)).subscribe(() => {
615
+ this.rebuildGroups();
616
+ this.cdr.detectChanges();
617
+ });
618
+ this.engine.Projects$.pipe(takeUntil(this.destroy$)).subscribe(() => {
619
+ this.rebuildGroups();
384
620
  this.cdr.detectChanges();
385
621
  });
386
622
  // Subscribe to conversation IDs with active tasks (hot set)
@@ -414,6 +650,11 @@ export class ConversationListComponent {
414
650
  this.toggleSelectionMode();
415
651
  this.closeHeaderMenu();
416
652
  }
653
+ onToggleGroupByClick(event) {
654
+ event.stopPropagation();
655
+ this.toggleGroupBy();
656
+ this.closeHeaderMenu();
657
+ }
417
658
  async onRefreshConversationsClick(event) {
418
659
  event.stopPropagation();
419
660
  if (this.isRefreshing)
@@ -450,6 +691,382 @@ export class ConversationListComponent {
450
691
  togglePinned() {
451
692
  this.pinnedExpanded = !this.pinnedExpanded;
452
693
  }
694
+ toggleFolders() {
695
+ this.foldersExpanded = !this.foldersExpanded;
696
+ }
697
+ toggleUngrouped() {
698
+ this.ungroupedExpanded = !this.ungroupedExpanded;
699
+ }
700
+ // ========================================================================
701
+ // FOLDER GROUPING
702
+ // ========================================================================
703
+ /**
704
+ * Recomputes pinned/unpinned/ungrouped lists and the folder tree from the
705
+ * engine's conversation + project caches and the current search filter.
706
+ */
707
+ rebuildGroups() {
708
+ const matching = this.filterConversations(this.engine.Conversations);
709
+ this.pinnedConversations = matching.filter(c => c.IsPinned);
710
+ this.unpinnedConversations = matching.filter(c => !c.IsPinned);
711
+ const projects = this.engine.Projects;
712
+ const projectIds = new Set(projects.map(p => NormalizeUUID(p.ID)));
713
+ // Bucket unpinned conversations by their folder (pinned ones live in the
714
+ // Pinned section). Conversations with no/unknown folder are "ungrouped".
715
+ const conversationsByProject = new Map();
716
+ const ungrouped = [];
717
+ for (const c of this.unpinnedConversations) {
718
+ const pid = c.ProjectID ? NormalizeUUID(c.ProjectID) : null;
719
+ if (pid && projectIds.has(pid)) {
720
+ const arr = conversationsByProject.get(pid) ?? [];
721
+ arr.push(c);
722
+ conversationsByProject.set(pid, arr);
723
+ }
724
+ else {
725
+ ungrouped.push(c);
726
+ }
727
+ }
728
+ this.ungroupedConversations = ungrouped;
729
+ // Index projects by parent. A project whose parent isn't loaded is treated
730
+ // as a root so it never disappears from the tree.
731
+ const childrenByParent = new Map();
732
+ for (const p of projects) {
733
+ const parentId = p.ParentID ? NormalizeUUID(p.ParentID) : null;
734
+ const key = parentId && projectIds.has(parentId) ? parentId : null;
735
+ const arr = childrenByParent.get(key) ?? [];
736
+ arr.push(p);
737
+ childrenByParent.set(key, arr);
738
+ }
739
+ const build = (parentKey, depth) => {
740
+ const projectsAtLevel = childrenByParent.get(parentKey) ?? [];
741
+ return projectsAtLevel.map(p => {
742
+ const children = build(NormalizeUUID(p.ID), depth + 1);
743
+ const conversations = conversationsByProject.get(NormalizeUUID(p.ID)) ?? [];
744
+ const totalCount = conversations.length + children.reduce((sum, ch) => sum + ch.totalCount, 0);
745
+ const hasContent = conversations.length > 0 || children.some(ch => ch.hasContent);
746
+ return { project: p, depth, conversations, children, totalCount, hasContent };
747
+ });
748
+ };
749
+ this.folderTree = build(null, 0);
750
+ this.flatFolders = this.flattenFolders(this.folderTree);
751
+ }
752
+ flattenFolders(nodes) {
753
+ const out = [];
754
+ for (const node of nodes) {
755
+ out.push(node);
756
+ out.push(...this.flattenFolders(node.children));
757
+ }
758
+ return out;
759
+ }
760
+ findFolderNode(nodes, projectId) {
761
+ for (const node of nodes) {
762
+ if (UUIDsEqual(node.project.ID, projectId))
763
+ return node;
764
+ const found = this.findFolderNode(node.children, projectId);
765
+ if (found)
766
+ return found;
767
+ }
768
+ return null;
769
+ }
770
+ isFolderExpanded(projectId) {
771
+ return !this.collapsedFolderIds.has(NormalizeUUID(projectId));
772
+ }
773
+ toggleFolder(projectId) {
774
+ const key = NormalizeUUID(projectId);
775
+ if (this.collapsedFolderIds.has(key)) {
776
+ this.collapsedFolderIds.delete(key);
777
+ }
778
+ else {
779
+ this.collapsedFolderIds.add(key);
780
+ }
781
+ this.saveFolderPrefs();
782
+ }
783
+ toggleGroupBy() {
784
+ this.groupBy = this.groupBy === 'project' ? 'none' : 'project';
785
+ this.saveFolderPrefs();
786
+ this.rebuildGroups();
787
+ }
788
+ loadFolderPrefs() {
789
+ try {
790
+ const raw = UserInfoEngine.Instance.GetSetting(ConversationListComponent.FolderPrefsKey);
791
+ if (!raw)
792
+ return;
793
+ const parsed = JSON.parse(raw);
794
+ this.collapsedFolderIds = new Set((parsed.collapsed ?? []).map(id => NormalizeUUID(id)));
795
+ if (parsed.groupBy === 'none' || parsed.groupBy === 'project') {
796
+ this.groupBy = parsed.groupBy;
797
+ }
798
+ }
799
+ catch {
800
+ // Corrupt/legacy value — ignore and use defaults
801
+ }
802
+ }
803
+ saveFolderPrefs() {
804
+ const payload = JSON.stringify({
805
+ collapsed: Array.from(this.collapsedFolderIds),
806
+ groupBy: this.groupBy
807
+ });
808
+ UserInfoEngine.Instance.SetSettingDebounced(ConversationListComponent.FolderPrefsKey, payload);
809
+ }
810
+ // ========================================================================
811
+ // DRAG & DROP (move conversation into/out of a folder)
812
+ // ========================================================================
813
+ onConversationDragStart(conversation, event) {
814
+ if (this.isSelectionMode)
815
+ return;
816
+ this.draggedFolderId = null;
817
+ this.draggedConversationId = conversation.ID;
818
+ if (event.dataTransfer) {
819
+ event.dataTransfer.effectAllowed = 'move';
820
+ event.dataTransfer.setData('text/plain', conversation.ID);
821
+ }
822
+ }
823
+ onConversationDragEnd() {
824
+ this.draggedConversationId = null;
825
+ this.dragOverTargetId = null;
826
+ }
827
+ onFolderDragStart(node, event) {
828
+ event.stopPropagation();
829
+ this.draggedConversationId = null;
830
+ this.draggedFolderId = node.project.ID;
831
+ if (event.dataTransfer) {
832
+ event.dataTransfer.effectAllowed = 'move';
833
+ event.dataTransfer.setData('text/plain', node.project.ID);
834
+ }
835
+ }
836
+ onFolderDragEnd() {
837
+ this.draggedFolderId = null;
838
+ this.dragOverTargetId = null;
839
+ }
840
+ onFolderDragOver(projectId, event) {
841
+ // A conversation can drop onto any folder; a folder can drop onto any folder
842
+ // that isn't itself or one of its own descendants (which would create a cycle).
843
+ const accepts = this.draggedConversationId
844
+ ? true
845
+ : this.draggedFolderId
846
+ ? this.isValidFolderDropTarget(projectId)
847
+ : false;
848
+ if (!accepts)
849
+ return;
850
+ event.preventDefault();
851
+ if (event.dataTransfer)
852
+ event.dataTransfer.dropEffect = 'move';
853
+ this.dragOverTargetId = projectId;
854
+ }
855
+ onUngroupedDragOver(event) {
856
+ if (!this.draggedConversationId)
857
+ return;
858
+ event.preventDefault();
859
+ if (event.dataTransfer)
860
+ event.dataTransfer.dropEffect = 'move';
861
+ this.dragOverTargetId = 'ungrouped';
862
+ }
863
+ /** The Folders section header accepts a dragged folder to move it back to the top level. */
864
+ onFoldersRootDragOver(event) {
865
+ if (!this.draggedFolderId)
866
+ return;
867
+ event.preventDefault();
868
+ if (event.dataTransfer)
869
+ event.dataTransfer.dropEffect = 'move';
870
+ this.dragOverTargetId = 'folders-root';
871
+ }
872
+ onDragLeave(targetId) {
873
+ if (this.dragOverTargetId === targetId) {
874
+ this.dragOverTargetId = null;
875
+ }
876
+ }
877
+ onFolderDrop(project, event) {
878
+ event.preventDefault();
879
+ const conversationId = this.draggedConversationId;
880
+ const folderId = this.draggedFolderId;
881
+ this.dragOverTargetId = null;
882
+ this.draggedConversationId = null;
883
+ this.draggedFolderId = null;
884
+ if (conversationId) {
885
+ this.moveConversation(conversationId, project.ID);
886
+ }
887
+ else if (folderId && this.isValidFolderDropTarget(project.ID, folderId)) {
888
+ this.moveFolder(folderId, project.ID);
889
+ }
890
+ }
891
+ onUngroupedDrop(event) {
892
+ event.preventDefault();
893
+ const conversationId = this.draggedConversationId;
894
+ this.dragOverTargetId = null;
895
+ this.draggedConversationId = null;
896
+ if (conversationId) {
897
+ this.moveConversation(conversationId, null);
898
+ }
899
+ }
900
+ onFoldersRootDrop(event) {
901
+ event.preventDefault();
902
+ const folderId = this.draggedFolderId;
903
+ this.dragOverTargetId = null;
904
+ this.draggedFolderId = null;
905
+ if (folderId) {
906
+ this.moveFolder(folderId, null);
907
+ }
908
+ }
909
+ /**
910
+ * A folder can be dropped onto a target folder only if the target isn't the dragged
911
+ * folder itself and isn't one of its descendants (otherwise we'd create a cycle).
912
+ */
913
+ isValidFolderDropTarget(targetId, draggedId = this.draggedFolderId) {
914
+ if (!draggedId)
915
+ return false;
916
+ if (UUIDsEqual(targetId, draggedId))
917
+ return false;
918
+ return !this.isDescendantOf(targetId, draggedId);
919
+ }
920
+ /** True when `nodeId` is a descendant of `ancestorId` in the folder tree. */
921
+ isDescendantOf(nodeId, ancestorId) {
922
+ const byId = new Map(this.engine.Projects.map(p => [NormalizeUUID(p.ID), p]));
923
+ const visited = new Set();
924
+ let current = byId.get(NormalizeUUID(nodeId));
925
+ while (current?.ParentID) {
926
+ const parentKey = NormalizeUUID(current.ParentID);
927
+ if (visited.has(parentKey))
928
+ break; // guard against malformed cycles
929
+ visited.add(parentKey);
930
+ if (UUIDsEqual(parentKey, ancestorId))
931
+ return true;
932
+ current = byId.get(parentKey);
933
+ }
934
+ return false;
935
+ }
936
+ /** Assigns a conversation to a folder (or null to ungroup) and refreshes the view. */
937
+ async moveConversation(conversationId, projectId) {
938
+ try {
939
+ await this.engine.MoveConversationToProject(conversationId, projectId, this.currentUser);
940
+ // Reveal the destination folder so the user sees where it landed
941
+ if (projectId) {
942
+ this.collapsedFolderIds.delete(NormalizeUUID(projectId));
943
+ }
944
+ this.rebuildGroups();
945
+ this.cdr.detectChanges();
946
+ }
947
+ catch (error) {
948
+ console.error('Error moving conversation:', error);
949
+ await this.dialogService.alert('Error', 'Failed to move conversation. Please try again.');
950
+ }
951
+ }
952
+ /** Reparents a folder under another folder (or to the top level when projectId is null). */
953
+ async moveFolder(folderId, parentId) {
954
+ // No-op if it's already under that parent
955
+ const folder = this.engine.Projects.find(p => UUIDsEqual(p.ID, folderId));
956
+ const currentParent = folder?.ParentID ?? null;
957
+ const sameParent = (currentParent === null && parentId === null) ||
958
+ (!!currentParent && !!parentId && UUIDsEqual(currentParent, parentId));
959
+ if (sameParent)
960
+ return;
961
+ try {
962
+ await this.engine.MoveProjectToParent(folderId, parentId, this.currentUser);
963
+ // Reveal the new parent so the moved folder is visible
964
+ if (parentId) {
965
+ this.collapsedFolderIds.delete(NormalizeUUID(parentId));
966
+ }
967
+ this.rebuildGroups();
968
+ this.cdr.detectChanges();
969
+ }
970
+ catch (error) {
971
+ console.error('Error moving folder:', error);
972
+ await this.dialogService.alert('Error', 'Failed to move folder. Please try again.');
973
+ }
974
+ }
975
+ // ========================================================================
976
+ // MOVE-TO-FOLDER MENU
977
+ // ========================================================================
978
+ openMoveSubmenu(conversationId, event) {
979
+ event.stopPropagation();
980
+ this.moveSubmenuConversationId = conversationId;
981
+ }
982
+ closeMoveSubmenu(event) {
983
+ event.stopPropagation();
984
+ this.moveSubmenuConversationId = null;
985
+ }
986
+ IsInFolder(conversation, projectId) {
987
+ return !!conversation.ProjectID && UUIDsEqual(conversation.ProjectID, projectId);
988
+ }
989
+ selectMoveTarget(conversation, projectId) {
990
+ this.moveConversation(conversation.ID, projectId);
991
+ this.closeMenu();
992
+ }
993
+ // ========================================================================
994
+ // FOLDER CRUD (reuses the existing project form modal)
995
+ // ========================================================================
996
+ createFolder(parentId, event) {
997
+ if (event)
998
+ event.stopPropagation();
999
+ this.openFolderModal(null, parentId);
1000
+ }
1001
+ editFolder(project, event) {
1002
+ if (event)
1003
+ event.stopPropagation();
1004
+ this.openFolderModal(project, null);
1005
+ }
1006
+ createFolderForConversation(conversation, event) {
1007
+ event.stopPropagation();
1008
+ const conversationId = conversation.ID;
1009
+ this.closeMenu();
1010
+ this.openFolderModal(null, null, (created) => this.moveConversation(conversationId, created.ID));
1011
+ }
1012
+ openFolderModal(project, parentId, onCreated) {
1013
+ const dialogRef = this.mjDialogService.open({
1014
+ content: ProjectFormModalComponent,
1015
+ width: 600,
1016
+ minWidth: 400
1017
+ });
1018
+ const instance = dialogRef.Content.instance;
1019
+ instance.dialogRef = dialogRef;
1020
+ instance.environmentId = this.environmentId;
1021
+ instance.currentUser = this.currentUser;
1022
+ if (project)
1023
+ instance.project = project;
1024
+ if (parentId)
1025
+ instance.parentId = parentId;
1026
+ instance.projectSaved.subscribe((saved) => {
1027
+ // The engine's entity-event handler keeps the projects cache in sync; we
1028
+ // just reveal the parent and refresh, then run any post-create action.
1029
+ if (parentId) {
1030
+ this.collapsedFolderIds.delete(NormalizeUUID(parentId));
1031
+ }
1032
+ this.rebuildGroups();
1033
+ this.cdr.detectChanges();
1034
+ if (onCreated)
1035
+ onCreated(saved);
1036
+ });
1037
+ }
1038
+ async deleteFolder(project, event) {
1039
+ if (event)
1040
+ event.stopPropagation();
1041
+ const node = this.findFolderNode(this.folderTree, project.ID);
1042
+ const total = node?.totalCount ?? 0;
1043
+ const childCount = node?.children.length ?? 0;
1044
+ let message = `Are you sure you want to delete the folder "${project.Name}"?`;
1045
+ if (total > 0 || childCount > 0) {
1046
+ message += `\n\nConversations inside will be moved out of the folder`;
1047
+ message += childCount > 0 ? ` and subfolders will move up one level.` : `.`;
1048
+ message += ` Nothing is deleted.`;
1049
+ }
1050
+ const confirmed = await this.dialogService.confirm({
1051
+ title: 'Delete Folder',
1052
+ message,
1053
+ okText: 'Delete',
1054
+ cancelText: 'Cancel',
1055
+ dangerous: true
1056
+ });
1057
+ if (!confirmed)
1058
+ return;
1059
+ try {
1060
+ await this.engine.DeleteProject(project.ID, this.currentUser);
1061
+ this.collapsedFolderIds.delete(NormalizeUUID(project.ID));
1062
+ this.rebuildGroups();
1063
+ this.cdr.detectChanges();
1064
+ }
1065
+ catch (error) {
1066
+ console.error('Error deleting folder:', error);
1067
+ await this.dialogService.alert('Error', error instanceof Error ? error.message : 'Failed to delete folder. Please try again.');
1068
+ }
1069
+ }
453
1070
  IsConversationActive(conversation) {
454
1071
  return UUIDsEqual(conversation.ID, this.selectedConversationId);
455
1072
  }
@@ -459,6 +1076,12 @@ export class ConversationListComponent {
459
1076
  IsMenuOpen(conversation) {
460
1077
  return UUIDsEqual(this.openMenuConversationId, conversation.ID);
461
1078
  }
1079
+ IsConversationDragging(conversation) {
1080
+ return UUIDsEqual(this.draggedConversationId, conversation.ID);
1081
+ }
1082
+ IsMoveSubmenuOpen(conversation) {
1083
+ return UUIDsEqual(this.moveSubmenuConversationId, conversation.ID);
1084
+ }
462
1085
  selectConversation(conversation) {
463
1086
  this.conversationSelected.emit(conversation.ID);
464
1087
  // Clear unread notifications when conversation is opened
@@ -524,6 +1147,7 @@ export class ConversationListComponent {
524
1147
  }
525
1148
  closeMenu() {
526
1149
  this.openMenuConversationId = null;
1150
+ this.moveSubmenuConversationId = null;
527
1151
  }
528
1152
  async togglePin(conversation, event) {
529
1153
  if (event)
@@ -621,35 +1245,29 @@ export class ConversationListComponent {
621
1245
  this.selectConversation(conversation);
622
1246
  }
623
1247
  }
624
- static ɵfac = function ConversationListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ConversationListComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.NotificationService), i0.ɵɵdirectiveInject(i3.ActiveTasksService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
1248
+ static ɵfac = function ConversationListComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || ConversationListComponent)(i0.ɵɵdirectiveInject(i1.DialogService), i0.ɵɵdirectiveInject(i2.NotificationService), i0.ɵɵdirectiveInject(i3.ActiveTasksService), i0.ɵɵdirectiveInject(i4.MJDialogService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
625
1249
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ConversationListComponent, selectors: [["mj-conversation-list"]], hostBindings: function ConversationListComponent_HostBindings(rf, ctx) { if (rf & 1) {
626
1250
  i0.ɵɵlistener("click", function ConversationListComponent_click_HostBindingHandler() { return ctx.onDocumentClick(); }, i0.ɵɵresolveDocument);
627
- } }, inputs: { environmentId: "environmentId", currentUser: "currentUser", selectedConversationId: "selectedConversationId", renamedConversationId: "renamedConversationId", isSidebarPinned: "isSidebarPinned", isMobileView: "isMobileView" }, outputs: { conversationSelected: "conversationSelected", conversationDeleted: "conversationDeleted", newConversationRequested: "newConversationRequested", pinSidebarRequested: "pinSidebarRequested", unpinSidebarRequested: "unpinSidebarRequested", refreshRequested: "refreshRequested" }, standalone: false, decls: 21, vars: 8, consts: [[1, "conversation-list"], [1, "list-header"], [1, "header-top"], ["type", "text", "placeholder", "Search conversations...", 1, "search-input", 3, "ngModelChange", "ngModel"], [1, "header-menu-container"], ["title", "New Conversation", 1, "btn-new-conversation", 3, "click"], [1, "fas", "fa-plus"], [1, "list-content"], [1, "sidebar-section", "pinned-section"], [1, "sidebar-section"], [1, "section-header", 3, "click"], [1, "section-title"], [1, "fas", "fa-chevron-right"], [1, "chat-list"], [1, "conversation-item", 3, "active", "renamed"], [1, "selection-action-bar"], ["title", "Options", 1, "btn-menu", 3, "click"], [1, "fas", "fa-ellipsis-v"], [1, "header-dropdown-menu"], [1, "dropdown-item", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], [1, "dropdown-item", 3, "click"], [1, "fas", "fa-check-square"], [1, "dropdown-item"], [1, "fas", "fa-table-columns"], [1, "fas", "fa-thumbtack", "section-icon"], [1, "conversation-item", 3, "click"], [1, "conversation-checkbox"], [1, "conversation-icon-wrapper"], [1, "conversation-icon", "has-tasks"], [1, "badge-overlay"], [3, "conversationId"], [1, "conversation-info", 3, "title"], [1, "conversation-name"], [1, "fas", "fa-share-nodes", "shared-indicator", 3, "title"], [1, "conversation-preview"], [1, "conversation-actions"], ["type", "checkbox", 3, "click", "checked"], [1, "fas", "fa-spinner", "fa-pulse"], ["title", "More options", 1, "menu-btn", 3, "click"], [1, "fas", "fa-ellipsis"], [1, "context-menu"], [1, "context-menu", 3, "click"], [1, "menu-item", 3, "click"], [1, "fas", "fa-thumbtack"], [1, "fas", "fa-edit"], [1, "menu-divider"], [1, "menu-item", "danger", 3, "click"], [1, "fas", "fa-trash"], [1, "selection-info"], [1, "selection-count"], [1, "link-btn"], [1, "selection-actions"], [1, "btn-delete-bulk", 3, "click", "disabled"], [1, "btn-cancel", 3, "click"], [1, "link-btn", 3, "click"]], template: function ConversationListComponent_Template(rf, ctx) { if (rf & 1) {
628
- i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "div", 2)(3, "input", 3);
629
- i0.ɵɵtwoWayListener("ngModelChange", function ConversationListComponent_Template_input_ngModelChange_3_listener($event) { i0.ɵɵtwoWayBindingSet(ctx.searchQuery, $event) || (ctx.searchQuery = $event); return $event; });
1251
+ } }, inputs: { environmentId: "environmentId", currentUser: "currentUser", selectedConversationId: "selectedConversationId", renamedConversationId: "renamedConversationId", isSidebarPinned: "isSidebarPinned", isMobileView: "isMobileView" }, outputs: { conversationSelected: "conversationSelected", conversationDeleted: "conversationDeleted", newConversationRequested: "newConversationRequested", pinSidebarRequested: "pinSidebarRequested", unpinSidebarRequested: "unpinSidebarRequested", refreshRequested: "refreshRequested" }, standalone: false, decls: 18, vars: 5, consts: [["folderNode", ""], ["conversationItem", ""], [1, "conversation-list"], [1, "list-header"], [1, "header-top"], ["type", "text", "placeholder", "Search conversations...", 1, "search-input", 3, "ngModelChange", "ngModel"], [1, "header-menu-container"], ["title", "New Conversation", 1, "btn-new-conversation", 3, "click"], [1, "fas", "fa-plus"], [1, "list-content"], [1, "sidebar-section", "pinned-section"], [1, "sidebar-section"], [1, "selection-action-bar"], ["title", "Options", 1, "btn-menu", 3, "click"], [1, "fas", "fa-ellipsis-v"], [1, "header-dropdown-menu"], [1, "dropdown-item", 3, "click", "disabled"], [1, "fas", "fa-sync-alt"], [1, "dropdown-item", 3, "click"], [1, "fas", "fa-check-square"], [1, "fas"], [1, "dropdown-item"], [1, "fas", "fa-table-columns"], [1, "section-header", 3, "click"], [1, "section-title"], [1, "fas", "fa-chevron-right"], [1, "fas", "fa-thumbtack", "section-icon"], [1, "chat-list"], [3, "ngTemplateOutlet", "ngTemplateOutletContext"], [1, "sidebar-section", "folders-section"], [1, "section-header", 3, "click", "dragover", "dragleave", "drop"], ["title", "New Folder", 1, "section-action-btn", 3, "click"], [1, "fas", "fa-folder-plus"], [1, "folder-empty-hint"], [1, "sidebar-section", "ungrouped-section", 3, "dragover", "dragleave", "drop"], [1, "selection-info"], [1, "selection-count"], [1, "link-btn"], [1, "selection-actions"], [1, "btn-delete-bulk", 3, "click", "disabled"], [1, "fas", "fa-trash"], [1, "btn-cancel", 3, "click"], [1, "link-btn", 3, "click"], [1, "folder-row", 3, "dragstart", "dragend", "click", "dragover", "dragleave", "drop", "draggable", "title"], [1, "fas", "fa-chevron-right", "folder-chevron"], [1, "folder-name"], [1, "folder-count"], [1, "folder-actions", 3, "click"], ["title", "New Subfolder", 1, "folder-action-btn", 3, "click"], ["title", "Edit Folder", 1, "folder-action-btn", 3, "click"], [1, "fas", "fa-pen"], ["title", "Delete Folder", 1, "folder-action-btn", "danger", 3, "click"], [1, "folder-children"], [1, "folder-empty-hint", 3, "paddingLeft"], [1, "conversation-item", 3, "dragstart", "dragend", "click", "draggable"], [1, "conversation-checkbox"], [1, "conversation-icon-wrapper"], [1, "conversation-icon", "has-tasks"], [1, "badge-overlay"], [3, "conversationId"], [1, "conversation-info", 3, "title"], [1, "conversation-name"], [1, "fas", "fa-share-nodes", "shared-indicator", 3, "title"], [1, "conversation-preview"], [1, "conversation-actions"], ["type", "checkbox", 3, "click", "checked"], [1, "fas", "fa-spinner", "fa-pulse"], ["title", "More options", 1, "menu-btn", 3, "click"], [1, "fas", "fa-ellipsis"], [1, "context-menu"], [1, "context-menu", 3, "click"], [1, "menu-item", "back", 3, "click"], [1, "fas", "fa-chevron-left"], [1, "menu-divider"], [1, "move-folder-list"], [1, "menu-item", 3, "click"], [1, "fas", "fa-inbox"], [1, "menu-item", 3, "current", "paddingLeft"], [1, "fas", "fa-thumbtack"], [1, "fas", "fa-folder-tree"], [1, "fas", "fa-chevron-right", "submenu-arrow"], [1, "fas", "fa-edit"], [1, "menu-item", "danger", 3, "click"]], template: function ConversationListComponent_Template(rf, ctx) { if (rf & 1) {
1252
+ const _r1 = i0.ɵɵgetCurrentView();
1253
+ i0.ɵɵelementStart(0, "div", 2)(1, "div", 3)(2, "div", 4)(3, "input", 5);
1254
+ i0.ɵɵtwoWayListener("ngModelChange", function ConversationListComponent_Template_input_ngModelChange_3_listener($event) { i0.ɵɵrestoreView(_r1); i0.ɵɵtwoWayBindingSet(ctx.searchQuery, $event) || (ctx.searchQuery = $event); return i0.ɵɵresetView($event); });
630
1255
  i0.ɵɵelementEnd();
631
- i0.ɵɵconditionalCreate(4, ConversationListComponent_Conditional_4_Template, 4, 1, "div", 4);
1256
+ i0.ɵɵconditionalCreate(4, ConversationListComponent_Conditional_4_Template, 4, 1, "div", 6);
632
1257
  i0.ɵɵelementEnd()();
633
- i0.ɵɵelementStart(5, "button", 5);
634
- i0.ɵɵlistener("click", function ConversationListComponent_Template_button_click_5_listener() { return ctx.createNewConversation(); });
635
- i0.ɵɵelement(6, "i", 6);
1258
+ i0.ɵɵelementStart(5, "button", 7);
1259
+ i0.ɵɵlistener("click", function ConversationListComponent_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); return i0.ɵɵresetView(ctx.createNewConversation()); });
1260
+ i0.ɵɵelement(6, "i", 8);
636
1261
  i0.ɵɵelementStart(7, "span");
637
1262
  i0.ɵɵtext(8, "New Conversation");
638
1263
  i0.ɵɵelementEnd()();
639
- i0.ɵɵelementStart(9, "div", 7);
640
- i0.ɵɵconditionalCreate(10, ConversationListComponent_Conditional_10_Template, 10, 4, "div", 8);
641
- i0.ɵɵelementStart(11, "div", 9)(12, "div", 10);
642
- i0.ɵɵlistener("click", function ConversationListComponent_Template_div_click_12_listener() { return ctx.toggleDirectMessages(); });
643
- i0.ɵɵelementStart(13, "div", 11);
644
- i0.ɵɵelement(14, "i", 12);
645
- i0.ɵɵelementStart(15, "span");
646
- i0.ɵɵtext(16, "Messages");
647
- i0.ɵɵelementEnd()()();
648
- i0.ɵɵelementStart(17, "div", 13);
649
- i0.ɵɵrepeaterCreate(18, ConversationListComponent_For_19_Template, 13, 12, "div", 14, _forTrack0);
650
- i0.ɵɵelementEnd()()();
651
- i0.ɵɵconditionalCreate(20, ConversationListComponent_Conditional_20_Template, 12, 4, "div", 15);
1264
+ i0.ɵɵelementStart(9, "div", 9);
1265
+ i0.ɵɵconditionalCreate(10, ConversationListComponent_Conditional_10_Template, 10, 4, "div", 10);
1266
+ i0.ɵɵconditionalCreate(11, ConversationListComponent_Conditional_11_Template, 21, 14)(12, ConversationListComponent_Conditional_12_Template, 9, 4, "div", 11);
1267
+ i0.ɵɵelementEnd();
1268
+ i0.ɵɵconditionalCreate(13, ConversationListComponent_Conditional_13_Template, 12, 4, "div", 12);
652
1269
  i0.ɵɵelementEnd();
1270
+ i0.ɵɵtemplate(14, ConversationListComponent_ng_template_14_Template, 15, 18, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor)(16, ConversationListComponent_ng_template_16_Template, 13, 17, "ng-template", null, 1, i0.ɵɵtemplateRefExtractor);
653
1271
  } if (rf & 2) {
654
1272
  i0.ɵɵadvance(3);
655
1273
  i0.ɵɵtwoWayProperty("ngModel", ctx.searchQuery);
@@ -657,15 +1275,11 @@ export class ConversationListComponent {
657
1275
  i0.ɵɵconditional(!ctx.isSelectionMode ? 4 : -1);
658
1276
  i0.ɵɵadvance(6);
659
1277
  i0.ɵɵconditional(ctx.pinnedConversations.length > 0 ? 10 : -1);
660
- i0.ɵɵadvance(2);
661
- i0.ɵɵclassProp("expanded", ctx.directMessagesExpanded);
662
- i0.ɵɵadvance(5);
663
- i0.ɵɵclassProp("expanded", ctx.directMessagesExpanded);
664
1278
  i0.ɵɵadvance();
665
- i0.ɵɵrepeater(ctx.unpinnedConversations);
1279
+ i0.ɵɵconditional(ctx.groupBy === "project" ? 11 : 12);
666
1280
  i0.ɵɵadvance(2);
667
- i0.ɵɵconditional(ctx.isSelectionMode ? 20 : -1);
668
- } }, dependencies: [i4.DefaultValueAccessor, i4.NgControlStatus, i4.NgModel, i5.NotificationBadgeComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n .conversation-list[_ngcontent-%COMP%] { display: flex; flex-direction: column; height: 100%; background: var(--mj-brand-secondary); }\n .list-header[_ngcontent-%COMP%] { padding: 8px; border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent); }\n .search-input[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]::placeholder { color: color-mix(in srgb, var(--mj-brand-on-secondary) 50%, transparent); }\n .search-input[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: var(--mj-brand-primary-hover); }\n .btn-new-conversation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 14px; }\n .list-content[_ngcontent-%COMP%] { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0; }\n\n \n\n .sidebar-section[_ngcontent-%COMP%] { margin-bottom: 20px; }\n .pinned-section[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] .section-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 11px;\n margin-left: 2px;\n }\n .section-header[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); }\n .section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:not(.section-icon) {\n transition: transform 0.2s;\n }\n .section-header.expanded[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:not(.section-icon) { transform: rotate(90deg); }\n .chat-list[_ngcontent-%COMP%] {\n padding: 4px 0;\n display: none;\n }\n .chat-list.expanded[_ngcontent-%COMP%] { display: block; }\n\n .conversation-item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); color: var(--mj-brand-on-secondary); }\n .conversation-item[_ngcontent-%COMP%]:hover .conversation-actions[_ngcontent-%COMP%] { opacity: 1; }\n .conversation-item.active[_ngcontent-%COMP%] { background: var(--mj-brand-primary); color: var(--mj-brand-on-secondary); }\n .conversation-icon-wrapper[_ngcontent-%COMP%] { position: relative; flex-shrink: 0; }\n .conversation-icon[_ngcontent-%COMP%] { font-size: 12px; width: 16px; text-align: center; }\n .conversation-icon.has-tasks[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n .badge-overlay[_ngcontent-%COMP%] { position: absolute; top: -4px; right: -4px; }\n .conversation-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .conversation-name[_ngcontent-%COMP%] { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }\n .shared-indicator[_ngcontent-%COMP%] { font-size: 10px; color: color-mix(in srgb, var(--mj-brand-on-secondary) 55%, transparent); flex-shrink: 0; }\n .conversation-item.active[_ngcontent-%COMP%] .shared-indicator[_ngcontent-%COMP%] { color: color-mix(in srgb, var(--mj-brand-on-secondary) 85%, transparent); }\n .conversation-preview[_ngcontent-%COMP%] { 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[_ngcontent-%COMP%] .conversation-preview[_ngcontent-%COMP%] { color: color-mix(in srgb, var(--mj-brand-on-secondary) 80%, transparent); }\n .conversation-meta[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }\n\n \n\n .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover .conversation-actions[_ngcontent-%COMP%] { opacity: 1; pointer-events: auto; }\n .conversation-item.active[_ngcontent-%COMP%] .conversation-actions[_ngcontent-%COMP%] { opacity: 1; pointer-events: auto; }\n .conversation-actions[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] { pointer-events: auto; }\n .pinned-icon[_ngcontent-%COMP%] { color: var(--mj-brand-accent); font-size: 12px; }\n\n \n\n .task-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 12px;\n margin-right: 8px;\n flex-shrink: 0;\n animation: _ngcontent-%COMP%_pulse-glow 2s ease-in-out infinite;\n }\n @keyframes _ngcontent-%COMP%_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[_ngcontent-%COMP%] .task-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n }\n\n .menu-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] .menu-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary-hover) !important;\n color: var(--mj-brand-on-secondary);\n }\n .menu-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 14px; }\n\n .context-menu[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n margin: 4px 0;\n }\n\n \n\n .conversation-item.renamed[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_renameHighlight 1500ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes _ngcontent-%COMP%_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 \n\n .header-top[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n \n\n .header-menu-container[_ngcontent-%COMP%] {\n position: relative;\n flex-shrink: 0;\n }\n\n .btn-menu[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .header-dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] .shortcut[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-right: 8px;\n flex-shrink: 0;\n }\n\n .conversation-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n }\n\n .selection-action-bar[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .link-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-on-secondary);\n }\n\n .selection-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex: 0 0 auto;\n }\n\n .btn-cancel[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 80%, black);\n }\n\n .btn-delete-bulk[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-delete-bulk[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }"] });
1281
+ i0.ɵɵconditional(ctx.isSelectionMode ? 13 : -1);
1282
+ } }, dependencies: [i5.NgTemplateOutlet, i6.DefaultValueAccessor, i6.NgControlStatus, i6.NgModel, i7.NotificationBadgeComponent], styles: ["[_nghost-%COMP%] { display: block; height: 100%; }\n .conversation-list[_ngcontent-%COMP%] { display: flex; flex-direction: column; height: 100%; background: var(--mj-brand-secondary); }\n .list-header[_ngcontent-%COMP%] { padding: 8px; border-bottom: 1px solid color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent); }\n .search-input[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]::placeholder { color: color-mix(in srgb, var(--mj-brand-on-secondary) 50%, transparent); }\n .search-input[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: var(--mj-brand-primary-hover); }\n .btn-new-conversation[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 14px; }\n .list-content[_ngcontent-%COMP%] { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 0; }\n\n \n\n .sidebar-section[_ngcontent-%COMP%] { margin-bottom: 20px; }\n .pinned-section[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] .section-icon[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 11px;\n margin-left: 2px;\n }\n .section-header[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); }\n .section-title[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 10px;\n }\n .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:not(.section-icon) {\n transition: transform 0.2s;\n }\n .section-header.expanded[_ngcontent-%COMP%] .section-title[_ngcontent-%COMP%] i[_ngcontent-%COMP%]:not(.section-icon) { transform: rotate(90deg); }\n .chat-list[_ngcontent-%COMP%] {\n padding: 4px 0;\n display: none;\n }\n .chat-list.expanded[_ngcontent-%COMP%] { display: block; }\n\n .conversation-item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); color: var(--mj-brand-on-secondary); }\n .conversation-item[_ngcontent-%COMP%]:hover .conversation-actions[_ngcontent-%COMP%] { opacity: 1; }\n .conversation-item.active[_ngcontent-%COMP%] { background: var(--mj-brand-primary); color: var(--mj-brand-on-secondary); }\n .conversation-icon-wrapper[_ngcontent-%COMP%] { position: relative; flex-shrink: 0; }\n .conversation-icon[_ngcontent-%COMP%] { font-size: 12px; width: 16px; text-align: center; }\n .conversation-icon.has-tasks[_ngcontent-%COMP%] { color: var(--mj-status-warning); }\n .badge-overlay[_ngcontent-%COMP%] { position: absolute; top: -4px; right: -4px; }\n .conversation-info[_ngcontent-%COMP%] { flex: 1; min-width: 0; }\n .conversation-name[_ngcontent-%COMP%] { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 6px; }\n .shared-indicator[_ngcontent-%COMP%] { font-size: 10px; color: color-mix(in srgb, var(--mj-brand-on-secondary) 55%, transparent); flex-shrink: 0; }\n .conversation-item.active[_ngcontent-%COMP%] .shared-indicator[_ngcontent-%COMP%] { color: color-mix(in srgb, var(--mj-brand-on-secondary) 85%, transparent); }\n .conversation-preview[_ngcontent-%COMP%] { 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[_ngcontent-%COMP%] .conversation-preview[_ngcontent-%COMP%] { color: color-mix(in srgb, var(--mj-brand-on-secondary) 80%, transparent); }\n .conversation-meta[_ngcontent-%COMP%] { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }\n\n \n\n .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .project-badge[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover .conversation-actions[_ngcontent-%COMP%] { opacity: 1; pointer-events: auto; }\n .conversation-item.active[_ngcontent-%COMP%] .conversation-actions[_ngcontent-%COMP%] { opacity: 1; pointer-events: auto; }\n .conversation-actions[_ngcontent-%COMP%] > *[_ngcontent-%COMP%] { pointer-events: auto; }\n .pinned-icon[_ngcontent-%COMP%] { color: var(--mj-brand-accent); font-size: 12px; }\n\n \n\n .task-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n font-size: 12px;\n margin-right: 8px;\n flex-shrink: 0;\n animation: _ngcontent-%COMP%_pulse-glow 2s ease-in-out infinite;\n }\n @keyframes _ngcontent-%COMP%_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[_ngcontent-%COMP%] .task-indicator[_ngcontent-%COMP%] {\n color: var(--mj-status-warning);\n }\n\n .menu-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] .menu-btn[_ngcontent-%COMP%] {\n background: var(--mj-brand-primary-hover) !important;\n color: var(--mj-brand-on-secondary);\n }\n .menu-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 14px; }\n\n .context-menu[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .menu-item.danger[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-item.danger[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-status-error);\n }\n\n .menu-divider[_ngcontent-%COMP%] {\n height: 1px;\n background: color-mix(in srgb, var(--mj-brand-on-secondary) 10%, transparent);\n margin: 4px 0;\n }\n\n \n\n .conversation-item.renamed[_ngcontent-%COMP%] {\n animation: _ngcontent-%COMP%_renameHighlight 1500ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n @keyframes _ngcontent-%COMP%_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 \n\n .header-top[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n align-items: center;\n }\n\n \n\n .header-menu-container[_ngcontent-%COMP%] {\n position: relative;\n flex-shrink: 0;\n }\n\n .btn-menu[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%]:hover i[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .header-dropdown-menu[_ngcontent-%COMP%] .dropdown-item[_ngcontent-%COMP%] .shortcut[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n margin-right: 8px;\n flex-shrink: 0;\n }\n\n .conversation-checkbox[_ngcontent-%COMP%] input[type=\"checkbox\"][_ngcontent-%COMP%] {\n width: 18px;\n height: 18px;\n cursor: pointer;\n accent-color: var(--mj-brand-primary);\n }\n\n .selection-action-bar[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\n color: var(--mj-brand-on-secondary);\n }\n\n .link-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover {\n color: var(--mj-brand-on-secondary);\n }\n\n .selection-actions[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n flex: 0 0 auto;\n }\n\n .btn-cancel[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-status-error) 80%, black);\n }\n\n .btn-delete-bulk[_ngcontent-%COMP%]:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .btn-delete-bulk[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 12px;\n }\n\n \n\n .section-action-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 12px; }\n\n .folder-row[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover { background: color-mix(in srgb, var(--mj-brand-on-secondary) 8%, transparent); }\n .folder-row.drag-over[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] { opacity: 0.4; }\n .section-header.drag-over[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] { transform: rotate(90deg); }\n .folder-icon[_ngcontent-%COMP%] { font-size: 12px; width: 16px; text-align: center; flex-shrink: 0; }\n .folder-name[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]:hover .folder-actions[_ngcontent-%COMP%] { opacity: 1; pointer-events: auto; }\n .folder-row[_ngcontent-%COMP%]:hover .folder-count[_ngcontent-%COMP%] { opacity: 0; }\n .folder-action-btn[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%]: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[_ngcontent-%COMP%]:hover {\n background: color-mix(in srgb, var(--mj-status-error) 18%, transparent);\n color: var(--mj-status-error);\n }\n .folder-action-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] { font-size: 11px; }\n .folder-children[_ngcontent-%COMP%] { display: block; }\n .folder-empty-hint[_ngcontent-%COMP%] {\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[_ngcontent-%COMP%] {\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 \n\n .conversation-item[_ngcontent-%COMP%] { user-select: none; }\n .conversation-item.dragging[_ngcontent-%COMP%] { opacity: 0.4; }\n\n \n\n .menu-item.back[_ngcontent-%COMP%] { font-weight: 600; }\n .menu-item[_ngcontent-%COMP%] .submenu-arrow[_ngcontent-%COMP%] { margin-left: auto; font-size: 10px; }\n .menu-item.current[_ngcontent-%COMP%] { background: color-mix(in srgb, var(--mj-brand-primary) 18%, transparent); }\n .move-folder-list[_ngcontent-%COMP%] { max-height: 240px; overflow-y: auto; }"] });
669
1283
  }
670
1284
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ConversationListComponent, [{
671
1285
  type: Component,
@@ -693,6 +1307,10 @@ export class ConversationListComponent {
693
1307
  <i class="fas fa-check-square"></i>
694
1308
  <span>Select Conversations</span>
695
1309
  </button>
1310
+ <button class="dropdown-item" (click)="onToggleGroupByClick($event)">
1311
+ <i class="fas" [class.fa-folder-tree]="groupBy !== 'project'" [class.fa-list]="groupBy === 'project'"></i>
1312
+ <span>{{ groupBy === 'project' ? 'Show as flat list' : 'Group by folder' }}</span>
1313
+ </button>
696
1314
  @if (!isMobileView) {
697
1315
  <button class="dropdown-item" (click)="onUnpinSidebarClick($event)">
698
1316
  <i class="fas fa-table-columns"></i>
@@ -722,136 +1340,75 @@ export class ConversationListComponent {
722
1340
  </div>
723
1341
  <div class="chat-list" [class.expanded]="pinnedExpanded">
724
1342
  @for (conversation of pinnedConversations; track conversation.ID) {
725
- <div class="conversation-item"
726
- [class.active]="IsConversationActive(conversation)"
727
- [class.renamed]="IsConversationRenamed(conversation)"
728
- (click)="handleConversationClick(conversation)">
729
- @if (isSelectionMode) {
730
- <div class="conversation-checkbox">
731
- <input type="checkbox"
732
- [checked]="selectedConversationIds.has(conversation.ID)"
733
- (click)="$event.stopPropagation(); toggleConversationSelection(conversation.ID)">
734
- </div>
735
- }
736
- <div class="conversation-icon-wrapper">
737
- @if (hasActiveTasks(conversation.ID)) {
738
- <div class="conversation-icon has-tasks">
739
- <i class="fas fa-spinner fa-pulse"></i>
740
- </div>
741
- }
742
- <div class="badge-overlay">
743
- <mj-notification-badge [conversationId]="conversation.ID"></mj-notification-badge>
744
- </div>
745
- </div>
746
- <div class="conversation-info" [title]="conversation.Name + (conversation.Description ? '\n' + conversation.Description : '')">
747
- <div class="conversation-name">
748
- {{ conversation.Name }}
749
- @if (isSharedWithMe(conversation)) {
750
- <i class="fas fa-share-nodes shared-indicator"
751
- [title]="sharedWithMeTooltip(conversation)"></i>
752
- }
753
- </div>
754
- <div class="conversation-preview">{{ conversation.Description }}</div>
755
- </div>
756
- @if (!isSelectionMode) {
757
- <div class="conversation-actions">
758
- <button class="menu-btn" (click)="toggleMenu(conversation.ID, $event)" title="More options">
759
- <i class="fas fa-ellipsis"></i>
760
- </button>
761
- @if (IsMenuOpen(conversation)) {
762
- <div class="context-menu" (click)="$event.stopPropagation()">
763
- <button class="menu-item" (click)="togglePin(conversation, $event)">
764
- <i class="fas fa-thumbtack"></i>
765
- <span>Unpin</span>
766
- </button>
767
- <button class="menu-item" (click)="renameConversation(conversation); closeMenu()">
768
- <i class="fas fa-edit"></i>
769
- <span>Rename</span>
770
- </button>
771
- <div class="menu-divider"></div>
772
- <button class="menu-item danger" (click)="deleteConversation(conversation); closeMenu()">
773
- <i class="fas fa-trash"></i>
774
- <span>Delete</span>
775
- </button>
776
- </div>
777
- }
778
- </div>
779
- }
780
- </div>
1343
+ <ng-container [ngTemplateOutlet]="conversationItem" [ngTemplateOutletContext]="{ $implicit: conversation }"></ng-container>
781
1344
  }
782
1345
  </div>
783
1346
  </div>
784
1347
  }
785
1348
 
786
- <!-- Messages Section -->
787
- <div class="sidebar-section">
788
- <div class="section-header" [class.expanded]="directMessagesExpanded" (click)="toggleDirectMessages()">
789
- <div class="section-title">
790
- <i class="fas fa-chevron-right"></i>
791
- <span>Messages</span>
1349
+ @if (groupBy === 'project') {
1350
+ <!-- Folders Section -->
1351
+ <div class="sidebar-section folders-section">
1352
+ <div class="section-header" [class.expanded]="foldersExpanded"
1353
+ [class.drag-over]="dragOverTargetId === 'folders-root'"
1354
+ (click)="toggleFolders()"
1355
+ (dragover)="onFoldersRootDragOver($event)"
1356
+ (dragleave)="onDragLeave('folders-root')"
1357
+ (drop)="onFoldersRootDrop($event)">
1358
+ <div class="section-title">
1359
+ <i class="fas fa-chevron-right"></i>
1360
+ <span>Folders</span>
1361
+ </div>
1362
+ <button class="section-action-btn" (click)="createFolder(null, $event)" title="New Folder">
1363
+ <i class="fas fa-folder-plus"></i>
1364
+ </button>
792
1365
  </div>
793
- </div>
794
- <div class="chat-list" [class.expanded]="directMessagesExpanded">
795
- @for (conversation of unpinnedConversations; track conversation.ID) {
796
- <div class="conversation-item"
797
- [class.active]="IsConversationActive(conversation)"
798
- [class.renamed]="IsConversationRenamed(conversation)"
799
- (click)="handleConversationClick(conversation)">
800
- @if (isSelectionMode) {
801
- <div class="conversation-checkbox">
802
- <input type="checkbox"
803
- [checked]="selectedConversationIds.has(conversation.ID)"
804
- (click)="$event.stopPropagation(); toggleConversationSelection(conversation.ID)">
805
- </div>
806
- }
807
- <div class="conversation-icon-wrapper">
808
- @if (hasActiveTasks(conversation.ID)) {
809
- <div class="conversation-icon has-tasks">
810
- <i class="fas fa-spinner fa-pulse"></i>
811
- </div>
812
- }
813
- <div class="badge-overlay">
814
- <mj-notification-badge [conversationId]="conversation.ID"></mj-notification-badge>
815
- </div>
816
- </div>
817
- <div class="conversation-info" [title]="conversation.Name + (conversation.Description ? '\n' + conversation.Description : '')">
818
- <div class="conversation-name">
819
- {{ conversation.Name }}
820
- @if (isSharedWithMe(conversation)) {
821
- <i class="fas fa-share-nodes shared-indicator"
822
- [title]="sharedWithMeTooltip(conversation)"></i>
823
- }
824
- </div>
825
- <div class="conversation-preview">{{ conversation.Description }}</div>
826
- </div>
827
- @if (!isSelectionMode) {
828
- <div class="conversation-actions">
829
- <button class="menu-btn" (click)="toggleMenu(conversation.ID, $event)" title="More options">
830
- <i class="fas fa-ellipsis"></i>
831
- </button>
832
- @if (IsMenuOpen(conversation)) {
833
- <div class="context-menu" (click)="$event.stopPropagation()">
834
- <button class="menu-item" (click)="togglePin(conversation, $event)">
835
- <i class="fas fa-thumbtack"></i>
836
- <span>Pin</span>
837
- </button>
838
- <button class="menu-item" (click)="renameConversation(conversation); closeMenu()">
839
- <i class="fas fa-edit"></i>
840
- <span>Rename</span>
841
- </button>
842
- <div class="menu-divider"></div>
843
- <button class="menu-item danger" (click)="deleteConversation(conversation); closeMenu()">
844
- <i class="fas fa-trash"></i>
845
- <span>Delete</span>
846
- </button>
847
- </div>
848
- }
849
- </div>
1366
+ <div class="chat-list" [class.expanded]="foldersExpanded">
1367
+ @for (node of folderTree; track node.project.ID) {
1368
+ @if (!isSearching || node.hasContent) {
1369
+ <ng-container [ngTemplateOutlet]="folderNode" [ngTemplateOutletContext]="{ $implicit: node }"></ng-container>
850
1370
  }
1371
+ }
1372
+ @if (folderTree.length === 0) {
1373
+ <div class="folder-empty-hint">No folders yet — create one to organize conversations.</div>
1374
+ }
1375
+ </div>
1376
+ </div>
1377
+
1378
+ <!-- Ungrouped Section (drop target to remove from folder) -->
1379
+ <div class="sidebar-section ungrouped-section"
1380
+ [class.drag-over]="dragOverTargetId === 'ungrouped'"
1381
+ (dragover)="onUngroupedDragOver($event)"
1382
+ (dragleave)="onDragLeave('ungrouped')"
1383
+ (drop)="onUngroupedDrop($event)">
1384
+ <div class="section-header" [class.expanded]="ungroupedExpanded" (click)="toggleUngrouped()">
1385
+ <div class="section-title">
1386
+ <i class="fas fa-chevron-right"></i>
1387
+ <span>{{ folderTree.length > 0 ? 'Ungrouped' : 'Messages' }}</span>
851
1388
  </div>
852
- }
1389
+ </div>
1390
+ <div class="chat-list" [class.expanded]="ungroupedExpanded">
1391
+ @for (conversation of ungroupedConversations; track conversation.ID) {
1392
+ <ng-container [ngTemplateOutlet]="conversationItem" [ngTemplateOutletContext]="{ $implicit: conversation }"></ng-container>
1393
+ }
1394
+ </div>
853
1395
  </div>
854
- </div>
1396
+ } @else {
1397
+ <!-- Flat Messages Section -->
1398
+ <div class="sidebar-section">
1399
+ <div class="section-header" [class.expanded]="directMessagesExpanded" (click)="toggleDirectMessages()">
1400
+ <div class="section-title">
1401
+ <i class="fas fa-chevron-right"></i>
1402
+ <span>Messages</span>
1403
+ </div>
1404
+ </div>
1405
+ <div class="chat-list" [class.expanded]="directMessagesExpanded">
1406
+ @for (conversation of unpinnedConversations; track conversation.ID) {
1407
+ <ng-container [ngTemplateOutlet]="conversationItem" [ngTemplateOutletContext]="{ $implicit: conversation }"></ng-container>
1408
+ }
1409
+ </div>
1410
+ </div>
1411
+ }
855
1412
  </div>
856
1413
 
857
1414
  <!-- Selection Action Bar -->
@@ -879,8 +1436,152 @@ export class ConversationListComponent {
879
1436
  </div>
880
1437
  }
881
1438
  </div>
882
- `, 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 "] }]
883
- }], () => [{ type: i1.DialogService }, { type: i2.NotificationService }, { type: i3.ActiveTasksService }, { type: i0.ChangeDetectorRef }], { environmentId: [{
1439
+
1440
+ <!-- Recursive folder node: header + nested children + direct conversations -->
1441
+ <ng-template #folderNode let-node>
1442
+ <div class="folder-row"
1443
+ [class.drag-over]="dragOverTargetId === node.project.ID"
1444
+ [class.dragging]="draggedFolderId === node.project.ID"
1445
+ [style.paddingLeft.px]="12 + node.depth * 14"
1446
+ [draggable]="true"
1447
+ (dragstart)="onFolderDragStart(node, $event)"
1448
+ (dragend)="onFolderDragEnd()"
1449
+ (click)="toggleFolder(node.project.ID)"
1450
+ (dragover)="onFolderDragOver(node.project.ID, $event)"
1451
+ (dragleave)="onDragLeave(node.project.ID)"
1452
+ (drop)="onFolderDrop(node.project, $event)"
1453
+ [title]="node.project.Name">
1454
+ <i class="fas fa-chevron-right folder-chevron" [class.expanded]="isFolderExpanded(node.project.ID)"></i>
1455
+ <i class="fas {{ node.project.Icon || 'fa-folder' }} folder-icon" [style.color]="node.project.Color || null"></i>
1456
+ <span class="folder-name">{{ node.project.Name }}</span>
1457
+ <span class="folder-count">{{ node.totalCount }}</span>
1458
+ <div class="folder-actions" (click)="$event.stopPropagation()">
1459
+ <button class="folder-action-btn" (click)="createFolder(node.project.ID, $event)" title="New Subfolder">
1460
+ <i class="fas fa-folder-plus"></i>
1461
+ </button>
1462
+ <button class="folder-action-btn" (click)="editFolder(node.project, $event)" title="Edit Folder">
1463
+ <i class="fas fa-pen"></i>
1464
+ </button>
1465
+ <button class="folder-action-btn danger" (click)="deleteFolder(node.project, $event)" title="Delete Folder">
1466
+ <i class="fas fa-trash"></i>
1467
+ </button>
1468
+ </div>
1469
+ </div>
1470
+ @if (isFolderExpanded(node.project.ID)) {
1471
+ <div class="folder-children">
1472
+ @for (child of node.children; track child.project.ID) {
1473
+ @if (!isSearching || child.hasContent) {
1474
+ <ng-container [ngTemplateOutlet]="folderNode" [ngTemplateOutletContext]="{ $implicit: child }"></ng-container>
1475
+ }
1476
+ }
1477
+ @for (conversation of node.conversations; track conversation.ID) {
1478
+ <ng-container [ngTemplateOutlet]="conversationItem" [ngTemplateOutletContext]="{ $implicit: conversation, depth: node.depth + 1 }"></ng-container>
1479
+ }
1480
+ @if (node.totalCount === 0 && !isSearching) {
1481
+ <div class="folder-empty-hint" [style.paddingLeft.px]="26 + node.depth * 14">Empty — drop a conversation here</div>
1482
+ }
1483
+ </div>
1484
+ }
1485
+ </ng-template>
1486
+
1487
+ <!-- Shared conversation row used by Pinned, folders, and Ungrouped/Messages -->
1488
+ <ng-template #conversationItem let-conversation let-depth="depth">
1489
+ <div class="conversation-item"
1490
+ [class.active]="IsConversationActive(conversation)"
1491
+ [class.renamed]="IsConversationRenamed(conversation)"
1492
+ [class.dragging]="IsConversationDragging(conversation)"
1493
+ [style.paddingLeft.px]="depth ? 16 + depth * 14 : 16"
1494
+ [draggable]="!isSelectionMode"
1495
+ (dragstart)="onConversationDragStart(conversation, $event)"
1496
+ (dragend)="onConversationDragEnd()"
1497
+ (click)="handleConversationClick(conversation)">
1498
+ @if (isSelectionMode) {
1499
+ <div class="conversation-checkbox">
1500
+ <input type="checkbox"
1501
+ [checked]="selectedConversationIds.has(conversation.ID)"
1502
+ (click)="$event.stopPropagation(); toggleConversationSelection(conversation.ID)">
1503
+ </div>
1504
+ }
1505
+ <div class="conversation-icon-wrapper">
1506
+ @if (hasActiveTasks(conversation.ID)) {
1507
+ <div class="conversation-icon has-tasks">
1508
+ <i class="fas fa-spinner fa-pulse"></i>
1509
+ </div>
1510
+ }
1511
+ <div class="badge-overlay">
1512
+ <mj-notification-badge [conversationId]="conversation.ID"></mj-notification-badge>
1513
+ </div>
1514
+ </div>
1515
+ <div class="conversation-info" [title]="conversation.Name + (conversation.Description ? '\n' + conversation.Description : '')">
1516
+ <div class="conversation-name">
1517
+ {{ conversation.Name }}
1518
+ @if (isSharedWithMe(conversation)) {
1519
+ <i class="fas fa-share-nodes shared-indicator"
1520
+ [title]="sharedWithMeTooltip(conversation)"></i>
1521
+ }
1522
+ </div>
1523
+ <div class="conversation-preview">{{ conversation.Description }}</div>
1524
+ </div>
1525
+ @if (!isSelectionMode) {
1526
+ <div class="conversation-actions">
1527
+ <button class="menu-btn" (click)="toggleMenu(conversation.ID, $event)" title="More options">
1528
+ <i class="fas fa-ellipsis"></i>
1529
+ </button>
1530
+ @if (IsMenuOpen(conversation)) {
1531
+ <div class="context-menu" (click)="$event.stopPropagation()">
1532
+ @if (IsMoveSubmenuOpen(conversation)) {
1533
+ <button class="menu-item back" (click)="closeMoveSubmenu($event)">
1534
+ <i class="fas fa-chevron-left"></i>
1535
+ <span>Move to folder</span>
1536
+ </button>
1537
+ <div class="menu-divider"></div>
1538
+ <div class="move-folder-list">
1539
+ <button class="menu-item" [class.current]="!conversation.ProjectID" (click)="selectMoveTarget(conversation, null)">
1540
+ <i class="fas fa-inbox"></i>
1541
+ <span>No folder</span>
1542
+ </button>
1543
+ @for (f of flatFolders; track f.project.ID) {
1544
+ <button class="menu-item" [class.current]="IsInFolder(conversation, f.project.ID)"
1545
+ [style.paddingLeft.px]="14 + f.depth * 12"
1546
+ (click)="selectMoveTarget(conversation, f.project.ID)">
1547
+ <i class="fas {{ f.project.Icon || 'fa-folder' }}" [style.color]="f.project.Color || null"></i>
1548
+ <span>{{ f.project.Name }}</span>
1549
+ </button>
1550
+ }
1551
+ </div>
1552
+ <div class="menu-divider"></div>
1553
+ <button class="menu-item" (click)="createFolderForConversation(conversation, $event)">
1554
+ <i class="fas fa-folder-plus"></i>
1555
+ <span>New folder…</span>
1556
+ </button>
1557
+ } @else {
1558
+ <button class="menu-item" (click)="togglePin(conversation, $event)">
1559
+ <i class="fas fa-thumbtack"></i>
1560
+ <span>{{ conversation.IsPinned ? 'Unpin' : 'Pin' }}</span>
1561
+ </button>
1562
+ <button class="menu-item" (click)="openMoveSubmenu(conversation.ID, $event)">
1563
+ <i class="fas fa-folder-tree"></i>
1564
+ <span>Move to folder</span>
1565
+ <i class="fas fa-chevron-right submenu-arrow"></i>
1566
+ </button>
1567
+ <button class="menu-item" (click)="renameConversation(conversation); closeMenu()">
1568
+ <i class="fas fa-edit"></i>
1569
+ <span>Rename</span>
1570
+ </button>
1571
+ <div class="menu-divider"></div>
1572
+ <button class="menu-item danger" (click)="deleteConversation(conversation); closeMenu()">
1573
+ <i class="fas fa-trash"></i>
1574
+ <span>Delete</span>
1575
+ </button>
1576
+ }
1577
+ </div>
1578
+ }
1579
+ </div>
1580
+ }
1581
+ </div>
1582
+ </ng-template>
1583
+ `, 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 "] }]
1584
+ }], () => [{ type: i1.DialogService }, { type: i2.NotificationService }, { type: i3.ActiveTasksService }, { type: i4.MJDialogService }, { type: i0.ChangeDetectorRef }], { environmentId: [{
884
1585
  type: Input
885
1586
  }], currentUser: [{
886
1587
  type: Input
@@ -908,5 +1609,5 @@ export class ConversationListComponent {
908
1609
  type: HostListener,
909
1610
  args: ['document:click']
910
1611
  }] }); })();
911
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationListComponent, { className: "ConversationListComponent", filePath: "src/lib/components/conversation/conversation-list.component.ts", lineNumber: 731 }); })();
1612
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(ConversationListComponent, { className: "ConversationListComponent", filePath: "src/lib/components/conversation/conversation-list.component.ts", lineNumber: 964 }); })();
912
1613
  //# sourceMappingURL=conversation-list.component.js.map