add link context menu

This commit is contained in:
刘浩远 2020-08-05 14:16:00 +08:00
parent aeb1b95975
commit 52e0c1b90c
9 changed files with 53 additions and 25 deletions

View File

@ -49,10 +49,10 @@ const utilsBridge = {
callback(pos, text)
})
},
addWebviewContextListener: (callback: (pos: [number, number], text: string) => any) => {
addWebviewContextListener: (callback: (pos: [number, number], text: string, url: string) => any) => {
ipcRenderer.removeAllListeners("webview-context-menu")
ipcRenderer.on("webview-context-menu", (_, pos, text) => {
callback(pos, text)
ipcRenderer.on("webview-context-menu", (_, pos, text, url) => {
callback(pos, text, url)
})
},
imageCallback: (type: ImageCallbackTypes) => {

View File

@ -19,7 +19,7 @@ type ArticleProps = {
toggleHasRead: (item: RSSItem) => void
toggleStarred: (item: RSSItem) => void
toggleHidden: (item: RSSItem) => void
textMenu: (text: string, position: [number, number]) => void
textMenu: (position: [number, number], text: string, url: string) => void
imageMenu: (position: [number, number]) => void
dismissContextMenu: () => void
}
@ -95,9 +95,9 @@ class Article extends React.Component<ArticleProps, ArticleState> {
]
})
contextMenuHandler = (pos: [number, number], text: string) => {
contextMenuHandler = (pos: [number, number], text: string, url: string) => {
if (pos) {
if (text) this.props.textMenu(text, pos)
if (text || url) this.props.textMenu(pos, text, url)
else this.props.imageMenu(pos)
} else {
this.props.dismissContextMenu()

View File

@ -16,6 +16,7 @@ export type ContextMenuProps = ContextReduxProps & {
item?: RSSItem
feedId?: string
text?: string
url?: string
viewType?: ViewType
filter?: FilterType
sids?: number[]
@ -143,15 +144,41 @@ export class ContextMenu extends React.Component<ContextMenuProps> {
onClick: () => { window.utils.writeClipboard(this.props.item.link) }
}
]
case ContextMenuType.Text: return [
{
key: "copyText",
text: intl.get("context.copy"),
iconProps: { iconName: "Copy" },
onClick: () => { window.utils.writeClipboard(this.props.text) }
},
getSearchItem(this.props.text)
]
case ContextMenuType.Text: {
const items: IContextualMenuItem[] = this.props.text? [
{
key: "copyText",
text: intl.get("context.copy"),
iconProps: { iconName: "Copy" },
onClick: () => { window.utils.writeClipboard(this.props.text) }
},
getSearchItem(this.props.text)
] : []
if (this.props.url) {
items.push({
key: "urlSection",
itemType: ContextualMenuItemType.Section,
sectionProps: {
topDivider: items.length > 0,
items: [
{
key: "openInBrowser",
text: intl.get("openExternal"),
iconProps: { iconName: "NavigateExternalInline" },
onClick: (e) => { window.utils.openExternal(this.props.url, platformCtrl(e)) }
},
{
key: "copyURL",
text: intl.get("context.copyURL"),
iconProps: { iconName: "Link" },
onClick: () => { window.utils.writeClipboard(this.props.url) }
}
]
}
})
}
return items
}
case ContextMenuType.Image: return [
{
key: "openInBrowser",

View File

@ -1,7 +1,7 @@
import * as React from "react"
import { connect } from 'react-redux'
import { ContextMenuContainer } from "../containers/context-menu-container"
import { closeContextMenu, openTextMenu } from "../scripts/models/app"
import { closeContextMenu } from "../scripts/models/app"
import PageContainer from "../containers/page-container"
import MenuContainer from "../containers/menu-container"
import NavContainer from "../containers/nav-container"

View File

@ -34,7 +34,7 @@ const mapDispatchToProps = (dispatch: AppDispatch) => {
toggleHasRead: (item: RSSItem) => dispatch(item.hasRead ? markUnread(item) : markRead(item)),
toggleStarred: (item: RSSItem) => dispatch(toggleStarred(item)),
toggleHidden: (item: RSSItem) => dispatch(toggleHidden(item)),
textMenu: (text: string, position: [number, number]) => dispatch(openTextMenu(text, position)),
textMenu: (position: [number, number], text: string, url: string) => dispatch(openTextMenu(position, text, url)),
imageMenu: (position: [number, number]) => dispatch(openImageMenu(position)),
dismissContextMenu: () => dispatch(closeContextMenu())
}

View File

@ -25,7 +25,8 @@ const mapStateToProps = createSelector(
case ContextMenuType.Text: return {
type: context.type,
position: context.position,
text: context.target as string
text: context.target[0],
url: context.target[1]
}
case ContextMenuType.View: return {
type: context.type,

View File

@ -23,7 +23,7 @@ const store = createStore(
store.dispatch(initApp())
window.utils.addMainContextListener((pos, text) => {
store.dispatch(openTextMenu(text, pos))
store.dispatch(openTextMenu(pos, text))
})
ReactDOM.render(

View File

@ -110,7 +110,7 @@ export function setUtilsListeners(manager: WindowManager) {
}
})
contents.on("context-menu", (_, params) => {
if ((params.hasImageContents || params.selectionText) && manager.hasWindow()) {
if ((params.hasImageContents || params.selectionText || params.linkURL) && manager.hasWindow()) {
if (params.hasImageContents) {
ipcMain.removeHandler("image-callback")
ipcMain.handleOnce("image-callback", (_, type: ImageCallbackTypes) => {
@ -132,7 +132,7 @@ export function setUtilsListeners(manager: WindowManager) {
})
manager.mainWindow.webContents.send("webview-context-menu", [params.x, params.y])
} else {
manager.mainWindow.webContents.send("webview-context-menu", [params.x, params.y], params.selectionText)
manager.mainWindow.webContents.send("webview-context-menu", [params.x, params.y], params.selectionText, params.linkURL)
}
contents.executeJavaScript(`new Promise(resolve => {
const dismiss = () => {

View File

@ -61,7 +61,7 @@ export class AppState {
type: ContextMenuType,
event?: MouseEvent | string,
position?: [number, number],
target?: [RSSItem, string] | number[] | string
target?: [RSSItem, string] | number[] | [string, string]
}
constructor() {
@ -92,7 +92,7 @@ interface OpenItemMenuAction {
interface OpenTextMenuAction {
type: typeof OPEN_TEXT_MENU
position: [number, number]
item: string
item: [string, string]
}
interface OpenViewMenuAction {
@ -153,11 +153,11 @@ export function openItemMenu(item: RSSItem, feedId: string, event: React.MouseEv
}
}
export function openTextMenu(text: string, position: [number, number]): ContextMenuActionTypes {
export function openTextMenu(position: [number, number], text: string, url: string = null): ContextMenuActionTypes {
return {
type: OPEN_TEXT_MENU,
position: position,
item: text
item: [text, url]
}
}