mirror of
https://github.com/thesleepingsage/hypr-lens.git
synced 2026-06-03 04:04:41 +02: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:
@@ -53,6 +53,42 @@ Initial public release! 🎉
|
||||
- **Installer Recovery** - Detect and recover missing shell integration during update mode
|
||||
- **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
|
||||
|
||||
### Added
|
||||
@@ -70,6 +106,8 @@ Initial public release! 🎉
|
||||
|
||||
| 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.1.0 | 2025-12-08 | Monitor capture buttons, installer recovery |
|
||||
| 1.0.0 | 2025-12-08 | Initial release |
|
||||
|
||||
@@ -109,7 +109,7 @@ cd hypr-lens
|
||||
| QML modules | `~/.config/quickshell/hypr-lens/` |
|
||||
| Scripts | `~/.local/share/hypr-lens/scripts/` |
|
||||
| Python venv | `~/.local/share/hypr-lens/venv/` (optional) |
|
||||
| Default config | `~/.config/hypr-lens/config.jsonc` |
|
||||
| Default config | `~/.config/hypr-lens/config.json` |
|
||||
|
||||
## Updating
|
||||
|
||||
@@ -229,7 +229,7 @@ See [MANUAL.md](MANUAL.md#ipc-commands) for detailed IPC documentation.
|
||||
|
||||
## Configuration
|
||||
|
||||
Config file: `~/.config/hypr-lens/config.jsonc`
|
||||
Config file: `~/.config/hypr-lens/config.json`
|
||||
|
||||
<details>
|
||||
<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 |
|
||||
|------|--------|---------|
|
||||
| `~/.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/venv/` | Create (optional) | Python venv for content detection |
|
||||
| `~/.config/quickshell/shell.qml` | Modify (optional) | Integration (with timestamped backup) |
|
||||
|
||||
@@ -44,9 +44,14 @@ Screenshot settings.
|
||||
|
||||
| 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 |
|
||||
|---------|---------|-------------|
|
||||
| `savePath` | `""` | Where to save recordings. Empty = `~/Videos` |
|
||||
| `savePath` | `""` | Where to save recordings. Empty = `~/Videos/hypr-lens` |
|
||||
|
||||
**Example:** `"/home/user/Videos/Recordings"`
|
||||
|
||||
@@ -136,4 +141,4 @@ Circle selection tool settings.
|
||||
|
||||
- Empty string `""` for path settings = use default behavior
|
||||
- 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/
|
||||
2. Scripts → ~/.local/share/hypr-lens/scripts/
|
||||
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):
|
||||
- keybinds.example.conf → Copy contents to your Hyprland keybinds config
|
||||
@@ -402,7 +402,7 @@ install_config() {
|
||||
|
||||
if dry_run_preview \
|
||||
"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
|
||||
return
|
||||
fi
|
||||
@@ -412,16 +412,28 @@ install_config() {
|
||||
# Always copy/update the README
|
||||
cp "$SCRIPT_DIR/defaults/CONFIG_README.md" "$CONFIG_DIR/CONFIG_README.md"
|
||||
|
||||
if [[ -f "$CONFIG_DIR/config.jsonc" ]]; then
|
||||
warn "Config already exists at $CONFIG_DIR/config.jsonc"
|
||||
# Migrate old config.jsonc to config.json if needed
|
||||
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
|
||||
cp "$SCRIPT_DIR/defaults/config.jsonc" "$CONFIG_DIR/config.jsonc"
|
||||
cp "$SCRIPT_DIR/defaults/config.json" "$CONFIG_DIR/config.json"
|
||||
success "Config overwritten"
|
||||
else
|
||||
success "Keeping existing config"
|
||||
fi
|
||||
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"
|
||||
fi
|
||||
success "Config README installed"
|
||||
@@ -802,8 +814,8 @@ discover_matugen() {
|
||||
|
||||
if [[ -n "$selected_path" ]]; then
|
||||
if [[ -f "$selected_path" ]]; then
|
||||
# Update config.jsonc with selected path
|
||||
if [[ -f "$CONFIG_DIR/config.jsonc" ]]; then
|
||||
# Update config.json with selected path
|
||||
if [[ -f "$CONFIG_DIR/config.json" ]]; then
|
||||
if dry_run_preview "Would set matugen path in config to: $selected_path"; then
|
||||
return
|
||||
fi
|
||||
@@ -811,8 +823,8 @@ discover_matugen() {
|
||||
# (jq doesn't support JSONC, so we use sed to strip // comments first)
|
||||
local tmp_config
|
||||
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
|
||||
mv "$tmp_config" "$CONFIG_DIR/config.jsonc"
|
||||
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.json"
|
||||
success "Matugen path set to: $selected_path"
|
||||
warn "Note: Comments were stripped from config. See CONFIG_README.md for reference."
|
||||
else
|
||||
@@ -964,7 +976,7 @@ update() {
|
||||
fi
|
||||
|
||||
# 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)"
|
||||
else
|
||||
install_config
|
||||
|
||||
@@ -56,12 +56,13 @@ Singleton {
|
||||
|
||||
// ─── Screenshots ──────────────────────────────────────────────
|
||||
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 ─────────────────────────────────────────
|
||||
property JsonObject screenRecord: JsonObject {
|
||||
property string savePath: "" // Save location (empty = ~/Videos)
|
||||
property string savePath: "" // Save location (empty = ~/Videos/hypr-lens)
|
||||
}
|
||||
|
||||
// ─── OCR ──────────────────────────────────────────────────────
|
||||
|
||||
@@ -17,7 +17,7 @@ Singleton {
|
||||
property string screenshotTemp: "/tmp/hypr-lens/screenshot"
|
||||
property string recordScriptPath: scriptPath + "/videos/record.sh"
|
||||
property string shellConfig: home + "/.config/hypr-lens"
|
||||
property string shellConfigPath: shellConfig + "/config.jsonc"
|
||||
property string shellConfigPath: shellConfig + "/config.json"
|
||||
|
||||
// Create directories on init
|
||||
Component.onCompleted: {
|
||||
|
||||
@@ -187,9 +187,9 @@ PanelWindow {
|
||||
// Each builder takes (rx, ry, rw, rh, absX, absY) and returns a command array.
|
||||
readonly property var commandBuilders: ({
|
||||
[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) =>
|
||||
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) =>
|
||||
SnipCommands.buildSearchCommand(root.screenshotPath, rx, ry, rw, rh, "https://lens.google.com"),
|
||||
[RegionSelection.SnipAction.CharRecognition]: (rx, ry, rw, rh, absX, absY) =>
|
||||
|
||||
@@ -9,6 +9,17 @@ import "../common/functions"
|
||||
Singleton {
|
||||
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
|
||||
function buildCropBase(screenshotPath: string, rx: int, ry: int, rw: int, rh: int): string {
|
||||
return `magick ${StringUtils.shellSingleQuoteEscape(screenshotPath)} -crop ${rw}x${rh}+${rx}+${ry}`;
|
||||
@@ -19,32 +30,50 @@ Singleton {
|
||||
return `rm '${StringUtils.shellSingleQuoteEscape(screenshotPath)}'`;
|
||||
}
|
||||
|
||||
// Copy to clipboard (with optional save to disk)
|
||||
function buildCopyCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int, saveDir: string): list<string> {
|
||||
// Default save location when savePath is empty
|
||||
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 cropToStdout = `${cropBase} -`;
|
||||
const cleanup = buildCleanup(screenshotPath);
|
||||
|
||||
if (saveDir === "") {
|
||||
// If not saving, just copy to clipboard
|
||||
if (!alsoSave) {
|
||||
return ["bash", "-c", `${cropToStdout} | wl-copy && ${cleanup}`];
|
||||
}
|
||||
|
||||
// Save + copy: use provided path or default
|
||||
const targetDir = saveDir !== "" ? saveDir : defaultSavePath;
|
||||
const expandedSaveDir = expandTilde(targetDir);
|
||||
return [
|
||||
"bash", "-c",
|
||||
`mkdir -p '${StringUtils.shellSingleQuoteEscape(saveDir)}' && \
|
||||
`mkdir -p '${StringUtils.shellSingleQuoteEscape(expandedSaveDir)}' && \
|
||||
saveFileName="screenshot-$(date '+%Y-%m-%d_%H.%M.%S').png" && \
|
||||
savePath="${saveDir}/$saveFileName" && \
|
||||
savePath="${expandedSaveDir}/$saveFileName" && \
|
||||
${cropToStdout} | tee >(wl-copy) > "$savePath" && \
|
||||
${cleanup}`
|
||||
];
|
||||
}
|
||||
|
||||
// Edit with swappy
|
||||
function buildEditCommand(screenshotPath: string, rx: int, ry: int, rw: int, rh: int): list<string> {
|
||||
// Edit with swappy (always saves to disk - uses default path if empty)
|
||||
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 cropToStdout = `${cropBase} -`;
|
||||
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)
|
||||
|
||||
@@ -25,14 +25,17 @@ get_active_monitor() {
|
||||
hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name'
|
||||
}
|
||||
|
||||
# Configuration
|
||||
CUSTOM_PATH=$(jq -r "$JSON_PATH" "$CONFIG_FILE" 2>/dev/null)
|
||||
# Configuration (strip // comments from JSONC before parsing)
|
||||
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
|
||||
RECORDING_DIR="$CUSTOM_PATH"
|
||||
else
|
||||
RECORDING_DIR="$HOME/Videos"
|
||||
RECORDING_DIR="$HOME/Videos/hypr-lens"
|
||||
fi
|
||||
|
||||
# Expand ~ to $HOME (tilde doesn't expand when read from config file)
|
||||
RECORDING_DIR="${RECORDING_DIR/#\~/$HOME}"
|
||||
|
||||
mkdir -p "$RECORDING_DIR"
|
||||
cd "$RECORDING_DIR" || exit
|
||||
|
||||
|
||||
Reference in New Issue
Block a user