Skip to content

Commit

Permalink
Check for unsupported app version if initialization fails.
Browse files Browse the repository at this point in the history
  • Loading branch information
renfeisong committed Oct 11, 2024
1 parent d6b887c commit 89b1be0
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 15 deletions.
64 changes: 62 additions & 2 deletions extensions/snippetslab/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 36 additions & 9 deletions extensions/snippetslab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,22 @@
"title": "Snippet Action: Primary",
"description": "The first Snippet action shown in the action menu.",
"data": [
{"title": "Show Snippet Details", "value": "push"},
{"title": "Copy to Clipboard", "value": "copy"},
{"title": "Open in SnippetsLab", "value": "open"},
{"title": "Paste to Active App", "value": "paste"}
{
"title": "Show Snippet Details",
"value": "push"
},
{
"title": "Copy to Clipboard",
"value": "copy"
},
{
"title": "Open in SnippetsLab",
"value": "open"
},
{
"title": "Paste to Active App",
"value": "paste"
}
],
"default": "push",
"required": false
Expand All @@ -81,10 +93,22 @@
"title": "Snippet Action: Secondary",
"description": "The second Snippet action shown in the action menu.",
"data": [
{"title": "Show Snippet Details", "value": "push"},
{"title": "Copy to Clipboard", "value": "copy"},
{"title": "Open in SnippetsLab", "value": "open"},
{"title": "Paste to Active App", "value": "paste"}
{
"title": "Show Snippet Details",
"value": "push"
},
{
"title": "Copy to Clipboard",
"value": "copy"
},
{
"title": "Open in SnippetsLab",
"value": "open"
},
{
"title": "Paste to Active App",
"value": "paste"
}
],
"default": "copy",
"required": false
Expand All @@ -101,11 +125,14 @@
"dependencies": {
"@raycast/api": "^1.79.1",
"execa": "^9.3.0",
"p-queue": "^8.0.1"
"p-queue": "^8.0.1",
"plist": "^3.1.0",
"semver": "^7.6.3"
},
"devDependencies": {
"@raycast/eslint-config": "^1.0.8",
"@types/node": "20.8.10",
"@types/plist": "^3.0.5",
"@types/react": "18.3.3",
"eslint": "^8.57.0",
"prettier": "^3.2.5",
Expand Down
16 changes: 14 additions & 2 deletions extensions/snippetslab/src/components/init_error.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { Action, ActionPanel, Detail, Icon } from "@raycast/api";
import semver from "semver";

/** The minimum SnippetsLab app version. Must be valid semver. */
const MIN_APP_VERSION = "2.5.0";

interface InitErrorProps {
error: Error;
appVersion?: string;
}

/** Error screen for when the command utility cannot be found or used. */
export function InitError({ error }: InitErrorProps) {
export function InitError({ error, appVersion }: InitErrorProps) {
const version = semver.coerce(appVersion);
const isUnsupportedAppVersion = version && semver.lt(version, MIN_APP_VERSION);
const unsupportedMessage = `It looks like you are using SnippetsLab ${appVersion}, but
version **${MIN_APP_VERSION} or later** is required.`;

const markdown = `
# An error occurred
Expand All @@ -14,11 +24,13 @@ permissions.
**Details**
${isUnsupportedAppVersion ? unsupportedMessage : ""}
${error.message}
**Troubleshooting Tips**
1. Ensure that **SnippetsLab 2.5 or later** is installed.
1. Ensure that **SnippetsLab ${MIN_APP_VERSION} or later** is installed.
2. The extension should typically locate the \`lab\` utility bundled with the app automatically.
You can also manually specify the path in extension preferences.
3. If using a custom path, it must be an absolute path pointing directly to the \`lab\` binary.
Expand Down
9 changes: 9 additions & 0 deletions extensions/snippetslab/src/hooks/useSnippetsLab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { execa } from "execa";
import fs from "fs";
import PQueue from "p-queue";
import path from "path";
import plist from "plist";
import { useEffect, useState } from "react";
import { getPreferences } from "../models/preferences";

const BUNDLE_ID_APP_STORE = "com.renfei.SnippetsLab";
const BUNDLE_ID_SETAPP = "com.renfei.snippetslab-setapp";
const CLI_RELPATH = "Contents/Helpers/lab";
const INFO_PLIST_RELPATH = "Contents/Info.plist";

/**
* A serial queue for all operations using the command-line utility.
Expand Down Expand Up @@ -43,6 +45,7 @@ export function useSnippetsLab() {
const [isInitializing, setInitializing] = useState<boolean>(true);
const [initializationError, setInitializationError] = useState<Error>();
const [resolvedCliPath, setResolvedCliPath] = useState<string>();
const [appVersion, setAppVersion] = useState<string>();

useEffect(() => {
const checkCli = async () => {
Expand Down Expand Up @@ -77,6 +80,11 @@ export function useSnippetsLab() {
throw new Error("SnippetsLab.app not found. Is it installed?");
}

const infoPlistPath = path.join(app.path, INFO_PLIST_RELPATH);
const infoPlistContents = fs.readFileSync(infoPlistPath, "utf8");
const infoDictionary = plist.parse(infoPlistContents) as Readonly<plist.PlistObject>;
setAppVersion(infoDictionary.CFBundleShortVersionString as string);

return path.join(app.path, CLI_RELPATH);
};

Expand Down Expand Up @@ -133,6 +141,7 @@ export function useSnippetsLab() {
return {
isInitializing,
initializationError,
appVersion, // undefined when using a custom CLI path in preferences.
app: { run, open },
};
}
4 changes: 2 additions & 2 deletions extensions/snippetslab/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { SnippetsSearch } from "./search";

/** Entry point for the Search in SnippetsLab command. */
export default function Command({ fallbackText }: LaunchProps) {
const { isInitializing, initializationError, app } = useSnippetsLab();
const { isInitializing, initializationError, appVersion, app } = useSnippetsLab();

if (isInitializing) {
return <List isLoading />;
} else if (initializationError) {
return <InitError error={initializationError} />;
return <InitError error={initializationError} appVersion={appVersion} />;
} else {
return <SnippetsSearch app={app} searchText={fallbackText} />;
}
Expand Down

0 comments on commit 89b1be0

Please sign in to comment.