auto trim spaces in the clip on save

This commit is contained in:
segemun 2025-01-18 19:07:05 +01:00
parent a8e3fc88e0
commit c8ad61176a
9 changed files with 72 additions and 88 deletions

View File

@ -118,7 +118,7 @@ interface CardValueViewerProps {
isExpanded: boolean
searchTerm: string
isDark: boolean
trimmedValue: string
textValue: string
}
export const CardValueViewer: FC<CardValueViewerProps> = ({
@ -133,7 +133,7 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
isVideo,
isMasked,
isLargeView,
trimmedValue,
textValue,
hasLinkCard,
metadataLinkByItemId,
metadataLinkImageWidth = 24,
@ -161,12 +161,12 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
}, [valuePreview])
const valueParsed = useMemo(() => {
if (!isImageData && !isCode && !isImage && trimmedValue) {
if (!isImageData && !isCode && !isImage && textValue) {
return isMasked
? maskValue(bbCode.remove(trimmedValue))
: bbCode.parse(trimmedValue)
? maskValue(bbCode.remove(textValue))
: bbCode.parse(textValue)
}
}, [trimmedValue])
}, [textValue])
const highlightedContent = useMemo(() => {
if (searchTerm.length > 1) {
@ -222,7 +222,7 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
<Box className="self-start mt-1 mb-1 text-xs w-full select-none overflow-hidden">
<LinkCard
isDisabled={
ensureUrlPrefix(trimmedValue) !== metadataLinkByItemId?.linkUrl &&
ensureUrlPrefix(textValue) !== metadataLinkByItemId?.linkUrl &&
!Boolean(metadataLinkByItemId?.linkIsTrack)
}
title={metadataLinkByItemId?.linkTitle}

View File

@ -93,7 +93,7 @@ export function ClipboardHistoryLargeViewComponent({
const contextMenuButtonRef = useRef<HTMLDivElement>(null)
const contextMenuTriggerRef = useRef<HTMLDivElement>(null)
const trimmedValue: string = clipboard?.value?.trim() ?? ''
const textValue: string = clipboard?.value ?? ''
const hasLinkCard =
clipboard?.isLink &&
clipboard?.linkMetadata?.linkTitle &&
@ -138,7 +138,7 @@ export function ClipboardHistoryLargeViewComponent({
<Box className="text-ellipsis self-start text-xs w-full select-text overflow-hidden">
<Box className="flex px-0 py-1 items-center justify-center">
<ImageWithFallback
src={trimmedValue}
src={textValue}
hasError={isBrokenImage}
key={clipboard.historyId}
decoding="async"
@ -160,7 +160,7 @@ export function ClipboardHistoryLargeViewComponent({
<Box className="text-ellipsis self-start text-xs w-full select-text overflow-hidden">
<Box className="flex px-0 pt-1.5 pb-0.5 items-center justify-center">
<ImageWithFallback
src={ensureUrlPrefix(trimmedValue)}
src={ensureUrlPrefix(textValue)}
key={clipboard.historyId}
hasError={isBrokenImage}
height={clipboard.imageHeight}
@ -173,8 +173,8 @@ export function ClipboardHistoryLargeViewComponent({
</Box>
<code className="pb-0.5">
{searchTerm
? highlightMatchedText(trimmedValue, searchTerm)
: hyperlinkText(trimmedValue, clipboard.arrLinks)}
? highlightMatchedText(textValue, searchTerm)
: hyperlinkText(textValue, clipboard.arrLinks)}
</code>
</Box>
) : clipboard.isImage && clipboard.imagePathFullRes ? (
@ -194,7 +194,7 @@ export function ClipboardHistoryLargeViewComponent({
>
<Highlight
theme={isDark ? themes.vsDark : themes.github}
code={trimmedValue}
code={textValue}
language={clipboard.detectedLanguage}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => {
@ -255,10 +255,10 @@ export function ClipboardHistoryLargeViewComponent({
key={clipboard.historyId}
>
{clipboard.isVideo ? (
<YoutubeEmbed url={trimmedValue} minWidth={530} />
<YoutubeEmbed url={textValue} minWidth={530} />
) : isSocialEmbed ? (
<CardSocialEmbed
url={trimmedValue}
url={textValue}
isTwitter={isTwitter}
isDark={isDark}
isInstagram={isInstagram}
@ -285,12 +285,12 @@ export function ClipboardHistoryLargeViewComponent({
)}
<code
className={`justify-start select-text ${
isWrapText ? 'whitespace-break-spaces' : 'whitespace-normal'
isWrapText ? 'whitespace-break-spaces' : 'whitespace-pre'
}`}
>
{searchTerm
? highlightMatchedText(trimmedValue, searchTerm)
: hyperlinkText(trimmedValue, clipboard.arrLinks)}
? highlightMatchedText(textValue, searchTerm)
: hyperlinkText(textValue, clipboard.arrLinks)}
{clipboard.valueMorePreviewChars && (
<Box className="select-none"> {'\u00A0'} </Box>
)}

View File

@ -263,7 +263,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
clipboard.isPinned,
])
const stringValue: string = clipboard?.value ?? ''
const textValue: string = clipboard?.value ?? ''
const hasLinkCard =
clipboard?.isLink &&
clipboard?.linkMetadata?.linkTitle &&
@ -277,7 +277,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
!hasLinkCard &&
clipboard?.isLink &&
clipboard?.value &&
!isEmailNotUrl(stringValue) &&
!isEmailNotUrl(textValue) &&
!hasClipboardHistoryURLErrors &&
!hasGenerateLinkMetaDataInProgress &&
isAutoGenerateLinkCardsEnabled
@ -467,7 +467,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
<Box className="text-ellipsis self-start text-xs w-full _select-text overflow-hidden cursor-pointer">
<Box className="flex px-0 py-1 items-center justify-center w-full">
<ImageWithFallback
src={stringValue}
src={textValue}
hasError={isBrokenImage}
onErrorCallback={() => {
setBrokenImageItem(clipboard.historyId)
@ -492,7 +492,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
<Box className="text-ellipsis self-start text-xs w-full _select-text cursor-pointer overflow-hidden">
<Box className="flex px-0 pt-1.5 pb-0.5 items-center justify-center w-full">
<ImageWithFallback
src={ensureUrlPrefix(stringValue)}
src={ensureUrlPrefix(textValue)}
hasError={isBrokenImage}
height={clipboard.imageHeight}
onErrorCallback={() => {
@ -508,17 +508,17 @@ export function ClipboardHistoryQuickPasteRowComponent({
</Box>
<code className="pb-0.5">
{searchTerm
? highlightWithPreviewMatchedText(stringValue, searchTerm)
: hyperlinkText(stringValue, clipboard.arrLinks)}
? highlightWithPreviewMatchedText(textValue, searchTerm)
: hyperlinkText(textValue, clipboard.arrLinks)}
</code>
</Box>
) : clipboard.isLink && clipboard.isVideo ? (
<Box className="text-ellipsis self-start text-xs w-full _select-text cursor-pointer overflow-hidden">
<YoutubeEmbed url={stringValue} />
<YoutubeEmbed url={textValue} />
<code className="pb-0.5">
{searchTerm
? highlightWithPreviewMatchedText(stringValue, searchTerm)
: hyperlinkText(stringValue, clipboard.arrLinks)}
? highlightWithPreviewMatchedText(textValue, searchTerm)
: hyperlinkText(textValue, clipboard.arrLinks)}
</code>
</Box>
) : clipboard.isImage && clipboard.imageDataUrl ? (
@ -545,7 +545,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
>
<Highlight
theme={isDark ? themes.vsDark : themes.github}
code={isExpanded ? stringValue : clipboard.valuePreview.trim()}
code={isExpanded ? textValue : clipboard.valuePreview.trim()}
language={clipboard.detectedLanguage}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => {
@ -616,8 +616,8 @@ export function ClipboardHistoryQuickPasteRowComponent({
{isExpanded ? (
<code className="justify-start cursor-pointer">
{searchTerm
? highlightMatchedText(stringValue, searchTerm)
: hyperlinkText(stringValue, clipboard.arrLinks)}
? highlightMatchedText(textValue, searchTerm)
: hyperlinkText(textValue, clipboard.arrLinks)}
{clipboard.valueMorePreviewChars && (
<Box className="select-none"> {'\u00A0'} </Box>
)}
@ -625,11 +625,11 @@ export function ClipboardHistoryQuickPasteRowComponent({
) : (
<code className="justify-start cursor-pointer">
{searchTerm
? highlightWithPreviewMatchedText(stringValue ?? '', searchTerm)
? highlightWithPreviewMatchedText(textValue ?? '', searchTerm)
: hyperlinkTextWithPreview({
previewLinkCard: !hasLinkCard && isLinkCardPreviewEnabled,
isPreviewError: hasClipboardHistoryURLErrors,
value: clipboard.valuePreview?.trim() ?? '',
value: clipboard.valuePreview ?? '',
links: clipboard.arrLinks,
itemId: null,
historyId: clipboard.historyId,
@ -642,7 +642,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
)}
{isMp3 && (
<PlayButton
src={stringValue}
src={textValue}
hasLinkCard={hasLinkCard}
isPinnedBoard={isPinnedTop}
isPinned={clipboard.isPinned}
@ -797,7 +797,7 @@ export function ClipboardHistoryQuickPasteRowComponent({
>
{clipboard.isVideo
? t('Type:::Video', { ns: 'common' })
: isEmailNotUrl(stringValue)
: isEmailNotUrl(textValue)
? t('Type:::Email', { ns: 'common' })
: isMp3
? t('Type:::Mp3', { ns: 'common' })

View File

@ -163,7 +163,7 @@ export function ClipCardBody({
}
}, [requestOptions])
const stringValue: string = value || '';
const textValue: string = value || '';
useEffect(() => {
if (isExpanded.value) {
@ -173,7 +173,7 @@ export function ClipCardBody({
useEffect(() => {
if (isPath) {
invoke('check_path', { path: stringValue })
invoke('check_path', { path: textValue })
.then(() => {
pathTypeCheck.value = pathType
})
@ -190,8 +190,8 @@ export function ClipCardBody({
}, [searchTerm])
const imageMaxHeight = isLargeView ? 'max-h-[600px]' : 'max-h-[300px]'
const isEmptyBody = stringValue.length === 0
const isMp3 = isLink && stringValue?.endsWith('.mp3')
const isEmptyBody = textValue.length === 0
const isMp3 = isLink && textValue?.endsWith('.mp3')
useEffect(() => {
if (isShowLinkedClip) {
@ -225,7 +225,7 @@ export function ClipCardBody({
)}
<Highlight
theme={isDark ? themes.vsDark : themes.github}
code={stringValue}
code={textValue}
language={'path'}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => {
@ -270,7 +270,7 @@ export function ClipCardBody({
<Box className="text-ellipsis self-start text-xs overflow-hidden select-none">
<Box className="flex px-0 py-1 items-center justify-center">
<ImageWithFallback
src={stringValue}
src={textValue}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -286,7 +286,7 @@ export function ClipCardBody({
<Box className="text-ellipsis self-start text-xs overflow-hidden select-none">
<Box className="flex px-0 pt-1.5 pb-0.5 items-center justify-center">
<ImageWithFallback
src={ensureUrlPrefix(stringValue)}
src={ensureUrlPrefix(textValue)}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -296,7 +296,7 @@ export function ClipCardBody({
className={`${imageMaxHeight} min-h-10`}
/>
</Box>
<code className="pb-0.5">{hyperlinkText(stringValue, arrLinks)}</code>
<code className="pb-0.5">{hyperlinkText(textValue, arrLinks)}</code>
</Box>
) : isImage ? (
<Box className="px-0 py-1.5 flex items-center justify-center relative animate-in fade-in duration-300 !fill-mode-forwards select-none">
@ -354,7 +354,7 @@ export function ClipCardBody({
isLargeView={isLargeView}
isShowMore={isExpanded.value || morePreviewLines == null}
isWrapped={isWrapText.value}
value={isExpanded.value ? stringValue : valuePreview}
value={isExpanded.value ? textValue : valuePreview}
language={detectedLanguage}
/>
</Box>
@ -368,7 +368,7 @@ export function ClipCardBody({
isShowMore={true}
isWrapped={isWrapText.value}
autoHideScrollbar={true}
value={stringValue}
value={textValue}
language="shell"
/>
{commandRequestOutput && (
@ -423,7 +423,7 @@ export function ClipCardBody({
isLargeView={isLargeView}
isShowMore={true}
isWrapped={isWrapText.value}
value={stringValue}
value={textValue}
autoHideScrollbar={true}
webRequestMethod={
isWebRequest ? webrequestLocalOptions.value.method : 'URL'
@ -503,7 +503,7 @@ export function ClipCardBody({
hasLinkCard={hasLinkCard}
metadataLinkByItemId={metadataLinkByItemId}
isImage={isImage}
trimmedValue={stringValue}
textValue={textValue}
valuePreview={valuePreview}
morePreviewLines={morePreviewLines}
isDark={isDark}
@ -601,7 +601,7 @@ export function ClipCardBody({
</Box>
) : isMp3 ? (
<PlayButton
src={stringValue}
src={textValue}
isPinnedBoard={false}
isClip={true}
id={clipId}
@ -721,7 +721,7 @@ export function ClipCardBody({
>
{isVideo
? t('Type:::Video', { ns: 'common' })
: isEmailNotUrl(stringValue)
: isEmailNotUrl(textValue)
? t('Type:::Email', { ns: 'common' })
: isMp3
? t('Type:::Mp3', { ns: 'common' })

View File

@ -478,7 +478,7 @@ export function ClipEditContent({
showPathValidationError.value = undefined
webrequestTestOutputObject.value = {}
const saveValue = clipValue.value
const saveValue = itemLocalOptions.value?.autoTrimSpaces === false ? clipValue.value : clipValue.value.trim()
if (!force) {
if (isTemplate) {

View File

@ -91,7 +91,7 @@ export function MenuCardViewBody({
const isWrapText = useSignal(false)
const { valuePreview, morePreviewLines, morePreviewChars } = getValuePreview(value)
const stringValue: string = value || '';
const textValue: string = value || '';
const isBrokenImage = useSignal(false)
const pathTypeCheck = useSignal<string | null | undefined>('')
@ -108,7 +108,7 @@ export function MenuCardViewBody({
useEffect(() => {
if (isPath) {
invoke('check_path', { path: stringValue })
invoke('check_path', { path: textValue })
.then(() => {
pathTypeCheck.value = pathType
})
@ -118,7 +118,7 @@ export function MenuCardViewBody({
}
}, [isPath])
const isEmptyBody = stringValue.length === 0
const isEmptyBody = textValue.length === 0
return (
<CardContent
@ -134,7 +134,7 @@ export function MenuCardViewBody({
{isPath ? (
<Highlight
theme={isDark ? themes.vsDark : themes.github}
code={stringValue}
code={textValue}
language={'path'}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => {
@ -176,7 +176,7 @@ export function MenuCardViewBody({
<Box className="text-ellipsis self-start text-xs overflow-hidden cursor-pointer">
<Box className="flex px-0 py-1 items-center justify-center">
<ImageWithFallback
src={stringValue}
src={textValue}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -192,7 +192,7 @@ export function MenuCardViewBody({
<Box className="text-ellipsis self-start text-xs cursor-pointer overflow-hidden">
<Box className="flex px-0 pt-1.5 pb-0.5 items-center justify-center">
<ImageWithFallback
src={ensureUrlPrefix(stringValue)}
src={ensureUrlPrefix(textValue)}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -202,7 +202,7 @@ export function MenuCardViewBody({
className="max-h-[200px] min-h-10"
/>
</Box>
<code className="pb-0.5">{hyperlinkText(stringValue, arrLinks ?? '')}</code>
<code className="pb-0.5">{hyperlinkText(textValue, arrLinks ?? '')}</code>
</Box>
) : isImage ? (
<Box className="px-0 py-1.5 flex items-center justify-center relative animate-in fade-in duration-300 !fill-mode-forwards">
@ -238,7 +238,7 @@ export function MenuCardViewBody({
isLargeView={false}
isShowMore={isExpanded.value || morePreviewLines == null}
isWrapped={isWrapText.value}
value={isExpanded.value ? stringValue : valuePreview}
value={isExpanded.value ? textValue : valuePreview}
language={detectedLanguage}
/>
</Box>
@ -258,7 +258,7 @@ export function MenuCardViewBody({
isMasked={isMasked}
isImage={isImage}
isDark={isDark}
trimmedValue={stringValue}
textValue={textValue}
valuePreview={valuePreview}
hasLinkCard={hasLinkCard}
metadataLinkByItemId={metadataLinkByItemId}
@ -413,7 +413,7 @@ export function MenuCardViewBody({
>
{isVideo
? t('Type:::Video', { ns: 'common' })
: isEmailNotUrl(stringValue)
: isEmailNotUrl(textValue)
? t('Type:::Email', { ns: 'common' })
: t('Type:::Link', { ns: 'common' })}
</Box>

View File

@ -147,7 +147,7 @@ export function MenuClipCardViewBody({
}
}, [requestOptions])
const stringValue: string = value || ''
const textValue: string = value || ''
useEffect(() => {
if (isExpanded.value) {
@ -157,7 +157,7 @@ export function MenuClipCardViewBody({
useEffect(() => {
if (isPath) {
invoke('check_path', { path: stringValue })
invoke('check_path', { path: textValue })
.then(() => {
pathTypeCheck.value = pathType
})
@ -168,7 +168,7 @@ export function MenuClipCardViewBody({
}, [isPath])
const imageMaxHeight = isLargeView ? 'max-h-[600px]' : 'max-h-[300px]'
const isEmptyBody = stringValue.length === 0
const isEmptyBody = textValue.length === 0
return (
<CardContent
@ -184,7 +184,7 @@ export function MenuClipCardViewBody({
{isPath ? (
<Highlight
theme={isDark ? themes.vsDark : themes.github}
code={stringValue}
code={textValue}
language={'path'}
>
{({ className, style, tokens, getLineProps, getTokenProps }) => {
@ -226,7 +226,7 @@ export function MenuClipCardViewBody({
<Box className="text-ellipsis self-start text-xs overflow-hidden cursor-pointer">
<Box className="flex px-0 py-1 items-center justify-center">
<ImageWithFallback
src={stringValue}
src={textValue}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -242,7 +242,7 @@ export function MenuClipCardViewBody({
<Box className="text-ellipsis self-start text-xs cursor-pointer overflow-hidden">
<Box className="flex px-0 pt-1.5 pb-0.5 items-center justify-center">
<ImageWithFallback
src={ensureUrlPrefix(stringValue)}
src={ensureUrlPrefix(textValue)}
hasError={isBrokenImage.value}
onErrorCallback={() => {
isBrokenImage.value = true
@ -252,7 +252,7 @@ export function MenuClipCardViewBody({
className={`${imageMaxHeight} min-h-10`}
/>
</Box>
<code className="pb-0.5">{hyperlinkText(stringValue, arrLinks)}</code>
<code className="pb-0.5">{hyperlinkText(textValue, arrLinks)}</code>
</Box>
) : isImage ? (
<Box className="px-0 py-1.5 flex items-center justify-center relative animate-in fade-in duration-300 !fill-mode-forwards">
@ -287,7 +287,7 @@ export function MenuClipCardViewBody({
isLargeView={isLargeView}
isShowMore={isExpanded.value || morePreviewLines == null}
isWrapped={isWrapText.value}
value={isExpanded.value ? stringValue : valuePreview}
value={isExpanded.value ? textValue : valuePreview}
language={detectedLanguage}
/>
</Box>
@ -300,7 +300,7 @@ export function MenuClipCardViewBody({
isShowMore={true}
isWrapped={isWrapText.value}
autoHideScrollbar={true}
value={stringValue}
value={textValue}
language="shell"
/>
{commandRequestOutput && (
@ -354,7 +354,7 @@ export function MenuClipCardViewBody({
isLargeView={isLargeView}
isShowMore={true}
isWrapped={isWrapText.value}
value={stringValue}
value={textValue}
autoHideScrollbar={true}
webRequestMethod={
isWebRequest ? webrequestLocalOptions.value.method : 'URL'
@ -428,7 +428,7 @@ export function MenuClipCardViewBody({
isCode={isCode}
isMasked={isMasked}
isImage={isImage}
trimmedValue={stringValue}
textValue={textValue}
valuePreview={valuePreview}
isDark={isDark}
hasLinkCard={hasLinkCard}
@ -636,7 +636,7 @@ export function MenuClipCardViewBody({
>
{isVideo
? t('Type:::Video', { ns: 'common' })
: isEmailNotUrl(stringValue)
: isEmailNotUrl(textValue)
? t('Type:::Email', { ns: 'common' })
: t('Type:::Link', { ns: 'common' })}
</Box>

View File

@ -100,11 +100,6 @@ where
Err(()) => None,
};
if let Ok(mut text) = clipboard_text {
text = text.to_string();
if copied_from_app.as_deref() != Some("PasteBar") {
text = text.trim().to_string();
}
if !text.is_empty() {
let mut is_excluded = false;

View File

@ -40,7 +40,6 @@ pub enum ClipFormKeyPress {
pub struct ItemField {
pub press_keys_after_paste: Option<ClipFormKeyPress>,
pub no_link_card: Option<bool>,
pub auto_trim_spaces: Option<bool>,
}
#[derive(Debug, Serialize, Deserialize)]
@ -198,7 +197,7 @@ pub async fn copy_clip_item(
copy_from_menu: bool,
) -> String {
// Fetch the item from the database
let mut item = match get_item_by_id(item_id.clone()) {
let item = match get_item_by_id(item_id.clone()) {
Ok(i) => i,
Err(e) => {
eprintln!("Failed to find item: {}", e);
@ -207,16 +206,6 @@ pub async fn copy_clip_item(
};
let mut manager = app_handle.clipboard_manager();
let mut auto_trim_spaces = true;
if let Some(item_options) = item.item_options {
if let Ok(item_field) = serde_json::from_str::<ItemField>(&item_options) {
auto_trim_spaces = item_field.auto_trim_spaces.unwrap_or(true);
}
}
if (auto_trim_spaces) {
item.value = item.value.map(|v| v.trim().to_string());
}
if let (Some(true), true) = (item.is_link, copy_from_menu) {
match &item.value {