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",
"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",

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 { 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 convertFormats = [
"WEBP",
"WEBPTrimmed",
"ASTC",
"BMP",
"DDS",
"EXR",
"GIF",
"HEIC",
"HEICS",
"ICNS",
"ICO",
"JPEG",
"JP2",
"KTX",
"PBM",
"PDF",
"PNG",
"PSD",
"PVR",
"TGA",
"TIFF",
"SVG",
];
const preferences = getPreferenceValues()
export default function Command(props: any) {
const preferences = getPreferenceValues();
if (preferences.name === 'openNewFinderWindow') {
console.log("nik preferences", preferences);
openNewFinderWindow(props)
console.log("Preference Name", preferences.name);
await showHUD(`🌈 New Finder Window 🦄`)
if (preferences.name === "trim") {
(async () => {
const selectedFiles = await getSelectedFiles();
return
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)
// console.log(preferences);
if (Object.hasOwnProperty.call(preferences, 'mp4ToMp3')) {
if (Object.hasOwnProperty.call(preferences, "mp4ToMp3")) {
console.log("here !");
console.log('here !')
(async () => {
const selectedFiles = await getSelectedFiles();
const selectedFiles = await getSelectedFiles();
await runOperation({
operation: () => any(selectedFiles, "MP3"),
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
successMessage: "Converted",
failureMessage: "Failed to convert",
});
await runOperation({
operation: () => any(selectedFiles, 'MP3'),
selectedImages: selectedFiles,
inProgressMessage: "Conversion in progress...",
successMessage: "Converted",
failureMessage: "Failed to convert",
});
await showHUD(`🌈 MP4 to MP3 🦄`)
return
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 (
<List searchBarPlaceholder="Search image transformations...">
<List searchBarPlaceholder="Search commands...">
<List.EmptyView
title="No Formats Enabled"
description="Enable formats in the command preferences (⌘⇧,)"
title="No Commands"
description="Configure commands in preferences"
icon={Icon.Image}
actions={
<ActionPanel>
@ -68,31 +220,6 @@ export default async function Command(props: any) {
</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>
);
}

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@ import path from "path";
import { environment, getPreferenceValues } from "@raycast/api";
import { convertPDF, convertSVG, moveImageResultsToFinalDestination } from "../utilities/utils";
import { ExtensionPreferences } from "../utilities/preferences";
import { ConvertPreferences, ExtensionPreferences } from "../utilities/preferences";
import { ImageResultHandling } from "../utilities/enums";
/**
@ -25,13 +25,19 @@ import { ImageResultHandling } from "../utilities/enums";
* @param desiredType The desired format to convert the images to.
* @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 convertPreferences = getPreferenceValues<ConvertPreferences & ExtensionPreferences>();
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));
@ -53,7 +59,24 @@ 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";
@ -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);

View File

@ -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;