mirror of
https://github.com/thesleepingsage/hypr-lens.git
synced 2026-11-01 06:56:42 +01:00
fix(screenshots): save to configured path with tilde expansion
Fixes #1 - Screenshots now properly save to disk when savePath is configured. Changes: - Changed config format from JSONC to JSON for reliable parsing - Added tilde (~) expansion for all save paths - Edit mode (swappy) now saves to configured savePath via -o flag - Default paths: ~/Pictures/hypr-lens, ~/Videos/hypr-lens - Added copyAlsoSaves option for users who want Copy to also save - Copy mode (left-click) now clipboard-only by default - Updated documentation and changelog Closes #1
This commit is contained in:
1 parent
9c97ec1364
commit
c616efa0cc
12 files changed
+168
-107
No files matched your search
@@ -53,6 +53,42 @@ Initial public release! 🎉
|
|||||||
- **Installer Recovery** - Detect and recover missing shell integration during update mode
|
- **Installer Recovery** - Detect and recover missing shell integration during update mode
|
||||||
- **Invalid Input Handling** - Improved input validation in integration recovery flow
|
- **Invalid Input Handling** - Improved input validation in integration recovery flow
|
||||||
|
|
||||||
|
## 1.4.0 - 2025-12-19
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **Screenshot Save Path** - Screenshots and edited images now properly save to configured `savePath`
|
||||||
|
- **Tilde Expansion** - `~/` paths now correctly expand in all save path configurations
|
||||||
|
- **Swappy Integration** - Edit mode (swappy) now saves to configured path instead of default Desktop
|
||||||
|
- **Config Parsing** - Changed config format from JSONC to JSON for reliable parsing
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Default Save Paths** - Screenshots default to `~/Pictures/hypr-lens`, recordings to `~/Videos/hypr-lens`
|
||||||
|
- **Copy Also Saves Option** - New `copyAlsoSaves` config option for users who want left-click to also save
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Copy Mode Behavior** - Left-click (Copy) now only copies to clipboard by default; use Edit mode (right-click) or enable `copyAlsoSaves` to save files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1.3.0 - 2025-12-16
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **Right-Click Edit on Monitor Buttons** - Right-click monitor buttons to capture and edit with swappy
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **MonitorButton Tooltip** - Fixed missing services import for tooltip functionality
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- **Documentation** - Clarified compatibility notes for non-Arch distributions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 1.2.0 - 2025-12-08
|
## 1.2.0 - 2025-12-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -70,6 +106,8 @@ Initial public release! 🎉
|
|||||||
|
|
||||||
| Version | Date | Highlights |
|
| Version | Date | Highlights |
|
||||||
|---------|------|------------|
|
|---------|------|------------|
|
||||||
|
| 1.4.0 | 2025-12-19 | Screenshot save fix, tilde expansion, swappy integration |
|
||||||
|
| 1.3.0 | 2025-12-16 | Right-click edit on monitor buttons |
|
||||||
| 1.2.0 | 2025-12-08 | Demo videos, security documentation |
|
| 1.2.0 | 2025-12-08 | Demo videos, security documentation |
|
||||||
| 1.1.0 | 2025-12-08 | Monitor capture buttons, installer recovery |
|
| 1.1.0 | 2025-12-08 | Monitor capture buttons, installer recovery |
|
||||||
| 1.0.0 | 2025-12-08 | Initial release |
|
| 1.0.0 | 2025-12-08 | Initial release |
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ cd hypr-lens
|
|||||||
| QML modules | `~/.config/quickshell/hypr-lens/` |
|
| QML modules | `~/.config/quickshell/hypr-lens/` |
|
||||||
| Scripts | `~/.local/share/hypr-lens/scripts/` |
|
| Scripts | `~/.local/share/hypr-lens/scripts/` |
|
||||||
| Python venv | `~/.local/share/hypr-lens/venv/` (optional) |
|
| Python venv | `~/.local/share/hypr-lens/venv/` (optional) |
|
||||||
| Default config | `~/.config/hypr-lens/config.jsonc` |
|
| Default config | `~/.config/hypr-lens/config.json` |
|
||||||
|
|
||||||
## Updating
|
## Updating
|
||||||
|
|
||||||
@@ -229,7 +229,7 @@ See [MANUAL.md](MANUAL.md#ipc-commands) for detailed IPC documentation.
|
|||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Config file: `~/.config/hypr-lens/config.jsonc`
|
Config file: `~/.config/hypr-lens/config.json`
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><strong>Full Configuration Reference</strong></summary>
|
<summary><strong>Full Configuration Reference</strong></summary>
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ The installer only touches files in your user directories:
|
|||||||
| Path | Action | Purpose |
|
| Path | Action | Purpose |
|
||||||
|------|--------|---------|
|
|------|--------|---------|
|
||||||
| `~/.config/quickshell/hypr-lens/` | Create | QML modules (UI components) |
|
| `~/.config/quickshell/hypr-lens/` | Create | QML modules (UI components) |
|
||||||
| `~/.config/hypr-lens/config.jsonc` | Create | User configuration file |
|
| `~/.config/hypr-lens/config.json` | Create | User configuration file |
|
||||||
| `~/.local/share/hypr-lens/scripts/` | Create | Helper scripts (OpenCV, recording) |
|
| `~/.local/share/hypr-lens/scripts/` | Create | Helper scripts (OpenCV, recording) |
|
||||||
| `~/.local/share/hypr-lens/venv/` | Create (optional) | Python venv for content detection |
|
| `~/.local/share/hypr-lens/venv/` | Create (optional) | Python venv for content detection |
|
||||||
| `~/.config/quickshell/shell.qml` | Modify (optional) | Integration (with timestamped backup) |
|
| `~/.config/quickshell/shell.qml` | Modify (optional) | Integration (with timestamped backup) |
|
||||||
|
|||||||
@@ -44,9 +44,14 @@ Screenshot settings.
|
|||||||
|
|
||||||
| Setting | Default | Description |
|
| Setting | Default | Description |
|
||||||
|---------|---------|-------------|
|
|---------|---------|-------------|
|
||||||
| `savePath` | `""` | Where to save screenshots. Empty = clipboard only |
|
| `savePath` | `""` | Where to save screenshots. Empty = `~/Pictures/hypr-lens` |
|
||||||
|
| `copyAlsoSaves` | `false` | If `true`, Copy mode (left-click) also saves to disk. If `false`, only Edit mode (swappy) saves. |
|
||||||
|
|
||||||
**Example:** `"/home/user/Pictures/Screenshots"`
|
**Behavior:**
|
||||||
|
- **Left-click (Copy)**: Copies to clipboard only (unless `copyAlsoSaves` is `true`)
|
||||||
|
- **Right-click (Edit)**: Opens swappy for annotation, then saves to `savePath`
|
||||||
|
|
||||||
|
**Example:** `"/home/user/Pictures/Screenshots"` or `"~/Pictures/Screenshots"`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -56,7 +61,7 @@ Screen recording settings.
|
|||||||
|
|
||||||
| Setting | Default | Description |
|
| Setting | Default | Description |
|
||||||
|---------|---------|-------------|
|
|---------|---------|-------------|
|
||||||
| `savePath` | `""` | Where to save recordings. Empty = `~/Videos` |
|
| `savePath` | `""` | Where to save recordings. Empty = `~/Videos/hypr-lens` |
|
||||||
|
|
||||||
**Example:** `"/home/user/Videos/Recordings"`
|
**Example:** `"/home/user/Videos/Recordings"`
|
||||||
|
|
||||||
@@ -136,4 +141,4 @@ Circle selection tool settings.
|
|||||||
|
|
||||||
- Empty string `""` for path settings = use default behavior
|
- Empty string `""` for path settings = use default behavior
|
||||||
- Restart quickshell after changes: `killall quickshell; quickshell &`
|
- Restart quickshell after changes: `killall quickshell; quickshell &`
|
||||||
- Use absolute paths (e.g., `/home/user/...` not `~/...`)
|
- Both absolute paths (`/home/user/...`) and tilde paths (`~/...`) are supported
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"appearance": {
|
||||||
|
"matugenPath": "",
|
||||||
|
"ripple": {
|
||||||
|
"usePrimaryColor": true,
|
||||||
|
"colorMixRatio": 0.65,
|
||||||
|
"solidRadius": 0.45,
|
||||||
|
"fadeRadius": 0.7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"screenSnip": {
|
||||||
|
"savePath": "",
|
||||||
|
"copyAlsoSaves": false
|
||||||
|
},
|
||||||
|
"screenRecord": {
|
||||||
|
"savePath": ""
|
||||||
|
},
|
||||||
|
"ocr": {
|
||||||
|
"useCircleSelection": false
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"imageSearch": {
|
||||||
|
"imageSearchEngineBaseUrl": "https://lens.google.com/uploadbyurl?url=",
|
||||||
|
"useCircleSelection": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"monitorOrder": [],
|
||||||
|
"regionSelector": {
|
||||||
|
"targetRegions": {
|
||||||
|
"windows": true,
|
||||||
|
"layers": false,
|
||||||
|
"content": true,
|
||||||
|
"showLabel": false,
|
||||||
|
"opacity": 0.3,
|
||||||
|
"contentRegionOpacity": 0.8,
|
||||||
|
"selectionPadding": 5
|
||||||
|
},
|
||||||
|
"rect": {
|
||||||
|
"showAimLines": true
|
||||||
|
},
|
||||||
|
"circle": {
|
||||||
|
"strokeWidth": 6,
|
||||||
|
"padding": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
{
|
|
||||||
// ─── Appearance ─────────────────────────────────────────────
|
|
||||||
// Theme and visual settings
|
|
||||||
"appearance": {
|
|
||||||
// Path to matugen.json for dynamic theming (empty = ~/.config/quickshell/matugen.json)
|
|
||||||
"matugenPath": "",
|
|
||||||
|
|
||||||
// Button click ripple effect
|
|
||||||
"ripple": {
|
|
||||||
"usePrimaryColor": true, // true = accent color, false = subtle gray
|
|
||||||
"colorMixRatio": 0.65, // 0.0 = bold/visible, 1.0 = invisible
|
|
||||||
"solidRadius": 0.45, // How far solid color extends (0.0-1.0)
|
|
||||||
"fadeRadius": 0.7 // Where fade ends (0.0-1.0)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// ─── Screenshots ────────────────────────────────────────────
|
|
||||||
"screenSnip": {
|
|
||||||
// Save location (empty = clipboard only)
|
|
||||||
// Example: "/home/user/Pictures/Screenshots"
|
|
||||||
"savePath": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
// ─── Screen Recording ───────────────────────────────────────
|
|
||||||
"screenRecord": {
|
|
||||||
// Save location (empty = ~/Videos)
|
|
||||||
"savePath": ""
|
|
||||||
},
|
|
||||||
|
|
||||||
// ─── OCR (Text Extraction) ──────────────────────────────────
|
|
||||||
"ocr": {
|
|
||||||
"useCircleSelection": false // true = circle tool, false = rectangle
|
|
||||||
},
|
|
||||||
|
|
||||||
// ─── Image Search ───────────────────────────────────────────
|
|
||||||
"search": {
|
|
||||||
"imageSearch": {
|
|
||||||
// Reverse image search URL (default: Google Lens)
|
|
||||||
// Alternatives: TinEye, Bing Visual Search
|
|
||||||
"imageSearchEngineBaseUrl": "https://lens.google.com/uploadbyurl?url=",
|
|
||||||
"useCircleSelection": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// ─── Monitor Order ──────────────────────────────────────────
|
|
||||||
// Monitor button order for full-screen capture (empty = auto-detect)
|
|
||||||
// Example: ["DP-2", "DP-1"] to show DP-2 button first
|
|
||||||
"monitorOrder": [],
|
|
||||||
|
|
||||||
// ─── Region Selector ────────────────────────────────────────
|
|
||||||
// Controls the selection overlay behavior
|
|
||||||
"regionSelector": {
|
|
||||||
// Auto-detection of clickable regions
|
|
||||||
"targetRegions": {
|
|
||||||
"windows": true, // Detect window boundaries
|
|
||||||
"layers": false, // Detect Hyprland layers (panels, bars)
|
|
||||||
"content": true, // OpenCV content detection
|
|
||||||
"showLabel": false, // Show labels on regions
|
|
||||||
"opacity": 0.3, // Highlight opacity (0.0-1.0)
|
|
||||||
"contentRegionOpacity": 0.8,
|
|
||||||
"selectionPadding": 5 // Extra pixels around regions
|
|
||||||
},
|
|
||||||
// Rectangle selection tool
|
|
||||||
"rect": {
|
|
||||||
"showAimLines": true // Show crosshair when drawing
|
|
||||||
},
|
|
||||||
// Circle selection tool
|
|
||||||
"circle": {
|
|
||||||
"strokeWidth": 6, // Outline thickness
|
|
||||||
"padding": 10 // Extra space around selection
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+23
-11
@@ -26,7 +26,7 @@ Components installed:
|
|||||||
1. QML modules → ~/.config/quickshell/hypr-lens/
|
1. QML modules → ~/.config/quickshell/hypr-lens/
|
||||||
2. Scripts → ~/.local/share/hypr-lens/scripts/
|
2. Scripts → ~/.local/share/hypr-lens/scripts/
|
||||||
3. Python venv → ~/.local/share/hypr-lens/venv/
|
3. Python venv → ~/.local/share/hypr-lens/venv/
|
||||||
4. Default config → ~/.config/hypr-lens/config.jsonc
|
4. Default config → ~/.config/hypr-lens/config.json
|
||||||
|
|
||||||
Generated (you copy manually):
|
Generated (you copy manually):
|
||||||
- keybinds.example.conf → Copy contents to your Hyprland keybinds config
|
- keybinds.example.conf → Copy contents to your Hyprland keybinds config
|
||||||
@@ -402,7 +402,7 @@ install_config() {
|
|||||||
|
|
||||||
if dry_run_preview \
|
if dry_run_preview \
|
||||||
"Would create: $CONFIG_DIR" \
|
"Would create: $CONFIG_DIR" \
|
||||||
"Would copy: $SCRIPT_DIR/defaults/config.jsonc → $CONFIG_DIR/config.jsonc" \
|
"Would copy: $SCRIPT_DIR/defaults/config.json → $CONFIG_DIR/config.json" \
|
||||||
"Would copy: $SCRIPT_DIR/defaults/CONFIG_README.md → $CONFIG_DIR/CONFIG_README.md"; then
|
"Would copy: $SCRIPT_DIR/defaults/CONFIG_README.md → $CONFIG_DIR/CONFIG_README.md"; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -412,16 +412,28 @@ install_config() {
|
|||||||
# Always copy/update the README
|
# Always copy/update the README
|
||||||
cp "$SCRIPT_DIR/defaults/CONFIG_README.md" "$CONFIG_DIR/CONFIG_README.md"
|
cp "$SCRIPT_DIR/defaults/CONFIG_README.md" "$CONFIG_DIR/CONFIG_README.md"
|
||||||
|
|
||||||
if [[ -f "$CONFIG_DIR/config.jsonc" ]]; then
|
# Migrate old config.jsonc to config.json if needed
|
||||||
warn "Config already exists at $CONFIG_DIR/config.jsonc"
|
if [[ -f "$CONFIG_DIR/config.jsonc" && ! -f "$CONFIG_DIR/config.json" ]]; then
|
||||||
|
warn "Found old config.jsonc - migrating to config.json"
|
||||||
|
# Strip comments and trailing commas for valid JSON
|
||||||
|
if sed 's|//.*||g; s/,\s*}/}/g; s/,\s*]/]/g' "$CONFIG_DIR/config.jsonc" | jq . > "$CONFIG_DIR/config.json" 2>/dev/null; then
|
||||||
|
success "Config migrated to config.json"
|
||||||
|
info "Old config.jsonc preserved as backup"
|
||||||
|
else
|
||||||
|
warn "Migration failed - installing default config"
|
||||||
|
cp "$SCRIPT_DIR/defaults/config.json" "$CONFIG_DIR/config.json"
|
||||||
|
success "Default config installed"
|
||||||
|
fi
|
||||||
|
elif [[ -f "$CONFIG_DIR/config.json" ]]; then
|
||||||
|
warn "Config already exists at $CONFIG_DIR/config.json"
|
||||||
if ask "Overwrite with defaults?"; then
|
if ask "Overwrite with defaults?"; then
|
||||||
cp "$SCRIPT_DIR/defaults/config.jsonc" "$CONFIG_DIR/config.jsonc"
|
cp "$SCRIPT_DIR/defaults/config.json" "$CONFIG_DIR/config.json"
|
||||||
success "Config overwritten"
|
success "Config overwritten"
|
||||||
else
|
else
|
||||||
success "Keeping existing config"
|
success "Keeping existing config"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
cp "$SCRIPT_DIR/defaults/config.jsonc" "$CONFIG_DIR/config.jsonc"
|
cp "$SCRIPT_DIR/defaults/config.json" "$CONFIG_DIR/config.json"
|
||||||
success "Default config installed"
|
success "Default config installed"
|
||||||
fi
|
fi
|
||||||
success "Config README installed"
|
success "Config README installed"
|
||||||
@@ -802,8 +814,8 @@ discover_matugen() {
|
|||||||
|
|
||||||
if [[ -n "$selected_path" ]]; then
|
if [[ -n "$selected_path" ]]; then
|
||||||
if [[ -f "$selected_path" ]]; then
|
if [[ -f "$selected_path" ]]; then
|
||||||
# Update config.jsonc with selected path
|
# Update config.json with selected path
|
||||||
if [[ -f "$CONFIG_DIR/config.jsonc" ]]; then
|
if [[ -f "$CONFIG_DIR/config.json" ]]; then
|
||||||
if dry_run_preview "Would set matugen path in config to: $selected_path"; then
|
if dry_run_preview "Would set matugen path in config to: $selected_path"; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
@@ -811,8 +823,8 @@ discover_matugen() {
|
|||||||
# (jq doesn't support JSONC, so we use sed to strip // comments first)
|
# (jq doesn't support JSONC, so we use sed to strip // comments first)
|
||||||
local tmp_config
|
local tmp_config
|
||||||
tmp_config=$(mktemp)
|
tmp_config=$(mktemp)
|
||||||
if sed 's|//.*||g' "$CONFIG_DIR/config.jsonc" | jq --arg path "$selected_path" '.appearance.matugenPath = $path' > "$tmp_config" 2>/dev/null; then
|
if sed 's|//.*||g' "$CONFIG_DIR/config.json" | jq --arg path "$selected_path" '.appearance.matugenPath = $path' > "$tmp_config" 2>/dev/null; then
|
||||||
mv "$tmp_config" "$CONFIG_DIR/config.jsonc"
|
mv "$tmp_config" "$CONFIG_DIR/config.json"
|
||||||
success "Matugen path set to: $selected_path"
|
success "Matugen path set to: $selected_path"
|
||||||
warn "Note: Comments were stripped from config. See CONFIG_README.md for reference."
|
warn "Note: Comments were stripped from config. See CONFIG_README.md for reference."
|
||||||
else
|
else
|
||||||
@@ -964,7 +976,7 @@ update() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Config is preserved (don't overwrite user settings)
|
# Config is preserved (don't overwrite user settings)
|
||||||
if [[ -f "$CONFIG_DIR/config.jsonc" ]]; then
|
if [[ -f "$CONFIG_DIR/config.json" ]]; then
|
||||||
success "Config preserved (not overwritten)"
|
success "Config preserved (not overwritten)"
|
||||||
else
|
else
|
||||||
install_config
|
install_config
|
||||||
|
|||||||
@@ -56,12 +56,13 @@ Singleton {
|
|||||||
|
|
||||||
// ─── Screenshots ──────────────────────────────────────────────
|
// ─── Screenshots ──────────────────────────────────────────────
|
||||||
property JsonObject screenSnip: JsonObject {
|
property JsonObject screenSnip: JsonObject {
|
||||||
property string savePath: "" // Save location (empty = clipboard only)
|
property string savePath: "" // Save location (empty = ~/Pictures/hypr-lens)
|
||||||
|
property bool copyAlsoSaves: false // true = Copy mode also saves to disk, false = clipboard only
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Screen Recording ─────────────────────────────────────────
|
// ─── Screen Recording ─────────────────────────────────────────
|
||||||
property JsonObject screenRecord: JsonObject {
|
property JsonObject screenRecord: JsonObject {
|
||||||
property string savePath: "" // Save location (empty = ~/Videos)
|
property string savePath: "" // Save location (empty = ~/Videos/hypr-lens)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── OCR ──────────────────────────────────────────────────────
|
// ─── OCR ──────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Singleton {
|
|||||||
property string screenshotTemp: "/tmp/hypr-lens/screenshot"
|
property string screenshotTemp: "/tmp/hypr-lens/screenshot"
|
||||||
property string recordScriptPath: scriptPath + "/videos/record.sh"
|
property string recordScriptPath: scriptPath + "/videos/record.sh"
|
||||||
property string shellConfig: home + "/.config/hypr-lens"
|
property string shellConfig: home + "/.config/hypr-lens"
|
||||||
property string shellConfigPath: shellConfig + "/config.jsonc"
|
property string shellConfigPath: shellConfig + "/config.json"
|
||||||
|
|
||||||
// Create directories on init
|
// Create directories on init
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|||||||
@@ -187,9 +187,9 @@ PanelWindow {
|
|||||||
// Each builder takes (rx, ry, rw, rh, absX, absY) and returns a command array.
|
// Each builder takes (rx, ry, rw, rh, absX, absY) and returns a command array.
|
||||||
readonly property var commandBuilders: ({
|
readonly property var commandBuilders: ({
|
||||||
[RegionSelection.SnipAction.Copy]: (rx, ry, rw, rh, absX, absY) =>
|
[RegionSelection.SnipAction.Copy]: (rx, ry, rw, rh, absX, absY) =>
|
||||||
SnipCommands.buildCopyCommand(root.screenshotPath, rx, ry, rw, rh, root.saveScreenshotDir),
|
SnipCommands.buildCopyCommand(root.screenshotPath, rx, ry, rw, rh, root.saveScreenshotDir, Config.options.screenSnip.copyAlsoSaves),
|
||||||
[RegionSelection.SnipAction.Edit]: (rx, ry, rw, rh, absX, absY) =>
|
[RegionSelection.SnipAction.Edit]: (rx, ry, rw, rh, absX, absY) =>
|
||||||
SnipCommands.buildEditCommand(root.screenshotPath, rx, ry, rw, rh),
|
SnipCommands.buildEditCommand(root.screenshotPath, rx, ry, rw, rh, root.saveScreenshotDir),
|
||||||
[RegionSelection.SnipAction.Search]: (rx, ry, rw, rh, absX, absY) =>
|
[RegionSelection.SnipAction.Search]: (rx, ry, rw, rh, absX, absY) =>
|
||||||
SnipCommands.buildSearchCommand(root.screenshotPath, rx, ry, rw, rh, "https://lens.google.com"),
|
SnipCommands.buildSearchCommand(root.screenshotPath, rx, ry, rw, rh, "https://lens.google.com"),
|
||||||
[RegionSelection.SnipAction.CharRecognition]: (rx, ry, rw, rh, absX, absY) =>
|
[RegionSelection.SnipAction.CharRecognition]: (rx, ry, rw, rh, absX, absY) =>
|
||||||
|
|||||||
@@ -9,6 +9,17 @@ import "../common/functions"
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
// Expand ~ to actual home directory (bash doesn't expand ~ in single quotes)
|
||||||
|
function expandTilde(path: string): string {
|
||||||
|
if (path.startsWith("~/")) {
|
||||||
|
return Directories.home + path.slice(1);
|
||||||
|
}
|
||||||
|
if (path === "~") {
|
||||||
|
return Directories.home;
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
// Build ImageMagick crop command base
|
// Build ImageMagick crop command base
|
||||||
function buildCropBase(screenshotPath: string, rx: int, ry: int, rw: int, rh: int): string {
|
function buildCropBase(screenshotPath: string, rx: int, ry: int, rw: int, rh: int): string {
|
||||||
return `magick ${StringUtils.shellSingleQuoteEscape(screenshotPath)} -crop ${rw}x${rh}+${rx}+${ry}`;
|
return `magick ${StringUtils.shellSingleQuoteEscape(screenshotPath)} -crop ${rw}x${rh}+${rx}+${ry}`;
|
||||||
@@ -19,32 +30,50 @@ Singleton {
|
|||||||
return `rm '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`;
|
return `rm '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy to clipboard (with optional save to disk)
|
// Default save location when savePath is empty
|
||||||
function buildCopyCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int, saveDir: string): list<string> {
|
readonly property string defaultSavePath: Directories.home + "/Pictures/hypr-lens"
|
||||||
|
|
||||||
|
// Copy to clipboard (optionally also saves to disk if copyAlsoSaves is true)
|
||||||
|
function buildCopyCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int, saveDir: string, alsoSave: bool): list<string> {
|
||||||
const cropBase = buildCropBase(screenshotPath, rx, ry, rw, rh);
|
const cropBase = buildCropBase(screenshotPath, rx, ry, rw, rh);
|
||||||
const cropToStdout = `${cropBase} -`;
|
const cropToStdout = `${cropBase} -`;
|
||||||
const cleanup = buildCleanup(screenshotPath);
|
const cleanup = buildCleanup(screenshotPath);
|
||||||
|
|
||||||
if (saveDir === "") {
|
// If not saving, just copy to clipboard
|
||||||
|
if (!alsoSave) {
|
||||||
return ["bash", "-c", `${cropToStdout} | wl-copy && ${cleanup}`];
|
return ["bash", "-c", `${cropToStdout} | wl-copy && ${cleanup}`];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save + copy: use provided path or default
|
||||||
|
const targetDir = saveDir !== "" ? saveDir : defaultSavePath;
|
||||||
|
const expandedSaveDir = expandTilde(targetDir);
|
||||||
return [
|
return [
|
||||||
"bash", "-c",
|
"bash", "-c",
|
||||||
`mkdir -p '${StringUtils.shellSingleQuoteEscape(saveDir)}' && \
|
`mkdir -p '${StringUtils.shellSingleQuoteEscape(expandedSaveDir)}' && \
|
||||||
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
|
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
|
||||||
savePath="${saveDir}/$saveFileName" && \
|
savePath="${expandedSaveDir}/$saveFileName" && \
|
||||||
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
|
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
|
||||||
${cleanup}`
|
${cleanup}`
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edit with swappy
|
// Edit with swappy (always saves to disk - uses default path if empty)
|
||||||
function buildEditCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int): list<string> {
|
function buildEditCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int, saveDir: string): list<string> {
|
||||||
const cropBase = buildCropBase(screenshotPath, rx, ry, rw, rh);
|
const cropBase = buildCropBase(screenshotPath, rx, ry, rw, rh);
|
||||||
const cropToStdout = `${cropBase} -`;
|
const cropToStdout = `${cropBase} -`;
|
||||||
const cleanup = buildCleanup(screenshotPath);
|
const cleanup = buildCleanup(screenshotPath);
|
||||||
return ["bash", "-c", `${cropToStdout} | swappy -f - && ${cleanup}`];
|
|
||||||
|
// Always save: use provided path or default
|
||||||
|
const targetDir = saveDir !== "" ? saveDir : defaultSavePath;
|
||||||
|
const expandedSaveDir = expandTilde(targetDir);
|
||||||
|
return [
|
||||||
|
"bash", "-c",
|
||||||
|
`mkdir -p '${StringUtils.shellSingleQuoteEscape(expandedSaveDir)}' && \
|
||||||
|
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
|
||||||
|
savePath="${expandedSaveDir}/$saveFileName" && \
|
||||||
|
${cropToStdout} | swappy -f - -o "$savePath" && \
|
||||||
|
${cleanup}`
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Image search (clipboard-based: copy to clipboard + open search page)
|
// Image search (clipboard-based: copy to clipboard + open search page)
|
||||||
|
|||||||
@@ -25,14 +25,17 @@ get_active_monitor() {
|
|||||||
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
|
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Configuration
|
# Configuration (strip // comments from JSONC before parsing)
|
||||||
CUSTOM_PATH=$(jq -r "$JSON_PATH" "$CONFIG_FILE" 2>/dev/null)
|
CUSTOM_PATH=$(sed 's|//.*||g' "$CONFIG_FILE" 2>/dev/null | jq -r "$JSON_PATH" 2>/dev/null)
|
||||||
if [[ -n "$CUSTOM_PATH" && "$CUSTOM_PATH" != "null" ]]; then
|
if [[ -n "$CUSTOM_PATH" && "$CUSTOM_PATH" != "null" ]]; then
|
||||||
RECORDING_DIR="$CUSTOM_PATH"
|
RECORDING_DIR="$CUSTOM_PATH"
|
||||||
else
|
else
|
||||||
RECORDING_DIR="$HOME/Videos"
|
RECORDING_DIR="$HOME/Videos/hypr-lens"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Expand ~ to $HOME (tilde doesn't expand when read from config file)
|
||||||
|
RECORDING_DIR="${RECORDING_DIR/#\~/$HOME}"
|
||||||
|
|
||||||
mkdir -p "$RECORDING_DIR"
|
mkdir -p "$RECORDING_DIR"
|
||||||
cd "$RECORDING_DIR" || exit
|
cd "$RECORDING_DIR" || exit
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user