diff --git a/TUILiveKit.main.js b/TUILiveKit.main.js index d02af1f..48a1f8f 100644 --- a/TUILiveKit.main.js +++ b/TUILiveKit.main.js @@ -509,6 +509,9 @@ function bindIPCEvent() { ipcMain.handle('app-path', () => { return app.getAppPath(); }); + ipcMain.handle('get-language', () => { + return language; + }); ipcMain.handle('window-type', (event) => { if (event.sender === windowMap.main?.webContents) { @@ -794,10 +797,8 @@ function bindIPCEvent() { postMessageToWindow(windowMap.confirm, 'port-to-confirm', null, [port]); }); - ipcMain.on('set-language', (event, args) => { - console.log(`${logPrefix}set-language`, args); - language = args; - }); + // Legacy 'set-language' channel removed — language updates now flow through + // the V2 mainProcessHandlers['setLanguage'] via ipcBridge.sendToElectronMain(). ipcMain.on('show-context-menu', (event) => { const template = [ @@ -948,6 +949,7 @@ function bindIPCEvent() { function unbindIPCMainEvent() { ipcMain.removeHandler('app-path'); + ipcMain.removeHandler('get-language'); ipcMain.removeHandler('window-type'); ipcMain.removeAllListeners('window-message'); // V2 IPC message router ipcMain.removeAllListeners('on-minimize-window'); @@ -957,7 +959,6 @@ function unbindIPCMainEvent() { ipcMain.removeAllListeners('close-child'); ipcMain.removeAllListeners('login'); ipcMain.removeAllListeners('port-to-child'); - ipcMain.removeAllListeners('set-language'); ipcMain.removeAllListeners('show-context-menu'); ipcMain.removeAllListeners('start-use-driver-installer'); ipcMain.removeAllListeners('app-quit-confirmed'); diff --git a/electron-builder.json5 b/electron-builder.json5 index c9837bb..7775c8a 100644 --- a/electron-builder.json5 +++ b/electron-builder.json5 @@ -23,10 +23,6 @@ { "from": "node_modules/trtc-electron-sdk/build/mac-framework/${arch}/", "to": "./Frameworks" - }, - { - "from": "node_modules/trtc-electron-plugin-xmagic/plugin/XMagic/mac/", - "to": "./Resources/app/plugin/XMagic/mac/" } ], "target": ["dmg"], @@ -47,21 +43,6 @@ "**/*" ] }, - { - "from": "node_modules/trtc-electron-plugin-xmagic/plugin/XMagic/win/${arch}/platforms/", - "to": "./resources/platforms", - "filter": ["**/*"], - }, - { - "from": "node_modules/trtc-electron-plugin-xmagic/plugin/XMagic/win/${arch}/", - "to": "./resources/app/plugin/XMagic/win/${arch}/", - "filter": ["**/*"], - }, - { - "from": "node_modules/trtc-electron-plugin-xmagic/plugin/XMagic/win/res/", - "to": "./resources/app/plugin/XMagic/win/res/", - "filter": ["**/*"], - }, ], "target": ["nsis", "zip"], }, diff --git a/main.js b/main.js index 47ee1e1..c797ee3 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -const { app, ipcMain } = require('electron'); +const { app, ipcMain, globalShortcut, Menu } = require('electron'); const { TUILiveKitMain } = require('./TUILiveKit.main'); function quitApplication() { @@ -15,7 +15,65 @@ ipcMain.on('openTUILiveKit', (event, args) => { TUILiveKitMain.on('closed', quitApplication); }); +function registerDisableRefreshShortcuts() { + const shortcuts = [ + 'CommandOrControl+R', + 'CommandOrControl+Shift+R', + 'F5', + ]; + shortcuts.forEach((shortcut) => { + const ok = globalShortcut.register(shortcut, () => { + console.log(`[main.js]blocked refresh shortcut: ${shortcut}`); + }); + if (!ok) { + console.warn(`[main.js]failed to register shortcut: ${shortcut}`); + } + }); +} + +function setupApplicationMenuWithoutReload() { + const template = []; + + if (process.platform === 'darwin') { + template.push({ + label: app.name, + submenu: [ + { role: 'about' }, + { type: 'separator' }, + { role: 'services' }, + { type: 'separator' }, + { role: 'hide' }, + { role: 'hideOthers' }, + { role: 'unhide' }, + { type: 'separator' }, + { role: 'quit' }, + ], + }); + } + + template.push( + { role: 'editMenu' }, + { + label: 'View', + submenu: [ + // Intentionally keep zoom/fullscreen/devtools, but remove reload/forceReload. + { role: 'resetZoom' }, + { role: 'zoomIn' }, + { role: 'zoomOut' }, + { type: 'separator' }, + { role: 'toggleDevTools' }, + { role: 'togglefullscreen' }, + ], + }, + { role: 'windowMenu' } + ); + + Menu.setApplicationMenu(Menu.buildFromTemplate(template)); +} + app.whenReady().then(() => { + registerDisableRefreshShortcuts(); + setupApplicationMenuWithoutReload(); TUILiveKitMain.open(); }); @@ -25,4 +83,8 @@ app.on('window-all-closed', () => { app.on('activate', () => { TUILiveKitMain.open(); -}); \ No newline at end of file +}); + +app.on('will-quit', () => { + globalShortcut.unregisterAll(); +}); diff --git a/package.json b/package.json index a7e4b8a..86c3ca6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ultra-live-electron", - "version": "5.5.2", + "version": "5.8.2", "description": "Tencent Cloud Living and Streaming Tool for desktop and laptop", "main": "main.js", "author": "Tencent Cloud", @@ -23,9 +23,9 @@ "start:with-upload-server": "concurrently \"npm run serve\" \"npm run upload-server\" \"npm run electron\"" }, "dependencies": { - "@tencentcloud/tuiroom-engine-electron": "~4.0.1", - "@tencentcloud/uikit-base-component-vue3": "1.3.7", - "tuikit-atomicx-vue3-electron": "5.5.2", + "@tencentcloud/tuiroom-engine-electron": "~4.0.2", + "@tencentcloud/uikit-base-component-vue3": "1.4.1", + "tuikit-atomicx-vue3-electron": "5.8.2", "core-js": "^3.36.1", "movable-resizable-js": "^0.2.0", "pinia": "^2.1.7", diff --git a/scripts/check-dialog-i18n.js b/scripts/check-dialog-i18n.js new file mode 100644 index 0000000..488fa3f --- /dev/null +++ b/scripts/check-dialog-i18n.js @@ -0,0 +1,219 @@ +/* eslint-disable no-console */ +const fs = require('node:fs'); +const path = require('node:path'); +const { parse, compileTemplate } = require('vue/compiler-sfc'); + +const projectRoot = path.resolve(__dirname, '..'); +const srcDir = path.join(projectRoot, 'src'); + +function walk(dir) { + if (!fs.existsSync(dir)) { + return []; + } + const entries = fs.readdirSync(dir, { withFileTypes: true }); + const out = []; + entries.forEach((entry) => { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + out.push(...walk(fullPath)); + return; + } + if (entry.isFile() && fullPath.endsWith('.vue')) { + out.push(fullPath); + } + }); + return out; +} + +function walkTemplateNodes(nodeOrNodes, visitor) { + if (!nodeOrNodes) { + return; + } + + if (Array.isArray(nodeOrNodes)) { + nodeOrNodes.forEach((node) => walkTemplateNodes(node, visitor)); + return; + } + + const node = nodeOrNodes; + switch (node.type) { + case 0: // Root + walkTemplateNodes(node.children, visitor); + break; + case 1: // Element + visitor(node); + walkTemplateNodes(node.children, visitor); + break; + case 9: // If + (node.branches || []).forEach((branch) => walkTemplateNodes(branch, visitor)); + break; + case 10: // IfBranch + walkTemplateNodes(node.children, visitor); + break; + case 11: // For + walkTemplateNodes(node.children, visitor); + break; + default: + break; + } +} + +function hasDialogTextProp(dialogNode, names) { + for (const prop of dialogNode.props || []) { + if (prop.type === 6 && names.has(prop.name)) { + return true; + } + + if ( + prop.type === 7 + && prop.name === 'bind' + && prop.arg + && prop.arg.type === 4 + && names.has(prop.arg.content) + ) { + return true; + } + } + return false; +} + +function isFooterSlotTemplate(node) { + for (const prop of node.props || []) { + if (prop.type === 6 && prop.name === 'slot' && prop.value && prop.value.content === 'footer') { + return true; + } + + if ( + prop.type === 7 + && prop.name === 'slot' + && prop.arg + && prop.arg.type === 4 + && prop.arg.content === 'footer' + ) { + return true; + } + } + + return false; +} + +function hasFooterSlot(dialogNode) { + let found = false; + walkTemplateNodes(dialogNode.children || [], (node) => { + if (found) { + return; + } + if (node.tag === 'template' && isFooterSlotTemplate(node)) { + found = true; + } + }); + return found; +} + +function getLineNumberByOffset(source, offset) { + return source.slice(0, offset).split('\n').length; +} + +function isIgnorableSfcParseError(error) { + return String(error).includes('At least one
{{ props.region.seatIndex }} - {{ t('Conn Wait') }} + {{ t('LiveView.WaitingForConnection') }}
@@ -28,10 +23,8 @@ import { ref, computed, defineProps, onMounted, onUnmounted } from 'vue'; import type { Ref } from 'vue'; import { TUIDeviceStatus } from '@tencentcloud/tuiroom-engine-electron'; import { TUIConnectionMode, TUIUserSeatStreamRegion } from '../../types'; -import { useI18n } from '../../locales'; +import { useUIKit } from '@tencentcloud/uikit-base-component-vue3'; import MicOffIcon from '../../common/icons/MicOffIcon.vue'; -import MoreIcon from '../../common/icons/MoreIcon.vue'; -import LiveMemberControl from '../LiveChildView/LiveMemberControl.vue'; import { DEFAULT_USER_AVATAR_URL } from '../../constants/tuiConstant'; import logger from '../../utils/logger'; @@ -42,12 +35,10 @@ type Props = { const logPrefix = '[TUILiveKitStreamCover]'; -const { t } = useI18n(); +const { t } = useUIKit(); const props = defineProps(); const streamCoverRef: Ref = ref(null); -const moreIconRef: Ref = ref(null); -const isMoreMenuVisible: Ref = ref(false); const positonStyle = computed(() => { return { @@ -58,35 +49,6 @@ const positonStyle = computed(() => { }; }); -const openMoreMenu = () => { - isMoreMenuVisible.value = true; -}; - -const closeMoreMenu = () => { - isMoreMenuVisible.value = false; -}; - -const onKickOffSeat = (userId: string) => { - logger.log(`${logPrefix}onKickOffSeat:${userId}`); - window.mainWindowPortInCover?.postMessage({ - key: 'kickOffSeat', - data: { - userId, - } - }); -}; - - -const onKickOutRoom = (userId: string) => { - logger.log(`${logPrefix}onKickOutRoom:${userId}`); - window.mainWindowPortInCover?.postMessage({ - key: 'kickOutRoom', - data: { - userId, - } - }); -}; - // eslint-disable-next-line no-undef let timerId: string | number | NodeJS.Timeout | undefined; const bindMouseEnterLeaveEvent = () => { @@ -106,23 +68,14 @@ const bindMouseEnterLeaveEvent = () => { } }; -const onClickOutMenuSide = (event: MouseEvent) => { - if (moreIconRef.value && moreIconRef.value.contains(event.target as Node)) { - return; - } - closeMoreMenu(); -}; - onMounted(() => { bindMouseEnterLeaveEvent(); - document.addEventListener('click', onClickOutMenuSide, false); }); onUnmounted(() => { if (timerId) { clearTimeout(timerId); } - document.removeEventListener('click', onClickOutMenuSide, false); }); @@ -146,33 +99,6 @@ onUnmounted(() => { } } - &:hover .tui-menu-icon { - display: block; - } - .tui-menu-icon { - display: none; - position: absolute; - top: 0.125rem; - right: 0.125rem; - width: 1.25rem; - height: 1.25rem; - border-radius: 0.25rem; - background-color: $color-cover-pendant-background; - cursor: pointer; - - .tui-more-icon { - transform: rotate(90deg); - } - - &:hover { - background-color: $font-button-text-hover-color; - } - - &:active { - background-color: $font-button-text-active-color; - } - } - .tui-stream-state { position: absolute; left: 0.125rem; @@ -216,24 +142,20 @@ onUnmounted(() => { flex-direction: column; align-items: center; justify-content: center; + text-align: center; color: var(--text-color-secondary); .tui-seat-index { - font-size: 1.25rem; - font-weight: 600; - line-height: 1.5; - color: var(--text-color-primary); + font-size: 1.5rem; + font-weight: 500; } .tui-seat-hint { - font-size: 0.75rem; - line-height: 1.5; - opacity: 0.7; + max-width: 80%; + font-size: 0.875rem; + font-weight: 400; + overflow-wrap: break-word; } } - - .tui-stream-cover-pop-menu { - top: 1.5rem; - } } diff --git a/src/TUILiveKit/components/LiveHeader/Index.vue b/src/TUILiveKit/components/LiveHeader/Index.vue deleted file mode 100644 index cbf0a27..0000000 --- a/src/TUILiveKit/components/LiveHeader/Index.vue +++ /dev/null @@ -1,345 +0,0 @@ - - - - - diff --git a/src/TUILiveKit/components/LiveMember/Index.vue b/src/TUILiveKit/components/LiveMember/Index.vue deleted file mode 100644 index fce271b..0000000 --- a/src/TUILiveKit/components/LiveMember/Index.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/src/TUILiveKit/components/LiveMessage/Index.vue b/src/TUILiveKit/components/LiveMessage/Index.vue deleted file mode 100644 index 90a124f..0000000 --- a/src/TUILiveKit/components/LiveMessage/Index.vue +++ /dev/null @@ -1,245 +0,0 @@ - - - diff --git a/src/TUILiveKit/components/LiveMessage/MessageText.vue b/src/TUILiveKit/components/LiveMessage/MessageText.vue deleted file mode 100644 index 8019d24..0000000 --- a/src/TUILiveKit/components/LiveMessage/MessageText.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - - - diff --git a/src/TUILiveKit/components/LiveMessage/chatEditor.vue b/src/TUILiveKit/components/LiveMessage/chatEditor.vue deleted file mode 100644 index 3764805..0000000 --- a/src/TUILiveKit/components/LiveMessage/chatEditor.vue +++ /dev/null @@ -1,141 +0,0 @@ -