@@ -17,19 +17,56 @@ document.addEventListener('DOMContentLoaded', async function() {
1717
1818 const config = await loadConfig ( ) ;
1919
20+ // Auto-resize textarea
21+ userInput . addEventListener ( 'input' , function ( ) {
22+ this . style . height = 'auto' ;
23+ this . style . height = this . scrollHeight + 'px' ;
24+ } ) ;
25+
26+ // Submit on Enter, newline on Shift+Enter
27+ userInput . addEventListener ( 'keydown' , function ( e ) {
28+ if ( e . key === 'Enter' && ! e . shiftKey ) {
29+ e . preventDefault ( ) ;
30+ chatForm . requestSubmit ( ) ;
31+ }
32+ } ) ;
33+
2034 if ( uploadBtn ) {
2135 if ( isAttachmentsEnabled ( config ) ) {
2236 uploadBtn . classList . remove ( 'hidden' ) ;
2337 } else {
2438 uploadBtn . classList . add ( 'hidden' ) ;
25- userInput . classList . add ( 'rounded-l-lg' ) ;
2639 }
2740 }
2841
42+ // Initialize model selector
43+ const modelSelect = document . getElementById ( 'modelSelect' ) ;
44+ const models = getModels ( config ) ;
45+ if ( modelSelect && models . length > 0 ) {
46+ modelSelect . classList . remove ( 'hidden' ) ;
47+ models . forEach ( m => {
48+ const opt = document . createElement ( 'option' ) ;
49+ opt . value = m . id ;
50+ opt . textContent = m . name ;
51+ if ( m . default ) opt . selected = true ;
52+ modelSelect . appendChild ( opt ) ;
53+ } ) ;
54+ const saved = getSelectedModel ( ) ;
55+ if ( saved && models . some ( m => m . id === saved ) ) {
56+ modelSelect . value = saved ;
57+ } else {
58+ const def = models . find ( m => m . default ) || models [ 0 ] ;
59+ setSelectedModel ( def . id ) ;
60+ }
61+ modelSelect . addEventListener ( 'change' , ( ) => setSelectedModel ( modelSelect . value ) ) ;
62+ } else if ( modelSelect ) {
63+ modelSelect . classList . add ( 'hidden' ) ;
64+ }
65+
2966 const loginMessage = document . getElementById ( 'loginMessage' ) ;
3067 if ( loginMessage ) {
3168 if ( config . authType === 'simple' ) {
32- loginMessage . textContent = 'Local Mode - Enter any username to continue' ;
69+ loginMessage . textContent = 'Local Mode — Enter any username to continue' ;
3370 } else {
3471 loginMessage . textContent = 'Sign in with your Cognito credentials' ;
3572 }
@@ -43,10 +80,8 @@ document.addEventListener('DOMContentLoaded', async function() {
4380
4481 loginForm . addEventListener ( 'submit' , async function ( e ) {
4582 e . preventDefault ( ) ;
46-
4783 const username = document . getElementById ( 'username' ) . value ;
4884 const password = document . getElementById ( 'password' ) . value ;
49-
5085 loginError . classList . add ( 'hidden' ) ;
5186
5287 try {
@@ -60,7 +95,6 @@ document.addEventListener('DOMContentLoaded', async function() {
6095
6196 chatForm . addEventListener ( 'submit' , async function ( e ) {
6297 e . preventDefault ( ) ;
63-
6498 const message = userInput . value . trim ( ) ;
6599 if ( ! message ) return ;
66100
@@ -69,16 +103,19 @@ document.addEventListener('DOMContentLoaded', async function() {
69103 return ;
70104 }
71105
72- addMessage ( message , 'user' ) ;
106+ const userMsg = addMessage ( message , 'user' ) ;
107+ requestAnimationFrame ( ( ) => {
108+ const headerH = document . querySelector ( '.chat-header' ) . offsetHeight ;
109+ const msgTop = userMsg . getBoundingClientRect ( ) . top + chatScreen . scrollTop - chatScreen . getBoundingClientRect ( ) . top ;
110+ chatScreen . scrollTo ( { top : msgTop - headerH - 24 , behavior : 'smooth' } ) ;
111+ } ) ;
73112 userInput . value = '' ;
113+ userInput . style . height = 'auto' ;
74114
75115 const auth = loadAuth ( ) ;
76- if ( ! auth || Date . now ( ) >= ( auth . expiresAt - 300000 ) ) {
116+ if ( isSessionExpired ( auth ) ) {
77117 addMessage ( 'Your session has expired. Please log in again.' , 'ai' , { isError : true } ) ;
78- setTimeout ( ( ) => {
79- clearAuth ( ) ;
80- showLoginScreen ( ) ;
81- } , 2000 ) ;
118+ setTimeout ( ( ) => { clearAuth ( ) ; showLoginScreen ( ) ; } , 2000 ) ;
82119 return ;
83120 }
84121
@@ -91,16 +128,14 @@ document.addEventListener('DOMContentLoaded', async function() {
91128 } catch ( error ) {
92129 removeLoading ( loadingId ) ;
93130 const retryFn = async ( ) => {
94- const errorMsg = messageContainer . lastElementChild ;
131+ const container = document . getElementById ( 'messageContainer' ) ;
132+ const errorMsg = container . lastElementChild ;
95133 if ( errorMsg ) errorMsg . remove ( ) ;
96134
97135 const freshAuth = loadAuth ( ) ;
98- if ( ! freshAuth || Date . now ( ) >= ( freshAuth . expiresAt - 300000 ) ) {
136+ if ( isSessionExpired ( freshAuth ) ) {
99137 addMessage ( 'Your session has expired. Please log in again.' , 'ai' , { isError : true } ) ;
100- setTimeout ( ( ) => {
101- clearAuth ( ) ;
102- showLoginScreen ( ) ;
103- } , 2000 ) ;
138+ setTimeout ( ( ) => { clearAuth ( ) ; showLoginScreen ( ) ; } , 2000 ) ;
104139 return ;
105140 }
106141
@@ -122,15 +157,18 @@ document.addEventListener('DOMContentLoaded', async function() {
122157
123158 const themeIcon = document . getElementById ( 'themeIcon' ) ;
124159 themeToggle . addEventListener ( 'click' , function ( ) {
125- const html = document . documentElement ;
126- html . classList . toggle ( 'dark ') ;
127- themeIcon . textContent = html . classList . contains ( 'dark' ) ? '☀️ ' : '🌙 ' ;
128- localStorage . setItem ( 'theme' , html . classList . contains ( 'dark' ) ? 'dark ' : 'light ' ) ;
160+ document . documentElement . classList . toggle ( 'light' ) ;
161+ const isLight = document . documentElement . classList . contains ( 'light ') ;
162+ themeIcon . textContent = isLight ? '🌙 ' : '☀️ ' ;
163+ localStorage . setItem ( 'theme' , isLight ? 'light ' : 'dark ' ) ;
129164 } ) ;
130165
131166 if ( localStorage . getItem ( 'theme' ) === 'dark' ) {
132- document . documentElement . classList . add ( 'dark ') ;
167+ document . documentElement . classList . remove ( 'light ') ;
133168 themeIcon . textContent = '☀️' ;
169+ } else {
170+ document . documentElement . classList . add ( 'light' ) ;
171+ themeIcon . textContent = '🌙' ;
134172 }
135173
136174 logoutBtn . addEventListener ( 'click' , function ( ) {
@@ -158,7 +196,7 @@ document.addEventListener('DOMContentLoaded', async function() {
158196 function showChatScreen ( ) {
159197 loginScreen . classList . add ( 'hidden' ) ;
160198 chatScreen . classList . remove ( 'hidden' ) ;
161-
199+ chatScreen . scrollTop = 0 ;
162200 const auth = loadAuth ( ) ;
163201 if ( auth ) {
164202 userDisplay . textContent = auth . username ;
0 commit comments