dataview实现获取最近修改文件列表,支持搜索

可以拖动到左侧或右侧面板中方便查看。

效果

代码

```dataviewjs
// 本脚本的文件的名字
const currFileName = dv.current()?.file?.name || "Recently Modified";
// 打开时设置为预览模式
const activeLeaf = this.app.workspace.activeLeaf;
if(activeLeaf?.view?.file?.basename === currFileName){
	const state = activeLeaf?.view.getState();
	state.mode = "preview"
	activeLeaf?.setViewState({type: "markdown", state: state});
}

// 关键词搜索
const searchStyle = `
background-color: transparent;
border: 1px solid #888;
border-radius: 5px;
margin-left: 20px;
height: 30px;
width: 80%;
padding: 0 5px;
color: var(--text-normal);
`;
const search = dv.el('input', '', { attr: { "style": searchStyle } });
search.addEventListener('input', function(e) {
    const keyword = e.target.value.trim().toLowerCase();
    const listItems = this.parentElement.querySelectorAll('.list-view-ul li');
    listItems.forEach(item => {
        const text = item.textContent.toLowerCase();
        if (keyword === '' || text.includes(keyword)) {
            item.style.display = 'list-item';
        } else {
            item.style.display = 'none';
        }
        // 关键词高亮
        const itemWords = item.querySelector('a span');
        if (keyword) {
            const regex = new RegExp(`(${keyword})`, 'gi');
            const highlightedText = itemWords.textContent.replace(regex, `<mark>$1</mark>`);
            itemWords.innerHTML = highlightedText;
        } else {
            // 如果搜索框为空,移除高亮样式,恢复原始文本
            itemWords.innerHTML = itemWords.textContent;
        }
    });
});

// 最近修改文件列表
let lastActiveLeaf;
dv.list(
    dv.pages()
    //.filter(p => moment(p.file.mday.toString()).format('MD') === moment().format('MD'))
    .sort(p => p.file.mtime, 'desc')
    .limit(100)
    .map(p => {
        const a=dv.el('a', p.file.name, { attr: { "data-href": p.file.path } });
        a.addEventListener('click', function(e) {
			let newLeaf = lastActiveLeaf || app.workspace.getLeaf('tab');
			// 当前激活文档不在root split则新标签打开
			if(!newLeaf.containerEl.closest(".mod-root")){
				newLeaf = app.workspace.getLeaf('tab');
			}
			// Ctrl或Meta键时则新标签打开
			if (isCtrlDown) {
			    newLeaf = app.workspace.getLeaf('tab');
			}
			// 如果叶子已关闭则新标签打开
			if(!newLeaf.containerEl.querySelector('.workspace-leaf-content')) {
			    newLeaf = app.workspace.getLeaf('tab');
			}
			newLeaf.openFile(app.vault.getAbstractFileByPath(this.getAttribute("data-href")));
	        setTimeout(() => {
		        lastActiveLeaf = app.workspace.activeLeaf;
	        }, 100);
        });
        return a;
    })
)

// 用于记录Ctrl键是否被按下
let isCtrlDown = false;
const handleKeyDown = function(event) {
    if (event.key === 'Control'|| event.key === 'Meta') {
        isCtrlDown = true;
    }
};
document.removeEventListener('keydown', handleKeyDown);
document.addEventListener('keydown', handleKeyDown);
const handleKeyUp = function(event) {
    if (event.key === 'Control'|| event.key === 'Meta') {
        isCtrlDown = false;
    }
};
document.removeEventListener('keyup', handleKeyUp);
document.addEventListener('keyup', handleKeyUp);
```

文件打开规则:

  1. 如果激活文档不在root split中(即不在中间主窗口中)则新标签打开

  2. 如果ctrl + 点击则新标签打开

  3. 其他情况则在当前激活文档中打开(即替换当前激活文档)

修改侧边栏脚本图标

如果在左侧面板中,可以在runjs插件加载时执行脚本中输入以下代码:

// 修改获取最近修改文档脚本图标
const modifyRecentlyIcon = () => {
    // "Recently Modified"脚本名字,根据你自己的脚本名修改
    const RecentlyScriptName = "Recently Modified";
    document.querySelectorAll(".mod-left-split .workspace-tab-header-container .workspace-tab-header").forEach((item)=>{
		if (item.querySelector(".workspace-tab-header-inner-title").textContent === RecentlyScriptName) {
			item.querySelector(".workspace-tab-header-inner-icon").innerHTML = '📝';
			return false;
		}
	});
}
modifyRecentlyIcon();
document.querySelector(".mod-left-split .workspace-tab-header-container-inner").addEventListener('click', ()=>{
	setTimeout(() => {
	    modifyRecentlyIcon();
	}, 300);
});

如果在右侧面板中,可参考上面思路自行实现。

更完美方式实现在当前激活叶子打开文档

如果想让"Recently Modified"脚本未激活时(即未点开脚本文档前)也能获取当前激活叶子,可以通过active-leaf-change事件结合全局变量实现,比如可在runjs插件加载时执行脚本中输入以下代码:

// 把最后一个被激活的叶子,设置为全局变量
(() => {
    // "Recently Modified"脚本名字,根据你自己的脚本名修改
    const RecentlyScriptName = "Recently Modified";
	let lastLeafTimer;
	const onActiveLeafChange = async (activeLeaf) => {
		// 定时防止无效触发,只取最后一个触发
		if(lastLeafTimer) clearTimeout(lastLeafTimer)
        lastLeafTimer = setTimeout(async () => {
	         if(activeLeaf?.view?.file?.basename !== RecentlyScriptName) {
	             window.lastActiveLeaf = activeLeaf;
	         }
		}, 42);
	};
	this.app.workspace.on('active-leaf-change', onActiveLeafChange);
	onActiveLeafChange(this.app.workspace.activeLeaf);
})();

说明:RecentlyScriptName = "Recently Modified" 这是"Recently Modified"脚本名字,根据你自己的脚本名修改。

然后修改 “Recently Modified” 脚本中的判断代码,比如:

let newLeaf = lastActiveLeaf || app.workspace.getLeaf('tab');

修改为

let newLeaf = window.lastActiveLeaf || lastActiveLeaf || app.workspace.getLeaf('tab');

3 个赞