Skip to content

Add Xtream Deck desklet - #1902

Open
sentinela-one wants to merge 5 commits into
linuxmint:masterfrom
sentinela-one:add-xtream-desklet-deck
Open

Add Xtream Deck desklet#1902
sentinela-one wants to merge 5 commits into
linuxmint:masterfrom
sentinela-one:add-xtream-desklet-deck

Conversation

@sentinela-one

Copy link
Copy Markdown

Summary

Adds Xtream Deck, a Stream Deck-style button grid desklet for Cinnamon: full button editor embedded in the panel (no separate settings window), bundled Font Awesome icon set with search, custom PNG/JPG/GIF icon upload, custom background colors, and drag-and-drop reordering between slots.

Source repo: https://github.com/sentinela-one/xtream-desklet-deck

Checklist

  • Ran ./validate-spice xtream-desklet-deck@sentinela-one locally - no errors
  • icon.png present and square
  • metadata.json has no icon/dangerous/last-edited fields, ASCII only
  • No compiled/minified assets or runtime external code fetches

Stream Deck-style button grid for Cinnamon: full button editor embedded
in the panel, bundled Font Awesome icon set, custom icon upload, custom
colors, drag-and-drop reordering.

Source: https://github.com/sentinela-one/xtream-desklet-deck
@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 9 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

⚠️ hardcoded_config_dir

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:675

let destDir = GLib.get_home_dir() + "/.config/xtream-desklet-deck/custom_icons";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:704

this._statePath = GLib.get_home_dir() + "/.config/xtream-desklet-deck/instances/" + desklet_id + ".json";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:825

Util.spawnCommandLine("xdg-open " + DONATE_URL);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 9 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

⚠️ hardcoded_config_dir

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:675

let destDir = GLib.get_home_dir() + "/.config/xtream-desklet-deck/custom_icons";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:704

this._statePath = GLib.get_home_dir() + "/.config/xtream-desklet-deck/instances/" + desklet_id + ".json";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:825

Util.spawnCommandLine("xdg-open " + DONATE_URL);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 9 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

⚠️ hardcoded_config_dir

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:675

let destDir = GLib.get_home_dir() + "/.config/xtream-desklet-deck/custom_icons";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:704

this._statePath = GLib.get_home_dir() + "/.config/xtream-desklet-deck/instances/" + desklet_id + ".json";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:825

Util.spawnCommandLine("xdg-open " + DONATE_URL);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 9 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

⚠️ hardcoded_config_dir

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:675

let destDir = GLib.get_home_dir() + "/.config/xtream-desklet-deck/custom_icons";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:704

this._statePath = GLib.get_home_dir() + "/.config/xtream-desklet-deck/instances/" + desklet_id + ".json";

Avoid hardcoding .config in paths. Use GLib.get_user_config_dir() instead,
which respects the XDG_CONFIG_HOME environment variable.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:825

Util.spawnCommandLine("xdg-open " + DONATE_URL);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 6 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

@sentinela-one
sentinela-one force-pushed the add-xtream-desklet-deck branch from 4810f00 to 8ee296a Compare September 10, 2026 13:03
@github-actions

Copy link
Copy Markdown

Best-practices scanner

This is a regex-based check for API usage that can pose security, performance or
maintainability issues, or that may already be provided by Cinnamon. Most findings
are advisory and do not automatically disqualify a pull request.

This check is not perfect and will not replace a normal review.


Found 6 potential issue(s):

⚠️ WARNING

⚠️ sync_file_get_contents

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:197

let [ok, contents] = GLib.file_get_contents(path);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:562

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:586

let [ok, contents] = GLib.file_get_contents(srcPath);

Synchronous file_get_contents() blocks the main loop.
Use Gio.File.load_contents_async() instead.

⚠️ sync_file_query_exists

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:560

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:584

if (!cacheFile.query_exists(null)) {

query_exists() is a synchronous call that can block on slow/network filesystems.
Prefer attempting the operation and handling a Gio.IOErrorEnum.NOT_FOUND error instead.

ℹ️ INFO

ℹ️ shell_string_spawn

xtream-desklet-deck@sentinela-one/files/xtream-desklet-deck@sentinela-one/desklet.js:817

Util.spawnCommandLine(command);

Prefer argument vector spawn functions over shell command strings.
This is especially important when arguments include untrusted input (user data,
filenames, settings values, etc.) as shell strings are vulnerable to injection.
Static command strings are generally fine, but argv is always safer.
Use Util.spawn(["cmd", "arg1", "arg2"]) or Util.trySpawn() instead.


Automated pattern check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant