Explorar o código

release: v0.0.6
- 优化页面信息卡片样式和动画
- 改进输入框焦点管理
- 优化侧边栏动画效果
- 提升整体用户体验

alibct hai 7 meses
pai
achega
1c077ffdfa
Modificáronse 5 ficheiros con 109 adicións e 20 borrados
  1. 4 0
      CHANGELOG.md
  2. 23 1
      css/chat.css
  3. 17 6
      css/content.css
  4. 44 4
      js/chat-ui.js
  5. 21 9
      js/content.js

+ 4 - 0
CHANGELOG.md

@@ -12,6 +12,10 @@
   - 改进输入框焦点管理
   - AI 回复完成后自动聚焦
   - 优化视觉反馈效果
+- 优化侧边栏动画
+  - 改进打开/关闭动画效果
+  - 优化动画执行时序
+  - 提升过渡流畅度
 
 ## [0.0.5] - 2024-03-xx
 

+ 23 - 1
css/chat.css

@@ -68,7 +68,8 @@
   background: #f0f4f8 !important;
   border-radius: 8px !important;
   padding: 8px 12px !important;
-  transition: all 0.2s ease !important;
+  transition: all 0.3s ease-out !important;
+  will-change: min-height, max-height !important;
   min-height: 40px !important; /* 设置最小高度 */
   max-height: 120px !important; /* 设置最大高度 */
 }
@@ -755,3 +756,24 @@
     transform: scale(1) rotate(360deg);
   }
 }
+
+/* 输入框过渡动画 */
+.input-transition {
+  transition: height 0.3s ease-out !important;
+  will-change: height !important; /* 优化动画性能 */
+}
+
+#chat-input {
+  flex: 1 !important;
+  border: none !important;
+  background: transparent !important;
+  resize: none !important;
+  padding: 8px !important;
+  font-size: 14px !important;
+  line-height: 1.5 !important;
+  min-height: 24px !important;
+  max-height: 100px !important;
+  outline: none !important;
+  color: #333 !important;
+  overflow-y: auto !important;
+}

+ 17 - 6
css/content.css

@@ -7,6 +7,11 @@ body {
   height: 100% !important;
 }
 
+/* 动画中状态 - 禁用页面滚动 */
+body.sidebar-animating {
+  overflow: hidden !important;
+}
+
 /* 主内容区域 */
 #paiwise-main-wrapper {
   position: fixed !important;
@@ -16,32 +21,38 @@ body {
   height: 100vh !important;
   overflow-y: auto !important;
   overflow-x: hidden !important;
-  transition: all 0.3s ease-in-out !important;
+  transition: width 0.3s ease-out !important;
+  backface-visibility: hidden !important; /* 优化动画性能 */
+  -webkit-font-smoothing: antialiased !important;
 }
 
 /* 侧边栏 */
 #paiwise-sidebar {
   position: fixed !important;
   top: 0 !important;
-  right: -400px !important;
+  right: 0 !important;
   width: 400px !important;
   height: 100vh !important;
   background: #fff !important;
   border: none !important;
   box-shadow: -4px 0 16px rgba(0, 0, 0, 0.08) !important;
   z-index: 2147483647 !important;
-  transition: transform 0.3s ease-in-out !important;
+  transform: translateX(100%) !important;
+  visibility: hidden !important;
+  opacity: 0 !important;
+  transition: transform 0.3s ease-out, visibility 0.3s, opacity 0.3s !important;
 }
 
 /* 侧边栏显示状态 */
 #paiwise-sidebar.show {
-  transform: translateX(-400px) !important;
-  box-shadow: -8px 0 24px rgba(0, 0, 0, 0.12) !important;
+  transform: translateX(0) !important;
+  visibility: visible !important;
+  opacity: 1 !important;
 }
 
 /* 主内容区域在侧边栏显示时的状态 */
 body.sidebar-open #paiwise-main-wrapper {
-  width: calc(100% - 400px) !important; /* 自动计算宽度 */
+  width: calc(100% - 400px) !important;
 }
 
 /* 移除所有动画关键帧,使用transform实现动画 */

+ 44 - 4
js/chat-ui.js

