Skip to content

Commit

Permalink
Merge pull request #33 from timrogers/timrogers/toggle
Browse files Browse the repository at this point in the history
feat: replace "Turn On" and "Turn Off" actions with "Toggle" action
  • Loading branch information
timrogers authored Mar 28, 2023
2 parents 9bde932 + 75ed52f commit 4b52d92
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 21 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Logitech Litra Changelog

## [Toggle your Litra, rather than turning it on or off] - 2023-03-28

- Instead of separate, painful-to-use "On" and "Off" actions, we now have a simple "Toggle" action. You'll need to update to the latest version of the `litra` npm package.

## [Brightness and temperature support] - 2023-03-04

- Add support for setting the brightness and temperature of your Litra devices - thanks to [@zalewskigrzegorz](https://github.com/zalewskigrzegorz) for the [suggestion](https://github.com/raycast/extensions/issues/5101)!
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ This [Raycast](https://www.raycast.com/) extension allows you to manage your Log

## Installation

To use this extension, as well as downloading the extension from the Raycast Store, you must also set up [Node.js](https://nodejs.org/en/) and [`npm`](https://www.npmjs.com/), and then install the `litra` npm package globally by running `npm install -g litra`.
To use this extension, as well as downloading the extension from the Raycast Store, you must also set up [Node.js](https://nodejs.org/en/) and [`npm`](https://www.npmjs.com/), and then install the `litra` npm package globally by running `npm install -g litra`. You must be running at least v4.4.0 of the package.

When you run the extension for the first time, you'll be prompted to provide the directory where the `litra` package's CLI is installed. You can get this by running `dirname $(which litra-on)` from a terminal.
3 changes: 2 additions & 1 deletion package-lock.json

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

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
}
],
"dependencies": {
"@raycast/api": "^1.48.9"
"@raycast/api": "^1.48.9",
"semver": "^7.3.8"
},
"devDependencies": {
"@types/node": "18.15.10",
Expand Down
26 changes: 12 additions & 14 deletions src/manage-devices.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ActionPanel, Action, Icon, List, showToast, Toast } from "@raycast/api";
import React, { useEffect, useState } from "react";
import { getCliDirectory } from "./preferences";
import { getDevices, turnOff, turnOn, setTemperatureInKelvin, setBrightnessPercentage } from "./utils";
import { getDevices, toggle, isOn, setTemperatureInKelvin, setBrightnessPercentage, checkLitraVersion } from "./utils";
import { getEnabledTemperaturePresets } from "./temperature-presets";
import { getEnabledBrightnessPresets } from "./brightness-presets";

Expand All @@ -19,6 +19,8 @@ export default function Command() {

useEffect(() => {
(async () => {
await checkLitraVersion(cliDirectory);

const devices = await getDevices(cliDirectory);
setDevices(devices);
})();
Expand All @@ -38,8 +40,6 @@ export default function Command() {
})();
}, []);

console.log({ enabledTemperaturePresets, enabledBrightnessPresets });

return (
<List isLoading={false}>
{devices.map((device) => (
Expand All @@ -50,19 +50,17 @@ export default function Command() {
actions={
<ActionPanel>
<Action
title="Turn On"
title="Toggle"
icon={Icon.LightBulb}
onAction={async () => {
await turnOn(cliDirectory, device.serial_number);
await showToast({ title: `Turned on ${device.name}`, style: Toast.Style.Success });
}}
/>
<Action
title="Turn Off"
icon={Icon.LightBulbOff}
onAction={async () => {
await turnOff(cliDirectory, device.serial_number);
await showToast({ title: `Turned off ${device.name}`, style: Toast.Style.Success });
await toggle(cliDirectory, device.serial_number);
const isDeviceOn = await isOn(cliDirectory, device.serial_number);

if (isDeviceOn) {
await showToast({ title: `Turned on ${device.name}`, style: Toast.Style.Success });
} else {
await showToast({ title: `Turned off ${device.name}`, style: Toast.Style.Success });
}
}}
/>
{Array.from(enabledTemperaturePresets).map((temperature) => (
Expand Down
42 changes: 38 additions & 4 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,45 @@ import fs from "fs";
import path from "path";
import { promisify } from "util";
import { exec as defaultExec } from "child_process";
import gte from "semver/functions/gte";
import parse from "semver/functions/parse";
const exec = promisify(defaultExec);

interface Device {
name: string;
serial_number: string;
is_on: boolean;
}

const MINIMUM_SUPPORTED_LITRA_VERSION = "4.4.0";

export const checkLitraVersion = async (cliDirectory: string): Promise<void> => {
const version = await getLitraVersion(cliDirectory);

if (gte(version, MINIMUM_SUPPORTED_LITRA_VERSION)) {
if (parse(version)?.major != parse(MINIMUM_SUPPORTED_LITRA_VERSION)?.major) {
throw `You are running v${version} of the \`litra\` package which is too new for this Raycast extension. Please downgrade to v${MINIMUM_SUPPORTED_LITRA_VERSION} or a later version within the same major version by running \`npm install -g litra@${MINIMUM_SUPPORTED_LITRA_VERSION}\`.`;
}
} else {
throw `You are running an old version of the \`litra\` package, v${version}. You must be running v${MINIMUM_SUPPORTED_LITRA_VERSION} or a later version within the same major version. Please update by running \`npm install -g litra@${MINIMUM_SUPPORTED_LITRA_VERSION}\`.`;
}
};

const getLitraVersion = async (cliDirectory: string): Promise<string> => {
const binPath = path.join(cliDirectory, "litra-devices");

try {
const { stdout: version } = await runLitraCommand(cliDirectory, "litra-devices", "--version");
return version.trim();
} catch (error: any) {
if (error.stderr.includes("unknown option")) {
throw `You seem to be running an old version of the \`litra\` package. You must be running at least v${MINIMUM_SUPPORTED_LITRA_VERSION}. Please update by running \`npm install -g litra@${MINIMUM_SUPPORTED_LITRA_VERSION}\`.`;
} else {
throw error;
}
}
};

const runLitraCommand = (
directory: string,
filename: string,
Expand All @@ -31,12 +63,14 @@ export const getDevices = async (cliDirectory: string): Promise<Device[]> => {
return JSON.parse(stdout) as Device[];
};

export const turnOn = async (cliDirectory: string, serialNumber: string): Promise<void> => {
await runLitraCommand(cliDirectory, "litra-on", `--serial-number ${serialNumber}`);
export const isOn = async (cliDirectory: string, serialNumber: string): Promise<boolean> => {
const devices = await getDevices(cliDirectory);
const device = devices.find((device) => device.serial_number === serialNumber) as Device;
return device.is_on;
};

export const turnOff = async (cliDirectory: string, serialNumber: string): Promise<void> => {
await runLitraCommand(cliDirectory, "litra-off", `--serial-number ${serialNumber}`);
export const toggle = async (cliDirectory: string, serialNumber: string): Promise<void> => {
await runLitraCommand(cliDirectory, "litra-toggle", `--serial-number ${serialNumber}`);
};

export const setTemperatureInKelvin = async (
Expand Down

0 comments on commit 4b52d92

Please sign in to comment.