mirror of
https://github.com/project-gauntlet/gauntlet.git
synced 2025-12-23 10:35:53 +00:00
Compare commits
170 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca066da5c9 | ||
|
|
ce76f8211c | ||
|
|
e62a89f45e | ||
|
|
1e8bd2eca9 | ||
|
|
de5166ccae | ||
|
|
1116190f7d | ||
|
|
3516d35a35 | ||
|
|
a577202ec9 | ||
|
|
b008fcd907 | ||
|
|
1a2368ffde | ||
|
|
24405c92bc | ||
|
|
204de4d88c | ||
|
|
4721a70111 | ||
|
|
204e4182c9 | ||
|
|
62a16d04e0 | ||
|
|
41f0fb460a | ||
|
|
e7c1f0343e | ||
|
|
32bf43438c | ||
|
|
0528b96fae | ||
|
|
39bf811b11 | ||
|
|
f82841aad4 | ||
|
|
35afc3b0cd | ||
|
|
dea6aee03a | ||
|
|
3245dcee96 | ||
|
|
f41ab9233b | ||
|
|
136b2c2ab6 | ||
|
|
b4340f4c10 | ||
|
|
72123db351 | ||
|
|
e1f2ca85ec | ||
|
|
242f5a2eea | ||
|
|
729b4f695f | ||
|
|
3cdd16cfb3 | ||
|
|
21f8ab6d09 | ||
|
|
b7b8413146 | ||
|
|
97fc6360ea | ||
|
|
e643dcc4f7 | ||
|
|
771e2f95d7 | ||
|
|
5c2db4d048 | ||
|
|
6bb5f40065 | ||
|
|
94c8984649 | ||
|
|
1c23514aac | ||
|
|
08c5bb2c49 | ||
|
|
a8287ede60 | ||
|
|
3a457450cb | ||
|
|
bced4daedd | ||
|
|
283285c317 | ||
|
|
70e815b795 | ||
|
|
9111dd074b | ||
|
|
d1e61d4d19 | ||
|
|
f529d061ff | ||
|
|
6645ce21ad | ||
|
|
a0bbad9fea | ||
|
|
f20537181e | ||
|
|
71e8adf44d | ||
|
|
f51a123411 | ||
|
|
0d7a9db4d9 | ||
|
|
2afecf3b80 | ||
|
|
29b1a4ab36 | ||
|
|
75fa1f3af5 | ||
|
|
e7f621018c | ||
|
|
3d1beaca15 | ||
|
|
8fd14b4dab | ||
|
|
e1787e7dc8 | ||
|
|
9021f0580e | ||
|
|
a91bf3066f | ||
|
|
f2fadf8b70 | ||
|
|
924fe69069 | ||
|
|
9fe9ccdb6b | ||
|
|
bce1969610 | ||
|
|
f7d7022000 | ||
|
|
e13ff1d688 | ||
|
|
04e0dfd44a | ||
|
|
547f502030 | ||
|
|
d5b4c71a61 | ||
|
|
41107d2043 | ||
|
|
fee4e9a18b | ||
|
|
747cb9435d | ||
|
|
901f8fdfa3 | ||
|
|
30963ffd73 | ||
|
|
1706840b8b | ||
|
|
7e46395152 | ||
|
|
5181a366e7 | ||
|
|
c0f61f444d | ||
|
|
b0fdaa6b9e | ||
|
|
a0275cce28 | ||
|
|
80bb33690b | ||
|
|
a8182f4b2e | ||
|
|
3599837033 | ||
|
|
2a80b51ff5 | ||
|
|
7a47cdb941 | ||
|
|
c9019ca772 | ||
|
|
3992897fcf | ||
|
|
624f37aaeb | ||
|
|
f0912c8e21 | ||
|
|
40fb6f2617 | ||
|
|
3064f7f297 | ||
|
|
5a52e1a9e5 | ||
|
|
2ddd9c8bf0 | ||
|
|
4ab582ddad | ||
|
|
4aec25397a | ||
|
|
80396abbad | ||
|
|
44d594c395 | ||
|
|
ba64162222 | ||
|
|
5b4f94cfc6 | ||
|
|
b6c0b780db | ||
|
|
f204969e63 | ||
|
|
59307623ca | ||
|
|
ebcee6a470 | ||
|
|
9abbc1909d | ||
|
|
c403a5a386 | ||
|
|
417ed8a13a | ||
|
|
affeccceb1 | ||
|
|
ace5a874e3 | ||
|
|
1a1c862973 | ||
|
|
87d6b1abb8 | ||
|
|
a72329aeb7 | ||
|
|
b8f07d5028 | ||
|
|
61eca05f42 | ||
|
|
7143ed2471 | ||
|
|
25a10d573c | ||
|
|
bdda05f579 | ||
|
|
4a99160427 | ||
|
|
8439f96430 | ||
|
|
6fafe23658 | ||
|
|
02f9d366fe | ||
|
|
d8b6010ad1 | ||
|
|
2bb69f8add | ||
|
|
a258bdf674 | ||
|
|
9f057c09dc | ||
|
|
ae0f833f15 | ||
|
|
aacf78a377 | ||
|
|
b47906fbad | ||
|
|
3d962f3405 | ||
|
|
6d37684fc8 | ||
|
|
c39ac08178 | ||
|
|
99f7ecec11 | ||
|
|
709f8337d4 | ||
|
|
d721bda736 | ||
|
|
90957f214a | ||
|
|
71284cbca8 | ||
|
|
6e04702903 | ||
|
|
8fc21934de | ||
|
|
2e2864e88a | ||
|
|
67c7234b41 | ||
|
|
345ab75143 | ||
|
|
c08e33c48c | ||
|
|
77d20bcd6c | ||
|
|
fc4df0efa1 | ||
|
|
d7d87d0829 | ||
|
|
6ccd091c8f | ||
|
|
74f6433bea | ||
|
|
053b0a1008 | ||
|
|
338540cdec | ||
|
|
4f715674c0 | ||
|
|
81c21e9ab6 | ||
|
|
704b466b20 | ||
|
|
93dbba1def | ||
|
|
9dfab9d537 | ||
|
|
fd481027e3 | ||
|
|
d4e88b97a5 | ||
|
|
705b42821c | ||
|
|
76609064df | ||
|
|
f96941d436 | ||
|
|
7e5d4aa8ea | ||
|
|
1aca32ae9c | ||
|
|
b5575725f0 | ||
|
|
b0f03daba7 | ||
|
|
e1216598a9 | ||
|
|
ecd21cf518 | ||
|
|
e2428ff759 |
598 changed files with 25014 additions and 19227 deletions
14
.editorconfig
Normal file
14
.editorconfig
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# EditorConfig is awesome: https://editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
|
||||
[*.yaml]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
2
.github/workflows/build.yaml
vendored
2
.github/workflows/build.yaml
vendored
|
|
@ -2,7 +2,7 @@ name: build
|
|||
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
|
|
|
|||
17
.github/workflows/format.yaml
vendored
17
.github/workflows/format.yaml
vendored
|
|
@ -1,12 +1,19 @@
|
|||
name: Format
|
||||
name: format
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
all:
|
||||
runs-on: ubuntu-latest
|
||||
rust:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: dtolnay/rust-toolchain@nightly
|
||||
with:
|
||||
components: rustfmt
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check format
|
||||
run: cargo +nightly fmt --all -- --check --verbose
|
||||
- name: rustfmt
|
||||
run: cargo +nightly fmt --all -- --check
|
||||
nix:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: cachix/install-nix-action@v31
|
||||
- uses: actions/checkout@v4
|
||||
- name: alejandra
|
||||
run: nix shell nixpkgs#alejandra -c alejandra -c .
|
||||
|
|
|
|||
11
.github/workflows/nix.yaml
vendored
Normal file
11
.github/workflows/nix.yaml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
name: nix build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
all:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: cachix/install-nix-action@v25
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
- run: nix-build
|
||||
2
.github/workflows/release.yaml
vendored
2
.github/workflows/release.yaml
vendored
|
|
@ -25,7 +25,7 @@ on:
|
|||
|
||||
jobs:
|
||||
publish-init:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
github-release-id: ${{ steps.init-step.outputs.github-release-id }}
|
||||
steps:
|
||||
|
|
|
|||
2
.github/workflows/setup-linux.yaml
vendored
2
.github/workflows/setup-linux.yaml
vendored
|
|
@ -14,7 +14,7 @@ on:
|
|||
|
||||
jobs:
|
||||
run-on-linux:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- run: sudo apt-get update
|
||||
|
|
|
|||
4
.github/workflows/setup-windows.yaml
vendored
4
.github/workflows/setup-windows.yaml
vendored
|
|
@ -14,7 +14,7 @@ on:
|
|||
|
||||
jobs:
|
||||
run-on-windows:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2022
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -27,7 +27,7 @@ jobs:
|
|||
- uses: dtolnay/rust-toolchain@stable
|
||||
|
||||
- run: choco install protoc
|
||||
- run: dotnet tool install --global wix
|
||||
- run: dotnet tool install --global wix --version 5.0.2
|
||||
- run: wix extension add -g WixToolset.Util.wixext/5.0.2
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
|
|
|||
27
.github/workflows/winget.yaml
vendored
Normal file
27
.github/workflows/winget.yaml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
name: Publish to WinGet
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
env:
|
||||
VERSION_REGEX: '^v(\d+)$'
|
||||
# winget-create will read the following environment variable to access the GitHub token needed for submitting a PR
|
||||
# See https://aka.ms/winget-create-token
|
||||
WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: windows-latest # Action can only run on Windows
|
||||
steps:
|
||||
- name: Publish To WinGet
|
||||
run: |
|
||||
$release = '${{ toJSON(github.event.release) }}' | ConvertFrom-Json
|
||||
$wingetRelevantAsset = $release | Select-Object -Property assets | Where-Object { $_.name -like '*.msi' } | Select-Object -First 1
|
||||
$regex = [Regex]::New($env:VERSION_REGEX)
|
||||
$version = $regex.Match($release.tag_name).Groups[1].Value
|
||||
|
||||
$wingetPackage = "Exidex.Gauntlet"
|
||||
|
||||
& curl.exe -JLO https://aka.ms/wingetcreate/latest
|
||||
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url
|
||||
140
CHANGELOG.md
140
CHANGELOG.md
|
|
@ -3,12 +3,148 @@
|
|||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project doesn't adhere to Semantic Versioning, see [Versioning](./README.md#versioning)
|
||||
and this project doesn't adhere to Semantic Versioning, see [Versioning](https://gauntlet.sh/docs/information/versioning)
|
||||
|
||||
For changes in `@project-gauntlet/tools` see [separate CHANGELOG.md](https://github.com/project-gauntlet/tools/blob/main/CHANGELOG.md)
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [21] - 2025-08-16
|
||||
|
||||
### General
|
||||
|
||||
- When opening `Opened windows` view second item is now focused by default
|
||||
- Because the window ordering is "most recently focused on the top", second can be considered as an "alternative" application that was focused before the last one
|
||||
- Implemented native hud notifications on Linux
|
||||
- Enabled by default
|
||||
- `linux.native_hud` boolean configuration option is available to disable this
|
||||
- Restricted JavaScript runtime heap size to 50 MB per plugin
|
||||
|
||||
### Plugins
|
||||
- It is now possible to programmatically control which item in grid/list is focused
|
||||
- `<List/>` and `<Grid/>` now have new property `focusedItemId`
|
||||
- If `focusedItemId` property is `undefined` the focus is uncontrolled
|
||||
- if `focusedItemId` property is `null` the focus is controlled and unset
|
||||
- if `focusedItemId` property is `string` the focus is controlled and set to item with specified `id`
|
||||
- Refine nullability of event function arguments on React components
|
||||
- **BREAKING CHANGE**: Following function properties now return `null` as an argument instead of `undefined`
|
||||
- `<Action/>`'s `onAction`
|
||||
- `<List/>`'s `onItemFocusChange`
|
||||
- `<Gird/>`'s `onItemFocusChange`
|
||||
- For following function property arguments `undefined` was removed from type signature
|
||||
- `<SearchBar/>`'s `onChange`
|
||||
- `<TextField/>`'s `onChange`
|
||||
- `<PasswordField/>`'s `onChange`
|
||||
- `<Select/>`'s `onChange`
|
||||
|
||||
### UI/UX improvements
|
||||
- Text in main view search results, plugin view, action panel and bottom panel right side is now smaller
|
||||
- Removed padding from content paragraph text
|
||||
- Keyboard shortcuts in UI now use Lucide icons
|
||||
|
||||
### Fixes
|
||||
- Settings are now part of the main application instead of the separate process
|
||||
- Only single settings window can now exist at the same time.
|
||||
- Fixed inline view being recreated each time key is pressed in search bar, causing useRef not preserve the value
|
||||
- Fixed back navigation being treated as whole separate view session
|
||||
- This also fixed state leaking between views when changing views very quickly
|
||||
- Fixed panic if state of the widget under specific id changed type
|
||||
- Fixed blurry window on Linux Wayland LayerShell due to missing fractional scaling support
|
||||
- Reworked viewport scrolling when using keyboard navigation
|
||||
- Fixed incorrect scrolling distance for long lists/grids
|
||||
- Fixed scrolling position sometimes not being reset correctly
|
||||
- Fixed `Opened Windows` view often not showing any windows
|
||||
|
||||
## [20] - 2025-07-07
|
||||
|
||||
### General
|
||||
|
||||
- Linux Gnome Wayland support
|
||||
- `zwlr_layer_shell_v1` Wayland protocol is no longer required. It is still preferred, but if not supported application falls back to regular `xdg_shell` window
|
||||
- Added `wayland.main_window_surface` config option to allow customization of this behavior
|
||||
- Linux Wayland LayerShell improvements
|
||||
- **BREAKING CHANGE**: Changed LayerShell surface namespace from `Gauntlet` to `gauntlet` for main window, and set namespace to `gauntlet-hud` for hud window
|
||||
- Migrated to yet another LayerShell implementation
|
||||
- Fixes event/keystroke duplication after suspend
|
||||
- Disabled global shortcuts by default on Linux Wayland
|
||||
- Added `wayland.global_shortcuts_api` config option to allow usage of legacy x11 api if supported by given environment
|
||||
- Global Shortcuts XDG Portal is not and will not be supported until there will be major changes to it
|
||||
- Input Method Editor (IME) support for input fields
|
||||
- Changed action panel shortcut from <kbd>ALT</kbd> + <kbd>K</kbd> to <kbd>CTRL</kbd> + <kbd>K</kbd> (Windows/Linux) and <kbd>CMD</kbd> + <kbd>K</kbd> (macOS), to match similar pattern in other apps
|
||||
- `gauntlet open` CLI command now hides window when executed while window is open, matching behavior of global shortcut
|
||||
- Lots of internal dependency updates
|
||||
|
||||
### Plugins
|
||||
- Updated Deno to 2.3.3
|
||||
- **BREAKING CHANGE**: Remove `<DatePicker/>` component
|
||||
- It caused difficulties when updating dependencies and needs a complete rework
|
||||
|
||||
### Fixes
|
||||
- Reduced glibc requirement from 2.38 to 2.35
|
||||
- Fixed systray open main and settings windows actions causing deadlock
|
||||
- Fixed LayerShell window taking exclusive keyboard focus preventing any desktop interactions while window was open
|
||||
- Fixed `useStorage` and `useCache` hooks crashing plugin runtime when closing the view
|
||||
- Fixed `npm run dev` not showing full error cause (contributed by @Gabrielbdd)
|
||||
- Fixed nix applications not being detected on macOS by following links inside `/Applications` (contributed by @deadbaed)
|
||||
|
||||
## [19] - 2025-05-11
|
||||
|
||||
### General
|
||||
- It is now possible to assign custom alias to entrypoints which is used for search
|
||||
- Windows in "Opened windows" view entrypoint are now sorted following "most recently focused on the top" order
|
||||
|
||||
### Plugins
|
||||
- Plugin manifest property `entrypoint.*.actions.*.shortcut` is now optional
|
||||
- Added `<Content.Svg/>` component to display SVG images
|
||||
- **BREAKING CHANGE**: Renamed TypeScript types: `ImageSource` to `DataSource`, `ImageSourceUrl` to `DataSourceUrl`, `ImageSourceAsset` to `DataSourceAsset`
|
||||
|
||||
### UI/UX improvements
|
||||
- Made font size in the Settings UI a little smaller
|
||||
|
||||
### Fixes
|
||||
- Fixed crash when closing inline view due to Action being run, again...
|
||||
- Fixed shortcut assignment error not being shown for global entrypoint shortcuts
|
||||
- Fixed crash on X11 when trying to assign shortcut that is already used by another application
|
||||
- Fixed `icon` in `EntrypointGenerator` requiring `number[]` instead of declared `ArrayBuffer`
|
||||
- Fixed text selection not being visible when selecting text in form view text fields
|
||||
- Fixed plugin runtime crash when using `assetDataSync()` function
|
||||
|
||||
## [18] - 2025-04-13
|
||||
|
||||
### General
|
||||
|
||||
- Entrypoints can now be run or opened using global shortcut set Settings UI
|
||||
- On Linux X11 there is a known bug which will cause a crash and prevent server startup if attempted to register global shortcut that is already registered by another application
|
||||
- Generated Entrypoints are now listed in the Settings UI
|
||||
|
||||
### Plugins
|
||||
- Added authors field to Plugin Manifest
|
||||
- `gauntlet.authors.*.name` - String
|
||||
- `gauntlet.authors.*.uris` - List of strings. URIs that identify the author. Can be a link to social media page or an email (if email it should begin with `mailto:` schema)
|
||||
- Added `$schema` field to Plugin Manifest which takes URL to the JSON Schema file
|
||||
- Some editors use it to validate the content of the file
|
||||
- Currently, the schema file is located inside the repository at path `https://raw.githubusercontent.com/project-gauntlet/gauntlet/refs/heads/main/docs/schema/plugin_manifest.schema.json` but at some point this will change
|
||||
|
||||
### Themes
|
||||
- Tweaked window border color of macOS Dark theme on non-macos platforms to be not as bright
|
||||
|
||||
### UI/UX improvements
|
||||
- Reworked shortcut selector widget in Setting UI
|
||||
|
||||
### Fixes
|
||||
- Fixed window sometimes not being hidden on X11
|
||||
- Main view search list is now refreshed when window being hidden instead of when it is shown, to avoid the list being changed after window was opened (contributed by @BennoCrafter)
|
||||
- Fixed plugin view being empty if the window is closed by toggling global shortcut
|
||||
- Fixes plugin view not being opened properly if it is created using global shortcut or cli command (contributed by @BennoCrafter)
|
||||
|
||||
## [17] - 2025-03-15
|
||||
- Fixed crash when typing/clicking fast in React-created plugin ui
|
||||
- Fixed events sometimes overwriting other parallel events when typing/clicking fast in React-created plugin ui
|
||||
- Fixes mouse clicks sometimes being ignored in high refresh rate views
|
||||
- Fixes keystrokes being rewritten/ignored when holding down keys or typing fast in input fields
|
||||
- Fixed crash when closing inline view due to Action being run
|
||||
- Fixed zombie processes being left over after closing Settings UI
|
||||
|
||||
## [16] - 2025-02-23
|
||||
|
||||
- Fixed application plugin being broken on non-macos platforms
|
||||
|
|
@ -628,4 +764,4 @@ Themes are versioned and only one version is supported at the same time by appli
|
|||
|
||||
### Added
|
||||
|
||||
- Initial release.
|
||||
- Initial release.
|
||||
|
|
|
|||
6240
Cargo.lock
generated
6240
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
51
Cargo.toml
51
Cargo.toml
|
|
@ -5,41 +5,39 @@ repository = "https://github.com/project-gauntlet/gauntlet"
|
|||
|
||||
[workspace]
|
||||
members = [
|
||||
"rust/management_client",
|
||||
"rust/client",
|
||||
"rust/server",
|
||||
"rust/common",
|
||||
"rust/common_ui",
|
||||
"rust/common_plugin_runtime",
|
||||
"rust/utils",
|
||||
"rust/utils_macros",
|
||||
"rust/cli",
|
||||
"rust/component_model",
|
||||
"rust/scenario_runner",
|
||||
"rust/manifest_schema",
|
||||
"rust/plugin_runtime",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[workspace.dependencies]
|
||||
# iced
|
||||
#iced = { version = "0.13.99", features = ["tiny-skia", "wgpu", "tokio", "lazy", "advanced", "image"] }
|
||||
iced = { git = "https://github.com/project-gauntlet/iced.git", branch = "gauntlet-0.13", default-features = false, features = ["tiny-skia", "wgpu", "tokio", "advanced", "image"] }
|
||||
#iced_aw = { version = "0.11.99", features = ["date_picker", "wrap", "number_input", "grid", "spinner"] }
|
||||
iced_aw = { git = "https://github.com/project-gauntlet/iced_aw.git", branch = "gauntlet-0.13", default-features = false, features = ["date_picker", "wrap", "number_input", "grid", "spinner"] }
|
||||
#iced_table = "0.13.99"
|
||||
iced_table = { git = "https://github.com/project-gauntlet/iced_table.git", branch = "gauntlet-0.13" }
|
||||
#iced_fonts = { version = "0.1.99", features = ["bootstrap"] }
|
||||
iced_fonts = { git = "https://github.com/project-gauntlet/iced_fonts.git", branch = "gauntlet-0.13", features = ["bootstrap"] }
|
||||
#iced_layershell = "0.13.99"
|
||||
iced_layershell = { git = "https://github.com/project-gauntlet/exwlshelleventloop.git", branch = "gauntlet-0.13" }
|
||||
#iced = { version = "0.13.99", features = ["wgpu", "tiny-skia", "web-colors", "tokio", "lazy", "advanced", "image", "svg"] }
|
||||
iced = { git = "https://github.com/project-gauntlet/iced.git", branch = "gauntlet-0.13.1", features = ["wgpu", "tiny-skia", "web-colors", "tokio", "lazy", "advanced", "image", "svg"] }
|
||||
#iced_fonts = { version = "0.2.99", features = ["bootstrap", "lucide"] }
|
||||
iced_fonts = { git = "https://github.com/project-gauntlet/iced_fonts.git", branch = "gauntlet-0.13.1", features = ["bootstrap", "lucide"] }
|
||||
|
||||
# workspaces
|
||||
gauntlet-common = { path = "./rust/common" }
|
||||
gauntlet-common-ui = { path = "./rust/common_ui" }
|
||||
gauntlet-management-client = { path = "./rust/management_client" }
|
||||
gauntlet-common-plugin-runtime = { path = "./rust/common_plugin_runtime" }
|
||||
gauntlet-plugin-runtime = { path = "./rust/plugin_runtime" }
|
||||
gauntlet-client = { path = "./rust/client" }
|
||||
gauntlet-server = { path = "./rust/server" }
|
||||
gauntlet-utils = { path = "./rust/utils" }
|
||||
gauntlet-plugin-runtime = { path = "./rust/plugin_runtime" }
|
||||
gauntlet-utils-macros = { path = "./rust/utils_macros" }
|
||||
gauntlet-component-model = { path = "./rust/component_model" }
|
||||
gauntlet-scenario-runner = { path = "./rust/scenario_runner" }
|
||||
|
||||
|
|
@ -48,7 +46,7 @@ anyhow = { version = "1", features = ["backtrace"] }
|
|||
tracing = { version = "0.1" }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
tokio = { version = "1.42" }
|
||||
tokio-util = "0.7"
|
||||
tokio-util = { version = "0.7" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0" }
|
||||
bincode = { version = "2.0.0-rc.3" }
|
||||
|
|
@ -67,13 +65,16 @@ walkdir = { version = "2.4.0" }
|
|||
typed-path = { version = "0.10.0" }
|
||||
interprocess = { version = "2.2.2", features = ["tokio"] }
|
||||
toml = "0.8"
|
||||
x11rb = { version = "0.13", features = ["extra-traits"] }
|
||||
x11rb-async = { version = "0.13", features = ["extra-traits"] }
|
||||
x11rb-protocol = { version = "0.13" }
|
||||
smithay-client-toolkit = { version = "0.19.2" }
|
||||
|
||||
[dependencies]
|
||||
gauntlet-cli = { path = "rust/cli" }
|
||||
|
||||
[features]
|
||||
release = ["gauntlet-cli/release"]
|
||||
scenario_runner = ["gauntlet-cli/scenario_runner"]
|
||||
|
||||
[profile.release-size]
|
||||
inherits = "release"
|
||||
|
|
@ -81,6 +82,18 @@ opt-level = "s"
|
|||
lto = "thin"
|
||||
strip = true
|
||||
|
||||
[patch.crates-io]
|
||||
# NOTE https://github.com/ipetkov/crane/issues/336
|
||||
libffi-sys = { git = "https://github.com/tov/libffi-rs", rev = "d0704d634b6f3ffef5b6fc7e07fe965a1cff5c7b" }
|
||||
#[patch.crates-io]
|
||||
#iced_fonts = { path = "../iced_fonts" }
|
||||
#iced = { path = "../iced" }
|
||||
#iced_debug = { path = "../iced/debug" }
|
||||
#iced_program = { path = "../iced/program" }
|
||||
#iced_core = { path = "../iced/core" }
|
||||
#iced_futures = { path = "../iced/futures" }
|
||||
#iced_graphics = { path = "../iced/graphics" }
|
||||
#iced_renderer = { path = "../iced/renderer" }
|
||||
#iced_runtime = { path = "../iced/runtime" }
|
||||
#iced_tiny_skia = { path = "../iced/tiny_skia" }
|
||||
#iced_wgpu = { path = "../iced/wgpu" }
|
||||
#iced_widget = { path = "../iced/widget" }
|
||||
#iced_winit = { path = "../iced/winit" }
|
||||
#winit = { path = "../winit" }
|
||||
|
|
|
|||
463
README.md
463
README.md
|
|
@ -6,398 +6,98 @@
|
|||
|
||||
Web-first cross-platform application launcher with React-based plugins
|
||||
|
||||
> [!NOTE]
|
||||
> Launcher is in active development, expect bugs, missing features, incomplete ux, etc.
|
||||
>
|
||||
> There will probably be breaking changes which will be documented in [changelog](CHANGELOG.md).
|
||||
> [!WARNING]
|
||||
> The project is no longer being developed.
|
||||
|
||||

|
||||
|
||||
## Demo
|
||||
|
||||
Slightly outdated demo
|
||||
|
||||
https://github.com/user-attachments/assets/19964ed6-9cd9-48d4-9835-6be04de14b66
|
||||
|
||||
## Features
|
||||
|
||||
- Plugin-first
|
||||
- Plugins are written in TypeScript
|
||||
- Plugins can have the following functionality
|
||||
- Create UI
|
||||
- One-shot commands
|
||||
- Dynamically provide list of one-shot commands
|
||||
- Render quick "inline" content directly under main search bar based on value in it
|
||||
- Get content from and add to Clipboard
|
||||
- Plugins are distributed as separate branch in Git repository, meaning plugin distribution doesn't need any central
|
||||
server
|
||||
- Plugins IDs are just Git Repository URLs
|
||||
- Built-in functionality is provided by bundled plugin
|
||||
- Plugins are written in TypeScript
|
||||
- Extensive plugin API
|
||||
- Create UI views
|
||||
- One-shot commands
|
||||
- Dynamically provide list of one-shot commands
|
||||
- Render quick "inline" content directly under main search bar based on value in it
|
||||
- Get content from and add to Clipboard
|
||||
- Plugins are distributed as separate branch in Git repository, meaning plugin distribution doesn't need any central
|
||||
server
|
||||
- Plugins IDs are just Git Repository URLs
|
||||
- [React](https://github.com/facebook/react)-based UI for plugins
|
||||
- Implemented using custom React Reconciler (no Electron)
|
||||
- [Deno JavaScript Runtime](https://github.com/denoland/deno)
|
||||
- Deno allows to sandbox JavaScript plugin code for better security
|
||||
- Plugins are required to explicitly specify what permissions they need to work
|
||||
- Node.js is used to run plugin tooling, but as a plugin developer you will always write code that runs on Deno
|
||||
- Designed with cross-platform in mind from the beginning
|
||||
- Commands and Views can be run/opened using custom global shortcuts
|
||||
- Custom search alias can be assigned to Commands or Views
|
||||
- Custom theme support
|
||||
- Built-in functionality is provided by bundled plugins
|
||||
- Applications: shows applications installed on the system in search results
|
||||
- Plugin also tracks windows and which application they belong to, so opening already opened application will by default bring up previously created window
|
||||
- Not all systems are supported at the moment. See [feature support](https://gauntlet.sh/docs/feature-support)
|
||||
- Calculator: shows result of mathematical operations directly under main search bar
|
||||
- Includes converting currency using exchange rates
|
||||
- Powered by [Numbat](https://github.com/sharkdp/numbat)
|
||||
- Settings: open Gauntlet Settings
|
||||
- More to come, see [#15](https://github.com/project-gauntlet/gauntlet/issues/15)
|
||||
- [React](https://github.com/facebook/react)-based UI for plugins
|
||||
- Implemented using custom React Reconciler (no Electron)
|
||||
- [iced-rs](https://github.com/iced-rs/iced) is used for UI
|
||||
- [Deno JavaScript Runtime](https://github.com/denoland/deno)
|
||||
- Deno allows us to sandbox JavaScript code for better security
|
||||
- Plugins are required to explicitly specify what permissions they need to work
|
||||
- NodeJS is used to run plugin tooling, but as a plugin developer you will always write code that runs on Deno
|
||||
- Frecency-based search result ordering
|
||||
- Frecency is a combination of frequency and recency
|
||||
- More often the item is used the higher in the result list it will be, but items used a lot in the past will be ranked lower than items used the same amount of times recently
|
||||
- Currently, there is no fuzzy matching. Results are matched per word by substring
|
||||
- Designed with cross-platform in mind
|
||||
- Permissions
|
||||
- By default, plugins do not have access to host system
|
||||
- If plugin asked for access to filesystem, env variables or running commands, it is required to specify
|
||||
which operating systems it supports.
|
||||
- If plugin doesn't use filesystem, env variables or running commands and just uses network and/or UI, it
|
||||
is cross-platform
|
||||
- Shortcuts
|
||||
- Plugins are allowed to use only limited set of keys for shortcuts to support widest possible range of keyboards
|
||||
- Only upper and lower-case letters, symbols and numbers
|
||||
- Shortcut can have either `"main"` or `"alternative"` kind so plugins do not need to specify shortcut separately for each OS
|
||||
- `"main"` shortcut requires following modifiers
|
||||
- Windows and Linux: <kbd>CTRL</kbd>
|
||||
- macOS: <kbd>CMD</kbd>
|
||||
- `"alternative"` shortcut requires following modifiers
|
||||
- Windows and Linux: <kbd>ALT</kbd>
|
||||
- macOS: <kbd>OPT</kbd>
|
||||
- Whether <kbd>SHIFT</kbd> is also required depends on character specified for shortcut, e.g `$` will
|
||||
require <kbd>SHIFT</kbd> to be pressed, while `4` will not
|
||||
- Results are matched per word by substring
|
||||
|
||||
##### OS Support
|
||||
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/linux.svg" width="18" height="18" /> Linux
|
||||
- Both X11 and Wayland (via LayerShell protocol) are supported
|
||||
- Application plugin depends on `gtk-launch`
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/apple.svg" width="18" height="18" /> macOS
|
||||
##### Official
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/linux.svg" width="18" height="18" /> Linux X11
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/apple.svg" width="18" height="18" /> macOS M1
|
||||
|
||||
##### Best-effort
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/linux.svg" width="18" height="18" /> Linux Wayland
|
||||
- <img src="https://img.icons8.com/windows/32/windows-11.png" width="18" height="18" /> Windows
|
||||
|
||||
##### Planned features
|
||||
|
||||
- See [#13](https://github.com/project-gauntlet/gauntlet/issues/13)
|
||||
- See [#15](https://github.com/project-gauntlet/gauntlet/issues/15)
|
||||
- See [#16](https://github.com/project-gauntlet/gauntlet/issues/16)
|
||||
|
||||
##### Plugin APIs
|
||||
|
||||
- UI
|
||||
- Detail
|
||||
- Form
|
||||
- Action Panel
|
||||
- List
|
||||
- Grid
|
||||
- Inline
|
||||
- View directly under main search bar
|
||||
- Requires separate permission to be explicitly specified in manifest because it reads everything user enters in main search bar
|
||||
- Stack-based Navigation
|
||||
- Assets
|
||||
- Files placed into `assets` directory in root of plugin repository are accessible at plugin runtime using `assetData` function
|
||||
- Preferences
|
||||
- Preferences defined in plugin manifest can be set by user and are accessible at plugin runtime using `pluginPreferences` and `entrypointPreferences` functions
|
||||
- Clipboard
|
||||
- Accessible via `Clipboard` api
|
||||
- Requires separate permission to be explicitly specified in manifest
|
||||
- HUD
|
||||
- Shows small popup window with feedback information
|
||||
- Accessible via `showHud` function
|
||||
- React Helper Hooks
|
||||
- `usePromise`
|
||||
- Helper to run promises in a context of React view
|
||||
- Returns `AsyncState` object which contains `isLoading`, `error` and `data` properties
|
||||
- `useStorage`
|
||||
- Helper to store data between entrypoint, plugin and application runs
|
||||
- Follows API similar to `useState` built-in React Hook
|
||||
- Uses `localStorage` internally
|
||||
- `useCache`
|
||||
- Helper to store data between entrypoint runs but will be reset when plugin or application is restarted
|
||||
- Follows API similar to `useState` built-in React Hook
|
||||
- Uses `sessionStorage` internally
|
||||
- `useCachedPromise`
|
||||
- Helper to run promises with caching done automatically
|
||||
- Follows `stale-while-revalidate` caching strategy
|
||||
- Uses `usePromise` and `useCache` Hooks internally
|
||||
- `useFetch`
|
||||
- Helper to run `fetch()` with caching done automatically
|
||||
- Follows `stale-while-revalidate` caching strategy
|
||||
- Uses `useCachedPromise` Hook internally
|
||||
- <img src="https://cdn.jsdelivr.net/gh/simple-icons/simple-icons@develop/icons/apple.svg" width="18" height="18" /> macOS Intel
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Create your own plugin
|
||||
### Install Gauntlet
|
||||
|
||||
- Go to [plugin-template](https://github.com/project-gauntlet/plugin-template) and create your own GitHub repo from it.
|
||||
- Run `npm run dev` to start dev server (requires running application server)
|
||||
- Dev server will automatically refresh the plugin on any file change
|
||||
- Do the changes you need
|
||||
- You can configure plugin using [Plugin manifest](#plugin-manifest)
|
||||
- Documentation is, at the moment, basically non-existent but TypeScript declarations in `@project-gauntlet/api`
|
||||
and `@project-gauntlet/deno` should help
|
||||
- For examples see [Dev Plugin](dev_plugin). It is very busy because it is used for Gauntlet development, but it has examples of pretty much every available API
|
||||
- Push changes to GitHub
|
||||
- Run `publish` GitHub Actions workflow to publish plugin to `gauntlet/release` branch
|
||||
- Profit!
|
||||
See [Installation](https://gauntlet.sh/docs/installation)
|
||||
|
||||
### Global Shortcut
|
||||
|
||||
Main window can be opened using global shortcut or CLI command:
|
||||
- Global Shortcut (can be changed in Settings)
|
||||
- Windows: <kbd>ALT</kbd> + <kbd>Space</kbd>
|
||||
- Linux X11: <kbd>Super</kbd> + <kbd>Space</kbd>
|
||||
- Linux Wayland
|
||||
- Global shortcut may not be supported, see [feature support](https://gauntlet.sh/docs/feature-support)
|
||||
- Please use CLI command instead, and invoke it using window manager specific approach
|
||||
- macOS: <kbd>CMD</kbd> + <kbd>Space</kbd>
|
||||
- CLI command
|
||||
- `gauntlet open`
|
||||
|
||||
### Install plugin
|
||||
|
||||
Plugins are installed in Settings UI. Use Git repository url of the plugin to install it.
|
||||
Plugins are installed in Settings UI. Use Git repository url of the plugin to install it, e.g. `https://github.com/project-gauntlet/readme-demo-plugin.git`
|
||||
|
||||

|
||||
|
||||
### Install application
|
||||
### Create your own plugin
|
||||
|
||||
#### macOS
|
||||
|
||||
Although it is possible to install Gauntlet by using `.dmg` directly, application doesn't have auto-update functionality so it is recommended to install using `brew` package manager.
|
||||
|
||||
Brew package: [link](https://formulae.brew.sh/cask/gauntlet)
|
||||
|
||||
To install run:
|
||||
```
|
||||
brew install --cask gauntlet
|
||||
```
|
||||
|
||||
To start, manually open application.
|
||||
|
||||
#### Windows
|
||||
|
||||
Download `.msi` at [Releases page](https://github.com/project-gauntlet/gauntlet/releases/latest) and open to install Gauntlet
|
||||
|
||||
Note: application doesn't have auto-update functionality, and has to be updated manually
|
||||
|
||||
To start, manually open application.
|
||||
|
||||
#### Arch Linux
|
||||
|
||||
AUR package: [link](https://aur.archlinux.org/packages/gauntlet-bin)
|
||||
|
||||
To install run:
|
||||
```
|
||||
yay -S gauntlet-bin
|
||||
```
|
||||
|
||||
To start `systemd` service run:
|
||||
```
|
||||
systemctl --user enable --now gauntlet.service
|
||||
```
|
||||
|
||||
#### Nix
|
||||
|
||||
The nix flake in this repository is community maintained. If you face a problem, please create an issue and hopefully somebody will work on it.
|
||||
|
||||
To install, you either know what to do, or you can read more [here](nix/README.md).
|
||||
|
||||
#### Other Linux Distributions
|
||||
|
||||
At the moment application is only available for Arch Linux and Nix. If you want to create a package for other distributions see [Application packaging for Linux](#application-packaging-for-Linux)
|
||||
|
||||
### Global Shortcut
|
||||
Main window can be opened using global shortcut or CLI command:
|
||||
- Shortcut:
|
||||
- Windows: <kbd>ALT</kbd> + <kbd>Space</kbd>
|
||||
- Linux X11: <kbd>Super</kbd> + <kbd>Space</kbd>
|
||||
- Linux Wayland: No global shortcut. Please use CLI command
|
||||
- macOS: <kbd>CMD</kbd> + <kbd>Space</kbd>
|
||||
- Can be changed in Settings
|
||||
- CLI command:
|
||||
- `gauntlet open`
|
||||
|
||||
## Configuration
|
||||
|
||||
### Plugin manifest
|
||||
|
||||
```toml
|
||||
[gauntlet]
|
||||
name = 'Plugin Name'
|
||||
description = """
|
||||
Plugin description
|
||||
"""
|
||||
|
||||
[[preferences]] # plugin preference
|
||||
name = 'testBool'
|
||||
type = 'enum' # available values: 'number', 'string,' 'bool', 'enum', 'list_of_strings', 'list_of_numbers', 'list_of_enums'
|
||||
default = 'item' # type of default depends on type field. Currently, list types have no default
|
||||
description = "Some preference description"
|
||||
enum_values = [{ label = 'Item', value = 'item'}] # defines list of available enum values, required for types "enum" and "list_of_enums"
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'ui-view' # id for entrypoint
|
||||
name = 'UI view' # name of entrypoint
|
||||
path = 'src/ui-view.tsx' # path to file, default export is expected to be function React Function Component
|
||||
icon = 'icon.png' # optional, path to file inside assets dir
|
||||
type = 'view'
|
||||
description = 'Some entrypoint description'
|
||||
|
||||
[[entrypoint.preferences]] # entrypoint preference
|
||||
name = 'boolPreference'
|
||||
type = 'bool'
|
||||
default = true
|
||||
description = "bool preference description"
|
||||
|
||||
[[entrypoint.actions]]
|
||||
id = 'someAction' # id of action, needs to align with value in <Action> "id" property
|
||||
description = "demo action description"
|
||||
shortcut = { key = ':', kind = 'main'} # key string only accepts lower and upper-case letters, numbers and symbols. kind can be "main" or "alternative"
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'command-a'
|
||||
name = 'Command A'
|
||||
path = 'src/command-a.ts' # path to file, the whole file is a js script
|
||||
type = 'command'
|
||||
description = 'Some entrypoint description'
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'entrypoint-generator'
|
||||
name = 'Entrypoint generator'
|
||||
path = 'src/entrypoint-generator.ts'
|
||||
type = 'entrypoint-generator'
|
||||
description = 'Some entrypoint description'
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'inline-view'
|
||||
name = 'Inline view'
|
||||
path = 'src/inline-view.tsx'
|
||||
type = 'inline-view'
|
||||
description = 'Some entrypoint description'
|
||||
|
||||
[permissions]
|
||||
network = ["github.com", "example.com:8833"]
|
||||
clipboard = ["read", "write", "clear"]
|
||||
main_search_bar = ["read"]
|
||||
|
||||
# if specified requires supported_system to be specified as well
|
||||
environment = ["ENV_VAR_NAME"]
|
||||
|
||||
# if specified requires supported_system to be specified as well
|
||||
system = ["apiName"]
|
||||
|
||||
# if specified requires supported_system to be specified as well
|
||||
[permissions.filesystem]
|
||||
read = [
|
||||
"C:\\ProgramFiles\\test",
|
||||
"C:/ProgramFiles/test",
|
||||
"{windows:user-home}\\test",
|
||||
"{windows:user-home}/test",
|
||||
"{linux:user-home}/test",
|
||||
"/etc/test"
|
||||
]
|
||||
write = ["/home/exidex/.test"]
|
||||
|
||||
# if specified requires supported_system to be specified as well
|
||||
[permissions.exec]
|
||||
command = ["ls"]
|
||||
executable = ["/usr/bin/ls"]
|
||||
|
||||
[[supported_system]]
|
||||
os = 'linux' # 'linux', 'windows' or 'macos'
|
||||
|
||||
```
|
||||
|
||||
### Application config
|
||||
|
||||
Located at `$XDG_CONFIG_HOME/gauntlet/config.toml` for Linux. Not used at the moment.
|
||||
|
||||
## CLI
|
||||
|
||||
### Application
|
||||
|
||||
The Application has a simple command line interface
|
||||
|
||||
- `gauntlet` - starts server
|
||||
- `gauntlet --minimized` - starts server without opening main window
|
||||
- `gauntlet open` - opens application window, can be used instead of global shortcut
|
||||
- `gauntlet settings` - settings, plugin installation and removal, preferences, etc
|
||||
|
||||
### Dev Tools
|
||||
|
||||
[`@project-gauntlet/tools`](https://www.npmjs.com/package/@project-gauntlet/tools) contains separate CLI tool for plugin
|
||||
development purposes. It has following commands:
|
||||
|
||||
- `gauntlet dev`
|
||||
- Starts development server which will automatically refreshed plugin on any file change.
|
||||
- `gauntlet build`
|
||||
- Builds plugin
|
||||
- `gauntlet publish`
|
||||
- Publishes plugin to separate git branch. Includes `build`
|
||||
- `publish` assumes some things about git repository, so it is recommended to publish plugin from GitHub Actions
|
||||
workflow
|
||||
|
||||
[Plugin template](https://github.com/project-gauntlet/plugin-template) has nice `npm run` wrappers for them.
|
||||
See [Getting started with plugin development](https://gauntlet.sh/docs/plugin-development/getting-started)
|
||||
|
||||
## Theming
|
||||
|
||||
See [THEME.md](./docs/THEME.md)
|
||||
|
||||
## Architecture
|
||||
|
||||
The Application consists of 4 parts: server, frontend, plugin runtime and settings.
|
||||
Each plugin runs in separate plugin runtime in separate OS process. Each plugin is its own sandboxed Deno Worker.
|
||||
In plugin manifest it is possible to configure permissions which will allow plugin to have access to filesystem,
|
||||
network, environment variables or subprocess execution.
|
||||
Server saves plugins themselves and state of plugins into SQLite database.
|
||||
|
||||
Frontend is GUI module that uses [iced-rs](https://github.com/iced-rs/iced) as a GUI framework. It is run in the same process as a server.
|
||||
|
||||
Plugins can create UI using [React](https://github.com/facebook/react).
|
||||
Plugin Runtime implements custom React Reconciler (similar to React Native) which renders GUI components to frontend.
|
||||
Plugin Runtime listens on signals from frontend, so when user opens view defined by plugin, frontend sends an open-view request.
|
||||
Plugin Runtime then receives it, runs React render and React Reconciler makes requests to the frontend containing information what actually should be rendered.
|
||||
When a user interacts with the UI by clicking button or entering text into form,
|
||||
frontend sends events to server to see whether any re-renders are needed.
|
||||
|
||||
Settings is a GUI application runs in separate process that communicates with server using a simple request-response approach.
|
||||
|
||||
Simplified communication:
|
||||

|
||||
|
||||
Components:
|
||||

|
||||
|
||||
Plugins (or rather its compiled state: manifest, js code and assets) are distributed via Git repository in `gauntlet/release` branch (similar to GitHub Pages).
|
||||
Which means there is no one central place required for plugin distribution.
|
||||
And to install plugin all you need is Git repository url.
|
||||
|
||||
## Application packaging for Linux
|
||||
|
||||
This section contains a list of things
|
||||
that could be useful for someone who wants to package application for Linux distribution.
|
||||
If something is missing, please [create an issue](https://github.com/project-gauntlet/gauntlet/issues).
|
||||
|
||||
Application is already packaged for [Arch Linux](#arch-linux) and [Nix](#nix) so you can use them as examples.
|
||||
|
||||
Relevant CLI commands:
|
||||
|
||||
- `$ gauntlet --minimized`
|
||||
- Server needs to be started when user logs in, e.g. using `systemd` service
|
||||
- `$ gauntlet open`
|
||||
- Main windows is usually opened using [global shortcut](#global-shortcut), this CLI command can be used in cases where global shortcut functionality is not available
|
||||
- `$ gauntlet settings`
|
||||
- Settings are usually started on demand from Gauntlet itself
|
||||
|
||||
`.desktop` sample file can be found [here](assets/linux/gauntlet.desktop)
|
||||
|
||||
`systemd` service sample file can be found [here](assets/linux/gauntlet.service)
|
||||
|
||||
###### Directories used
|
||||
|
||||
- data dir - `$XDG_DATA_HOME/gauntlet` or `$HOME/.local/share/gauntlet`
|
||||
- contains application state `data.db`
|
||||
- cache dir - `$XDG_CACHE_HOME/gauntlet` or `$HOME/.cache/gauntlet`
|
||||
- contains icon cache
|
||||
- config dir - `$XDG_CONFIG_HOME/gauntlet` or `$HOME/.config/gauntlet`
|
||||
- contains application config `config.toml`
|
||||
- application will never do changes to config file
|
||||
- state dir - `$XDG_STATE_HOME/gauntlet` or `$HOME/.local/state/gauntlet`
|
||||
- contains log files created by plugin development
|
||||
- `.desktop` files at locations defined by [Desktop Entry Specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html)
|
||||
|
||||
Client and Setting applications have GUI and therefore use all the usual graphics-related stuff from X11.
|
||||
Wayland support requires LayerShell protocol `zwlr_layer_shell_v1`.
|
||||
See [Theming](https://gauntlet.sh/docs/theming)
|
||||
|
||||
## Building Gauntlet
|
||||
|
||||
You will need:
|
||||
- NodeJS
|
||||
- Rust
|
||||
|
|
@ -405,6 +105,8 @@ You will need:
|
|||
- CMake (not used by the project itself, but is required by a dependency)
|
||||
- On Linux: `libxkbcommon-dev` (note: name may differ depending on used distribution)
|
||||
|
||||
### Dev
|
||||
|
||||
To build dev run:
|
||||
```bash
|
||||
npm ci
|
||||
|
|
@ -412,14 +114,35 @@ npm run build
|
|||
npm run build-dev-plugin
|
||||
cargo build
|
||||
```
|
||||
In dev (without "release" feature) application will use only directories inside project directory to store state or cache.
|
||||
In dev (without "release" feature) application will use directories ONLY inside project directory to store state or cache, to avoid messing up global installation
|
||||
|
||||
To build release run:
|
||||
### Not-yet-packaged
|
||||
|
||||
To build not-yet-packaged release binary, run:
|
||||
```bash
|
||||
npm ci
|
||||
npm run build
|
||||
cargo build --release --features release
|
||||
```
|
||||
|
||||
### Packaged
|
||||
To build os-specific package, run one of the following:
|
||||
|
||||
macOS:
|
||||
```bash
|
||||
npm run build-macos-project --workspace @project-gauntlet/build
|
||||
```
|
||||
|
||||
Windows:
|
||||
```bash
|
||||
npm run build-windows-project --workspace @project-gauntlet/build
|
||||
```
|
||||
|
||||
Linux:
|
||||
```bash
|
||||
npm run build-linux-project --workspace @project-gauntlet/build
|
||||
```
|
||||
|
||||
But the new version release needs to be done via GitHub Actions
|
||||
|
||||
## Contributing
|
||||
|
|
@ -428,29 +151,5 @@ If you'd like to help build Gauntlet you can do it in more ways than just contri
|
|||
- Reporting a bug or UI/UX problem
|
||||
- Creating a plugin
|
||||
|
||||
If you are looking for things to do see pinned [issues](https://github.com/project-gauntlet/gauntlet/issues).
|
||||
|
||||
For simple problems feel free to open an issue or PR and tackle it yourself!
|
||||
|
||||
For simple problems feel free to open an issue or PR and tackle it yourself.
|
||||
For more significant changes please contact creators on Discord (invite link on top of README) and discuss first.
|
||||
|
||||
All and any contributions are welcome.
|
||||
|
||||
## Versioning
|
||||
|
||||
### Application
|
||||
|
||||
Application uses simple incremental integers starting from `1`.
|
||||
It doesn't follow the SemVer versioning.
|
||||
Given application's reliance on plugins, once it is stable,
|
||||
introducing breaking changes will be done carefully (if at all) and will be given a reasonable grace period to migrate.
|
||||
SemVer is about a hard cutoff between major versions with breaking changes, which doesn't fit this kind of application.
|
||||
Before application is declared stable, breaking changes could be done without a grace period.
|
||||
|
||||
### Tools
|
||||
|
||||
[`@project-gauntlet/tools`](https://www.npmjs.com/package/@project-gauntlet/tools) uses SemVer.
|
||||
|
||||
### Plugins
|
||||
|
||||
Plugins only have the latest published "version".
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
|||
16
|
||||
21
|
||||
|
|
@ -29,10 +29,10 @@ enum_values = [
|
|||
|
||||
[[entrypoint]]
|
||||
id = 'windows'
|
||||
name = 'All Open Windows'
|
||||
name = 'Opened Windows'
|
||||
path = 'src/windows.tsx'
|
||||
type = 'view'
|
||||
description = 'Show all open windows'
|
||||
description = 'Show all opened windows'
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'settings'
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ export default async function Applications(context: GeneratorContext<object, Ent
|
|||
}),
|
||||
add,
|
||||
remove,
|
||||
{ exts: ["app"], maxDepth: 2 }
|
||||
{ exts: ["app"], maxDepth: 2, followSymlinks: true, }
|
||||
);
|
||||
}
|
||||
case "windows": {
|
||||
|
|
|
|||
|
|
@ -2,32 +2,45 @@ import {
|
|||
GeneratedEntrypoint,
|
||||
GeneratedEntrypointAccessory,
|
||||
GeneratedEntrypointAction,
|
||||
showHud
|
||||
} from "@project-gauntlet/api/helpers";
|
||||
import { linux_open_application } from "gauntlet:bridge/internal-linux";
|
||||
import React from "react";
|
||||
import { useState } from "react";
|
||||
import { Action, ActionPanel, List } from "@project-gauntlet/api/components";
|
||||
|
||||
export function ListOfWindows({ windows, focus }: { windows: OpenWindowData[], focus: (windowId: string) => void }) {
|
||||
export function ListOfWindows({ windows, focusWindow, focusSecond }: {
|
||||
windows: Record<string, OpenWindowData>,
|
||||
focusWindow: (windowId: string) => void,
|
||||
focusSecond: boolean
|
||||
}) {
|
||||
const knownWindows = readWindowOrder();
|
||||
|
||||
const sortedWindows = Object.keys(windows) // sort windows based on array stored on storage
|
||||
.sort((a, b) => knownWindows.indexOf(a) - knownWindows.indexOf(b));
|
||||
|
||||
const [id, setId] = useState<string | null>(
|
||||
focusSecond ? sortedWindows.at(1) || null : null
|
||||
);
|
||||
|
||||
return (
|
||||
<List
|
||||
actions={
|
||||
<ActionPanel>
|
||||
<Action
|
||||
label="Focus window"
|
||||
onAction={(id: string | undefined) => {
|
||||
onAction={id => {
|
||||
if (id) {
|
||||
focus(id)
|
||||
console.log("focus: " + id)
|
||||
focusAndSort(id, focusWindow)
|
||||
return { close: true }
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ActionPanel>
|
||||
}
|
||||
onItemFocusChange={setId}
|
||||
focusedItemId={id}
|
||||
>
|
||||
{
|
||||
windows.map(window => <List.Item key={window.id} id={window.id} title={window.title}/>)
|
||||
sortedWindows.map(window => <List.Item key={window} id={window} title={windows[window]!!.title}/>)
|
||||
}
|
||||
</List>
|
||||
)
|
||||
|
|
@ -39,7 +52,13 @@ export type OpenWindowData = {
|
|||
appId: string
|
||||
}
|
||||
|
||||
export const openWindows: Record<string, OpenWindowData> = {};
|
||||
|
||||
export function openWindows(): Record<string, OpenWindowData> {
|
||||
if ((globalThis as any).__openWindows == undefined) {
|
||||
(globalThis as any).__openWindows = {}
|
||||
}
|
||||
return (globalThis as any).__openWindows
|
||||
}
|
||||
|
||||
export function applicationActions(
|
||||
id: string,
|
||||
|
|
@ -58,12 +77,16 @@ export function applicationActions(
|
|||
]
|
||||
}
|
||||
|
||||
const appWindows = Object.entries(openWindows)
|
||||
.filter(([_, windowData]) => windowData.appId == id)
|
||||
const appWindows = Object.fromEntries(
|
||||
Object.entries(openWindows())
|
||||
.filter(([_, windowData]) => windowData.appId == id)
|
||||
)
|
||||
|
||||
// TODO ability to close window
|
||||
|
||||
if (appWindows.length == 0) {
|
||||
const windowCount = Object.keys(appWindows).length;
|
||||
|
||||
if (windowCount == 0) {
|
||||
return [
|
||||
{
|
||||
label: "Open application",
|
||||
|
|
@ -72,14 +95,13 @@ export function applicationActions(
|
|||
},
|
||||
}
|
||||
]
|
||||
} else if (appWindows.length == 1) {
|
||||
} else if (windowCount == 1) {
|
||||
return [
|
||||
{
|
||||
label: "Focus window",
|
||||
run: () => {
|
||||
let [appWindow] = appWindows;
|
||||
let [windowId, _] = appWindow!!;
|
||||
focusWindow(windowId)
|
||||
let [windowId] = Object.keys(appWindows);
|
||||
focusAndSort(windowId!!, focusWindow)
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -89,15 +111,18 @@ export function applicationActions(
|
|||
},
|
||||
}
|
||||
]
|
||||
} else if (appWindows.length > 1) {
|
||||
} else if (windowCount > 1) {
|
||||
return [
|
||||
{
|
||||
label: "Show windows",
|
||||
view: () => {
|
||||
const appWindowsArr = appWindows
|
||||
.map(([_, window]) => window);
|
||||
|
||||
return <ListOfWindows windows={appWindowsArr} focus={windowId => focusWindow(windowId)}/>
|
||||
return (
|
||||
<ListOfWindows
|
||||
windows={appWindows}
|
||||
focusWindow={windowId => focusWindow(windowId)}
|
||||
focusSecond={false}
|
||||
/>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
@ -117,15 +142,15 @@ export function applicationAccessories(id: string, experimentalWindowTracking: b
|
|||
return []
|
||||
}
|
||||
|
||||
const appWindows = Object.entries(openWindows)
|
||||
const appWindows = Object.entries(openWindows())
|
||||
.filter(([_, windowData]) => windowData.appId == id)
|
||||
|
||||
if (appWindows.length == 0) {
|
||||
return []
|
||||
} else if (appWindows.length == 1) {
|
||||
return [{ text: "1 window open" }]
|
||||
return [{ text: "1 window" }]
|
||||
} else if (appWindows.length > 1) {
|
||||
return [{ text: `${appWindows.length} windows open` }]
|
||||
return [{ text: `${appWindows.length} windows` }]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
|
|
@ -141,12 +166,16 @@ export function addOpenWindow(
|
|||
add: (id: string, data: GeneratedEntrypoint) => void,
|
||||
) {
|
||||
if (generatedEntrypoint) {
|
||||
openWindows[windowId] = {
|
||||
openWindows()[windowId] = {
|
||||
id: windowId,
|
||||
appId: appId,
|
||||
title: windowTitle
|
||||
}
|
||||
|
||||
const knownWindows = readWindowOrder();
|
||||
knownWindows.push(windowId);
|
||||
writeWindowOrder(knownWindows)
|
||||
|
||||
add(appId, {
|
||||
...generatedEntrypoint,
|
||||
actions: applicationActions(appId, true, openApplication, focusWindow),
|
||||
|
|
@ -162,11 +191,15 @@ export function deleteOpenWindow(
|
|||
get: (id: string) => GeneratedEntrypoint | undefined,
|
||||
add: (id: string, data: GeneratedEntrypoint) => void,
|
||||
) {
|
||||
const openWindow = openWindows[windowId];
|
||||
const openWindow = openWindows()[windowId];
|
||||
if (openWindow) {
|
||||
const generatedEntrypoint = get(openWindow.appId);
|
||||
|
||||
delete openWindows[windowId];
|
||||
delete openWindows()[windowId];
|
||||
|
||||
const knownWindows = readWindowOrder();
|
||||
const newKnownWindows = knownWindows.filter(id => id != windowId)
|
||||
writeWindowOrder(newKnownWindows)
|
||||
|
||||
if (generatedEntrypoint) {
|
||||
add(openWindow.appId, {
|
||||
|
|
@ -182,4 +215,29 @@ export function openLinuxApplication(appId: string) {
|
|||
return () => {
|
||||
linux_open_application(appId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function focusAndSort(windowId: string, focus: (windowId: string) => void): void {
|
||||
focus(windowId)
|
||||
|
||||
// TODO would probably be better if this is based on os focus events
|
||||
const knownWindows = readWindowOrder();
|
||||
const newKnownWindows = knownWindows.filter(id => id != windowId)
|
||||
newKnownWindows.unshift(windowId);
|
||||
writeWindowOrder(newKnownWindows)
|
||||
}
|
||||
|
||||
const WINDOW_LIST_STORE_KEY = "opened-window-list";
|
||||
|
||||
function readWindowOrder(): string[] {
|
||||
const item = sessionStorage.getItem(WINDOW_LIST_STORE_KEY);
|
||||
if (item == null || item === "") {
|
||||
return []
|
||||
} else {
|
||||
return item.split(",")
|
||||
}
|
||||
}
|
||||
|
||||
function writeWindowOrder(windowIds: string[]): void {
|
||||
return sessionStorage.setItem(WINDOW_LIST_STORE_KEY, windowIds.join(","));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,23 @@ import { focusWaylandWindow } from "./window/wayland";
|
|||
import { focusX11Window } from "./window/x11";
|
||||
|
||||
export default function Windows(): ReactElement {
|
||||
const windows = Object.entries(openWindows)
|
||||
.map(([_, window]) => window)
|
||||
|
||||
switch (current_os()) {
|
||||
case "linux": {
|
||||
if (wayland()) {
|
||||
return (
|
||||
<ListOfWindows windows={windows} focus={(windowId) => focusWaylandWindow(windowId)}/>
|
||||
<ListOfWindows
|
||||
windows={openWindows()}
|
||||
focusWindow={(windowId) => focusWaylandWindow(windowId)}
|
||||
focusSecond={true}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<ListOfWindows windows={windows} focus={(windowId) => focusX11Window(windowId)}/>
|
||||
<ListOfWindows
|
||||
windows={openWindows()}
|
||||
focusWindow={(windowId) => focusX11Window(windowId)}
|
||||
focusSecond={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ text = [
|
|||
[window.border]
|
||||
radius = 8
|
||||
width = 1
|
||||
color = { color = "#646464", alpha = 0.5 }
|
||||
color = { color = "#383838", alpha = 1 }
|
||||
|
||||
[content.border]
|
||||
radius = 4.0
|
||||
|
|
|
|||
1
dev_data/.gitignore
vendored
Normal file
1
dev_data/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
scenarios
|
||||
|
|
@ -1,3 +1,11 @@
|
|||
|
||||
#[main_window]
|
||||
#close_on_unfocus = false
|
||||
#close_on_unfocus = false
|
||||
|
||||
[wayland]
|
||||
#main_window_surface = "xdg_shell"
|
||||
global_shortcuts_api = "legacy_x11_api"
|
||||
#global_shortcuts_api = "none"
|
||||
|
||||
[linux]
|
||||
native_hud = true
|
||||
|
|
|
|||
74
dev_plugin/assets/image.svg
Normal file
74
dev_plugin/assets/image.svg
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg id="svg2" width="620" height="472" xmlns="http://www.w3.org/2000/svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs id="defs4">
|
||||
<path id="box1" d="m0 0h77v210h-77z" stroke="#000" stroke-width="2"/>
|
||||
<path id="box2" d="m0 0h77v60h-77z" stroke="#000" stroke-width="2"/>
|
||||
</defs>
|
||||
<path id="bg" d="m0 0h620v472h-620z" fill="#fff"/>
|
||||
<g font-family="DejaVu Sans, Arial, Helvetica" stroke-width="1" xml:space="preserve">
|
||||
<g id="g9" transform="translate(2 1)">
|
||||
<use id="use11" fill="#fff" xlink:href="#box1"/>
|
||||
<use id="use13" x="77" fill="#ff0" xlink:href="#box1"/>
|
||||
<use id="use15" x="154" fill="#0ff" xlink:href="#box1"/>
|
||||
<use id="use17" x="231" fill="#0f0" xlink:href="#box1"/>
|
||||
<use id="use19" x="308" fill="#f0f" xlink:href="#box1"/>
|
||||
<use id="use21" x="385" fill="red" xlink:href="#box1"/>
|
||||
<use id="use23" x="462" fill="#00f" xlink:href="#box1"/>
|
||||
<use id="use25" x="539" xlink:href="#box1"/>
|
||||
</g>
|
||||
<g id="g45" transform="translate(2 220)">
|
||||
<use id="use47" fill="#0f0" xlink:href="#box2"/>
|
||||
<use id="use49" x="77" fill="#0f0" xlink:href="#box2"/>
|
||||
<use id="use51" x="154" fill="#0f0" xlink:href="#box2"/>
|
||||
<use id="use53" x="231" fill="#0f0" xlink:href="#box2"/>
|
||||
<use id="use55" x="308" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use57" x="385" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use59" x="462" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use61" x="539" fill="#fff" xlink:href="#box2"/>
|
||||
<text id="green100" x="30" y="35" fill="#fff">0.59</text>
|
||||
</g>
|
||||
<g id="g27" transform="translate(2 280)">
|
||||
<use id="use29" fill="red" xlink:href="#box2"/>
|
||||
<use id="use31" x="77" fill="red" xlink:href="#box2"/>
|
||||
<use id="use33" x="154" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use35" x="231" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use37" x="308" fill="red" xlink:href="#box2"/>
|
||||
<use id="use39" x="385" fill="red" xlink:href="#box2"/>
|
||||
<use id="use41" x="462" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use43" x="539" fill="#fff" xlink:href="#box2"/>
|
||||
<text id="red100" x="20" y="35" fill="#fff">+0.30</text>
|
||||
</g>
|
||||
<g id="g63" transform="translate(2 340)">
|
||||
<use id="use65" fill="#00f" xlink:href="#box2"/>
|
||||
<use id="use67" x="77" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use69" x="154" fill="#00f" xlink:href="#box2"/>
|
||||
<use id="use71" x="231" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use73" x="308" fill="#00f" xlink:href="#box2"/>
|
||||
<use id="use75" x="385" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="use77" x="462" fill="#00f" xlink:href="#box2"/>
|
||||
<use id="use79" x="539" fill="#fff" xlink:href="#box2"/>
|
||||
<text id="blue100" x="20" y="35" fill="#fff">+0.11</text>
|
||||
</g>
|
||||
<g id="g63" transform="translate(2 410)">
|
||||
<use id="grey100" fill="#fff" xlink:href="#box2"/>
|
||||
<use id="grey89" x="77" fill="#e3e3e3" xlink:href="#box2"/>
|
||||
<use id="grey70" x="154" fill="#b2b2b2" xlink:href="#box2"/>
|
||||
<use id="grey59" x="231" fill="#969696" xlink:href="#box2"/>
|
||||
<use id="grey41" x="308" fill="#696969" xlink:href="#box2"/>
|
||||
<use id="grey30" x="385" fill="#4d4d4d" xlink:href="#box2"/>
|
||||
<use id="grey11" x="462" fill="#1c1c1c" xlink:href="#box2"/>
|
||||
<use id="grey0" x="539" fill="#000" xlink:href="#box2"/>
|
||||
<text id="txgrey100" x="20" y="35">100%</text>
|
||||
<text id="txgrey89" x="102" y="35">89%</text>
|
||||
<text id="txgrey70" x="179" y="35">70%</text>
|
||||
<text id="txgrey59" x="256" y="35">59%</text>
|
||||
<text id="txgrey41" x="333" y="35" fill="#fff">41%</text>
|
||||
<text id="txgrey30" x="408" y="35" fill="#fff">30%</text>
|
||||
<text id="txgrey11" x="487" y="35" fill="#fff">11%</text>
|
||||
<text id="txgrey0" x="569" y="35" fill="#fff">0%</text>
|
||||
</g>
|
||||
<text id="text3446-0" x="90" y="184" fill="#fff" font-size="180" stroke-width="4">TEST</text>
|
||||
<text id="text3446" x="80" y="174" stroke-width="4"><tspan id="tspan3448" x="80" y="174" font-size="180">TEST</tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4 KiB |
|
|
@ -147,6 +147,7 @@ export default function DetailView(): ReactElement {
|
|||
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
||||
culpa qui officia deserunt mollit anim id est laborum.
|
||||
</Detail.Content.Paragraph>
|
||||
<Detail.Content.Svg source={{ asset: "image.svg" }}/>
|
||||
</Detail.Content>
|
||||
<Detail.Metadata>
|
||||
<Detail.Metadata.TagList label="Tags 1">
|
||||
|
|
@ -183,7 +184,7 @@ export default function DetailView(): ReactElement {
|
|||
</Detail.Metadata.TagList.Item>
|
||||
<Detail.Metadata.TagList.Item
|
||||
onClick={() => {
|
||||
readFile("https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/PNG_Test.png/477px-PNG_Test.png?20240527104658")
|
||||
readFile("https://github.com/project-gauntlet/gauntlet/blob/main/docs/logo.png?raw=true")
|
||||
.then(image => Clipboard.write({ "text/plain": "Gauntlet Test 1", "image/png": image }));
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -64,12 +64,6 @@ export default function FormView(): ReactElement {
|
|||
<Form.Select.Item value={"select_item_3"}>Select Item 3</Form.Select.Item>
|
||||
<Form.Select.Item value={"select_item_4"}>Select Item 4</Form.Select.Item>
|
||||
</Form.Select>
|
||||
<Form.DatePicker
|
||||
label={"What is your birthday?"}
|
||||
onChange={value => {
|
||||
console.log(`uncontrolled value: ${value}`)
|
||||
}}
|
||||
/>
|
||||
<Form.Separator/>
|
||||
{/* controlled */}
|
||||
<Form.TextField
|
||||
|
|
@ -105,12 +99,6 @@ export default function FormView(): ReactElement {
|
|||
<Form.Select.Item value={"default_selected_item"}>Default Select Item</Form.Select.Item>
|
||||
<Form.Select.Item value={"select_item_4"}>Select Item 4</Form.Select.Item>
|
||||
</Form.Select>
|
||||
<Form.DatePicker
|
||||
value={"2024-03-22"}
|
||||
onChange={value => {
|
||||
console.log(`controlled value: ${value}`)
|
||||
}}
|
||||
/>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,20 +1,17 @@
|
|||
import { Action, ActionPanel, Element, Icons, List } from "@project-gauntlet/api/components";
|
||||
import React, { ReactElement, ReactNode, useRef, useState } from "react";
|
||||
import React, { ReactElement, ReactNode, useRef } from "react";
|
||||
import { useCachedPromise, useFetch, useNavigation, usePromise } from "@project-gauntlet/api/hooks";
|
||||
|
||||
export default function ListView(): ReactElement {
|
||||
const { pushView } = useNavigation();
|
||||
|
||||
const [id, setId] = useState<string | undefined>(undefined);
|
||||
|
||||
return (
|
||||
<List
|
||||
actions={
|
||||
<ActionPanel>
|
||||
<Action label="Run hook" onAction={() => pushPrimaryAction(id, pushView)}/>
|
||||
<Action label="Run hook" onAction={(id) => pushPrimaryAction(id, pushView)}/>
|
||||
</ActionPanel>
|
||||
}
|
||||
onItemFocusChange={itemId => setId(itemId)}
|
||||
>
|
||||
<List.Item id="UsePromiseTestBasic" title="UsePromiseTestBasic"/>
|
||||
<List.Item id="UsePromiseTestExecuteFalse" title="UsePromiseTestExecuteFalse"/>
|
||||
|
|
@ -33,7 +30,7 @@ export default function ListView(): ReactElement {
|
|||
)
|
||||
}
|
||||
|
||||
function pushPrimaryAction(id: string | undefined, pushView: (component: ReactNode) => void) {
|
||||
function pushPrimaryAction(id: string | null, pushView: (component: ReactNode) => void) {
|
||||
switch (id) {
|
||||
case "UsePromiseTestBasic": {
|
||||
pushView(<UsePromiseTestBasic/>)
|
||||
|
|
@ -421,4 +418,4 @@ function printState(data: any, error: unknown, isLoading: boolean) {
|
|||
console.dir(data)
|
||||
console.dir(error)
|
||||
console.dir(isLoading)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { Environment } from "@project-gauntlet/api/helpers";
|
|||
export default function ListView(): ReactElement {
|
||||
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
|
||||
|
||||
const onClick = (id: string | undefined) => {
|
||||
const onClick = (id: string | null) => {
|
||||
if (id == "print-env") {
|
||||
console.log(Environment.gauntletVersion);
|
||||
console.log(Environment.isDevelopment);
|
||||
|
|
@ -63,4 +63,4 @@ export default function ListView(): ReactElement {
|
|||
</List.Section>
|
||||
</List>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,43 @@
|
|||
import { ReactElement } from "react";
|
||||
import { Grid } from "@project-gauntlet/api/components";
|
||||
import { ReactElement, useState } from "react";
|
||||
import { Action, ActionPanel, Grid } from "@project-gauntlet/api/components";
|
||||
|
||||
export default function Main(): ReactElement {
|
||||
const content = (
|
||||
const [id, setId] = useState<string | null>(null);
|
||||
|
||||
const content = (id: string) => (
|
||||
<Grid.Item.Content>
|
||||
<Grid.Item.Content.Paragraph>
|
||||
Test
|
||||
{id}
|
||||
</Grid.Item.Content.Paragraph>
|
||||
</Grid.Item.Content>
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<Grid onItemFocusChange={(id: string | undefined) => console.log("onItemFocusChange", id)}>
|
||||
<Grid.Item id="adarian" title="Adarian">{content}</Grid.Item>
|
||||
<Grid.Item id="aruzan" title="Aruzan">{content}</Grid.Item>
|
||||
<Grid.Item id="blutopian" title="Blutopian">{content}</Grid.Item>
|
||||
<Grid.Item id="caphex" title="Caphex">{content}</Grid.Item>
|
||||
<Grid.Item id="condluran" title="Condluran">{content}</Grid.Item>
|
||||
<Grid.Item id="frozian" title="Frozian">{content}</Grid.Item>
|
||||
<Grid.Item id="evereni" title="Evereni">{content}</Grid.Item>
|
||||
<Grid.Item id="ezaraa" title="Ezaraa">{content}</Grid.Item>
|
||||
<Grid.Item id="houk" title="Houk">{content}</Grid.Item>
|
||||
<Grid.Item id="inleshat" title="Inleshat">{content}</Grid.Item>
|
||||
<Grid
|
||||
onItemFocusChange={setId}
|
||||
focusedItemId={id}
|
||||
actions={
|
||||
<ActionPanel>
|
||||
<Action
|
||||
label={`Focused: ${id}`}
|
||||
onAction={(id) => {
|
||||
console.log(id)
|
||||
setId("condluran")
|
||||
}}
|
||||
/>
|
||||
</ActionPanel>
|
||||
}
|
||||
>
|
||||
<Grid.Item id="adarian" title="Adarian">{content("adarian")}</Grid.Item>
|
||||
<Grid.Item id="aruzan" title="Aruzan">{content("aruzan")}</Grid.Item>
|
||||
<Grid.Item id="blutopian" title="Blutopian">{content("blutopian")}</Grid.Item>
|
||||
<Grid.Item id="caphex" title="Caphex">{content("caphex")}</Grid.Item>
|
||||
<Grid.Item id="condluran" title="Condluran">{content("condluran")}</Grid.Item>
|
||||
<Grid.Item id="frozian" title="Frozian">{content("frozian")}</Grid.Item>
|
||||
<Grid.Item id="evereni" title="Evereni">{content("evereni")}</Grid.Item>
|
||||
<Grid.Item id="ezaraa" title="Ezaraa">{content("ezaraa")}</Grid.Item>
|
||||
<Grid.Item id="houk" title="Houk">{content("houk")}</Grid.Item>
|
||||
<Grid.Item id="inleshat" title="Inleshat">{content("inleshat")}</Grid.Item>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ import { ReactElement, useState } from "react";
|
|||
import { List } from "@project-gauntlet/api/components";
|
||||
|
||||
export default function Main(): ReactElement {
|
||||
const [id, setId] = useState<string | undefined>(undefined);
|
||||
const [id, setId] = useState<string | null>(null);
|
||||
|
||||
return (
|
||||
<List onItemFocusChange={setId}>
|
||||
<List onItemFocusChange={setId} focusedItemId={id}>
|
||||
<List.Item id="adarian" title="Adarian"/>
|
||||
<List.Item id="aruzan" title="Aruzan"/>
|
||||
<List.Item id="blutopian" title="Blutopian"/>
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
# Gauntlet Theming
|
||||
|
||||
Currently, in Gauntlet with themes it is possible to change (list is likely be extended with future updates):
|
||||
- Colors of text and background
|
||||
- Window border color, width and radius
|
||||
- Border radius of components in content
|
||||
|
||||
Theming is only affects main window and doesn't affect settings
|
||||
|
||||
Theme config file is in TOML format
|
||||
|
||||
Theme config file locations:
|
||||
- Windows: `C:\Users\Username\AppData\Roaming\Gauntlet\config\theme.toml`
|
||||
- Linux: `$XDG_CONFIG_HOME/gauntlet/theme.toml`
|
||||
- macOS: `$HOME/Library/Application Support/dev.project-gauntlet.gauntlet/theme.toml`
|
||||
|
||||
Currently, theme change is only applied after application restart
|
||||
|
||||
Any errors in theme parsing will be shown in application logs
|
||||
|
||||
See bundled themes for examples [here](./../bundled_themes)
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
@startuml
|
||||
|
||||
node "Frontend"
|
||||
node "Server"
|
||||
node "Deno worker 1" as Deno1
|
||||
node "Deno worker 2" as Deno2
|
||||
node "Deno worker 3" as Deno3
|
||||
node "Deno worker 4" as Deno4
|
||||
|
||||
[Frontend] --> [Server]
|
||||
|
||||
[Server] --> [Deno1]
|
||||
[Server] --> [Deno2]
|
||||
[Server] --> [Deno3]
|
||||
[Server] --> [Deno4]
|
||||
|
||||
@enduml
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
|
|
@ -1,31 +0,0 @@
|
|||
@startuml
|
||||
|
||||
'https://www.planttext.com/
|
||||
|
||||
== Frontend: Start ==
|
||||
|
||||
Frontend -> Server: list of views and commands request
|
||||
Server --> Frontend: list of views and commands response
|
||||
|
||||
== Frontend: Initial View Render ==
|
||||
|
||||
Frontend -> Server: open-view event
|
||||
Server -> Frontend: render components request
|
||||
Frontend --> Server: render components response
|
||||
|
||||
== Frontend: Command Execution ==
|
||||
|
||||
Frontend -> Server: execute command
|
||||
|
||||
== Frontend: View Update On Event ==
|
||||
|
||||
Frontend -> Server: button click, key press in input component, etc
|
||||
Server -> Frontend: render components request
|
||||
Frontend --> Server: render components response
|
||||
|
||||
== Settings ==
|
||||
|
||||
Settings -> Server: request
|
||||
Server --> Settings: response
|
||||
|
||||
@enduml
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 31 KiB |
|
|
@ -1 +1 @@
|
|||
The identifier of an action. Referenced in [plugin manifest]($LINK$__PLUGIN_MANIFEST__) to assign shortcut to button in UI
|
||||
The identifier of an action. Referenced in plugin manifest to assign shortcut to button in UI
|
||||
|
|
@ -1 +1 @@
|
|||
Function that is called when action button is clicked or the shortcut is pressed (including primary and secondary shortcuts). ID parameter is an id of currently focused grid or list item
|
||||
Function that is called when action button is clicked or the shortcut is pressed (including primary and secondary shortcuts). ID parameter is an id of currently focused grid or list item. Returning `{ close: true }` object from the action will close the window
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Checkbox is a type of form input that produces boolean value, either `true` or `false`
|
||||
Checkbox is a type of form input that produces boolean value, either "true" or "false"
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
A container for a set of non-interactable components.
|
||||
Used in a variety of places like [Detail]($COMPONENT$__DETAIL__), [Inline]($COMPONENT$__INLINE__) and [GridItem]($COMPONENT$__GRID_ITEM__).
|
||||
Content is a container for a set of non-interactable components.
|
||||
Used in a variety of places like <Detail/>, <Inline/> and <GridItem/>.
|
||||
By utilizing the power of React the content can also be made dynamic
|
||||
|
|
@ -1 +0,0 @@
|
|||
Date Picker is a type of form input that produces date value represented as a string in `YYYY-MM-DD` format
|
||||
|
|
@ -1 +0,0 @@
|
|||
Text displayed in UI to the left of the date picker itself
|
||||
|
|
@ -1 +0,0 @@
|
|||
Function that is called when the value of the data picker was changed
|
||||
|
|
@ -1 +0,0 @@
|
|||
Value of the Date Picker. Can be used to implement controlled form
|
||||
|
|
@ -1 +1 @@
|
|||
Detail is a root component that contains a possibly dynamic, non-interactable [Content]($COMPONENT$__CONTENT__) and an optional side panel
|
||||
Detail is a root component that contains a possibly dynamic, non-interactable <Content/> component and an optional side panel
|
||||
|
|
@ -1 +1 @@
|
|||
If `true` loading bar is shown above content
|
||||
If "true" loading bar is shown above content
|
||||
|
|
@ -1 +1 @@
|
|||
If `true` loading bar is shown above content
|
||||
If "true" loading bar is shown above content
|
||||
1
docs/js/components/grid/props/focusedItemId.md
Normal file
1
docs/js/components/grid/props/focusedItemId.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Sets item with specified id to be the one that is focused. `undefined` - uncontrolled, `null` - controlled and unset, other values - controlled and set
|
||||
|
|
@ -1 +1 @@
|
|||
If `true` loading bar is shown above content
|
||||
If "true" loading bar is shown above content
|
||||
|
|
@ -1 +1 @@
|
|||
Image data. Supported formats: `png`, `gif`, `jpg`, `webp`, `tiff`
|
||||
Image data. Supported formats: "png", "gif', "jpg", "webp", "tiff"
|
||||
|
|
@ -1,2 +1,2 @@
|
|||
Inline is a root component used with `inline-view` entrypoint type.
|
||||
Inline is a root component used with "inline-view" entrypoint type.
|
||||
Displayed right under search bar in main view
|
||||
1
docs/js/components/list/props/focusedItemId.md
Normal file
1
docs/js/components/list/props/focusedItemId.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Sets item with specified id to be the one that is focused. `undefined` - uncontrolled, `null` - controlled and unset, other values - controlled and set
|
||||
|
|
@ -1 +1 @@
|
|||
If `true` loading bar is shown above content
|
||||
If "true" loading bar is shown above content
|
||||
|
|
@ -1 +1 @@
|
|||
Adds search bar above the content
|
||||
Adds search bar above the content. Text in search bar can be read and set
|
||||
1
docs/js/components/svg/description.md
Normal file
1
docs/js/components/svg/description.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
Component that displays arbitrary SVG image
|
||||
1
docs/js/components/svg/props/source.md
Normal file
1
docs/js/components/svg/props/source.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
SVG image
|
||||
860
docs/schema/plugin_manifest.schema.json
Normal file
860
docs/schema/plugin_manifest.schema.json
Normal file
|
|
@ -0,0 +1,860 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "PluginManifest",
|
||||
"description": "Plugin Manifest definition",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"entrypoint",
|
||||
"gauntlet"
|
||||
],
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"entrypoint": {
|
||||
"description": "Plugin entrypoints, all plugin will have at least one entrypoint",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestEntrypoint"
|
||||
}
|
||||
},
|
||||
"gauntlet": {
|
||||
"description": "General plugin metadata",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestMetadata"
|
||||
}
|
||||
]
|
||||
},
|
||||
"permissions": {
|
||||
"description": "Permissions required by the plugin",
|
||||
"default": {
|
||||
"environment": [],
|
||||
"network": [],
|
||||
"filesystem": {
|
||||
"read": [],
|
||||
"write": []
|
||||
},
|
||||
"exec": {
|
||||
"command": [],
|
||||
"executable": []
|
||||
},
|
||||
"system": [],
|
||||
"clipboard": [],
|
||||
"main_search_bar": []
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestPermissions"
|
||||
}
|
||||
]
|
||||
},
|
||||
"preferences": {
|
||||
"description": "Preferences that can be configured by the user in the settings view",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestPreference"
|
||||
}
|
||||
},
|
||||
"supported_system": {
|
||||
"description": "List of supported operating systems",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestSupportedSystem"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"PluginManifestAction": {
|
||||
"description": "Action definition",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of what the action does",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier for the action, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"shortcut": {
|
||||
"description": "Default keyboard shortcut to trigger the action",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestActionShortcut"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestActionShortcut": {
|
||||
"description": "Keyboard shortcut for a plugin action",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"key",
|
||||
"kind"
|
||||
],
|
||||
"properties": {
|
||||
"key": {
|
||||
"description": "The main key to be pressed for this shortcut",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestActionShortcutKey"
|
||||
}
|
||||
]
|
||||
},
|
||||
"kind": {
|
||||
"description": "The kind of shortcut, defines required modifiers",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestActionShortcutKind"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestActionShortcutKey": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"!",
|
||||
"@",
|
||||
"#",
|
||||
"$",
|
||||
"%",
|
||||
"^",
|
||||
"&",
|
||||
"*",
|
||||
"(",
|
||||
")",
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
"d",
|
||||
"e",
|
||||
"f",
|
||||
"g",
|
||||
"h",
|
||||
"i",
|
||||
"j",
|
||||
"k",
|
||||
"l",
|
||||
"m",
|
||||
"n",
|
||||
"o",
|
||||
"p",
|
||||
"q",
|
||||
"r",
|
||||
"s",
|
||||
"t",
|
||||
"u",
|
||||
"v",
|
||||
"w",
|
||||
"x",
|
||||
"y",
|
||||
"z",
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E",
|
||||
"F",
|
||||
"G",
|
||||
"H",
|
||||
"I",
|
||||
"J",
|
||||
"K",
|
||||
"L",
|
||||
"M",
|
||||
"N",
|
||||
"O",
|
||||
"P",
|
||||
"Q",
|
||||
"R",
|
||||
"S",
|
||||
"T",
|
||||
"U",
|
||||
"V",
|
||||
"W",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"-",
|
||||
"=",
|
||||
",",
|
||||
".",
|
||||
"/",
|
||||
"[",
|
||||
"]",
|
||||
";",
|
||||
"'",
|
||||
"\\",
|
||||
"_",
|
||||
"+",
|
||||
"<",
|
||||
">",
|
||||
"?",
|
||||
"{",
|
||||
"}",
|
||||
":",
|
||||
"\"",
|
||||
"|"
|
||||
]
|
||||
},
|
||||
"PluginManifestActionShortcutKind": {
|
||||
"description": "The kind of shortcut",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Main kind shortcuts require Ctrl modifier on Windows/Linux or Cmd on macOS",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"main"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Alternative kind shortcuts require Alt modifier on Windows/Linux or Opt on macOS",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"alternative"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginManifestClipboardPermissions": {
|
||||
"description": "Clipboard permissions for the plugin",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Allows the plugin to read from the clipboard",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Allows the plugin to write to the clipboard",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"write"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Allows the plugin to clear the clipboard contents",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"clear"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginManifestEntrypoint": {
|
||||
"description": "Plugin entrypoint definition",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"path",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"actions": {
|
||||
"description": "List of definitions of plugin actions",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestAction"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"description": "Entrypoint description",
|
||||
"type": "string"
|
||||
},
|
||||
"icon": {
|
||||
"description": "Entrypoint icon, path to file in assets relative to it",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the entrypoint, can only contain small letters, numbers and dash",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Entrypoint name",
|
||||
"type": "string"
|
||||
},
|
||||
"path": {
|
||||
"description": "Path to TypeScript file relative to package directory",
|
||||
"type": "string"
|
||||
},
|
||||
"preferences": {
|
||||
"description": "List of definitions of plugin preferences",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestPreference"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"description": "Type of the entrypoint",
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestEntrypointTypes"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestEntrypointTypes": {
|
||||
"description": "Types of plugin entrypoints",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "A function-based entrypoint",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"command"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "A view-based entrypoint",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"view"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "A view-based entrypoint displayed under main search bar",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"inline-view"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Entrypoint that can dynamically generates endpoints",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"entrypoint-generator"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginManifestMainSearchBarPermissions": {
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "Allows the plugin to read the main search bar",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"read"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginManifestMetadata": {
|
||||
"description": "General plugin metadata",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"authors": {
|
||||
"description": "List of plugin authors",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestMetadataAuthor"
|
||||
}
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the plugin",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the plugin",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestMetadataAuthor": {
|
||||
"description": "Plugin author",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"name"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Author name",
|
||||
"type": "string"
|
||||
},
|
||||
"uris": {
|
||||
"description": "URIs that identify the author. Can be a link to social media page or an email (if email it should begin with mailto: schema)",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestPermissions": {
|
||||
"description": "Permissions required by the plugin",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"clipboard": {
|
||||
"description": "Clipboard permissions for the plugin",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestClipboardPermissions"
|
||||
}
|
||||
},
|
||||
"environment": {
|
||||
"description": "Environment variables that the plugin can access",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"exec": {
|
||||
"description": "Execution permissions for the plugin",
|
||||
"default": {
|
||||
"command": [],
|
||||
"executable": []
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestPermissionsExec"
|
||||
}
|
||||
]
|
||||
},
|
||||
"filesystem": {
|
||||
"description": "Filesystem permissions for the plugin",
|
||||
"default": {
|
||||
"read": [],
|
||||
"write": []
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/PluginManifestPermissionsFileSystem"
|
||||
}
|
||||
]
|
||||
},
|
||||
"main_search_bar": {
|
||||
"description": "Permissions for the main search bar",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestMainSearchBarPermissions"
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
"description": "Network address (domain or ip address + optional port) that the plugin can access",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"system": {
|
||||
"description": "Deno system permissions for the plugin",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestPermissionsExec": {
|
||||
"description": "Execution permissions for the plugin",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"command": {
|
||||
"description": "List of commands on PATH that the plugin can execute",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"executable": {
|
||||
"description": "List of paths to executables that the plugin can run",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestPermissionsFileSystem": {
|
||||
"description": "Filesystem permissions for the plugin",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"read": {
|
||||
"description": "Paths that the plugin can read from",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"description": "Paths that the plugin can write to",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestPreference": {
|
||||
"description": "User-configurable preference options",
|
||||
"oneOf": [
|
||||
{
|
||||
"description": "A numeric preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "Default value",
|
||||
"type": [
|
||||
"number",
|
||||
"null"
|
||||
],
|
||||
"format": "double"
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"number"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A string preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "Default value",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"string"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "An enum preference with selectable values",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"enum_values",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "Default value",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"enum_values": {
|
||||
"description": "List of allowed enum values",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestPreferenceEnumValue"
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"enum"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A boolean preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"default": {
|
||||
"description": "Default value",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"bool"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A list of strings preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"list_of_strings"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A list of numbers preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"list_of_numbers"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "A list of enumerated preference values",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"description",
|
||||
"enum_values",
|
||||
"id",
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"description": {
|
||||
"description": "Description of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"enum_values": {
|
||||
"description": "List of allowed enum values",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/PluginManifestPreferenceEnumValue"
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"description": "Unique identifier of the preference, can only contain letters and numbers",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Display name of the preference",
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"list_of_enums"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"PluginManifestPreferenceEnumValue": {
|
||||
"description": "Definition of the values available in enumerated preference",
|
||||
"type": "object",
|
||||
"required": [
|
||||
"label",
|
||||
"value"
|
||||
],
|
||||
"properties": {
|
||||
"label": {
|
||||
"description": "Displayed name",
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"description": "Internal enum value",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PluginManifestSupportedSystem": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"os"
|
||||
],
|
||||
"properties": {
|
||||
"os": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"linux"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"os"
|
||||
],
|
||||
"properties": {
|
||||
"os": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"windows"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"os"
|
||||
],
|
||||
"properties": {
|
||||
"os": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"macos"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 520 KiB After Width: | Height: | Size: 678 KiB |
3
example_plugins/.gitignore
vendored
Normal file
3
example_plugins/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
run
|
||||
out_screenshot
|
||||
out
|
||||
4
example_plugins/plugins/command/assets/masterpiece.txt
Normal file
4
example_plugins/plugins/command/assets/masterpiece.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
44
example_plugins/plugins/command/gauntlet.toml
Normal file
44
example_plugins/plugins/command/gauntlet.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Command'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start simple
|
||||
[[entrypoint]]
|
||||
id = 'simple'
|
||||
name = 'Simple'
|
||||
path = 'src/simple.tsx'
|
||||
type = 'command'
|
||||
description = ''
|
||||
# docs-code-segment:end
|
||||
|
||||
# docs-code-segment:start assets
|
||||
[[entrypoint]]
|
||||
id = 'assets'
|
||||
name = 'Assets'
|
||||
path = 'src/assets.tsx'
|
||||
type = 'command'
|
||||
description = ''
|
||||
# docs-code-segment:end
|
||||
|
||||
# docs-code-segment:start preferences
|
||||
[[preferences]]
|
||||
id = 'testBool'
|
||||
name = 'Test Boolean Preference'
|
||||
type = 'bool'
|
||||
default = true
|
||||
description = ""
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'preferences'
|
||||
name = 'Preferences'
|
||||
path = 'src/preferences.tsx'
|
||||
type = 'command'
|
||||
description = ''
|
||||
|
||||
[[entrypoint.preferences]]
|
||||
id = 'testStr'
|
||||
name = 'Test String Preference'
|
||||
type = 'string'
|
||||
default = 'test_value'
|
||||
description = ""
|
||||
# docs-code-segment:end
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-detailt",
|
||||
"name": "@project-gauntlet/docs-command",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
7
example_plugins/plugins/command/src/assets.tsx
Normal file
7
example_plugins/plugins/command/src/assets.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import { assetData } from "@project-gauntlet/api/helpers";
|
||||
|
||||
export default async function Command() {
|
||||
const data = await assetData("masterpiece.txt");
|
||||
const decodedData = new TextDecoder().decode(data);
|
||||
console.log(decodedData)
|
||||
}
|
||||
8
example_plugins/plugins/command/src/preferences.tsx
Normal file
8
example_plugins/plugins/command/src/preferences.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { CommandContext } from "@project-gauntlet/api/helpers";
|
||||
|
||||
type PluginCommandContext = CommandContext<{ testBool: boolean }, { testStr: string }>;
|
||||
|
||||
export default async function Command({ pluginPreferences, entrypointPreferences }: PluginCommandContext) {
|
||||
console.log(pluginPreferences.testBool);
|
||||
console.log(entrypointPreferences.testStr);
|
||||
}
|
||||
3
example_plugins/plugins/command/src/simple.tsx
Normal file
3
example_plugins/plugins/command/src/simple.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default async function Command() {
|
||||
console.log("Running the Gauntlet...")
|
||||
}
|
||||
13
example_plugins/plugins/command_environment/gauntlet.toml
Normal file
13
example_plugins/plugins/command_environment/gauntlet.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Command Environment'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start environment
|
||||
[[entrypoint]]
|
||||
id = 'environment'
|
||||
name = 'Environment'
|
||||
path = 'src/environment.tsx'
|
||||
type = 'command'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:end
|
||||
17
example_plugins/plugins/command_environment/package.json
Normal file
17
example_plugins/plugins/command_environment/package.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-command-environment",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { Environment } from "@project-gauntlet/api/helpers";
|
||||
|
||||
export default function Command() {
|
||||
console.log(Environment.gauntletVersion)
|
||||
console.log(Environment.isDevelopment)
|
||||
console.log(Environment.pluginDataDir)
|
||||
console.log(Environment.pluginCacheDir)
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator Accessories'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start accessories
|
||||
[[entrypoint]]
|
||||
id = 'accessories'
|
||||
name = 'Accessories'
|
||||
path = 'src/accessories.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator-accessories",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
import { Icons } from "@project-gauntlet/api/components";
|
||||
|
||||
export default function EntrypointGenerator({ add }: GeneratorContext): void {
|
||||
add('generated', {
|
||||
name: 'Generated Command',
|
||||
actions: [
|
||||
{
|
||||
label: "Run the Gauntlet",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet...')
|
||||
}
|
||||
}
|
||||
],
|
||||
accessories: [{ icon: Icons.Battery, text: "100 %" }]
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator Action Shortcut'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start action-shortcut
|
||||
[[entrypoint]]
|
||||
id = 'action-shortcut'
|
||||
name = 'Action Shortcut'
|
||||
path = 'src/action-shortcut.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
|
||||
[[entrypoint.actions]]
|
||||
id = 'anotherAction'
|
||||
description = ''
|
||||
shortcut = { key = 'g', kind = 'main'}
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator-action-shortcuts",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
|
||||
type PluginGeneratorContext = GeneratorContext<{ testBool: boolean }, { testStr: string }>;
|
||||
|
||||
export default function EntrypointGenerator({ add }: PluginGeneratorContext): void {
|
||||
add('generated', {
|
||||
name: 'Generated Command',
|
||||
actions: [
|
||||
{
|
||||
label: "Primary Action", // Executed when Enter is pressed
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet... - Primary Action')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Secondary Action", // Executed when Shift+Enter is pressed
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet... - Secondary Action')
|
||||
}
|
||||
},
|
||||
{
|
||||
ref: "anotherAction", // Executed when pressing shortcut specified in Plugin Manifest
|
||||
label: "Another Action",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet... - Another Action')
|
||||
}
|
||||
}
|
||||
],
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator FS Events'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start fs-events
|
||||
[[entrypoint]]
|
||||
id = 'fs-events'
|
||||
name = 'FS Events'
|
||||
path = 'src/fs-events.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
|
||||
[permissions.filesystem]
|
||||
read = ["/tmp/gauntlet-example"]
|
||||
write = ["/tmp/gauntlet-example"]
|
||||
|
||||
[[supported_system]]
|
||||
os = 'linux'
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator-fs-events",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
|
||||
export default async function EntrypointGenerator({ add, remove }: GeneratorContext): Promise<void | (() => void)> {
|
||||
const id = "generated";
|
||||
const path = "/tmp/gauntlet-example";
|
||||
|
||||
await Deno.create(path)
|
||||
add(id, generatedItem("default"))
|
||||
|
||||
const watcher = Deno.watchFs(path);
|
||||
|
||||
(async () => {
|
||||
for await (const _event of watcher) {
|
||||
try {
|
||||
const value = await Deno.readTextFile(path);
|
||||
add(id, generatedItem(value))
|
||||
} catch (err) {
|
||||
remove(id)
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
watcher.close()
|
||||
}
|
||||
}
|
||||
|
||||
function generatedItem(value: string) {
|
||||
return {
|
||||
name: `Generated Command - ${value}`,
|
||||
actions: [
|
||||
{
|
||||
label: "Run the Gauntlet",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet...')
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator Icons'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start icons
|
||||
[[entrypoint]]
|
||||
id = 'icons'
|
||||
name = 'Icons'
|
||||
path = 'src/icons.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
|
||||
[permissions]
|
||||
network = ["img.icons8.com"]
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
|
||||
export default async function EntrypointGenerator({ add }: GeneratorContext): Promise<void> {
|
||||
|
||||
const response = await fetch("https://img.icons8.com/?size=32&id=21276&format=png");
|
||||
const arrayBuffer = await response.bytes();
|
||||
|
||||
add('generated', {
|
||||
name: 'Generated Command',
|
||||
actions: [
|
||||
{
|
||||
label: "Run the Gauntlet",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet...')
|
||||
}
|
||||
}
|
||||
],
|
||||
icon: arrayBuffer
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator Preferences'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start preferences
|
||||
[[preferences]]
|
||||
id = 'testBool'
|
||||
name = 'Test Boolean Preference'
|
||||
type = 'bool'
|
||||
default = true
|
||||
description = ""
|
||||
|
||||
[[entrypoint]]
|
||||
id = 'preferences'
|
||||
name = 'Preferences'
|
||||
path = 'src/preferences.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
|
||||
[[entrypoint.preferences]]
|
||||
id = 'testStr'
|
||||
name = 'Test String Preference'
|
||||
type = 'string'
|
||||
default = 'test_value'
|
||||
description = ""
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator-preferences",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
|
||||
type PluginGeneratorContext = GeneratorContext<{ testBool: boolean }, { testStr: string }>;
|
||||
|
||||
export default function EntrypointGenerator({ add, pluginPreferences, entrypointPreferences }: PluginGeneratorContext): void {
|
||||
add('generated', {
|
||||
name: 'Generated Command - ' + entrypointPreferences.testStr,
|
||||
actions: [
|
||||
{
|
||||
label: "Run the Gauntlet",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet... ' + pluginPreferences.testBool)
|
||||
}
|
||||
}
|
||||
],
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"module": "ES2022",
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2022",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"lib": ["ES2020"]
|
||||
}
|
||||
2
example_plugins/plugins/entrypoint_generator_simple/.gitignore
vendored
Normal file
2
example_plugins/plugins/entrypoint_generator_simple/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
dist
|
||||
node_modules
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Entrypoint Generator Simple'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start simple
|
||||
[[entrypoint]]
|
||||
id = 'simple'
|
||||
name = 'Simple'
|
||||
path = 'src/simple.tsx'
|
||||
type = 'entrypoint-generator'
|
||||
description = ''
|
||||
# docs-code-segment:end
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "@project-gauntlet/docs-entrypoint-generator-simple",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "gauntlet build",
|
||||
"dev": "gauntlet dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@project-gauntlet/api": "file:../../js/api"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/deno": "*",
|
||||
"@project-gauntlet/tools": "*",
|
||||
"typescript": "*"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { GeneratorContext } from "@project-gauntlet/api/helpers";
|
||||
import { ReactElement } from "react";
|
||||
import { List } from "@project-gauntlet/api/components";
|
||||
|
||||
function ListView(): ReactElement {
|
||||
return (
|
||||
<List>
|
||||
<List.Item id="example-item" title="Example Item"/>
|
||||
</List>
|
||||
)
|
||||
}
|
||||
|
||||
export default function EntrypointGenerator({ add }: GeneratorContext): void {
|
||||
add('generated', {
|
||||
name: 'Generated Command',
|
||||
actions: [
|
||||
{
|
||||
label: "Run the Gauntlet",
|
||||
run: () => {
|
||||
console.log('Running the Gauntlet...')
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
add('generated', {
|
||||
name: 'Generated View',
|
||||
actions: [
|
||||
{
|
||||
label: "Open generated view",
|
||||
view: () => <ListView/>
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"module": "ES2022",
|
||||
"esModuleInterop": true,
|
||||
"target": "ES2022",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"lib": ["ES2020"]
|
||||
}
|
||||
2
example_plugins/plugins/ui_action_panel/.gitignore
vendored
Normal file
2
example_plugins/plugins/ui_action_panel/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
dist
|
||||
node_modules
|
||||
26
example_plugins/plugins/ui_action_panel/gauntlet.toml
Normal file
26
example_plugins/plugins/ui_action_panel/gauntlet.toml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
[gauntlet]
|
||||
name = 'Docs Action Panel'
|
||||
description = ''
|
||||
|
||||
# docs-code-segment:start action
|
||||
[[entrypoint]]
|
||||
id = 'action'
|
||||
name = 'Action'
|
||||
path = 'src/action.tsx'
|
||||
type = 'view'
|
||||
description = ''
|
||||
|
||||
[[entrypoint.actions]]
|
||||
id = 'actionId'
|
||||
description = ''
|
||||
shortcut = { key = 'g', kind = 'main'}
|
||||
# docs-code-segment:end
|
||||
|
||||
# docs-code-segment:start section
|
||||
[[entrypoint]]
|
||||
id = 'section'
|
||||
name = 'Section'
|
||||
path = 'src/section.tsx'
|
||||
type = 'view'
|
||||
description = ''
|
||||
# docs-code-segment:end
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue