main
js 137 lines 4.17 KB
Raw
1 import { createStore } from "/js/AlpineStore.js";
2 import { toggleCssProperty } from "/js/css.js";
3
4 const model = {
5 settings: {},
6
7 async init() {
8 this.settings =
9 JSON.parse(localStorage.getItem("messageResizeSettings") || "null") ||
10 this._getDefaultSettings();
11 this._applyAllSettings();
12 },
13
14 _getDefaultSettings() {
15 return {
16 "message": { minimized: false, maximized: false },
17 "message-agent": { minimized: true, maximized: false },
18 "message-agent-response": { minimized: false, maximized: true },
19 };
20 },
21
22 getSetting(className) {
23 return this.settings[className] || { minimized: false, maximized: false };
24 },
25
26 _getDefaultSetting() {
27 return { minimized: false, maximized: false };
28 },
29
30 _setSetting(className, setting) {
31 this.settings[className] = setting;
32 localStorage.setItem(
33 "messageResizeSettings",
34 JSON.stringify(this.settings)
35 );
36 },
37
38 _applyAllSettings() {
39 for (const [className, setting] of Object.entries(this.settings)) {
40 this._applySetting(className, setting);
41 }
42 },
43
44 async minimizeMessageClass(className, event) {
45 const set = this.getSetting(className);
46 set.minimized = !set.minimized;
47 this._setSetting(className, set);
48 this._applySetting(className, set);
49 this._applyScroll(event);
50 },
51
52 async maximizeMessageClass(className, event) {
53 const set = this.getSetting(className);
54 if (set.minimized) return this.minimizeMessageClass(className, event); // if minimized, unminimize first
55 set.maximized = !set.maximized;
56 this._setSetting(className, set);
57 this._applySetting(className, set);
58 this._applyScroll(event);
59 },
60
61 _applyScroll(event) {
62 if (!event || !event.target) {
63 return;
64 }
65
66 // Store the element reference to avoid issues with event being modified
67 const targetElement = event.target;
68 const clickY = event.clientY;
69
70 // Use requestAnimationFrame for smoother timing with browser rendering
71 // requestAnimationFrame(() => {
72 try {
73 // Get fresh measurements after potential re-renders
74 const rect = targetElement.getBoundingClientRect();
75 const viewHeight = window.innerHeight || document.documentElement.clientHeight;
76
77 // Get chat history element
78 const chatHistory = document.getElementById('chat-history');
79 if (!chatHistory) {
80 return;
81 }
82
83 // Get chat history position
84 const chatRect = chatHistory.getBoundingClientRect();
85
86 // Calculate element's middle position relative to chat history
87 const elementHeight = rect.height;
88 const elementMiddle = rect.top + (elementHeight / 2);
89 const relativeMiddle = elementMiddle - chatRect.top;
90
91 // Calculate target scroll position
92 let scrollTop;
93
94 if (typeof clickY === 'number') {
95 // Calculate based on click position
96 const clickRelativeToChat = clickY - chatRect.top;
97 // Add current scroll position and adjust to keep element middle at click position
98 scrollTop = chatHistory.scrollTop + relativeMiddle - clickRelativeToChat;
99 } else {
100 // Position element middle at 50% from the top of chat history viewport (center)
101 const targetPosition = chatHistory.clientHeight * 0.5;
102 scrollTop = chatHistory.scrollTop + relativeMiddle - targetPosition;
103 }
104
105 // Apply scroll with instant behavior
106 chatHistory.scrollTo({
107 top: scrollTop,
108 behavior: "auto"
109 });
110 } catch (e) {
111 // Silent error handling
112 }
113 // });
114 },
115
116 _applySetting(className, setting) {
117 toggleCssProperty(
118 `.${className} .message-body`,
119 "max-height",
120 setting.maximized ? "unset" : "30em"
121 );
122 toggleCssProperty(
123 `.${className} .message-body`,
124 "overflow-y",
125 setting.maximized ? "hidden" : "auto"
126 );
127 toggleCssProperty(
128 `.${className} .message-body`,
129 "display",
130 setting.minimized ? "none" : "block"
131 );
132 },
133 };
134
135 const store = createStore("messageResize", model);
136
137 export { store };