feat: add single-click copy/paste option and update settings for clipboard behavior
This commit is contained in:
parent
440d6693fa
commit
a7df032f3f
5
.changeset/mighty-ears-live.md
Normal file
5
.changeset/mighty-ears-live.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'pastebar-app-ui': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Added single-click copy/paste option in user preferences
|
@ -207,6 +207,7 @@ function App() {
|
|||||||
isSavedClipsPanelVisibleOnly: settings.isSavedClipsPanelVisibleOnly?.valueBool,
|
isSavedClipsPanelVisibleOnly: settings.isSavedClipsPanelVisibleOnly?.valueBool,
|
||||||
isSimplifiedLayout: settings.isSimplifiedLayout?.valueBool ?? true,
|
isSimplifiedLayout: settings.isSimplifiedLayout?.valueBool ?? true,
|
||||||
isMainWindowOnTop: settings.isMainWindowOnTop?.valueBool ?? false,
|
isMainWindowOnTop: settings.isMainWindowOnTop?.valueBool ?? false,
|
||||||
|
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool ?? false,
|
||||||
isAppReady: true,
|
isAppReady: true,
|
||||||
})
|
})
|
||||||
settingsStore.initConstants({
|
settingsStore.initConstants({
|
||||||
|
@ -45,8 +45,10 @@ function QuickPasteApp() {
|
|||||||
i18n.changeLanguage(i18n.resolvedLanguage)
|
i18n.changeLanguage(i18n.resolvedLanguage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error
|
||||||
settingsStore.initSettings({
|
settingsStore.initSettings({
|
||||||
appDataDir: '',
|
appDataDir: '',
|
||||||
|
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool,
|
||||||
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
|
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
|
||||||
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
|
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
|
||||||
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
|
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
|
||||||
|
@ -38,3 +38,6 @@ Show/Hide Quick Paste Window: Show/Hide Quick Paste Window
|
|||||||
Simplified Panel Layout: Simplified Panel Layout
|
Simplified Panel Layout: Simplified Panel Layout
|
||||||
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.
|
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.
|
||||||
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
|
||||||
|
? Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.
|
||||||
|
: Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.
|
||||||
|
Single Click Copy/Paste: Single Click Copy/Paste
|
||||||
|
@ -14,19 +14,7 @@ import { MINUTE_IN_MS } from '~/constants'
|
|||||||
import { isEmailNotUrl } from '~/libs/utils'
|
import { isEmailNotUrl } from '~/libs/utils'
|
||||||
import { formatLocale as format } from '~/locales/date-locales'
|
import { formatLocale as format } from '~/locales/date-locales'
|
||||||
import { hoveringHistoryRowId, isKeyAltPressed, isKeyCtrlPressed } from '~/store'
|
import { hoveringHistoryRowId, isKeyAltPressed, isKeyCtrlPressed } from '~/store'
|
||||||
import {
|
import { Check, Dot, Star } from 'lucide-react'
|
||||||
ArrowDownToLine,
|
|
||||||
Check,
|
|
||||||
Clipboard,
|
|
||||||
ClipboardPaste,
|
|
||||||
Dot,
|
|
||||||
Grip,
|
|
||||||
MoreVertical,
|
|
||||||
MoveDown,
|
|
||||||
MoveUp,
|
|
||||||
Star,
|
|
||||||
X,
|
|
||||||
} from 'lucide-react'
|
|
||||||
import { Highlight, themes } from 'prism-react-renderer'
|
import { Highlight, themes } from 'prism-react-renderer'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
@ -36,7 +24,7 @@ import ImageWithFallback from '~/components/atoms/image/image-with-fallback-on-e
|
|||||||
import LinkCard from '~/components/atoms/link-card/link-card'
|
import LinkCard from '~/components/atoms/link-card/link-card'
|
||||||
import PlayButton from '~/components/atoms/play-button/PlayButton'
|
import PlayButton from '~/components/atoms/play-button/PlayButton'
|
||||||
import ToolTip from '~/components/atoms/tooltip'
|
import ToolTip from '~/components/atoms/tooltip'
|
||||||
import { Badge, Box, ContextMenu, ContextMenuTrigger, Flex, Text } from '~/components/ui'
|
import { Badge, Box } from '~/components/ui'
|
||||||
import YoutubeEmbed from '~/components/video-player/YoutubeEmbed'
|
import YoutubeEmbed from '~/components/video-player/YoutubeEmbed'
|
||||||
|
|
||||||
import { useSignal } from '~/hooks/use-signal'
|
import { useSignal } from '~/hooks/use-signal'
|
||||||
@ -114,6 +102,7 @@ interface ClipboardHistoryQuickPasteRowProps {
|
|||||||
setRowHeight?: (index: number, height: number) => void
|
setRowHeight?: (index: number, height: number) => void
|
||||||
setHistoryFilters?: Dispatch<SetStateAction<string[]>>
|
setHistoryFilters?: Dispatch<SetStateAction<string[]>>
|
||||||
setAppFilters?: Dispatch<SetStateAction<string[]>>
|
setAppFilters?: Dispatch<SetStateAction<string[]>>
|
||||||
|
isSingleClickToCopyPaste?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
@ -156,26 +145,24 @@ export function ClipboardHistoryQuickPasteRowComponent({
|
|||||||
setLargeViewItemId = () => {},
|
setLargeViewItemId = () => {},
|
||||||
pastingCountDown,
|
pastingCountDown,
|
||||||
onCopyPaste = () => {},
|
onCopyPaste = () => {},
|
||||||
onCopy = () => {},
|
|
||||||
invalidateClipboardHistoryQuery = () => {},
|
invalidateClipboardHistoryQuery = () => {},
|
||||||
generateLinkMetaData,
|
generateLinkMetaData,
|
||||||
removeLinkMetaData = () => Promise.resolve(),
|
|
||||||
isBrokenImage = false,
|
isBrokenImage = false,
|
||||||
setExpanded = () => {},
|
setExpanded = () => {},
|
||||||
onMovePinnedUpDown = ({}) => {},
|
|
||||||
setWrapText = () => {},
|
setWrapText = () => {},
|
||||||
setBrokenImageItem = () => {},
|
setBrokenImageItem = () => {},
|
||||||
setSelectHistoryItem = () => {},
|
setSelectHistoryItem = () => {},
|
||||||
isDragPreview = false,
|
isDragPreview = false,
|
||||||
setRowHeight = () => {},
|
setRowHeight = () => {},
|
||||||
setHistoryFilters = () => {},
|
isSingleClickToCopyPaste = false,
|
||||||
setAppFilters = () => {},
|
|
||||||
}: ClipboardHistoryQuickPasteRowProps) {
|
}: ClipboardHistoryQuickPasteRowProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const rowRef = useRef<HTMLDivElement>(null)
|
const rowRef = useRef<HTMLDivElement>(null)
|
||||||
const rowKeyboardRef = useRef<HTMLDivElement>(null)
|
const rowKeyboardRef = useRef<HTMLDivElement>(null)
|
||||||
const isCopiedOrPasted = isCopied || isPasted || isSaved
|
const isCopiedOrPasted = isCopied || isPasted || isSaved
|
||||||
|
|
||||||
|
console.log('isSingleClickToCopyPaste', isSingleClickToCopyPaste)
|
||||||
|
|
||||||
const contentElementRendered = useSignal<boolean>(false)
|
const contentElementRendered = useSignal<boolean>(false)
|
||||||
const contextMenuOpen = useSignal<boolean>(false)
|
const contextMenuOpen = useSignal<boolean>(false)
|
||||||
|
|
||||||
@ -414,6 +401,9 @@ export function ClipboardHistoryQuickPasteRowComponent({
|
|||||||
} else if (largeViewItemId && !isLargeView) {
|
} else if (largeViewItemId && !isLargeView) {
|
||||||
window.getSelection()?.removeAllRanges()
|
window.getSelection()?.removeAllRanges()
|
||||||
setLargeViewItemId(clipboard.historyId)
|
setLargeViewItemId(clipboard.historyId)
|
||||||
|
} else if (isSingleClickToCopyPaste && !getSelectedText().text) {
|
||||||
|
// Single-click in quick paste mode triggers copy+paste
|
||||||
|
onCopyPaste(clipboard.historyId)
|
||||||
} else {
|
} else {
|
||||||
setKeyboardSelected(clipboard.historyId)
|
setKeyboardSelected(clipboard.historyId)
|
||||||
hoveringHistoryRowId.value = !isPinnedTop
|
hoveringHistoryRowId.value = !isPinnedTop
|
||||||
@ -430,7 +420,9 @@ export function ClipboardHistoryQuickPasteRowComponent({
|
|||||||
hoveringHistoryRowId.value = null
|
hoveringHistoryRowId.value = null
|
||||||
}}
|
}}
|
||||||
onDoubleClickCapture={e => {
|
onDoubleClickCapture={e => {
|
||||||
onCopyPaste(clipboard.historyId)
|
if (!isSingleClickToCopyPaste) {
|
||||||
|
onCopyPaste(clipboard.historyId)
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
|
@ -121,6 +121,7 @@ interface ClipboardHistoryRowProps {
|
|||||||
setRowHeight?: (index: number, height: number) => void
|
setRowHeight?: (index: number, height: number) => void
|
||||||
setHistoryFilters?: Dispatch<SetStateAction<string[]>>
|
setHistoryFilters?: Dispatch<SetStateAction<string[]>>
|
||||||
setAppFilters?: Dispatch<SetStateAction<string[]>>
|
setAppFilters?: Dispatch<SetStateAction<string[]>>
|
||||||
|
isSingleClickToCopyPaste?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||||
@ -178,6 +179,7 @@ export function ClipboardHistoryRowComponent({
|
|||||||
setRowHeight = () => {},
|
setRowHeight = () => {},
|
||||||
setHistoryFilters = () => {},
|
setHistoryFilters = () => {},
|
||||||
setAppFilters = () => {},
|
setAppFilters = () => {},
|
||||||
|
isSingleClickToCopyPaste = false,
|
||||||
}: ClipboardHistoryRowProps) {
|
}: ClipboardHistoryRowProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const rowRef = useRef<HTMLDivElement>(null)
|
const rowRef = useRef<HTMLDivElement>(null)
|
||||||
@ -434,7 +436,17 @@ export function ClipboardHistoryRowComponent({
|
|||||||
}`
|
}`
|
||||||
}`}
|
}`}
|
||||||
onClickCapture={e => {
|
onClickCapture={e => {
|
||||||
if ((isWindows && e.ctrlKey) || (e.metaKey && !isWindows)) {
|
if (
|
||||||
|
(isSingleClickToCopyPaste &&
|
||||||
|
!getSelectedText().text &&
|
||||||
|
isWindows &&
|
||||||
|
e.ctrlKey) ||
|
||||||
|
(e.metaKey && !isWindows)
|
||||||
|
) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
onCopyPaste(clipboard.historyId)
|
||||||
|
} else if ((isWindows && e.ctrlKey) || (e.metaKey && !isWindows)) {
|
||||||
setSelectHistoryItem(clipboard.historyId)
|
setSelectHistoryItem(clipboard.historyId)
|
||||||
} else if (e.ctrlKey || e.metaKey) {
|
} else if (e.ctrlKey || e.metaKey) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -447,6 +459,25 @@ export function ClipboardHistoryRowComponent({
|
|||||||
} else if (largeViewItemId && !isLargeView) {
|
} else if (largeViewItemId && !isLargeView) {
|
||||||
window.getSelection()?.removeAllRanges()
|
window.getSelection()?.removeAllRanges()
|
||||||
setLargeViewItemId(clipboard.historyId)
|
setLargeViewItemId(clipboard.historyId)
|
||||||
|
} else if (isSingleClickToCopyPaste && !getSelectedText().text) {
|
||||||
|
// Check if click is on context menu button or its children
|
||||||
|
const isContextMenuClick = contextMenuButtonRef.current &&
|
||||||
|
(contextMenuButtonRef.current.contains(e.target as Node) ||
|
||||||
|
contextMenuButtonRef.current === e.target)
|
||||||
|
|
||||||
|
if (isContextMenuClick) {
|
||||||
|
return // Don't copy/paste if clicking on context menu
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
e.altKey ||
|
||||||
|
(e.metaKey && isWindows) ||
|
||||||
|
(e.ctrlKey && !isWindows)
|
||||||
|
) {
|
||||||
|
onCopyPaste(clipboard.historyId)
|
||||||
|
} else {
|
||||||
|
onCopy(clipboard.historyId)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
hoveringHistoryRowId.value = !isPinnedTop
|
hoveringHistoryRowId.value = !isPinnedTop
|
||||||
? clipboard.historyId
|
? clipboard.historyId
|
||||||
@ -462,7 +493,7 @@ export function ClipboardHistoryRowComponent({
|
|||||||
hoveringHistoryRowId.value = null
|
hoveringHistoryRowId.value = null
|
||||||
}}
|
}}
|
||||||
onDoubleClickCapture={e => {
|
onDoubleClickCapture={e => {
|
||||||
if (!getSelectedText().text) {
|
if (!isSingleClickToCopyPaste && !getSelectedText().text) {
|
||||||
if (e.altKey || e.metaKey) {
|
if (e.altKey || e.metaKey) {
|
||||||
onCopyPaste(clipboard.historyId)
|
onCopyPaste(clipboard.historyId)
|
||||||
} else {
|
} else {
|
||||||
|
@ -249,6 +249,7 @@ function DashboardComponent({
|
|||||||
clipNotesMaxHeight,
|
clipNotesMaxHeight,
|
||||||
isSimplifiedLayout,
|
isSimplifiedLayout,
|
||||||
clipNotesMaxWidth,
|
clipNotesMaxWidth,
|
||||||
|
isSingleClickToCopyPaste,
|
||||||
} = useAtomValue(settingsStoreAtom)
|
} = useAtomValue(settingsStoreAtom)
|
||||||
|
|
||||||
const boardsIds = useMemo(
|
const boardsIds = useMemo(
|
||||||
@ -606,6 +607,7 @@ function DashboardComponent({
|
|||||||
showOrganizeLayout.value || isPinnedPanelReorder.value
|
showOrganizeLayout.value || isPinnedPanelReorder.value
|
||||||
}
|
}
|
||||||
isPinnedBoard={true}
|
isPinnedBoard={true}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -1166,6 +1168,7 @@ function DashboardComponent({
|
|||||||
isDragPreview
|
isDragPreview
|
||||||
isClipNotesHoverCardsEnabled={false}
|
isClipNotesHoverCardsEnabled={false}
|
||||||
isDark={isDark}
|
isDark={isDark}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
|
@ -194,6 +194,7 @@ export function BoardComponent({
|
|||||||
clipNotesHoverCardsDelayMS,
|
clipNotesHoverCardsDelayMS,
|
||||||
clipNotesMaxHeight,
|
clipNotesMaxHeight,
|
||||||
clipNotesMaxWidth,
|
clipNotesMaxWidth,
|
||||||
|
isSingleClickToCopyPaste,
|
||||||
} = useAtomValue(settingsStoreAtom)
|
} = useAtomValue(settingsStoreAtom)
|
||||||
|
|
||||||
const contextMenuOpen = useSignal(false)
|
const contextMenuOpen = useSignal(false)
|
||||||
@ -759,6 +760,7 @@ export function BoardComponent({
|
|||||||
isKeyboardSelected={
|
isKeyboardSelected={
|
||||||
keyboardSelectedClipId?.value === item.id
|
keyboardSelectedClipId?.value === item.id
|
||||||
}
|
}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
|
@ -318,6 +318,7 @@ interface ClipCardProps {
|
|||||||
setSelectedItemId?: (id: UniqueIdentifier) => void
|
setSelectedItemId?: (id: UniqueIdentifier) => void
|
||||||
isDragPreview?: boolean
|
isDragPreview?: boolean
|
||||||
isKeyboardSelected?: boolean
|
isKeyboardSelected?: boolean
|
||||||
|
isSingleClickToCopyPaste?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClipDragData {
|
export interface ClipDragData {
|
||||||
@ -358,6 +359,7 @@ export function ClipCard({
|
|||||||
setShowDetailsItem = () => {},
|
setShowDetailsItem = () => {},
|
||||||
setSelectedItemId = () => {},
|
setSelectedItemId = () => {},
|
||||||
isKeyboardSelected = false,
|
isKeyboardSelected = false,
|
||||||
|
isSingleClickToCopyPaste = false,
|
||||||
}: ClipCardProps) {
|
}: ClipCardProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { isNoteIconsEnabled, defaultNoteIconType } = useAtomValue(settingsStoreAtom)
|
const { isNoteIconsEnabled, defaultNoteIconType } = useAtomValue(settingsStoreAtom)
|
||||||
@ -715,10 +717,30 @@ export function ClipCard({
|
|||||||
} else {
|
} else {
|
||||||
setShowDetailsItem(null)
|
setShowDetailsItem(null)
|
||||||
}
|
}
|
||||||
|
} else if (isSingleClickToCopyPaste && !copyDisabled) {
|
||||||
|
// Check if click is on context menu button or its children
|
||||||
|
const isContextMenuClick = contextMenuButtonRef.current &&
|
||||||
|
(contextMenuButtonRef.current.contains(e.target as Node) ||
|
||||||
|
contextMenuButtonRef.current === e.target)
|
||||||
|
|
||||||
|
if (isContextMenuClick) {
|
||||||
|
return // Don't copy/paste if clicking on context menu
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-click copy mode
|
||||||
|
if (e.altKey || e.metaKey) {
|
||||||
|
if (clip.isForm) {
|
||||||
|
setPastedItem(clip.id, undefined, true)
|
||||||
|
} else {
|
||||||
|
setPastedItem(clip.id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setCopiedItem(clip.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onDoubleClickCapture={e => {
|
onDoubleClickCapture={e => {
|
||||||
if (copyDisabled || e.shiftKey) {
|
if (copyDisabled || e.shiftKey || isSingleClickToCopyPaste) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -238,6 +238,7 @@ export default function ClipboardHistoryPage() {
|
|||||||
isHistoryPanelVisibleOnly,
|
isHistoryPanelVisibleOnly,
|
||||||
isSimplifiedLayout,
|
isSimplifiedLayout,
|
||||||
isSavedClipsPanelVisibleOnly,
|
isSavedClipsPanelVisibleOnly,
|
||||||
|
isSingleClickToCopyPaste,
|
||||||
} = useAtomValue(settingsStoreAtom)
|
} = useAtomValue(settingsStoreAtom)
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
@ -1488,6 +1489,7 @@ export default function ClipboardHistoryPage() {
|
|||||||
clipboard={item}
|
clipboard={item}
|
||||||
removeLinkMetaData={removeLinkMetaData}
|
removeLinkMetaData={removeLinkMetaData}
|
||||||
generateLinkMetaData={generateLinkMetaData}
|
generateLinkMetaData={generateLinkMetaData}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
@ -2111,6 +2113,7 @@ export default function ClipboardHistoryPage() {
|
|||||||
clipboard={clipboard}
|
clipboard={clipboard}
|
||||||
removeLinkMetaData={removeLinkMetaData}
|
removeLinkMetaData={removeLinkMetaData}
|
||||||
generateLinkMetaData={generateLinkMetaData}
|
generateLinkMetaData={generateLinkMetaData}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
index={index}
|
index={index}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
@ -2170,6 +2173,7 @@ export default function ClipboardHistoryPage() {
|
|||||||
: clip.historyId ===
|
: clip.historyId ===
|
||||||
activeDragId.toString().split('::pinned')[0]
|
activeDragId.toString().split('::pinned')[0]
|
||||||
})}
|
})}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</DragOverlay>
|
</DragOverlay>
|
||||||
|
@ -102,8 +102,11 @@ export default function ClipboardHistoryQuickPastePage() {
|
|||||||
const isShowSearch = useSignal(false)
|
const isShowSearch = useSignal(false)
|
||||||
const { movePinnedClipboardHistoryUpDown } = useMovePinnedClipboardHistoryUpDown()
|
const { movePinnedClipboardHistoryUpDown } = useMovePinnedClipboardHistoryUpDown()
|
||||||
|
|
||||||
const { isAutoPreviewLinkCardsEnabled, isAutoGenerateLinkCardsEnabled } =
|
const {
|
||||||
useAtomValue(settingsStoreAtom)
|
isAutoPreviewLinkCardsEnabled,
|
||||||
|
isAutoGenerateLinkCardsEnabled,
|
||||||
|
isSingleClickToCopyPaste,
|
||||||
|
} = useAtomValue(settingsStoreAtom)
|
||||||
|
|
||||||
const [historyFilters, setHistoryFilters] = useState<string[]>([])
|
const [historyFilters, setHistoryFilters] = useState<string[]>([])
|
||||||
const [codeFilters, setCodeFilters] = useState<string[]>([])
|
const [codeFilters, setCodeFilters] = useState<string[]>([])
|
||||||
@ -722,6 +725,7 @@ export default function ClipboardHistoryQuickPastePage() {
|
|||||||
clipboard={item}
|
clipboard={item}
|
||||||
removeLinkMetaData={removeLinkMetaData}
|
removeLinkMetaData={removeLinkMetaData}
|
||||||
generateLinkMetaData={generateLinkMetaData}
|
generateLinkMetaData={generateLinkMetaData}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@ -917,6 +921,7 @@ export default function ClipboardHistoryQuickPastePage() {
|
|||||||
clipboard={clipboard}
|
clipboard={clipboard}
|
||||||
removeLinkMetaData={removeLinkMetaData}
|
removeLinkMetaData={removeLinkMetaData}
|
||||||
generateLinkMetaData={generateLinkMetaData}
|
generateLinkMetaData={generateLinkMetaData}
|
||||||
|
isSingleClickToCopyPaste={isSingleClickToCopyPaste}
|
||||||
index={index}
|
index={index}
|
||||||
style={style}
|
style={style}
|
||||||
/>
|
/>
|
||||||
|
@ -93,6 +93,8 @@ export default function UserPreferences() {
|
|||||||
setIsSavedClipsPanelVisibleOnly,
|
setIsSavedClipsPanelVisibleOnly,
|
||||||
isSimplifiedLayout,
|
isSimplifiedLayout,
|
||||||
setIsSimplifiedLayout,
|
setIsSimplifiedLayout,
|
||||||
|
isSingleClickToCopyPaste,
|
||||||
|
setIsSingleClickToCopyPaste,
|
||||||
} = useAtomValue(settingsStoreAtom)
|
} = useAtomValue(settingsStoreAtom)
|
||||||
|
|
||||||
const { setFontSize, fontSize, setIsSwapPanels, isSwapPanels, returnRoute, isMacOSX } =
|
const { setFontSize, fontSize, setIsSwapPanels, isSwapPanels, returnRoute, isMacOSX } =
|
||||||
@ -725,6 +727,36 @@ export default function UserPreferences() {
|
|||||||
</Card>
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box className="animate-in fade-in max-w-xl mt-4">
|
||||||
|
<Card
|
||||||
|
className={`${
|
||||||
|
!isSingleClickToCopyPaste &&
|
||||||
|
'opacity-80 bg-gray-100 dark:bg-gray-900/80'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-1">
|
||||||
|
<CardTitle className="animate-in fade-in text-md font-medium w-full">
|
||||||
|
{t('Single Click Copy/Paste', { ns: 'settings2' })}
|
||||||
|
</CardTitle>
|
||||||
|
<Switch
|
||||||
|
checked={isSingleClickToCopyPaste}
|
||||||
|
className="ml-auto"
|
||||||
|
onCheckedChange={() => {
|
||||||
|
setIsSingleClickToCopyPaste(!isSingleClickToCopyPaste)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
<Text className="text-sm text-muted-foreground">
|
||||||
|
{t(
|
||||||
|
'Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.',
|
||||||
|
{ ns: 'settings2' }
|
||||||
|
)}
|
||||||
|
</Text>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box className="animate-in fade-in max-w-xl mt-4">
|
<Box className="animate-in fade-in max-w-xl mt-4">
|
||||||
<Card
|
<Card
|
||||||
className={`${
|
className={`${
|
||||||
|
@ -97,6 +97,7 @@ type Settings = {
|
|||||||
isSavedClipsPanelVisibleOnly: boolean
|
isSavedClipsPanelVisibleOnly: boolean
|
||||||
isSimplifiedLayout: boolean
|
isSimplifiedLayout: boolean
|
||||||
isMainWindowOnTop: boolean
|
isMainWindowOnTop: boolean
|
||||||
|
isSingleClickToCopyPaste: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type Constants = {
|
type Constants = {
|
||||||
@ -180,6 +181,7 @@ export interface SettingsStoreState {
|
|||||||
setShowBothPanels: (isVisible: boolean) => void
|
setShowBothPanels: (isVisible: boolean) => void
|
||||||
setIsSimplifiedLayout: (isEnabled: boolean) => void
|
setIsSimplifiedLayout: (isEnabled: boolean) => void
|
||||||
setIsMainWindowOnTop: (isEnabled: boolean) => void
|
setIsMainWindowOnTop: (isEnabled: boolean) => void
|
||||||
|
setIsSingleClickToCopyPaste: (isEnabled: boolean) => void
|
||||||
hashPassword: (pass: string) => Promise<string>
|
hashPassword: (pass: string) => Promise<string>
|
||||||
isNotTourCompletedOrSkipped: (tourName: string) => boolean
|
isNotTourCompletedOrSkipped: (tourName: string) => boolean
|
||||||
verifyPassword: (pass: string, hash: string) => Promise<boolean>
|
verifyPassword: (pass: string, hash: string) => Promise<boolean>
|
||||||
@ -272,6 +274,7 @@ const initialState: SettingsStoreState & Settings = {
|
|||||||
isSavedClipsPanelVisibleOnly: false,
|
isSavedClipsPanelVisibleOnly: false,
|
||||||
isSimplifiedLayout: true,
|
isSimplifiedLayout: true,
|
||||||
isMainWindowOnTop: false,
|
isMainWindowOnTop: false,
|
||||||
|
isSingleClickToCopyPaste: false,
|
||||||
CONST: {
|
CONST: {
|
||||||
APP_DETECT_LANGUAGES_SUPPORTED: [],
|
APP_DETECT_LANGUAGES_SUPPORTED: [],
|
||||||
},
|
},
|
||||||
@ -337,6 +340,7 @@ const initialState: SettingsStoreState & Settings = {
|
|||||||
setShowBothPanels: () => {},
|
setShowBothPanels: () => {},
|
||||||
setIsSimplifiedLayout: () => {},
|
setIsSimplifiedLayout: () => {},
|
||||||
setIsMainWindowOnTop: () => {},
|
setIsMainWindowOnTop: () => {},
|
||||||
|
setIsSingleClickToCopyPaste: () => {},
|
||||||
initConstants: () => {},
|
initConstants: () => {},
|
||||||
setAppDataDir: () => {}, // Keep if used for other general app data
|
setAppDataDir: () => {}, // Keep if used for other general app data
|
||||||
setCustomDbPath: () => {},
|
setCustomDbPath: () => {},
|
||||||
@ -705,6 +709,11 @@ export const settingsStore = createStore<SettingsStoreState & Settings>()((set,
|
|||||||
setIsMainWindowOnTop: async (isEnabled: boolean) => {
|
setIsMainWindowOnTop: async (isEnabled: boolean) => {
|
||||||
return get().updateSetting('isMainWindowOnTop', isEnabled)
|
return get().updateSetting('isMainWindowOnTop', isEnabled)
|
||||||
},
|
},
|
||||||
|
setIsSingleClickToCopyPaste: async (isEnabled: boolean) => {
|
||||||
|
get().syncStateUpdate('isSingleClickToCopyPaste', isEnabled)
|
||||||
|
|
||||||
|
return get().updateSetting('isSingleClickToCopyPaste', isEnabled)
|
||||||
|
},
|
||||||
isNotTourCompletedOrSkipped: (tourName: string) => {
|
isNotTourCompletedOrSkipped: (tourName: string) => {
|
||||||
const { appToursCompletedList, appToursSkippedList } = get()
|
const { appToursCompletedList, appToursSkippedList } = get()
|
||||||
return (
|
return (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user