Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/main/services/streamdeck/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ async function discardVerdict(clip: Clip): Promise<ReturnType<typeof discardable
* "Kept" after a five second hold was the first time somebody learned the
* newest clip was protected, which is the wrong moment. So the key shows the
* clip itself, its own thumbnail, and whether it would be kept, and the press
* only confirms what is already on the key. The picture is 144 pixels tall,
* only confirms what is already on the key. The picture is 144 pixels square,
* which is the key's own height at 2x; the cached thumbnail is 1280 wide.
*/
export async function latestPreview(): Promise<KeyResult> {
Expand All @@ -242,7 +242,21 @@ export async function latestPreview(): Promise<KeyResult> {
const file = await videoService.ensureThumbnail(clip);
const image = nativeImage.createFromPath(file);
if (!image.isEmpty()) {
thumbnail = `data:image/jpeg;base64,${image.resize({ height: 144 }).toJPEG(80).toString('base64')}`;
/*
* Cropped square here, not in the key's SVG. The Stream Deck app draws
* SVG with a renderer that ignores `preserveAspectRatio="... slice"`, so
* a 21:9 frame handed to it was squashed into the square key rather than
* covering it. The middle of the frame is where the action is.
*/
const { width, height } = image.getSize();
const side = Math.min(width, height);
const square = image.crop({
x: Math.floor((width - side) / 2),
y: Math.floor((height - side) / 2),
width: side,
height: side,
});
thumbnail = `data:image/jpeg;base64,${square.resize({ width: 144, height: 144 }).toJPEG(82).toString('base64')}`;
}
} catch {
// No picture is a key with a plain face, not a failed key.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://schemas.elgato.com/streamdeck/plugins/manifest.json",
"UUID": "io.github.darrellvs.goodbit",
"Name": "GoodBit",
"Version": "0.4.1.0",
"Version": "0.4.2.0",
"Author": "GoodBit",
"Description": "Save the replay, then tag, publish or discard the clip you just saved, and see today's count, without leaving the game. Needs GoodBit running with the Stream Deck connection switched on in Settings, Connections.",
"URL": "https://darrellvs.github.io/goodbit/",
Expand Down
6 changes: 4 additions & 2 deletions streamdeck-plugin/src/actions/discard-latest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ export class DiscardLatest extends SingletonAction {
/**
* The key's face as an SVG data URL, or '' for the plain icon from the manifest.
*
* 144 square. The thumbnail fills it at nearly full brightness, because the
* 144 square. The thumbnail arrives already cropped square by GoodBit (the
* Stream Deck's SVG renderer ignores `slice` and would squash a wide frame),
* and fills the key at nearly full brightness, because the
* picture is the point of the key: darkening the whole frame so the mark read
* made the clip itself unreadable on the LCD. The mark sits on a small dark
* disc of its own instead, trash in the danger colour, or a lock in the light
Expand All @@ -131,7 +133,7 @@ function face(preview: Preview): string {
const colour = kept ? '#f2efea' : '#d45757';
const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="144" height="144" viewBox="0 0 144 144">
<rect width="144" height="144" fill="#121110"/>
<image x="0" y="0" width="144" height="144" preserveAspectRatio="xMidYMid slice" xlink:href="${preview.thumbnail}"/>
<image x="0" y="0" width="144" height="144" xlink:href="${preview.thumbnail}"/>
<rect width="144" height="144" fill="#121110" opacity="${kept ? 0.3 : 0.08}"/>
<circle cx="72" cy="72" r="30" fill="#121110" opacity="0.72"/>
<g transform="translate(50 50) scale(0.171875)" fill="${colour}">${glyph}</g>
Expand Down
Loading