@@ -12,12 +12,32 @@ class ChatUI {
     }
     this.aiService = window.aiService;
 
-    this.typingSpeed = 50; // 打字速度(毫秒/字符)
+    this.typingSpeed = 50;
+    this.inputWrapper = document.querySelector(".input-wrapper");
+
+    // 先添加过渡动画类
+    this.input.classList.add("input-transition");
 
+    // 设置初始高度
+    this.input.style.height = "40px";
+
+    // 初始化其他组件
     this.setupEventListeners();
-    this.adjustInputHeight();
     this.init();
 
+    // 使用微任务确保DOM更新后再调整高度
+    Promise.resolve().then(() => {
+      // 第一帧:等待过渡动画类生效
+      requestAnimationFrame(() => {
+        // 第二帧:执行高度调整
+        requestAnimationFrame(() => {
+          this.adjustInputHeight();
+          // 触发一次输入框focus以确保正确的高度
+          this.input.focus();
+        });
+      });
+    });
+
     // 添加新消息指示器
     this.createNewMessageIndicator();
 
@@ -45,7 +65,6 @@ class ChatUI {
 
     this.isTyping = false; // 添加打字状态标记
     this.loadingDiv = null; // 添加加载动画的引用
-    this.inputWrapper = document.querySelector(".input-wrapper");
 
     // 初始化页面信息卡片
     this.initPageInfoCard();
@@ -74,6 +93,11 @@ class ChatUI {
     // 自动调整输入框高度
     this.input.addEventListener("input", () => this.adjustInputHeight());
 
+    // 添加focus事件监听,确保在获得焦点时高度正确
+    this.input.addEventListener("focus", () => {
+      requestAnimationFrame(() => this.adjustInputHeight());
+    });
+
     // 快捷指令面板
     this.promptButton.addEventListener("click", () => this.togglePromptPanel());
     document.querySelector(".close-prompt").addEventListener("click", () => {
@@ -271,8 +295,24 @@ class ChatUI {
   }
 
   adjustInputHeight() {
+    const scrollPos = this.input.scrollTop;
+
+    // 获取当前高度
+    const currentHeight = this.input.style.height;
+
+    // 重置高度
     this.input.style.height = "auto";
-    this.input.style.height = Math.min(this.input.scrollHeight, 120) + "px";
+
+    // 计算新高度
+    const newHeight = Math.min(this.input.scrollHeight, 120);
+
+    // 如果高度有变化才设置
+    if (currentHeight !== `${newHeight}px`) {
+      this.input.style.height = `${newHeight}px`;
+    }
+
+    // 恢复滚动位置
+    this.input.scrollTop = scrollPos;
   }
 
   scrollToBottom() {

+ 21 - 9
js/content.js

@@ -227,21 +227,33 @@ class SidebarManager {
       const iframe = document.createElement("iframe");
       iframe.id = this.sidebarId;
       iframe.src = chrome.runtime.getURL("sidebar.html");
+
+      // 先添加到DOM,但不添加show类
       document.body.appendChild(iframe);
 
-      // 使用 RAF 确保 DOM 更新后再添加动画类
-      requestAnimationFrame(() => {
-        document.body.classList.add("sidebar-open");
-        iframe.classList.add("show");
+      // 等待iframe加载完成
+      await new Promise((resolve) => {
+        iframe.onload = () => {
+          // 发送页面信息
+          this.sendPageInfo();
+          resolve();
+        };
+      });
+
+      // 等待一帧以确保DOM更新
+      await new Promise((resolve) => requestAnimationFrame(resolve));
+
+      // 触发动画
+      document.body.classList.add("sidebar-open");
+      iframe.classList.add("show");
+
+      // 等待动画完成
+      await new Promise((resolve) => {
+        iframe.addEventListener("transitionend", resolve, { once: true });
       });
 
       this.isOpen = true;
       await Utils.setStorageData(SidebarManager.CONFIG.STORAGE_KEY, true);
-
-      // 在iframe加载完成后发送页面信息
-      iframe.onload = () => {
-        this.sendPageInfo();
-      };
     } catch (error) {
       console.error("Failed to create sidebar:", error);
       this.unwrapPageContent();