Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed nethesis-phone-island-0.17.13.tgz
Binary file not shown.
77 changes: 41 additions & 36 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"@nethesis/nethesis-brands-svg-icons": "github:nethesis/Font-Awesome#ns-brands",
"@nethesis/nethesis-light-svg-icons": "github:nethesis/Font-Awesome#ns-light",
"@nethesis/nethesis-solid-svg-icons": "github:nethesis/Font-Awesome#ns-solid",
"@nethesis/phone-island": "^0.18.0",
"@nethesis/phone-island": "^0.18.1",
"@tailwindcss/forms": "^0.5.7",
"@types/lodash": "^4.14.202",
"@types/node": "^18.19.9",
Expand Down Expand Up @@ -106,6 +106,8 @@
"dmg-license": "^1.0.11"
},
"dependencies": {
"@nut-tree-fork/nut-js": "^4.2.6"
"@nut-tree-fork/nut-js": "^4.2.6",
"koffi": "^2.15.0",
"uiohook-napi": "^1.5.4"
}
}
9 changes: 8 additions & 1 deletion public/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@
"IP Phone": "IP Phone",
"Only nethlink": "Only Nethlink",
"ShortcutToCall": "Shortcut to Call",
"CommandBarShortcut": "Shortcut for Command Bar",
"ShortcutHelp": "Enter a keyboard shortcut to start a call after selecting some text.",
"ShortcutHelpDesc": "Unsupported keys: \"Tab\", \"CapsLock\", \"NumLock\", \"Insert\", \"Escape\", \"Shift\".",
"Clear and remove shortcut": "Clear and remove shortcut"
Expand Down Expand Up @@ -376,8 +377,10 @@
"Theme": "Theme",
"Settings": "Settings",
"Shortcut": "Shortcut",
"Keyboard shortcut to call": "Keyboard shortcut to call",
"Keyboard shortcut to call": "Keyboard shortcut to Call",
"Keyboard shortcut for command bar": "Keyboard shortcut for Command bar",
"Shortcut title description": "Choose a keyboard shortcut to dial any selected number. ",
"Command bar shortcut title description": "Choose a keyboard shortcut to open or hide the Command Bar. To trigger it, press the shortcut twice in a row.",
"Shortcut subtitle description": "Avoid using system-reserved shortcuts.",
"Shortcut body description": "Keys not supported: tab, capsLock, numLock, insert, esc, shift",
"Preferred devices": "Audio and Video settings",
Expand Down Expand Up @@ -931,6 +934,10 @@
"update_available": "Update available for download",
"download": "Download the update"
},
"CommandBar": {
"Placeholder": "Enter a phone number...",
"Call": "Call"
},
"Errors": {
"browser_permissions": "Browser permissions error",
"user_permissions": "Media permissions error",
Expand Down
9 changes: 8 additions & 1 deletion public/locales/it/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,8 @@
"Available presence": "Presence disponibili",
"IP Phone": "Telefono IP",
"Only nethlink": "Solo Nethlink",
"ShortcutToCall": "Scorciatoia per chiamare",
"ShortcutToCall": "Scorciatoia per Chiamare",
"CommandBarShortcut": "Scorciatoia per Command Bar",
"ShortcutHelp": "Inserisci una scorciatoia da tastiera per far partire una chiamata dopo aver selezionato un testo.",
"ShortcutHelpDesc": "Caratteri non consentiti: \"Tab\", \"CapsLock\", \"NumLock\", \"Insert\", \"Escape\", \"Shift\".",
"Clear and remove shortcut": "Ripristina e rimuovi scorciatoia"
Expand Down Expand Up @@ -377,7 +378,9 @@
"Settings": "Impostazioni",
"Shortcut": "Scorciatoia",
"Keyboard shortcut to call": "Scorciatoia per chiamare",
"Keyboard shortcut for command bar": "Scorciatoia per Command Bar",
"Shortcut title description": "Scegli una combinazione di tasti per avviare una chiamata dopo aver selezionato un testo.",
"Command bar shortcut title description": "Scegli una combinazione di tasti per aprire o nascondere la Command Bar. Per attivarla, premi la scorciatoia due volte di seguito.",
"Shortcut subtitle description": "Non usare scorciatoie già presenti nel sistema.",
"Shortcut body description": "Tasti non consentiti: tab, capsLock, numLock, insert, esc, shift",
"Preferred devices": "Impostazioni Audio e Video",
Expand Down Expand Up @@ -931,6 +934,10 @@
"update_available": "Aggiornamento disponibile per il download",
"download": "Scarica l'aggiornamento"
},
"CommandBar": {
"Placeholder": "Inserisci un numero di telefono...",
"Call": "Chiama"
},
"Errors": {
"browser_permissions": "Errore nei permessi del browser",
"user_permissions": "Errore nei permessi dei media",
Expand Down
16 changes: 16 additions & 0 deletions src/main/classes/controllers/AccountController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,22 @@ export class AccountController {
}
}

async updateCommandBarShortcut(commandBarShortcut: any) {
if (store.store) {
const account = store.store.account
if (account) {
account.commandBarShortcut = commandBarShortcut

store.set('account', account, true)
const auth = store.store.auth

auth!.availableAccounts[getAccountUID(account)] = account
store.set('auth', auth, true)
}
store.saveToDisk()
}
}


getAccountPhoneIslandPosition(): { x: number; y: number } | undefined {
return store.store.account?.phoneIslandPosition
Expand Down
149 changes: 149 additions & 0 deletions src/main/classes/controllers/CommandBarController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { CommandBarWindow } from '../windows'
import { IPC_EVENTS } from '@shared/constants'
import { Log } from '@shared/utils/logger'
import { debouncer } from '@shared/utils/utils'
import { forceWindowFocus } from '@/lib/windowsFocus'
import { screen } from 'electron'

export class CommandBarController {
static instance: CommandBarController
window: CommandBarWindow
private isVisible: boolean = false
private isShowingInProgress: boolean = false // Grace period to ignore blur during focus transition
private lastToggleTime: number = 0 // Throttle toggle calls
private originalSize = { width: 500, height: 80 }

constructor() {
CommandBarController.instance = this
this.window = new CommandBarWindow()
this.setupBlurListener()
}

private setupBlurListener() {
this.window.addOnBuildListener(() => {
const window = this.window.getWindow()
if (window) {
window.on('blur', () => {
// Ignore blur during the grace period after showing
if (!this.isShowingInProgress) {
this.hide()
}
})
}
})
}

show() {
try {
const window = this.window.getWindow()
if (window && !this.isVisible) {
// Start grace period to ignore blur events during focus transition
this.isShowingInProgress = true

// Restore original size if it was reset to [0,0]
window.setBounds({
width: this.originalSize.width,
height: this.originalSize.height
})

const cursorPoint = screen.getCursorScreenPoint()
const currentDisplay = screen.getDisplayNearestPoint(cursorPoint)
const { x, y, width, height } = currentDisplay.workArea
const windowBounds = window.getBounds()

const centerX = x + Math.round((width - windowBounds.width) / 2)
const centerY = y + Math.round(height * 0.3)

window.setBounds({ x: centerX, y: centerY })

const isWindows = process.platform === 'win32'

this.isVisible = true

if (isWindows) {
// Windows: use native API to force focus
window.show()
window.setAlwaysOnTop(true, 'screen-saver')
setTimeout(() => {
// Use native Windows API to force foreground
forceWindowFocus(window)
window.focus()
window.webContents?.focus()
// Emit SHOW_COMMAND_BAR after focus operations complete
this.window.emit(IPC_EVENTS.SHOW_COMMAND_BAR)
// End grace period after focus is applied
setTimeout(() => {
this.isShowingInProgress = false
}, 350)
}, 50)
} else {
// macOS/Linux
window.show()
window.setAlwaysOnTop(true, 'screen-saver')
this.window.emit(IPC_EVENTS.SHOW_COMMAND_BAR)
setTimeout(() => {
window.focus()
window.webContents?.focus()
// End grace period after focus is applied
this.isShowingInProgress = false
}, 50)
}
}
} catch (e) {
this.isShowingInProgress = false
Log.warning('error during showing CommandBarWindow:', e)
}
}

hide() {
const isMac = process.platform === 'darwin'

try {
const window = this.window.getWindow()
if (window && this.isVisible) {
this.isVisible = false
// Reset size to [0,0] to avoid slowness/inconsistent state - same as PhoneIsland pattern
window.setBounds({ width: 0, height: 0 })

if (isMac) {
window.hide()
this.window.emit(IPC_EVENTS.HIDE_COMMAND_BAR)
} else {
debouncer(
'hide-command-bar',
() => {
window.hide()
this.window.emit(IPC_EVENTS.HIDE_COMMAND_BAR)
},
100
)
}
}
} catch (e) {
Log.warning('error during hiding CommandBarWindow:', e)
}
}

toggle() {
// Throttle toggle calls to prevent rapid open/close cycles
const now = Date.now()
if (now - this.lastToggleTime < 300) {
return
}
this.lastToggleTime = now

if (this.isVisible) {
this.hide()
} else {
this.show()
}
}

isOpen(): boolean {
return this.isVisible
}

async safeQuit() {
await this.window.quit(true)
}
}
1 change: 1 addition & 0 deletions src/main/classes/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './LoginController'
export * from './PhoneIslandController'
export * from './TrayController'
export * from './DevToolsController'
export * from './CommandBarController'
Loading