更新为第2版
更新内容:
- UI美化
- 增加右键菜单
- 增加HoverPopover
- 增加tooltip
- 增加多语言
代码
```dataviewjs
// 显示条数
const maxNum = 100;
// 本脚本的文件的名字
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});
activeLeaf?.containerEl.classList.add('recently-modified-view');
}
// 检查recently-modified-view是否设置成功
if(!document.querySelector('recently-modified-view')){
app.workspace.getLeavesOfType('markdown').forEach(leaf => {
if(leaf.view.file?.basename === currFileName){
leaf?.containerEl.classList.add('recently-modified-view');
if (leaf?.view?.getState()?.mode !== 'preview') {
leaf?.setViewState({type: "markdown", state: state});
}
}
})
}
// 多语言,默认为中文
const langMap = {
en: {
"标题:": "Title: ",
"创建于:": "Created on: ",
"更新于:": "Updated on: ",
"所在文件夹:": "Folder: ",
"根目录": "Root directory",
"搜索...": "Search...",
}
}
function t(str) {
const lang = moment.locale();
if(langMap[lang] && langMap[lang][str]) {
return langMap[lang][str];
}
return str;
}
//添加样式
const style = `
.recently-modified-view .search-input {
background-color: transparent;
border: 1px solid #888;
border-radius: 5px;
height: 27px;
width: 80%;
padding: 0 5px;
color: var(--text-normal);
margin-top: 2px;
margin-left: 2px;
}
.recently-modified-view .search-input:focus {
box-shadow: 0 0 0 2px var(--background-modifier-border-focus);
border-color: var(--background-modifier-border-focus);
transition: box-shadow 0.15s ease-in-out, border 0.15s ease-in-out;
}
.recently-modified-view .markdown-preview-view ul{
padding-left: 0;
user-select: none;
}
.recently-modified-view .markdown-preview-view ul > li{
list-style: none;
padding: 4px 8px;
border-radius: var(--radius-s);
}
.recently-modified-view .markdown-preview-view ul > li:hover{
background-color: var(--nav-item-background-hover);
}
.recently-modified-view .markdown-preview-view ul > li.menu-hover {
background-color: var(--nav-item-background-hover);
}
.recently-modified-view .markdown-preview-view ul > li a {
text-decoration: none;
color: var(--nav-item-color);
width: 100%;
display: list-item;
}
.recently-modified-view li:has(a[data-starred='true'])::after {
content: "✩";
position: absolute;
top: 4px;
right: 4px;
}
.recently-modified-view .inline-title {
font-size: 23px;
}
/* 修改tooltip对齐方式 */
body:has(.recently-modified-view) .tooltip{
text-align: left;
}
`;
const dvStyle = document.head.querySelector("#recently-modified-style");
if(dvStyle) dvStyle.remove();
document.head.appendChild(
createEl("style", {
attr: { id: "recently-modified-style" },
text: style,
type: "text/css",
})
);
// 关键词搜索
const search = dv.el('input', '', { attr: { "class": "search-input", "placeholder": t("搜索...") } });
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(maxNum||100)
.map(p => {
let title = `${t('标题:')}${p.file.name}\n`;
title += `${t('创建于:')}${moment(Number(p.file.ctime)).format('YYYY-MM-DD HH:mm:ss')}\n`;
title += `${t('更新于:')}${moment(Number(p.file.mtime)).format('YYYY-MM-DD HH:mm:ss')}\n`;
title += `${t('所在文件夹:')}${p.file.folder||t('根目录')}`;
const a=dv.el('a', p.file.name, { attr: { "data-href": p.file.path, "data-starred": p.file.starred, "aria-label": title, "data-tooltip-position": "right" } });
//click
a.addEventListener('click', function(e) {
let newLeaf = window.lastActiveLeaf || 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);
});
// hover popover
a.addEventListener('mouseover', function(event) {
if(!isCtrlDown) return;
if (!this?.getAttribute("data-href")) return;
app.workspace.trigger('hover-link', {
event,
source: 'preview',
hoverParent: this.closest('.dataview.list-view-ul'),
targetEl: this,
linktext: this.getAttribute("data-href"),
});
});
// context menu
a.addEventListener('contextmenu', function(event) {
if (!this?.getAttribute("data-href")) return false;
this.closest("li").classList.add('menu-hover');
const file = app.vault.getAbstractFileByPath(this.getAttribute("data-href"));
const menu = new obsidian.Menu();
menu.addItem((item) =>
item.setSection('action')
.setTitle('Open in new tab')
.setIcon('file-plus')
.onClick(() => {
const leaf = app.workspace.getLeaf('tab');
leaf.openFile(file);
})
);
app.workspace.trigger(
'file-menu',
menu,
file,
'link-context-menu',
);
menu.showAtPosition({ x: event.clientX, y: event.clientY });
menu.onHide(() => {
document.querySelectorAll('.recently-modified-view li.menu-hover')?.forEach(item=>item?.classList.remove('menu-hover'));
});
// 阻止浏默认的右键菜单
return false;
});
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楼
效果