diff --git a/yazi-adaptor/src/adaptor.rs b/yazi-adaptor/src/adaptor.rs index 8dbb5a2b..4d16fa30 100644 --- a/yazi-adaptor/src/adaptor.rs +++ b/yazi-adaptor/src/adaptor.rs @@ -7,7 +7,7 @@ use tracing::warn; use yazi_config::PREVIEW; use yazi_shared::{env_exists, RoCell}; -use super::{Iterm2, Kitty}; +use super::{Iterm2, Kitty, KittyOld}; use crate::{ueberzug::Ueberzug, Sixel, TMUX}; static IMAGE_SHOWN: AtomicBool = AtomicBool::new(false); @@ -18,6 +18,7 @@ static UEBERZUG: RoCell>>> = RoCe #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Adaptor { Kitty, + KittyOld, Iterm2, Sixel, @@ -83,7 +84,7 @@ impl Adaptor { let mut protocols = match Self::emulator() { Emulator::Unknown => vec![], Emulator::Kitty => vec![Self::Kitty], - Emulator::Konsole => vec![Self::Kitty, Self::Iterm2, Self::Sixel], + Emulator::Konsole => vec![Self::KittyOld, Self::Iterm2, Self::Sixel], Emulator::Iterm2 => vec![Self::Iterm2, Self::Sixel], Emulator::WezTerm => vec![Self::Iterm2, Self::Sixel], Emulator::Foot => vec![Self::Sixel], @@ -99,6 +100,9 @@ impl Adaptor { if env_exists("ZELLIJ_SESSION_NAME") { protocols.retain(|p| *p == Self::Sixel); } + if *TMUX && protocols.len() > 1 { + protocols.retain(|p| *p != Self::KittyOld); + } if let Some(p) = protocols.first() { return *p; } @@ -148,6 +152,7 @@ impl ToString for Adaptor { fn to_string(&self) -> String { match self { Self::Kitty => "kitty", + Self::KittyOld => "kitty", Self::Iterm2 => "iterm2", Self::Sixel => "sixel", Self::X11 => "x11", @@ -174,6 +179,7 @@ impl Adaptor { match self { Self::Kitty => Kitty::image_show(path, rect).await, + Self::KittyOld => KittyOld::image_show(path, rect).await, Self::Iterm2 => Iterm2::image_show(path, rect).await, Self::Sixel => Sixel::image_show(path, rect).await, _ => Ok(if let Some(tx) = &*UEBERZUG { @@ -190,6 +196,7 @@ impl Adaptor { match self { Self::Kitty => Kitty::image_hide(rect), Self::Iterm2 => Iterm2::image_hide(rect), + Self::KittyOld => KittyOld::image_hide(), Self::Sixel => Sixel::image_hide(rect), _ => Ok(if let Some(tx) = &*UEBERZUG { tx.send(None)?; @@ -199,6 +206,6 @@ impl Adaptor { #[inline] pub(super) fn needs_ueberzug(self) -> bool { - !matches!(self, Self::Kitty | Self::Iterm2 | Self::Sixel) + !matches!(self, Self::Kitty | Self::KittyOld | Self::Iterm2 | Self::Sixel) } } diff --git a/yazi-adaptor/src/kitty_old.rs b/yazi-adaptor/src/kitty_old.rs new file mode 100644 index 00000000..72e9f2fa --- /dev/null +++ b/yazi-adaptor/src/kitty_old.rs @@ -0,0 +1,76 @@ +use std::{io::{stdout, Write}, path::Path}; + +use anyhow::Result; +use base64::{engine::general_purpose, Engine}; +use image::DynamicImage; +use ratatui::prelude::Rect; +use yazi_shared::Term; + +use super::image::Image; +use crate::{CLOSE, ESCAPE, START}; + +pub(super) struct KittyOld; + +impl KittyOld { + pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> { + let img = Image::downscale(path, (rect.width, rect.height)).await?; + let b = Self::encode(img).await?; + + Self::image_hide()?; + Term::move_lock(stdout().lock(), (rect.x, rect.y), |stdout| Ok(stdout.write_all(&b)?)) + } + + #[inline] + pub(super) fn image_hide() -> Result<()> { + let mut stdout = stdout().lock(); + stdout.write_all(format!("{}_Gq=1,a=d,d=A{}\\{}", START, ESCAPE, CLOSE).as_bytes())?; + stdout.flush()?; + Ok(()) + } + + async fn encode(img: DynamicImage) -> Result> { + fn output(raw: &[u8], format: u8, size: (u32, u32)) -> Result> { + let b64 = general_purpose::STANDARD.encode(raw).chars().collect::>(); + + let mut it = b64.chunks(4096).peekable(); + let mut buf = Vec::with_capacity(b64.len() + it.len() * 50); + if let Some(first) = it.next() { + write!( + buf, + "{}_Gq=1,a=T,z=-1,C=1,f={},s={},v={},m={};{}{}\\{}", + START, + format, + size.0, + size.1, + it.peek().is_some() as u8, + first.iter().collect::(), + ESCAPE, + CLOSE + )?; + } + + while let Some(chunk) = it.next() { + write!( + buf, + "{}_Gm={};{}{}\\{}", + START, + it.peek().is_some() as u8, + chunk.iter().collect::(), + ESCAPE, + CLOSE + )?; + } + + buf.write_all(CLOSE.as_bytes())?; + Ok(buf) + } + + let size = (img.width(), img.height()); + tokio::task::spawn_blocking(move || match img { + DynamicImage::ImageRgb8(v) => output(v.as_raw(), 24, size), + DynamicImage::ImageRgba8(v) => output(v.as_raw(), 32, size), + v => output(v.to_rgb8().as_raw(), 24, size), + }) + .await? + } +} diff --git a/yazi-adaptor/src/lib.rs b/yazi-adaptor/src/lib.rs index 0f3929a8..de261e47 100644 --- a/yazi-adaptor/src/lib.rs +++ b/yazi-adaptor/src/lib.rs @@ -4,12 +4,14 @@ mod adaptor; mod image; mod iterm2; mod kitty; +mod kitty_old; mod sixel; mod ueberzug; use adaptor::*; use iterm2::*; use kitty::*; +use kitty_old::*; use sixel::*; use yazi_shared::{env_exists, RoCell};