mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 22:52:08 +08:00
feat(SelectionAssistant): open URL for search action (#11770)
* feat(SelectionAssistant): open URL for search action When selected text is a valid URI or file path, directly open it instead of searching. This enhances the search action to be smarter about handling URLs and file paths. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> * fix: format * feat: increase maximum custom and enabled items in settings actions list Updated the maximum number of custom items from 8 to 10 and enabled items from 6 to 8 in the settings actions list to enhance user customization options. --------- Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
parent
600a045ff7
commit
c4fd48376d
@ -9,8 +9,8 @@ import { DEFAULT_SEARCH_ENGINES } from '../components/SelectionActionSearchModal
|
|||||||
|
|
||||||
const logger = loggerService.withContext('useSettingsActionsList')
|
const logger = loggerService.withContext('useSettingsActionsList')
|
||||||
|
|
||||||
const MAX_CUSTOM_ITEMS = 8
|
const MAX_CUSTOM_ITEMS = 10
|
||||||
const MAX_ENABLED_ITEMS = 6
|
const MAX_ENABLED_ITEMS = 8
|
||||||
|
|
||||||
export const useActionItems = (
|
export const useActionItems = (
|
||||||
initialItems: ActionItem[] | undefined,
|
initialItems: ActionItem[] | undefined,
|
||||||
|
|||||||
@ -202,6 +202,30 @@ const SelectionToolbar: FC<{ demo?: boolean }> = ({ demo = false }) => {
|
|||||||
}
|
}
|
||||||
}, [customCss, demo])
|
}, [customCss, demo])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if text is a valid URI or file path
|
||||||
|
*/
|
||||||
|
const isUriOrFilePath = (text: string): boolean => {
|
||||||
|
const trimmed = text.trim()
|
||||||
|
// Must not contain newlines or whitespace
|
||||||
|
if (/\s/.test(trimmed)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// URI patterns: http://, https://, ftp://, file://, etc.
|
||||||
|
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(trimmed)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Windows absolute path: C:\, D:\, etc.
|
||||||
|
if (/^[a-zA-Z]:[/\\]/.test(trimmed)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Unix absolute path: /path/to/file
|
||||||
|
if (/^\/[^/]/.test(trimmed)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// copy selected text to clipboard
|
// copy selected text to clipboard
|
||||||
const handleCopy = useCallback(async () => {
|
const handleCopy = useCallback(async () => {
|
||||||
if (selectedText.current) {
|
if (selectedText.current) {
|
||||||
@ -219,6 +243,43 @@ const SelectionToolbar: FC<{ demo?: boolean }> = ({ demo = false }) => {
|
|||||||
}
|
}
|
||||||
}, [setTimeoutTimer])
|
}, [setTimeoutTimer])
|
||||||
|
|
||||||
|
const handleSearch = useCallback((action: ActionItem) => {
|
||||||
|
if (!action.selectedText) return
|
||||||
|
|
||||||
|
const selectedText = action.selectedText.trim()
|
||||||
|
|
||||||
|
let actionString = ''
|
||||||
|
if (isUriOrFilePath(selectedText)) {
|
||||||
|
actionString = selectedText
|
||||||
|
} else {
|
||||||
|
if (!action.searchEngine) return
|
||||||
|
|
||||||
|
const customUrl = action.searchEngine.split('|')[1]
|
||||||
|
if (!customUrl) return
|
||||||
|
|
||||||
|
actionString = customUrl.replace('{{queryString}}', encodeURIComponent(selectedText))
|
||||||
|
}
|
||||||
|
|
||||||
|
window.api?.openWebsite(actionString)
|
||||||
|
window.api?.selection.hideToolbar()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quote the selected text to the inputbar of the main window
|
||||||
|
*/
|
||||||
|
const handleQuote = (action: ActionItem) => {
|
||||||
|
if (action.selectedText) {
|
||||||
|
window.api?.quoteToMainWindow(action.selectedText)
|
||||||
|
window.api?.selection.hideToolbar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDefaultAction = (action: ActionItem) => {
|
||||||
|
// [macOS] only macOS has the available isFullscreen mode
|
||||||
|
window.api?.selection.processAction(action, isFullScreen.current)
|
||||||
|
window.api?.selection.hideToolbar()
|
||||||
|
}
|
||||||
|
|
||||||
const handleAction = useCallback(
|
const handleAction = useCallback(
|
||||||
(action: ActionItem) => {
|
(action: ActionItem) => {
|
||||||
if (demo) return
|
if (demo) return
|
||||||
@ -241,36 +302,9 @@ const SelectionToolbar: FC<{ demo?: boolean }> = ({ demo = false }) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[demo, handleCopy]
|
[demo, handleCopy, handleSearch]
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleSearch = (action: ActionItem) => {
|
|
||||||
if (!action.searchEngine) return
|
|
||||||
|
|
||||||
const customUrl = action.searchEngine.split('|')[1]
|
|
||||||
if (!customUrl) return
|
|
||||||
|
|
||||||
const searchUrl = customUrl.replace('{{queryString}}', encodeURIComponent(action.selectedText || ''))
|
|
||||||
window.api?.openWebsite(searchUrl)
|
|
||||||
window.api?.selection.hideToolbar()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quote the selected text to the inputbar of the main window
|
|
||||||
*/
|
|
||||||
const handleQuote = (action: ActionItem) => {
|
|
||||||
if (action.selectedText) {
|
|
||||||
window.api?.quoteToMainWindow(action.selectedText)
|
|
||||||
window.api?.selection.hideToolbar()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDefaultAction = (action: ActionItem) => {
|
|
||||||
// [macOS] only macOS has the available isFullscreen mode
|
|
||||||
window.api?.selection.processAction(action, isFullScreen.current)
|
|
||||||
window.api?.selection.hideToolbar()
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<LogoWrapper $draggable={!demo}>
|
<LogoWrapper $draggable={!demo}>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user