11<script setup lang="ts">
2- import { ref , onMounted , onUnmounted , computed , watchEffect } from ' vue' ;
2+ import { ref , onMounted , onUnmounted , computed , watchEffect , watch , nextTick } from ' vue' ;
33import { useStorage , onClickOutside } from ' @vueuse/core' ;
44import { LogicalSize } from ' @tauri-apps/api/window' ;
55import { invoke } from ' @tauri-apps/api/core' ;
@@ -148,16 +148,13 @@ onMounted(() => {
148148 }
149149});
150150
151- // Watch and adjust physical window dimensions when entering or leaving pocket layout mode
151+ // Watch and adjust physical window dimensions when entering or leaving pocket layout mode.
152+ // In pocket mode the width is driven by the auto-size logic below (content width);
153+ // in full mode we always restore the standard 800x600 window.
152154watchEffect (async () => {
153- const isPocket = pocketMode .value ;
154- if (isPocket && isSettingsOpen .value ) return ;
155+ if (pocketMode .value ) return ; // 袖珍模式宽度由自适应逻辑控制
155156 try {
156- if (isPocket ) {
157- await win .appWindow .setSize (new LogicalSize (420 , 52 ));
158- } else {
159- await win .appWindow .setSize (new LogicalSize (800 , 600 ));
160- }
157+ await win .appWindow .setSize (new LogicalSize (800 , 600 ));
161158 } catch (e ) {
162159 console .error (' Failed to resize window:' , e );
163160 }
@@ -174,6 +171,75 @@ watchEffect(async () => {
174171 }
175172});
176173
174+ // --- 袖珍模式窗口宽度自适应 ---
175+ // 窗口宽度跟随内容宽度自动伸缩(避免固定 420px 下长文本如猫猫语导致控件溢出)。
176+ // 防循环关键: PocketLayout 根容器使用 w-max(宽度由内容决定),窗口 resize 不会改变内容宽度,
177+ // 因此 ResizeObserver -> setSize 不会再次触发内容宽度变化,不会形成死循环。
178+ const pocketContentRef = ref <HTMLElement | null >(null );
179+ let pocketObserver: ResizeObserver | null = null ;
180+ let pocketRaf = 0 ;
181+ const POCKET_HEIGHT = 52 ;
182+ const POCKET_X_PADDING = 12 ; // 外层 p-1.5 左右各 6px
183+ const POCKET_MIN_WIDTH = 240 ;
184+
185+ async function resizePocketToContent() {
186+ const el = pocketContentRef .value ;
187+ if (! el ) return ;
188+ const targetW = Math .max (
189+ Math .ceil (el .getBoundingClientRect ().width + POCKET_X_PADDING ),
190+ POCKET_MIN_WIDTH ,
191+ );
192+ try {
193+ await win .appWindow .setSize (new LogicalSize (targetW , POCKET_HEIGHT ));
194+ } catch (e ) {
195+ console .error (' Failed to resize pocket window:' , e );
196+ }
197+ }
198+
199+ function startPocketObserver() {
200+ stopPocketObserver ();
201+ const el = pocketContentRef .value ;
202+ if (! el ) return ;
203+ pocketObserver = new ResizeObserver ((entries ) => {
204+ if (! pocketMode .value || isSettingsOpen .value ) return ;
205+ const entry = entries [0 ];
206+ if (! entry ) return ;
207+ if (pocketRaf ) cancelAnimationFrame (pocketRaf );
208+ pocketRaf = requestAnimationFrame (() => void resizePocketToContent ());
209+ });
210+ pocketObserver .observe (el );
211+ }
212+
213+ function stopPocketObserver() {
214+ pocketObserver ?.disconnect ();
215+ pocketObserver = null ;
216+ if (pocketRaf ) cancelAnimationFrame (pocketRaf );
217+ pocketRaf = 0 ;
218+ }
219+
220+ // 进入/退出袖珍模式时启停自适应
221+ watch (pocketMode , async (isPocket ) => {
222+ if (isPocket ) {
223+ await nextTick ();
224+ startPocketObserver ();
225+ if (! isSettingsOpen .value ) await resizePocketToContent ();
226+ } else {
227+ stopPocketObserver ();
228+ }
229+ }, { immediate: true });
230+
231+ // 设置对话框打开时暂停自适应(由上方 watchEffect 展开到 800),关闭后恢复自适应宽度
232+ watch (isSettingsOpen , async (open ) => {
233+ if (! pocketMode .value ) return ;
234+ if (open ) {
235+ stopPocketObserver ();
236+ } else {
237+ await nextTick ();
238+ startPocketObserver ();
239+ await resizePocketToContent ();
240+ }
241+ });
242+
177243// Central action button hover animations
178244const onCentralBtnHover = () => {
179245 if (centralBtnRef .value ) {
@@ -251,6 +317,7 @@ watchEffect(() => {
251317});
252318
253319onUnmounted (() => {
320+ stopPocketObserver ();
254321 if (breatheAnim ) breatheAnim .pause ();
255322 if (dotPulseAnim ) dotPulseAnim .pause ();
256323});
@@ -269,9 +336,11 @@ onUnmounted(() => {
269336 @click =" pocketLayoutRef?.closePopup()"
270337 />
271338
339+ <!-- 包裹层: 宽度由内容决定(w-max),供窗口自适应宽度测量 -->
340+ <div ref =" pocketContentRef" class =" relative z-20 w-max" >
272341 <PocketLayout
273342 ref="pocketLayoutRef"
274- class="flex-1 relative z-20 "
343+ class="relative"
275344 :serverState =" server .serverState .value "
276345 :connectionMode =" server .connectionMode .value "
277346 :serverPort =" server .serverPort .value "
@@ -296,6 +365,7 @@ onUnmounted(() => {
296365 @openSettings =" isSettingsOpen = true "
297366 @update :popupOpen =" v => pocketPopupOpen = v "
298367 />
368+ </div >
299369 </div >
300370
301371 <!-- Full Mode -->
0 commit comments