From d2bfd8f99116ace879edf9d639a49d4a92675102 Mon Sep 17 00:00:00 2001 From: Nikolaj Frey Date: Wed, 3 Apr 2024 16:36:11 +1100 Subject: [PATCH] =?UTF-8?q?Fixed=20multiple=20image=20trim's=20not=20worki?= =?UTF-8?q?ng=20=F0=9F=99=8F=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- raycast/package.json | 47 ++++- raycast/raycast-env.d.ts | 109 +++++++++++ raycast/src/commander.tsx | 257 ++++++++++++++++++------- raycast/src/commanderConvert.tsx | 1 + raycast/src/commanderTrim.tsx | 1 + raycast/src/convert.tsx | 3 +- raycast/src/operations/anyOperation.ts | 58 +++++- raycast/src/utilities/preferences.ts | 3 +- 8 files changed, 401 insertions(+), 78 deletions(-) create mode 100644 raycast/raycast-env.d.ts create mode 120000 raycast/src/commanderConvert.tsx create mode 120000 raycast/src/commanderTrim.tsx diff --git a/raycast/package.json b/raycast/package.json index caf1da3..48ff3c2 100644 --- a/raycast/package.json +++ b/raycast/package.json @@ -143,6 +143,29 @@ } ] }, + { + "name": "commanderTrim", + "title": "Trim image", + "description": "Will trim all whitespace from an image", + "mode": "no-view", + "fallbackText": "test2", + "keywords": [ + "commander", + "thingtime", + "ai" + ], + "preferences": [ + { + "name": "name", + "required": false, + "type": "textfield", + "key": "name", + "title": "Name of Command to run", + "description": "The name of the command/function to run", + "defaultValue": "trim" + } + ] + }, { "name": "commanderMp4ToMp3", "title": "mp4 to mp3", @@ -156,7 +179,7 @@ ], "preferences": [ { - "name": "mp4ToMp3", + "name": "name", "required": false, "type": "textfield", "key": "name", @@ -167,12 +190,31 @@ ] }, { - "name": "convert", + "name": "commanderConvert", "title": "Convert Images", "description": "Convert the selected images to the specified format", "mode": "view", "preferences": [ { + "name": "name", + "required": false, + "type": "textfield", + "key": "name", + "title": "Name of Command to run", + "description": "The name of the command/function to run", + "defaultValue": "convert" + }, + { + "title": "Additional", + "label": "Trim", + "name": "trim", + "description": "Whether to trim the image", + "type": "checkbox", + "default": false, + "required": false + }, + { + "title": "Enabled Formats", "label": "WEBP", "name": "showWEBP", "description": "Whether to show WEBP as a conversion option", @@ -181,7 +223,6 @@ "required": false }, { - "title": "Enabled Formats", "label": "ASTC", "name": "showASTC", "description": "Whether to show ASTC as a conversion option", diff --git a/raycast/raycast-env.d.ts b/raycast/raycast-env.d.ts new file mode 100644 index 0000000..cf7540b --- /dev/null +++ b/raycast/raycast-env.d.ts @@ -0,0 +1,109 @@ +/// + +/* 🚧 🚧 🚧 + * This file is auto-generated from the extension's manifest. + * Do not modify manually. Instead, update the `package.json` file. + * 🚧 🚧 🚧 */ + +/* eslint-disable @typescript-eslint/ban-types */ + +type ExtensionPreferences = { + /** Image Input - Where to obtain the image to modify. */ + "inputMethod": "Finder" | "Path Finder" | "Clipboard", + /** Image Output - How to handle the result of the image modification, i.e. where to save the modified image, or whether to copy it to the clipboard. */ + "imageResultHandling": "replaceOriginal" | "saveInContainingFolder" | "copyToClipboard" | "openInPreview" | "saveToDownloads" | "saveToDesktop", + /** cwebp Lossless - Whether to use lossless conversion */ + "cwebpLossless": boolean +} + +/** Preferences accessible in all the extension's commands */ +declare type Preferences = ExtensionPreferences + +declare namespace Preferences { + /** Preferences accessible in the `commander` command */ + export type Commander = ExtensionPreferences & { + /** Name of Command to run - The name of the command/function to run */ + "name"?: string +} + /** Preferences accessible in the `commanderOpenNewFinderWindow` command */ + export type CommanderOpenNewFinderWindow = ExtensionPreferences & { + /** Name of Command to run - The name of the command/function to run */ + "name"?: string +} + /** Preferences accessible in the `commanderTrim` command */ + export type CommanderTrim = ExtensionPreferences & { + /** Name of Command to run - The name of the command/function to run */ + "name"?: string +} + /** Preferences accessible in the `commanderMp4ToMp3` command */ + export type CommanderMp4ToMp3 = ExtensionPreferences & { + /** Name of Command to run - The name of the command/function to run */ + "name"?: string +} + /** Preferences accessible in the `commanderConvert` command */ + export type CommanderConvert = ExtensionPreferences & { + /** Name of Command to run - The name of the command/function to run */ + "name"?: string, + /** Additional - Whether to trim the image */ + "trim": boolean, + /** Enabled Formats - Whether to show WEBP as a conversion option */ + "showWEBP": boolean, + /** - Whether to show ASTC as a conversion option */ + "showASTC": boolean, + /** - Whether to show BMP as a conversion option */ + "showBMP": boolean, + /** - Whether to show DDS as a conversion option */ + "showDDS": boolean, + /** - Whether to show EXR as a conversion option */ + "showEXR": boolean, + /** - Whether to show GIF as a conversion option */ + "showGIF": boolean, + /** - Whether to show HEIC as a conversion option */ + "showHEIC": boolean, + /** - Whether to show HEICS as a conversion option */ + "showHEICS": boolean, + /** - Whether to show ICNS as a conversion option */ + "showICNS": boolean, + /** - Whether to show ICO as a conversion option */ + "showICO": boolean, + /** - Whether to show JPEG as a conversion option */ + "showJPEG": boolean, + /** - Whether to show JP2 as a conversion option */ + "showJP2": boolean, + /** - Whether to show KTX as a conversion option */ + "showKTX": boolean, + /** - Whether to show PBM as a conversion option */ + "showPBM": boolean, + /** - Whether to show PDF as a conversion option */ + "showPDF": boolean, + /** - Whether to show PNG as a conversion option */ + "showPNG": boolean, + /** - Whether to show PSD as a conversion option */ + "showPSD": boolean, + /** - Whether to show PVR as a conversion option */ + "showPVR": boolean, + /** - Whether to show TGA as a conversion option */ + "showTGA": boolean, + /** - Whether to show TIFF as a conversion option */ + "showTIFF": boolean, + /** - Whether to show SVG as a conversion option */ + "showSVG": boolean +} +} + +declare namespace Arguments { + /** Arguments passed to the `commander` command */ + export type Commander = {} + /** Arguments passed to the `commanderOpenNewFinderWindow` command */ + export type CommanderOpenNewFinderWindow = { + /** Path */ + "path": string +} + /** Arguments passed to the `commanderTrim` command */ + export type CommanderTrim = {} + /** Arguments passed to the `commanderMp4ToMp3` command */ + export type CommanderMp4ToMp3 = {} + /** Arguments passed to the `commanderConvert` command */ + export type CommanderConvert = {} +} + diff --git a/raycast/src/commander.tsx b/raycast/src/commander.tsx index a402499..a54a302 100644 --- a/raycast/src/commander.tsx +++ b/raycast/src/commander.tsx @@ -1,4 +1,15 @@ -import { Action, ActionPanel, getPreferenceValues, showToast, Toast, Icon, List, openCommandPreferences, closeMainWindow, showHUD } from "@raycast/api"; +import { + Action, + ActionPanel, + getPreferenceValues, + showToast, + Toast, + Icon, + List, + openCommandPreferences, + closeMainWindow, + showHUD, +} from "@raycast/api"; import any from "./operations/anyOperation"; import { getSelectedFiles, getSelectedImages } from "./utilities/utils"; @@ -11,52 +22,193 @@ import { execSync } from "child_process"; * All supported image formats for conversion. */ -const formats = [ - "MP3", - "MP4", -] +const formats = ["MP3", "MP4"]; -export default async function Command(props: any) { - - const preferences = getPreferenceValues() - - if (preferences.name === 'openNewFinderWindow') { - - openNewFinderWindow(props) - - await showHUD(`🌈 New Finder Window 🦄`) - - return - +const convertFormats = [ + "WEBP", + "WEBPTrimmed", + "ASTC", + "BMP", + "DDS", + "EXR", + "GIF", + "HEIC", + "HEICS", + "ICNS", + "ICO", + "JPEG", + "JP2", + "KTX", + "PBM", + "PDF", + "PNG", + "PSD", + "PVR", + "TGA", + "TIFF", + "SVG", +]; + +export default function Command(props: any) { + const preferences = getPreferenceValues(); + + console.log("nik preferences", preferences); + + console.log("Preference Name", preferences.name); + + if (preferences.name === "trim") { + (async () => { + const selectedFiles = await getSelectedFiles(); + + const selectedImages = await getSelectedImages(); + + await runOperation({ + operation: () => any(selectedFiles, "Trim"), + selectedImages: selectedImages, + inProgressMessage: "Trimming in progress...", + successMessage: "Trimmed", + failureMessage: "Failed to trim", + }); + + await showHUD(`🌈 Trim 🦄`); + })(); + + return; + } + + if (preferences.name === "openNewFinderWindow") { + openNewFinderWindow(props); + + (async () => { + await showHUD(`🌈 New Finder Window 🦄`); + })(); + + return; } // log preferences - console.log(preferences) - - if (Object.hasOwnProperty.call(preferences, 'mp4ToMp3')) { - - console.log('here !') - - const selectedFiles = await getSelectedFiles(); + // console.log(preferences); - await runOperation({ - operation: () => any(selectedFiles, 'MP3'), - selectedImages: selectedFiles, - inProgressMessage: "Conversion in progress...", - successMessage: "Converted", - failureMessage: "Failed to convert", - }); - - await showHUD(`🌈 MP4 to MP3 🦄`) - - return - + if (Object.hasOwnProperty.call(preferences, "mp4ToMp3")) { + console.log("here !"); + + (async () => { + const selectedFiles = await getSelectedFiles(); + + await runOperation({ + operation: () => any(selectedFiles, "MP3"), + selectedImages: selectedFiles, + inProgressMessage: "Conversion in progress...", + successMessage: "Converted", + failureMessage: "Failed to convert", + }); + + await showHUD(`🌈 MP4 to MP3 🦄`); + })(); + + return; } - + + console.log("nik hey?"); + + if (preferences.name === "mp4ToMp3") { + return ( + + + await openCommandPreferences()} + shortcut={{ modifiers: ["cmd", "shift"], key: "," }} + /> + + } + /> + {formats.map((format) => { + return ( + + { + const selectedFiles = await getSelectedFiles(); + await runOperation({ + operation: () => any(selectedFiles, format), + selectedImages: selectedFiles, + inProgressMessage: "Conversion in progress...", + successMessage: "Converted", + failureMessage: "Failed to convert", + }); + }} + /> + + } + /> + ); + })} + + ); + } + + if (preferences.name === "convert") { + return ( + + + await openCommandPreferences()} + shortcut={{ modifiers: ["cmd", "shift"], key: "," }} + /> + + } + /> + {convertFormats.map((format) => { + return ( + + { + const selectedFiles = await getSelectedFiles(); + await runOperation({ + operation: () => any(selectedFiles, format), + selectedImages: selectedFiles, + inProgressMessage: "Conversion in progress...", + successMessage: "Converted", + failureMessage: "Failed to convert", + }); + }} + /> + + } + /> + ); + })} + + ); + } + + console.log("shouldn't be here..."); + return ( - + @@ -68,31 +220,6 @@ export default async function Command(props: any) { } /> - {formats.map((format) => { - return ( - - { - const selectedFiles = await getSelectedFiles(); - await runOperation({ - operation: () => any(selectedFiles, format), - selectedImages: selectedFiles, - inProgressMessage: "Conversion in progress...", - successMessage: "Converted", - failureMessage: "Failed to convert", - }); - }} - /> - - } - /> - ); - })} ); } diff --git a/raycast/src/commanderConvert.tsx b/raycast/src/commanderConvert.tsx new file mode 120000 index 0000000..85dbfb1 --- /dev/null +++ b/raycast/src/commanderConvert.tsx @@ -0,0 +1 @@ +commander.tsx \ No newline at end of file diff --git a/raycast/src/commanderTrim.tsx b/raycast/src/commanderTrim.tsx new file mode 120000 index 0000000..85dbfb1 --- /dev/null +++ b/raycast/src/commanderTrim.tsx @@ -0,0 +1 @@ +commander.tsx \ No newline at end of file diff --git a/raycast/src/convert.tsx b/raycast/src/convert.tsx index 3376372..1f61b21 100644 --- a/raycast/src/convert.tsx +++ b/raycast/src/convert.tsx @@ -38,7 +38,6 @@ const FORMATS = [ "PVR", "TGA", "TIFF", - "WEBP", "SVG", ]; @@ -46,6 +45,8 @@ export default function Command() { const preferences = getPreferenceValues(); const enabledFormats = FORMATS.filter((format) => preferences[`show${format}`]); + console.log("nik here????"); + return ( (); + const convertPreferences = getPreferenceValues(); + + trim = trim || convertPreferences?.trim || desiredType?.includes("Trimmed"); + const resultPaths = []; for (const item of sourcePaths) { + const extension = desiredType.toLowerCase()?.replace("trimmed", ""); + const pathComponents = item.split("."); - let newPath = pathComponents.slice(0, -1).join("") + "." + desiredType.toLowerCase(); + let newPath = pathComponents.slice(0, -1).join(""); if (preferences.imageResultHandling == ImageResultHandling.SaveToDownloads) { newPath = path.join(os.homedir(), "Downloads", path.basename(newPath)); @@ -52,9 +58,26 @@ export default async function any(sourcePaths: string[], desiredType: string) { ); iter++; } - - console.log('nik desiredType', desiredType) - + + console.log("nik trim", trim); + + console.log("nik desiredType", desiredType); + + if (desiredType?.includes("Trimmed")) { + desiredType = desiredType?.replace("Trimmed", ""); + } + + console.log("nik desiredType", desiredType); + + const trimmedPath = `${newPath}.${extension}`; + if (trim) { + newPath = `${newPath}.tmp.${extension}`; + } else { + newPath = `${newPath}.${extension}`; + } + + console.log("nik desiredType", desiredType); + if (desiredType === "MP3") { // const platform = os.arch() === "arm64" ? "/arm" : "/x86"; // execSync(`chmod +x ${environment.assetsPath}/webp${platform}/cwebp`); @@ -62,13 +85,32 @@ export default async function any(sourcePaths: string[], desiredType: string) { // use ${item} as input.mp4 and ${newPath} as output.mp3 execSync(`ffmpeg -i "${item}" -vn -ar 44100 -ac 2 -ab 320k -f mp3 "${newPath}"`); // resultPaths.push(newPath); - + } else if (desiredType === "Trim") { + // using convert -trim ${item} ${newPath} + execSync(`convert -trim "${item}" "${newPath}"`); } else if (desiredType === "WEBP") { // Input Format -> WebP // detect platform is arm or x86 const platform = os.arch() === "arm64" ? "/arm" : "/x86"; execSync(`chmod +x ${environment.assetsPath}/webp${platform}/cwebp`); - execSync(`${environment.assetsPath}/webp${platform}/cwebp ${preferences?.cwebpLossless ? '-lossless' : ''} "${item}" -o "${newPath}"`); + execSync( + `${environment.assetsPath}/webp${platform}/cwebp ${ + preferences?.cwebpLossless ? "-lossless" : "" + } "${item}" -o "${newPath}"` + ); + + console.log("nik trim", trim); + + if (trim) { + // const trimmedPath = + // execSync(`echo $(which convert) >> /tmp/convert.txt`); + // execSync(`convert -trim "${newPath}" "${trimmedPath}"`); + // /opt/homebrew/bin/convert + execSync(`/opt/homebrew/bin/convert -trim "${newPath}" "${trimmedPath}"`); + + // remove the tmp file + fs.unlinkSync(newPath); + } } else if (pathComponents.at(-1)?.toLowerCase() == "svg") { // SVG -> NSBitmapImageRep -> Desired Format convertSVG(desiredType, item, newPath); diff --git a/raycast/src/utilities/preferences.ts b/raycast/src/utilities/preferences.ts index 6240a6d..0ed149e 100644 --- a/raycast/src/utilities/preferences.ts +++ b/raycast/src/utilities/preferences.ts @@ -20,7 +20,7 @@ export interface ExtensionPreferences { * The strategy for handling the result of the image processing, i.e. where to save or display the result. One of {@link ImageResultHandling}. */ imageResultHandling: string; - + /** * Whether to use lossless conversions with cwebp */ @@ -31,6 +31,7 @@ export interface ExtensionPreferences { * Preferences for the convert command. Specifies which image formats to show in the conversion formats list. */ export interface ConvertPreferences { + trim: boolean; showASTC: boolean; showBMP: boolean; showDDS: boolean;