base on Loungy is a WIP launcher in the vein of Spotlight, Alfred, Raycast. <h1 align="center">
<img src="./icons/icon_512x512@
[email protected]" width="100" alt="Logo"/><br/>
Loungy
</h1>
<p align="center">
Loungy is an application launcher in the vein of Raycast and Alfred.<br>
It's built using GPUI, a GPU accelerated application framework for Rust.
</p>
## Showcase
https://github.com/MatthiasGrandl/Loungy/assets/50196894/d5c84579-77e6-4e0b-980a-7d1f1975d713
## Features
- [x] Launching apps
- [x] Calculator (including unit/currency/date conversions, thanks to [Numbat](https://numbat.dev/))
- [x] Task manager (killing processes)
- [x] MacOS menu search
- [x] Clipboard manager
- [x] Tailscale peer list
- [x] Bitwarden password client (only viewing, not editing)
- [x] Matrix Chat client (very early WIP)
In the absence of a proper extension system (which is wanted, but still quite far out at this point) I am adding features I need, but that aren't universally useful behind cargo feature flags.
So far there is `clipboard`, `tailscale`, `bitwarden` and `matrix`. You can also build all optional features with `cargo build --all-features --release`.
## Installation
Either download the `.dmg` from the [releases section](https://github.com/MatthiasGrandl/Loungy/releases) or use homebrew:
```sh
brew install loungy
```
The pre-built version comes with the following optional crate features:
- `clipboard`
If you want to try any other optional features, at the moment you will have to build Loungy yourself.
## Development
### Requirements
- Xcode Apple Swift 5.9.2
- Rust v1.75.0
### Running
```
cargo run dev
```
## Caveats
- ~~It is MacOS only, but I would love to support a Linux build in the future. That won't happen until GPUI adds Linux support.~~ There is some very rough Linux support. It's still very early since a lot of functionality in GPUI required for Loungy hasn't made it into the Linux GPUI yet (they are obviously focusing on getting Zed features running first).
- Accessibility is still a nightmare. GPUI is lacking a proper accessible text input so currently I am implementing one myself. Screen readers or people with impairments please don't try to use this yet.
- ~~The window position is currently hardcoded, so depending on your screen resolution it might not be in the best position. Will be fixed as soon as there is an API for it in GPUI.~~ I kinda fixed this, but it's probably still wonky on multi display setups.
- ~~The hotkey is currently hardcoded to `Opt+Ctrl+Cmd+Space`~~ Hotkeys are now rebindable, but it's still a bit sketchy since GPUI doesn't report raw keycodes, while the Tauri hotkey manager uses raw keycodes. To rebind you can simple select any command in the root search and use the `Change Hotkey` action.
### Linux
Experimental Linux support. Building requires (on Fedora Wayland):
- `openssl-devel`
- `wayland-devel`
- `g++`
- `fontconfig-devel`
- `libxcb-devel`
- `libxkbcommon-x11-devel`
- `libxkbcommon-devel`
Many features won't work yet, since I am using a lot of MacOS specific APIs for autofilling. So notably the `clipboard` and `bitwarden` features will need Linux specific implementations to get working.
### Credits
Loungy wouldn't be possible without the awesome open source ecosystem:
- [GPUI](https://www.gpui.rs/) : The lovely framework
- [Numbat](https://numbat.dev/) : Used as the calculator
- [Lucide](https://lucide.dev/) : Amazing open source SVG icon-set
- [Catppuccin](https://github.com/catppuccin) : The theme that makes everything look good
- [swift-rs](https://github.com/Brendonovich/swift-rs) : For providing a way to interface with accessibility APIs and other MacOS native stuff that I wouldn't know how to do with pure Rust
- [nucleo](https://github.com/helix-editor/nucleo) : Fuzzy searcher implemented by the team of my favorite modal editor [Helix](https://github.com/helix-editor/helix)
", Assign "at most 3 tags" to the expected json: {"id":"7649","tags":[]} "only from the tags list I provide: [{"id":77,"name":"3d"},{"id":89,"name":"agent"},{"id":17,"name":"ai"},{"id":54,"name":"algorithm"},{"id":24,"name":"api"},{"id":44,"name":"authentication"},{"id":3,"name":"aws"},{"id":27,"name":"backend"},{"id":60,"name":"benchmark"},{"id":72,"name":"best-practices"},{"id":39,"name":"bitcoin"},{"id":37,"name":"blockchain"},{"id":1,"name":"blog"},{"id":45,"name":"bundler"},{"id":58,"name":"cache"},{"id":21,"name":"chat"},{"id":49,"name":"cicd"},{"id":4,"name":"cli"},{"id":64,"name":"cloud-native"},{"id":48,"name":"cms"},{"id":61,"name":"compiler"},{"id":68,"name":"containerization"},{"id":92,"name":"crm"},{"id":34,"name":"data"},{"id":47,"name":"database"},{"id":8,"name":"declarative-gui "},{"id":9,"name":"deploy-tool"},{"id":53,"name":"desktop-app"},{"id":6,"name":"dev-exp-lib"},{"id":59,"name":"dev-tool"},{"id":13,"name":"ecommerce"},{"id":26,"name":"editor"},{"id":66,"name":"emulator"},{"id":62,"name":"filesystem"},{"id":80,"name":"finance"},{"id":15,"name":"firmware"},{"id":73,"name":"for-fun"},{"id":2,"name":"framework"},{"id":11,"name":"frontend"},{"id":22,"name":"game"},{"id":81,"name":"game-engine "},{"id":23,"name":"graphql"},{"id":84,"name":"gui"},{"id":91,"name":"http"},{"id":5,"name":"http-client"},{"id":51,"name":"iac"},{"id":30,"name":"ide"},{"id":78,"name":"iot"},{"id":40,"name":"json"},{"id":83,"name":"julian"},{"id":38,"name":"k8s"},{"id":31,"name":"language"},{"id":10,"name":"learning-resource"},{"id":33,"name":"lib"},{"id":41,"name":"linter"},{"id":28,"name":"lms"},{"id":16,"name":"logging"},{"id":76,"name":"low-code"},{"id":90,"name":"message-queue"},{"id":42,"name":"mobile-app"},{"id":18,"name":"monitoring"},{"id":36,"name":"networking"},{"id":7,"name":"node-version"},{"id":55,"name":"nosql"},{"id":57,"name":"observability"},{"id":46,"name":"orm"},{"id":52,"name":"os"},{"id":14,"name":"parser"},{"id":74,"name":"react"},{"id":82,"name":"real-time"},{"id":56,"name":"robot"},{"id":65,"name":"runtime"},{"id":32,"name":"sdk"},{"id":71,"name":"search"},{"id":63,"name":"secrets"},{"id":25,"name":"security"},{"id":85,"name":"server"},{"id":86,"name":"serverless"},{"id":70,"name":"storage"},{"id":75,"name":"system-design"},{"id":79,"name":"terminal"},{"id":29,"name":"testing"},{"id":12,"name":"ui"},{"id":50,"name":"ux"},{"id":88,"name":"video"},{"id":20,"name":"web-app"},{"id":35,"name":"web-server"},{"id":43,"name":"webassembly"},{"id":69,"name":"workflow"},{"id":87,"name":"yaml"}]" returns me the "expected json"