diff --git a/public/locales/en/translations.json b/public/locales/en/translations.json
index dd5f1d85..24187630 100644
--- a/public/locales/en/translations.json
+++ b/public/locales/en/translations.json
@@ -82,7 +82,11 @@
"Screen share dialog description": "This application requires permission to record the screen.\n\nClick 'Open Settings' and then select 'Privacy & Security' then 'Screen & System Audio Recording' from the list and enable the permission for 'NethLink'.",
"Cancel button": "Cancel",
"Open settings button": "Open Settings",
- "Shortcut": "Define a keyboard shortcut"
+ "Shortcut": "Define a keyboard shortcut",
+ "PlusOther_one": "+ {{count}} other",
+ "PlusOther_other": "+ {{count}} others",
+ "Copy": "Copy",
+ "Copied": "Copied"
},
"Login": {
"Welcome": "Welcome",
diff --git a/public/locales/it/translations.json b/public/locales/it/translations.json
index e8807552..c4644779 100644
--- a/public/locales/it/translations.json
+++ b/public/locales/it/translations.json
@@ -82,7 +82,11 @@
"Screen share dialog description": "Questa applicazione richiede il permesso di registrare lo schermo.\n\nClicca su 'Apri Impostazioni', poi seleziona 'Privacy & Sicurezza' poi 'Registrazione Schermo e Audio di Sistema' dalla lista e abilita il permesso per 'NethLink'.",
"Cancel button": "Annulla",
"Open settings button": "Apri Impostazioni",
- "Shortcut": "Scegli una combinazione di tasti"
+ "Shortcut": "Scegli una combinazione di tasti",
+ "PlusOther_one": "+ {{count}} altro",
+ "PlusOther_other": "+ {{count}} altri",
+ "Copy": "Copia",
+ "Copied": "Copiato"
},
"Login": {
"Welcome": "Benvenuto",
diff --git a/src/main/lib/ipcEvents.ts b/src/main/lib/ipcEvents.ts
index 09d59d14..a1375c41 100644
--- a/src/main/lib/ipcEvents.ts
+++ b/src/main/lib/ipcEvents.ts
@@ -9,7 +9,7 @@ import { Log } from '@shared/utils/logger'
import { NethLinkController } from '@/classes/controllers/NethLinkController'
import { AppController } from '@/classes/controllers/AppController'
import { store } from './mainStore'
-import { debouncer, getAccountUID, getPageFromQuery } from '@shared/utils/utils'
+import { debouncer, getAccountUID, getPageFromQuery, isDev } from '@shared/utils/utils'
import { NetworkController } from '@/classes/controllers/NetworkController'
import { useLogin } from '@shared/useLogin'
import { PhoneIslandWindow } from '@/classes/windows'
@@ -212,8 +212,17 @@ export function registerIpcEvents() {
shell.openExternal(join('https://' + account!.host, path))
})
- ipcMain.on(IPC_EVENTS.OPEN_EXTERNAL_PAGE, async (_, path) => {
- shell.openExternal(join(path))
+ ipcMain.on(IPC_EVENTS.OPEN_EXTERNAL_PAGE, async (event, path) => {
+ if (isDev()) {
+ const window = BrowserWindow.fromWebContents(event.sender);
+ window?.loadURL(join(path))
+ } else {
+ shell.openExternal(join(path))
+ }
+ })
+
+ ipcMain.on(IPC_EVENTS.COPY_TO_CLIPBOARD, async (_, text) => {
+ clipboard.writeText(text)
})
ipcMain.on(IPC_EVENTS.PHONE_ISLAND_RESIZE, (_, size) => {
diff --git a/src/preload/index.ts b/src/preload/index.ts
index d207406a..af4031cc 100644
--- a/src/preload/index.ts
+++ b/src/preload/index.ts
@@ -40,6 +40,7 @@ export interface IElectronAPI {
exitNethLink(): void
hidePhoneIsland(): void
showPhoneIsland(size: Size): void
+ copyToClipboard(text: string): void
}
@@ -98,6 +99,7 @@ const api: IElectronAPI = {
exitNethLink: setEmitter(IPC_EVENTS.CLOSE_NETH_LINK),
hidePhoneIsland: setEmitter(IPC_EVENTS.HIDE_PHONE_ISLAND),
showPhoneIsland: setEmitter(IPC_EVENTS.SHOW_PHONE_ISLAND),
+ copyToClipboard: setEmitter(IPC_EVENTS.COPY_TO_CLIPBOARD),
//LISTENERS - receive data async
onUpdateAppNotification: addListener(IPC_EVENTS.UPDATE_APP_NOTIFICATION),
diff --git a/src/renderer/public/locales/en/translations.json b/src/renderer/public/locales/en/translations.json
index dd5f1d85..24187630 100644
--- a/src/renderer/public/locales/en/translations.json
+++ b/src/renderer/public/locales/en/translations.json
@@ -82,7 +82,11 @@
"Screen share dialog description": "This application requires permission to record the screen.\n\nClick 'Open Settings' and then select 'Privacy & Security' then 'Screen & System Audio Recording' from the list and enable the permission for 'NethLink'.",
"Cancel button": "Cancel",
"Open settings button": "Open Settings",
- "Shortcut": "Define a keyboard shortcut"
+ "Shortcut": "Define a keyboard shortcut",
+ "PlusOther_one": "+ {{count}} other",
+ "PlusOther_other": "+ {{count}} others",
+ "Copy": "Copy",
+ "Copied": "Copied"
},
"Login": {
"Welcome": "Welcome",
diff --git a/src/renderer/public/locales/it/translations.json b/src/renderer/public/locales/it/translations.json
index e8807552..c4644779 100644
--- a/src/renderer/public/locales/it/translations.json
+++ b/src/renderer/public/locales/it/translations.json
@@ -82,7 +82,11 @@
"Screen share dialog description": "Questa applicazione richiede il permesso di registrare lo schermo.\n\nClicca su 'Apri Impostazioni', poi seleziona 'Privacy & Sicurezza' poi 'Registrazione Schermo e Audio di Sistema' dalla lista e abilita il permesso per 'NethLink'.",
"Cancel button": "Annulla",
"Open settings button": "Apri Impostazioni",
- "Shortcut": "Scegli una combinazione di tasti"
+ "Shortcut": "Scegli una combinazione di tasti",
+ "PlusOther_one": "+ {{count}} altro",
+ "PlusOther_other": "+ {{count}} altri",
+ "Copy": "Copia",
+ "Copied": "Copiato"
},
"Login": {
"Welcome": "Benvenuto",
diff --git a/src/renderer/src/components/ModuleTitle.tsx b/src/renderer/src/components/ModuleTitle.tsx
index e6bd1be6..4e5977c7 100644
--- a/src/renderer/src/components/ModuleTitle.tsx
+++ b/src/renderer/src/components/ModuleTitle.tsx
@@ -3,13 +3,16 @@ import { Button } from "./Nethesis"
import { IconProp } from "@fortawesome/fontawesome-svg-core"
import { DefaultTFuncReturn } from "i18next"
import { ReactNode } from "react"
+import { ClassNames } from "@renderer/utils"
+import { Tooltip } from 'react-tooltip'
export interface ModuleTitleProps {
- title: string | DefaultTFuncReturn,
+ title?: string | DefaultTFuncReturn | ReactNode,
action?: () => void,
actionText?: string | DefaultTFuncReturn,
actionIcon?: IconProp
- actionComponent?: ReactNode
+ actionComponent?: ReactNode,
+ className?: string
}
export const ModuleTitle = ({
@@ -17,15 +20,27 @@ export const ModuleTitle = ({
action,
actionText,
actionIcon,
- actionComponent
+ actionComponent,
+ className
}: ModuleTitleProps) => {
return (
-
-
+
+ {title &&
{title}
-
+ }
+
{action && (
}
- {actionText &&
+ {actionText &&
{actionText}
}
diff --git a/src/renderer/src/components/Modules/NethVoice/BaseModule/ContactNameAndAction.tsx b/src/renderer/src/components/Modules/NethVoice/BaseModule/ContactNameAndAction.tsx
index 31e263e4..3f8528c5 100644
--- a/src/renderer/src/components/Modules/NethVoice/BaseModule/ContactNameAndAction.tsx
+++ b/src/renderer/src/components/Modules/NethVoice/BaseModule/ContactNameAndAction.tsx
@@ -16,19 +16,23 @@ export const ContactNameAndActions = ({
number,
isHighlight,
displayedNumber,
+ otherNumber,
avatarDim,
username,
isFavourite,
- isSearchData
+ isSearchData,
+ onOpenDetail
}: {
contact: ContactType
number: string
isHighlight: boolean
displayedNumber: string | ReactNode[]
+ otherNumber?: string
avatarDim: 'small' | 'base' | 'extra_small' | 'large' | 'extra_large'
username: string | undefined
isFavourite: boolean
- isSearchData: boolean
+ isSearchData: boolean,
+ onOpenDetail?: () => void
}) => {
const { isCallsEnabled } = useAccount()
const [operators] = useNethlinkData('operators')
@@ -37,6 +41,23 @@ export const ContactNameAndActions = ({
const isOperator = username && !!operators?.operators?.[username]
+ const onClick = (e) => {
+ if (onOpenDetail) {
+ e.stopPropagation()
+ e.preventDefault()
+ onOpenDetail()
+ }
+ }
+
+ const displayName = isFavourite
+ ? contact.company && contact.company !== ' '
+ ? contact.company : `${t('Common.Unknown')}`
+ : contact.name && contact.name !== ' '
+ ? contact.name
+ : contact.company && contact.company !== ' '
+ ? contact.company
+ : `${t('Common.Unknown')}`
+
return (
-
- {isFavourite
- ? contact.company || `${t('Common.Unknown')}`
- : contact.name || contact.company || `${t('Common.Unknown')}`}
+
+ {displayName}
{isDev() && (
{
@@ -100,19 +125,23 @@ export const ContactNameAndActions = ({
}}
/>
)}
-
- {displayedNumber !== ' ' &&
- displayedNumber !== '' &&
- displayedNumber !== null &&
- (!Array.isArray(displayedNumber) || displayedNumber.length > 0)
- ? displayedNumber
- : '-'}
-
+
+
+
+ {displayedNumber !== ' ' &&
+ displayedNumber !== '' &&
+ displayedNumber !== null &&
+ (!Array.isArray(displayedNumber) || displayedNumber.length > 0)
+ ? displayedNumber
+ : '-'}
+
+ {otherNumber}
+
diff --git a/src/renderer/src/components/Modules/NethVoice/BaseModule/Sidebar.tsx b/src/renderer/src/components/Modules/NethVoice/BaseModule/Sidebar.tsx
index aed7a8b9..b07683ee 100644
--- a/src/renderer/src/components/Modules/NethVoice/BaseModule/Sidebar.tsx
+++ b/src/renderer/src/components/Modules/NethVoice/BaseModule/Sidebar.tsx
@@ -69,7 +69,7 @@ export function Sidebar({ onChangeMenu }: SidebarProps): JSX.Element {
}, [parkedCalls, selectedSidebarMenu])
return (
-
+
{/* FAVOURITE */}
{
@@ -13,6 +15,10 @@ export const PhoneBookSearchModule = () => {
const [searchResult, setSearchResult] = useState()
const [, setShowPhonebookSearchModule] = useNethlinkData('showPhonebookSearchModule')
const [, setShowAddContactModule] = useNethlinkData('showAddContactModule')
+ const [contactDetail, setContactDetail] = useState<{
+ contact: SearchData,
+ primaryNumber: string | null
+ }>()
useEffect(() => {
if ((searchText?.length || 0) >= 3) {
@@ -31,12 +37,21 @@ export const PhoneBookSearchModule = () => {
return (
<>
- {
setShowAddContactModule(true)
setShowPhonebookSearchModule(false)
}}
+ showContactDetail={(contact, primaryNumber) => {
+ setShowAddContactModule(false)
+ setContactDetail(() => ({ contact, primaryNumber }))
+ }}
/>
+ {
+ setContactDetail(() => undefined)
+ }} />
>
)
}
diff --git a/src/renderer/src/components/Modules/NethVoice/SearchResults/SearchNumber.tsx b/src/renderer/src/components/Modules/NethVoice/SearchResults/SearchNumber.tsx
index b583b205..842e830d 100644
--- a/src/renderer/src/components/Modules/NethVoice/SearchResults/SearchNumber.tsx
+++ b/src/renderer/src/components/Modules/NethVoice/SearchResults/SearchNumber.tsx
@@ -9,13 +9,15 @@ import { usePhoneIslandEventHandler } from '@renderer/hooks/usePhoneIslandEventH
import { ContactNameAndActions } from '@renderer/components/Modules/NethVoice/BaseModule/ContactNameAndAction'
import { useFavouriteModule } from '../Speeddials/hook/useFavouriteModule'
import { debouncer } from '@shared/utils/utils'
+import { ClassNames } from '@renderer/utils'
export interface SearchNumberProps {
user: SearchData
- className?: string
+ className?: string,
+ onClick?: (user: SearchData, primaryNumber: string | null) => void
}
-export function SearchNumber({ user, className }: SearchNumberProps) {
+export function SearchNumber({ user, className, onClick }: SearchNumberProps) {
const phoneBookModule = usePhonebookSearchModule()
const { callNumber } = usePhoneIslandEventHandler()
const [searchText] = phoneBookModule.searchTextState
@@ -23,6 +25,18 @@ export function SearchNumber({ user, className }: SearchNumberProps) {
const { isCallsEnabled } = useAccount()
const { isSearchAlsoAFavourite } = useFavouriteModule()
+
+ const otherNumbers = [
+ user.cellphone,
+ user.workphone,
+ user.homephone,
+ ].reduce((p, c) => {
+ if (c && !p.includes(c)) {
+ p.push(c)
+ }
+ return p
+ }, [] as string[])
+
const getUsernameFromPhoneNumber = (number: string) => {
return user.type !== 'extension' ? operators?.extensions[number]?.username : undefined
}
@@ -78,16 +92,25 @@ export function SearchNumber({ user, className }: SearchNumberProps) {
return (
-
+
1 ? t('Common.PlusOther', { count: otherNumbers.length - 1 }) as string : ''}
isHighlight={true}
username={username}
isFavourite={false}
isSearchData={true}
+ onOpenDetail={onClick ? () => {
+ onClick?.(user, phoneNumber)
+ } : undefined}
/>
{phoneNumber && phoneNumber !== '' && (