Преглед на файлове

feat(ui/chat): switch to mpv with terminal geometry detection

Use mpv as default image viewer instead of imv — supports all target
formats including animated GIFs and WebP. On X11, auto-detect terminal
window geometry via xdotool so mpv opens at the same position and size.
Add --force-window and --loop-file=inf flags for mpv.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
claude преди 1 месец
родител
ревизия
5b4653c431
променени са 4 файла, в които са добавени 54 реда и са изтрити 16 реда
  1. 6 5
      CLAUDE.md
  2. 9 9
      README.md
  3. 1 1
      internal/config/config.toml
  4. 38 1
      internal/ui/chat/messages_list.go

+ 6 - 5
CLAUDE.md

@@ -44,14 +44,15 @@ This is the persistent context file for Claude Code. Keep it concise and useful.
 - Config defaults embedded via `//go:embed config.toml`
 
 ## Our Changes (vs upstream)
-- **Image viewer**: `image_viewer` config (default: `imv`) — opens image attachments in configured viewer with TUI suspend/resume instead of browser
+- **Image viewer**: `image_viewer` config (default: `mpv`) — opens image attachments in configured viewer with TUI suspend/resume instead of browser
+- **mpv geometry**: `viewerArgs()` auto-detects terminal geometry via `xdotool` on X11, passes `--geometry`, `--force-window`, `--loop-file=inf` to mpv
 - **Save image**: `save_image` keybind (`S`) — saves image attachment to `image_save_dir`
 - **Attachment URL fix**: split `builder.Write(filename+"\n"+url)` into proper `NewLine()` + `.Url()` style
 - **Supported image types**: jpeg, png, webp, gif (via `supportedImageTypes` map)
 - **ShortHelp**: `o` (open) now shows in bottom tooltip bar when message has attachments/URLs
 
 ## Config Fields We Added
-- `image_viewer` — external image viewer command (default: `"imv"`, `"default"` = system opener)
+- `image_viewer` — external image viewer command (default: `"mpv"`, `"default"` = system opener)
 - `image_save_dir` — directory for saved images (supports `~/`, default: current dir)
 - `keybinds.messages_list.save_image` — save image keybind (default: `S`)
 
@@ -60,7 +61,7 @@ This is the persistent context file for Claude Code. Keep it concise and useful.
 - Install: `sudo mv discordo-plus /usr/local/bin/`
 - Run: `discordo-plus`
 - Test: `go test ./...` (only config + keyring packages have tests)
-- Dependencies: `imv` (or configured image viewer)
+- Dependencies: `mpv` (or configured image viewer), `xdotool` (optional, X11 geometry detection)
 
 ## Git
 - Identity: `claude <claude@altsol.dev>`
@@ -69,5 +70,5 @@ This is the persistent context file for Claude Code. Keep it concise and useful.
 
 ## Known Issues
 - Discord ToS discourages third-party clients — use at own risk
-- `imv` package on some distros installs as `imv-x11`/`imv-wayland` without an `imv` symlink
-- WebP support depends on the configured viewer (imv supports it, feh may not)
+- `xdotool` geometry detection only works on X11; on Wayland use compositor window rules for mpv positioning
+- `viewerArgs()` only adds special flags for mpv; other viewers get plain `viewer path` invocation

+ 9 - 9
README.md

