Skip to content

Commit

Permalink
fix: use a unique Id for each tab (#1826)
Browse files Browse the repository at this point in the history
  • Loading branch information
sxyazi authored Oct 24, 2024
1 parent 35d781e commit e8c1d62
Show file tree
Hide file tree
Showing 24 changed files with 143 additions and 82 deletions.
13 changes: 5 additions & 8 deletions yazi-core/src/manager/commands/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@ use std::{collections::HashSet, path::PathBuf};

use yazi_dds::Pubsub;
use yazi_macro::render;
use yazi_shared::{event::{Cmd, Data}, fs::{Url, Urn}};
use yazi_shared::{Id, event::{Cmd, Data}, fs::{Url, Urn}};

use crate::manager::Manager;

struct Opt {
url: Option<Url>,
tab: Option<usize>,
tab: Option<Id>,
}

impl From<Cmd> for Opt {
fn from(mut c: Cmd) -> Self {
Self {
url: c.take_first().and_then(Data::into_url),
tab: c.get("tab").and_then(Data::as_usize),
}
Self { url: c.take_first().and_then(Data::into_url), tab: c.get("tab").and_then(Data::as_id) }
}
}
impl From<Option<Url>> for Opt {
Expand Down Expand Up @@ -49,10 +46,10 @@ impl Manager {
self.watcher.watch(to_watch);

// Publish through DDS
Pubsub::pub_from_hover(self.active().idx, self.hovered().map(|h| &h.url));
Pubsub::pub_from_hover(self.active().id, self.hovered().map(|h| &h.url));
}

fn hover_do(&mut self, url: Url, tab: Option<usize>) {
fn hover_do(&mut self, url: Url, tab: Option<Id>) {
// Hover on the file
if let Ok(p) = url.strip_prefix(&self.current_or(tab).url).map(PathBuf::from) {
render!(self.current_or_mut(tab).repos(Some(Urn::new(&p))));
Expand Down
1 change: 0 additions & 1 deletion yazi-core/src/manager/commands/tab_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ impl Tabs {
self.set_idx(self.absolute(1));
}

self.reorder();
render!();
}
}
4 changes: 1 addition & 3 deletions yazi-core/src/manager/commands/tab_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ impl Tabs {
return;
}

let mut tab = Tab { idx: self.cursor + 1, ..Default::default() };

let mut tab = Tab::default();
if !opt.current {
tab.cd(opt.url);
} else if let Some(h) = self.active().hovered() {
Expand All @@ -52,7 +51,6 @@ impl Tabs {

self.items.insert(self.cursor + 1, tab);
self.set_idx(self.cursor + 1);
self.reorder();
render!();
}
}
1 change: 0 additions & 1 deletion yazi-core/src/manager/commands/tab_swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ impl Tabs {

self.items.swap(self.cursor, idx);
self.set_idx(idx);
self.reorder();
render!();
}
}
2 changes: 1 addition & 1 deletion yazi-core/src/manager/commands/update_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ impl Manager {
return;
}

ManagerProxy::hover(None, tab.idx); // Re-hover in next loop
ManagerProxy::hover(None, tab.id); // Re-hover in next loop
ManagerProxy::update_paged(); // Update for paged files in next loop
if calc {
tasks.prework_sorted(&tab.current.files);
Expand Down
10 changes: 5 additions & 5 deletions yazi-core/src/manager/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use ratatui::layout::Rect;
use yazi_adapter::Dimension;
use yazi_config::popup::{Origin, Position};
use yazi_fs::Folder;
use yazi_shared::fs::{File, Url};
use yazi_shared::{Id, fs::{File, Url}};

use super::{Mimetype, Tabs, Watcher, Yanked};
use crate::tab::Tab;
Expand Down Expand Up @@ -48,10 +48,10 @@ impl Manager {
pub fn active_mut(&mut self) -> &mut Tab { self.tabs.active_mut() }

#[inline]
pub fn active_or(&self, idx: Option<usize>) -> &Tab { self.tabs.active_or(idx) }
pub fn active_or(&self, id: Option<Id>) -> &Tab { self.tabs.active_or(id) }

#[inline]
pub fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab { self.tabs.active_or_mut(idx) }
pub fn active_or_mut(&mut self, id: Option<Id>) -> &mut Tab { self.tabs.active_or_mut(id) }

#[inline]
pub fn current(&self) -> &Folder { &self.active().current }
Expand All @@ -60,10 +60,10 @@ impl Manager {
pub fn current_mut(&mut self) -> &mut Folder { &mut self.active_mut().current }

#[inline]
pub fn current_or(&self, idx: Option<usize>) -> &Folder { &self.active_or(idx).current }
pub fn current_or(&self, idx: Option<Id>) -> &Folder { &self.active_or(idx).current }

#[inline]
pub fn current_or_mut(&mut self, idx: Option<usize>) -> &mut Folder {
pub fn current_or_mut(&mut self, idx: Option<Id>) -> &mut Folder {
&mut self.active_or_mut(idx).current
}

Expand Down
18 changes: 6 additions & 12 deletions yazi-core/src/manager/tabs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut};
use yazi_boot::BOOT;
use yazi_dds::Pubsub;
use yazi_proxy::ManagerProxy;
use yazi_shared::fs::Url;
use yazi_shared::{Id, fs::Url};

use crate::tab::Tab;

Expand All @@ -16,7 +16,6 @@ impl Tabs {
pub fn make() -> Self {
let mut tabs =
Self { cursor: 0, items: (0..BOOT.cwds.len()).map(|_| Tab::default()).collect() };
tabs.reorder();

for (i, tab) in tabs.iter_mut().enumerate() {
let file = &BOOT.files[i];
Expand All @@ -37,11 +36,6 @@ impl Tabs {
}
}

#[inline]
pub(super) fn reorder(&mut self) {
self.items.iter_mut().enumerate().for_each(|(i, tab)| tab.idx = i);
}

pub(super) fn set_idx(&mut self, idx: usize) {
// Reset the preview of the last active tab
if let Some(active) = self.items.get_mut(self.cursor) {
Expand All @@ -63,16 +57,16 @@ impl Tabs {
pub(super) fn active_mut(&mut self) -> &mut Tab { &mut self.items[self.cursor] }

#[inline]
pub fn active_or(&self, idx: Option<usize>) -> &Tab {
idx.and_then(|i| self.items.get(i)).unwrap_or(&self.items[self.cursor])
pub fn active_or(&self, id: Option<Id>) -> &Tab {
id.and_then(|id| self.iter().find(|&t| t.id == id)).unwrap_or(self.active())
}

#[inline]
pub(super) fn active_or_mut(&mut self, idx: Option<usize>) -> &mut Tab {
if let Some(i) = idx.filter(|&i| i < self.items.len()) {
pub(super) fn active_or_mut(&mut self, id: Option<Id>) -> &mut Tab {
if let Some(i) = id.and_then(|id| self.iter().position(|t| t.id == id)) {
&mut self.items[i]
} else {
&mut self.items[self.cursor]
self.active_mut()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/arrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Tab {
}
}

ManagerProxy::hover(None, self.idx);
ManagerProxy::hover(None, self.id);
render!();
}
}
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/cd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl Tab {
self.backstack.push(opt.target.clone());
}

Pubsub::pub_from_cd(self.idx, self.cwd());
Pubsub::pub_from_cd(self.id, self.cwd());
ManagerProxy::refresh();
render!();
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/filter_do.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Tab {

self.current.repos(hovered.as_ref().map(|u| u.as_urn()));
if self.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) {
ManagerProxy::hover(None, self.idx);
ManagerProxy::hover(None, self.id);
}

render!();
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Tab {
self.apply_files_attrs();

if hovered.as_ref() != self.hovered().map(|f| &f.url) {
ManagerProxy::hover(hovered, self.idx);
ManagerProxy::hover(hovered, self.id);
} else if self.hovered().is_some_and(|f| f.is_dir()) {
ManagerProxy::peek(true);
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/reveal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ impl Tab {

self.cd(parent.clone());
FilesOp::Creating(parent, vec![File::from_dummy(opt.target.clone(), None)]).emit();
ManagerProxy::hover(Some(opt.target), self.idx);
ManagerProxy::hover(Some(opt.target), self.id);
}
}
27 changes: 24 additions & 3 deletions yazi-core/src/tab/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ use yazi_adapter::Dimension;
use yazi_config::{LAYOUT, popup::{Origin, Position}};
use yazi_fs::{Folder, FolderStage};
use yazi_macro::render;
use yazi_shared::fs::{File, Url};
use yazi_shared::{Id, Ids, fs::{File, Url}};

use super::{Backstack, Config, Finder, History, Mode, Preview};
use crate::tab::Selected;

#[derive(Default)]
pub struct Tab {
pub idx: usize,
pub id: Id,
pub mode: Mode,
pub conf: Config,
pub current: Folder,
Expand All @@ -29,6 +28,28 @@ pub struct Tab {
pub search: Option<JoinHandle<Result<()>>>,
}

impl Default for Tab {
fn default() -> Self {
static IDS: Ids = Ids::new();

Self {
id: IDS.next(),
mode: Default::default(),
conf: Default::default(),
current: Default::default(),
parent: Default::default(),

backstack: Default::default(),
history: Default::default(),
selected: Default::default(),

preview: Default::default(),
finder: Default::default(),
search: Default::default(),
}
}
}

impl Tab {
pub fn shutdown(&mut self) {
if let Some(handle) = self.search.take() {
Expand Down
12 changes: 6 additions & 6 deletions yazi-dds/src/body/cd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@ use std::borrow::Cow;

use mlua::{IntoLua, Lua, Value};
use serde::{Deserialize, Serialize};
use yazi_shared::fs::Url;
use yazi_shared::{Id, fs::Url};

use super::Body;

#[derive(Debug, Serialize, Deserialize)]
pub struct BodyCd<'a> {
pub tab: usize,
pub tab: Id,
pub url: Cow<'a, Url>,
#[serde(skip)]
dummy: bool,
}

impl<'a> BodyCd<'a> {
#[inline]
pub fn borrowed(tab: usize, url: &'a Url) -> Body<'a> {
pub fn borrowed(tab: Id, url: &'a Url) -> Body<'a> {
Self { tab, url: Cow::Borrowed(url), dummy: false }.into()
}
}

impl BodyCd<'static> {
#[inline]
pub fn dummy(tab: usize) -> Body<'static> {
pub fn dummy(tab: Id) -> Body<'static> {
Self { tab, url: Default::default(), dummy: true }.into()
}
}
Expand All @@ -36,11 +36,11 @@ impl IntoLua<'_> for BodyCd<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = Some(self.url).filter(|_| !self.dummy) {
lua.create_table_from([
("tab", self.tab.into_lua(lua)?),
("tab", self.tab.get().into_lua(lua)?),
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
])?
} else {
lua.create_table_from([("tab", self.tab)])?
lua.create_table_from([("tab", self.tab.get())])?
}
.into_lua(lua)
}
Expand Down
12 changes: 6 additions & 6 deletions yazi-dds/src/body/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ use std::borrow::Cow;

use mlua::{IntoLua, Lua, Value};
use serde::{Deserialize, Serialize};
use yazi_shared::fs::Url;
use yazi_shared::{Id, fs::Url};

use super::Body;

#[derive(Debug, Serialize, Deserialize)]
pub struct BodyHover<'a> {
pub tab: usize,
pub tab: Id,
pub url: Option<Cow<'a, Url>>,
}

impl<'a> BodyHover<'a> {
#[inline]
pub fn borrowed(tab: usize, url: Option<&'a Url>) -> Body<'a> {
pub fn borrowed(tab: Id, url: Option<&'a Url>) -> Body<'a> {
Self { tab, url: url.map(Cow::Borrowed) }.into()
}
}

impl BodyHover<'static> {
#[inline]
pub fn dummy(tab: usize) -> Body<'static> { Self { tab, url: None }.into() }
pub fn dummy(tab: Id) -> Body<'static> { Self { tab, url: None }.into() }
}

impl<'a> From<BodyHover<'a>> for Body<'a> {
Expand All @@ -32,11 +32,11 @@ impl IntoLua<'_> for BodyHover<'static> {
fn into_lua(self, lua: &Lua) -> mlua::Result<Value> {
if let Some(Cow::Owned(url)) = self.url {
lua.create_table_from([
("tab", self.tab.into_lua(lua)?),
("tab", self.tab.get().into_lua(lua)?),
("url", lua.create_any_userdata(url)?.into_lua(lua)?),
])?
} else {
lua.create_table_from([("tab", self.tab)])?
lua.create_table_from([("tab", self.tab.get())])?
}
.into_lua(lua)
}
Expand Down
6 changes: 3 additions & 3 deletions yazi-dds/src/pubsub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::{HashMap, HashSet};
use mlua::Function;
use parking_lot::RwLock;
use yazi_boot::BOOT;
use yazi_shared::{RoCell, fs::Url};
use yazi_shared::{Id, RoCell, fs::Url};

use crate::{Client, ID, PEERS, body::{Body, BodyBulk, BodyCd, BodyDelete, BodyHi, BodyHover, BodyMove, BodyMoveItem, BodyRename, BodyTab, BodyTrash, BodyYank}};

Expand Down Expand Up @@ -88,7 +88,7 @@ impl Pubsub {
true
}

pub fn pub_from_cd(tab: usize, url: &Url) {
pub fn pub_from_cd(tab: Id, url: &Url) {
if LOCAL.read().contains_key("cd") {
Self::pub_(BodyCd::dummy(tab));
}
Expand All @@ -100,7 +100,7 @@ impl Pubsub {
}
}

pub fn pub_from_hover(tab: usize, url: Option<&Url>) {
pub fn pub_from_hover(tab: Id, url: Option<&Url>) {
if LOCAL.read().contains_key("hover") {
Self::pub_(BodyHover::dummy(tab));
}
Expand Down
2 changes: 1 addition & 1 deletion yazi-fm/src/lives/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Tab {

pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
lua.register_userdata_type::<Self>(|reg| {
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
reg.add_field_method_get("id", |_, me| Ok(me.id.get()));
reg.add_method("name", |lua, me, ()| {
lua.create_string(me.current.url.name().as_encoded_bytes())
});
Expand Down
Loading

0 comments on commit e8c1d62

Please sign in to comment.