Fixed multiple image trim's not working 🙏 main

This commit is contained in:
Nikolaj Frey 2024-04-03 16:36:11 +11:00
parent 29a7a0feb2
commit d2bfd8f991
8 changed files with 401 additions and 78 deletions

View File

@ -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", "name": "commanderMp4ToMp3",
"title": "mp4 to mp3", "title": "mp4 to mp3",
@ -156,7 +179,7 @@
], ],
"preferences": [ "preferences": [
{ {
"name": "mp4ToMp3", "name": "name",
"required": false, "required": false,
"type": "textfield", "type": "textfield",
"key": "name", "key": "name",
@ -167,12 +190,31 @@
] ]
}, },
{ {
"name": "convert", "name": "commanderConvert",
"title": "Convert Images", "title": "Convert Images",
"description": "Convert the selected images to the specified format", "description": "Convert the selected images to the specified format",
"mode": "view", "mode": "view",
"preferences": [ "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", "label": "WEBP",
"name": "showWEBP", "name": "showWEBP",
"description": "Whether to show WEBP as a conversion option", "description": "Whether to show WEBP as a conversion option",
@ -181,7 +223,6 @@
"required": false "required": false
}, },
{ {
"title": "Enabled Formats",
"label": "ASTC", "label": "ASTC",
"name": "showASTC", "name": "showASTC",
"description": "Whether to show ASTC as a conversion option", "description": "Whether to show ASTC as a conversion option",

109
raycast/raycast-env.d.ts vendored Normal file
View File

@ -0,0 +1,109 @@
/// <reference types="@raycast/api">
/* 🚧 🚧 🚧
* 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 = {}
}

View File

@ -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 any from "./operations/anyOperation";
import { getSelectedFiles, getSelectedImages } from "./utilities/utils"; import { getSelectedFiles, getSelectedImages } from "./utilities/utils";
@ -11,52 +22,193 @@ import { execSync } from "child_process";
* All supported image formats for conversion. * All supported image formats for conversion.
*/ */
const formats = [ const formats = ["MP3", "MP4"];
"MP3",
"MP4",
]
export default async function Command(props: any) { const convertFormats = [
"WEBP",
const preferences = getPreferenceValues() "WEBPTrimmed",
"ASTC",
if (preferences.name === 'openNewFinderWindow') { "BMP",
"DDS",
openNewFinderWindow(props) "EXR",
"GIF",
await showHUD(`🌈 New Finder Window 🦄`) "HEIC",
"HEICS",
return "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 // log preferences
console.log(preferences) // console.log(preferences);
if (Object.hasOwnProperty.call(preferences, 'mp4ToMp3')) {
console.log('here !')
const selectedFiles = await getSelectedFiles();
await runOperation({ if (Object.hasOwnProperty.call(preferences, "mp4ToMp3")) {
operation: () => any(selectedFiles, 'MP3'), console.log("here !");
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...", (async () => {
successMessage: "Converted", const selectedFiles = await getSelectedFiles();
failureMessage: "Failed to convert",
}); await runOperation({
operation: () => any(selectedFiles, "MP3"),
await showHUD(`🌈 MP4 to MP3 🦄`) selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
return successMessage: "Converted",
failureMessage: "Failed to convert",
});
await showHUD(`🌈 MP4 to MP3 🦄`);
})();
return;
} }
console.log("nik hey?");
if (preferences.name === "mp4ToMp3") {
return (
<List searchBarPlaceholder="Search video transformations...">
<List.EmptyView
title="No Formats Enabled"
description="Enable formats in the command preferences (⌘⇧,)"
icon={Icon.Image}
actions={
<ActionPanel>
<Action
title="Open Command Preferences"
onAction={async () => await openCommandPreferences()}
shortcut={{ modifiers: ["cmd", "shift"], key: "," }}
/>
</ActionPanel>
}
/>
{formats.map((format) => {
return (
<List.Item
title={format}
key={format}
actions={
<ActionPanel>
<Action
title={`Convert to ${format}`}
onAction={async () => {
const selectedFiles = await getSelectedFiles();
await runOperation({
operation: () => any(selectedFiles, format),
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
successMessage: "Converted",
failureMessage: "Failed to convert",
});
}}
/>
</ActionPanel>
}
/>
);
})}
</List>
);
}
if (preferences.name === "convert") {
return (
<List searchBarPlaceholder="Search image transformations...">
<List.EmptyView
title="No Formats Enabled"
description="Enable formats in the command preferences (⌘⇧,)"
icon={Icon.Image}
actions={
<ActionPanel>
<Action
title="Open Command Preferences"
onAction={async () => await openCommandPreferences()}
shortcut={{ modifiers: ["cmd", "shift"], key: "," }}
/>
</ActionPanel>
}
/>
{convertFormats.map((format) => {
return (
<List.Item
title={format}
key={format}
actions={
<ActionPanel>
<Action
title={`Convert to ${format}`}
onAction={async () => {
const selectedFiles = await getSelectedFiles();
await runOperation({
operation: () => any(selectedFiles, format),
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
successMessage: "Converted",
failureMessage: "Failed to convert",
});
}}
/>
</ActionPanel>
}
/>
);
})}
</List>
);
}
console.log("shouldn't be here...");
return ( return (
<List searchBarPlaceholder="Search image transformations..."> <List searchBarPlaceholder="Search commands...">
<List.EmptyView <List.EmptyView
title="No Formats Enabled" title="No Commands"
description="Enable formats in the command preferences (⌘⇧,)" description="Configure commands in preferences"
icon={Icon.Image} icon={Icon.Image}
actions={ actions={
<ActionPanel> <ActionPanel>
@ -68,31 +220,6 @@ export default async function Command(props: any) {
</ActionPanel> </ActionPanel>
} }
/> />
{formats.map((format) => {
return (
<List.Item
title={format}
key={format}
actions={
<ActionPanel>
<Action
title={`Convert to ${format}`}
onAction={async () => {
const selectedFiles = await getSelectedFiles();
await runOperation({
operation: () => any(selectedFiles, format),
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
successMessage: "Converted",
failureMessage: "Failed to convert",
});
}}
/>
</ActionPanel>
}
/>
);
})}
</List> </List>
); );
} }

View File

@ -0,0 +1 @@
commander.tsx

View File

@ -0,0 +1 @@
commander.tsx

View File

@ -38,7 +38,6 @@ const FORMATS = [
"PVR", "PVR",
"TGA", "TGA",
"TIFF", "TIFF",
"WEBP",
"SVG", "SVG",
]; ];
@ -46,6 +45,8 @@ export default function Command() {
const preferences = getPreferenceValues<ConvertPreferences & ExtensionPreferences>(); const preferences = getPreferenceValues<ConvertPreferences & ExtensionPreferences>();
const enabledFormats = FORMATS.filter((format) => preferences[`show${format}`]); const enabledFormats = FORMATS.filter((format) => preferences[`show${format}`]);
console.log("nik here????");
return ( return (
<List searchBarPlaceholder="Search image transformations..."> <List searchBarPlaceholder="Search image transformations...">
<List.EmptyView <List.EmptyView

View File

@ -15,7 +15,7 @@ import path from "path";
import { environment, getPreferenceValues } from "@raycast/api"; import { environment, getPreferenceValues } from "@raycast/api";
import { convertPDF, convertSVG, moveImageResultsToFinalDestination } from "../utilities/utils"; import { convertPDF, convertSVG, moveImageResultsToFinalDestination } from "../utilities/utils";
import { ExtensionPreferences } from "../utilities/preferences"; import { ConvertPreferences, ExtensionPreferences } from "../utilities/preferences";
import { ImageResultHandling } from "../utilities/enums"; import { ImageResultHandling } from "../utilities/enums";
/** /**
@ -25,13 +25,19 @@ import { ImageResultHandling } from "../utilities/enums";
* @param desiredType The desired format to convert the images to. * @param desiredType The desired format to convert the images to.
* @returns A promise that resolves when the operation is complete. * @returns A promise that resolves when the operation is complete.
*/ */
export default async function any(sourcePaths: string[], desiredType: string) { export default async function any(sourcePaths: string[], desiredType: string, trim?: boolean) {
const preferences = getPreferenceValues<ExtensionPreferences>(); const preferences = getPreferenceValues<ExtensionPreferences>();
const convertPreferences = getPreferenceValues<ConvertPreferences & ExtensionPreferences>();
trim = trim || convertPreferences?.trim || desiredType?.includes("Trimmed");
const resultPaths = []; const resultPaths = [];
for (const item of sourcePaths) { for (const item of sourcePaths) {
const extension = desiredType.toLowerCase()?.replace("trimmed", "");
const pathComponents = item.split("."); 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) { if (preferences.imageResultHandling == ImageResultHandling.SaveToDownloads) {
newPath = path.join(os.homedir(), "Downloads", path.basename(newPath)); newPath = path.join(os.homedir(), "Downloads", path.basename(newPath));
@ -52,9 +58,26 @@ export default async function any(sourcePaths: string[], desiredType: string) {
); );
iter++; 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") { if (desiredType === "MP3") {
// const platform = os.arch() === "arm64" ? "/arm" : "/x86"; // const platform = os.arch() === "arm64" ? "/arm" : "/x86";
// execSync(`chmod +x ${environment.assetsPath}/webp${platform}/cwebp`); // 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 // use ${item} as input.mp4 and ${newPath} as output.mp3
execSync(`ffmpeg -i "${item}" -vn -ar 44100 -ac 2 -ab 320k -f mp3 "${newPath}"`); execSync(`ffmpeg -i "${item}" -vn -ar 44100 -ac 2 -ab 320k -f mp3 "${newPath}"`);
// resultPaths.push(newPath); // resultPaths.push(newPath);
} else if (desiredType === "Trim") {
// using convert -trim ${item} ${newPath}
execSync(`convert -trim "${item}" "${newPath}"`);
} else if (desiredType === "WEBP") { } else if (desiredType === "WEBP") {
// Input Format -> WebP // Input Format -> WebP
// detect platform is arm or x86 // detect platform is arm or x86
const platform = os.arch() === "arm64" ? "/arm" : "/x86"; const platform = os.arch() === "arm64" ? "/arm" : "/x86";
execSync(`chmod +x ${environment.assetsPath}/webp${platform}/cwebp`); 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") { } else if (pathComponents.at(-1)?.toLowerCase() == "svg") {
// SVG -> NSBitmapImageRep -> Desired Format // SVG -> NSBitmapImageRep -> Desired Format
convertSVG(desiredType, item, newPath); convertSVG(desiredType, item, newPath);

View File

@ -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}. * 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; imageResultHandling: string;
/** /**
* Whether to use lossless conversions with cwebp * 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. * Preferences for the convert command. Specifies which image formats to show in the conversion formats list.
*/ */
export interface ConvertPreferences { export interface ConvertPreferences {
trim: boolean;
showASTC: boolean; showASTC: boolean;
showBMP: boolean; showBMP: boolean;
showDDS: boolean; showDDS: boolean;