@@ -4,7 +4,7 @@ A fork of [discordo](https://github.com/ayn2op/discordo) — a lightweight Disco
 
 ## Changes from upstream
 
-- **Image viewer**: Opens image attachments (jpeg, png, webp, gif) in a configurable viewer (`imv` by default) instead of the browser
+- **Image viewer**: Opens image attachments (jpeg, png, webp, gif) in a configurable viewer (`mpv` by default) instead of the browser. On X11, auto-detects terminal window geometry so the viewer opens at the same position and size
 - **Save image**: `S` keybind saves the selected message's image attachment to a configurable directory
 - **Attachment URL fix**: Links no longer break due to bad newline handling
 - **Tooltip**: `o open` appears in the bottom help bar when a message has attachments or URLs
@@ -14,11 +14,12 @@ A fork of [discordo](https://github.com/ayn2op/discordo) — a lightweight Disco
 ### Requirements
 
 ```bash
-sudo pacman -S go imv wl-clipboard
+sudo pacman -S go mpv xdotool wl-clipboard
 ```
 
 - `go` — Go compiler (1.22+)
-- `imv` — lightweight image viewer (Wayland + X11, supports jpeg/png/webp/gif)
+- `mpv` — media player used as image viewer (supports jpeg/png/webp/gif with animation)
+- `xdotool` — used to detect terminal window geometry on X11 (optional, image viewer still works without it)
 - `wl-clipboard` — clipboard support on Wayland (skip if using X11)
 
 ### Build and install
@@ -48,8 +49,9 @@ The default config is used if no file exists. See [the default config](./interna
 
 ```toml
 # External image viewer (must accept a file path as first argument)
+# When set to "mpv", auto-adds --geometry, --force-window, --loop-file flags
 # Set to "default" to use xdg-open
-image_viewer = "imv"
+image_viewer = "mpv"
 
 # Directory for saved images (supports ~/, empty = current directory)
 image_save_dir = "~/Pictures/discordo"
@@ -63,11 +65,9 @@ save_image = "S"
 
 ### Notes
 
-- If `imv` installs as `imv-x11` or `imv-wayland` without a plain `imv` binary, create a symlink:
-  ```bash
-  sudo ln -s /usr/bin/imv-wayland /usr/local/bin/imv
-  ```
-- Alternative viewers: `feh`, `sxiv`, `nsxiv` — set via `image_viewer` in config (note: `feh` lacks WebP support)
+- On X11, `xdotool` is used to detect terminal geometry so `mpv` opens at the same position and size as your terminal. Without `xdotool`, `mpv` opens at its default position.
+- On Wayland, `xdotool` doesn't work — use compositor window rules instead (e.g., sway: `for_window [app_id="mpv"] floating enable, move position center`)
+- Alternative viewers: `imv`, `nsxiv`, `feh` — set via `image_viewer` in config. Geometry detection only applies to `mpv`.
 
 ## Usage
 

+ 1 - 1
internal/config/config.toml

@@ -15,7 +15,7 @@ show_attachment_links = true
 
 # Program used to view image attachments. Must accept a file path as its
 # first argument. Set to "default" to use xdg-open / open.
-image_viewer = "imv"
+image_viewer = "mpv"
 
 # Directory where images are saved with the save_image keybind.
 # Supports ~ for home directory. Leave empty to use the current directory.

+ 38 - 1
internal/ui/chat/messages_list.go

@@ -1220,6 +1220,42 @@ var supportedImageTypes = map[string]bool{
 	"image/gif":  true,
 }
 
+func terminalGeometry() string {
+	out, err := exec.Command("xdotool", "getactivewindow", "getwindowgeometry", "--shell").Output()
+	if err != nil {
+		return ""
+	}
+	var x, y, w, h string
+	for _, line := range strings.Split(string(out), "\n") {
+		switch {
+		case strings.HasPrefix(line, "X="):
+			x = strings.TrimPrefix(line, "X=")
+		case strings.HasPrefix(line, "Y="):
+			y = strings.TrimPrefix(line, "Y=")
+		case strings.HasPrefix(line, "WIDTH="):
+			w = strings.TrimPrefix(line, "WIDTH=")
+		case strings.HasPrefix(line, "HEIGHT="):
+			h = strings.TrimPrefix(line, "HEIGHT=")
+		}
+	}
+	if w != "" && h != "" && x != "" && y != "" {
+		return w + "x" + h + "+" + x + "+" + y
+	}
+	return ""
+}
+
+func viewerArgs(viewer, path string) []string {
+	if strings.HasSuffix(viewer, "mpv") || strings.Contains(viewer, "mpv ") {
+		args := []string{viewer, "--force-window", "--loop-file=inf"}
+		if geom := terminalGeometry(); geom != "" {
+			args = append(args, "--geometry="+geom)
+		}
+		args = append(args, path)
+		return args
+	}
+	return []string{viewer, path}
+}
+
 func (ml *messagesList) openAttachment(attachment discord.Attachment) {
 	path, err := ml.downloadToCache(attachment)
 	if err != nil {
@@ -1229,7 +1265,8 @@ func (ml *messagesList) openAttachment(attachment discord.Attachment) {
 
 	viewer := ml.cfg.ImageViewer
 	if viewer != "" && supportedImageTypes[attachment.ContentType] {
-		cmd := exec.Command(viewer, path)
+		args := viewerArgs(viewer, path)
+		cmd := exec.Command(args[0], args[1:]...)
 		cmd.Stdin = os.Stdin
 		cmd.Stdout = os.Stdout
 		cmd.Stderr = os.Stderr