(position?: 'left' | 'right')
| 15 | * @returns |
| 16 | */ |
| 17 | export function mountFloatingBall(position?: 'left' | 'right') { |
| 18 | // 如果配置禁用了悬浮球或已存在实例,则不创建 |
| 19 | if (config.disableFloatingBall || floatingBallInstance) { |
| 20 | return; |
| 21 | } |
| 22 | |
| 23 | // 使用传入的位置参数或配置中的位置 |
| 24 | const ballPosition = position || config.floatingBallPosition || 'right'; |
| 25 | // 更新配置 |
| 26 | config.floatingBallPosition = ballPosition; |
| 27 | |
| 28 | // 创建容器元素 |
| 29 | const container = document.createElement('div'); |
| 30 | container.id = 'fluent-read-floating-ball-container'; |
| 31 | document.body.appendChild(container); |
| 32 | |
| 33 | // 创建 Vue 应用实例 |
| 34 | app = createApp(FloatingBall, { |
| 35 | position: ballPosition, |
| 36 | showMenu: true, |
| 37 | onDocClick: () => { |
| 38 | }, |
| 39 | onSettingsClick: () => { |
| 40 | browser.runtime.sendMessage({ type: 'openOptionsPage' }); |
| 41 | }, |
| 42 | // 添加位置变化事件监听 |
| 43 | onPositionChanged: (newPosition: 'left' | 'right') => { |
| 44 | // 保存位置到配置 |
| 45 | config.floatingBallPosition = newPosition; |
| 46 | |
| 47 | // 保存配置到存储 |
| 48 | saveConfig(); |
| 49 | |
| 50 | }, |
| 51 | // 添加翻译状态变化事件监听 |
| 52 | onTranslationToggle: (isTranslating: boolean) => { |
| 53 | if (isTranslating && !isTranslated) { |
| 54 | // 触发翻译开始事件 |
| 55 | document.dispatchEvent(new CustomEvent('fluentread-translation-started')); |
| 56 | |
| 57 | // 触发即时翻译 |
| 58 | autoTranslateEnglishPage(); |
| 59 | isTranslated = true; |
| 60 | } else if (!isTranslating && isTranslated) { |
| 61 | // 触发翻译结束事件 |
| 62 | document.dispatchEvent(new CustomEvent('fluentread-translation-ended')); |
| 63 | |
| 64 | // 恢复原文 |
| 65 | restoreOriginalContent(); |
| 66 | isTranslated = false; |
| 67 | |
| 68 | // 恢复后确保状态同步 |
| 69 | floatingBallInstance.$el.classList.remove('is-translating'); |
| 70 | } |
| 71 | } |
| 72 | }); |
| 73 | |
| 74 | // 挂载应用 |
no test coverage detected