我正在尝试存储与一个人在特定选项卡/URL上停留的时间有关的信息。
使用铬API-https://developer.chrome.com/docs/extensions/reference/tabs/#type-选项卡-我可以跟踪选项卡的活动信息和突出显示的信息来完成此操作。
我目前正在用我的扩展程序跟踪几个不同的数据点,如下所示,我希望能够跟踪我在特定选项卡上的时间(因此我在该选项卡上的具体时间(,以及我在选项卡之间移动或创建新选项卡的频率。
export type TAB_USAGE = {
tabId: number;
index?: number;
highlighted: boolean;
url: string;
startTime: string;
endTime?: string;
startFocus?: string;
endFocus?: string;
};
const getHostname = (url: string) => {
// use URL constructor and return hostname
return new URL(url).hostname;
};
export function enableTabListener(
socket: any,
currentPages: TAB_USAGE[],
visitedPages: Partial<TAB_USAGE>[]
) {
chrome.tabs.onUpdated.addListener(
});
setInterval(async () => {
console.log('sent tab data:', visitedPages);
}, 50000);
}
我不能100%确定这里的最佳方法——我在想,检查一下旧数据是否有效,而新数据是否有效?
所以像
if (tabExisting.highlighted != tab.highlighted) {
//set endFocus?
}
当使用这种方法时,它似乎不起作用,tabExisting基本上很多时候都是null。
或者使用另一个侦听器API,以便在突出显示更改时,在某个位置每小时设置一个计数器?我很想看看有多少个标签,我多久在它们之间切换一次,停留在其中一个标签上,真的是每小时一次,试图找到一个好的方法来做到这一点。
我喜欢这里的一些反馈——我的大脑因为盯着这些文档而有点兴奋,我希望得到一些指导。
您的方法在某种程度上是正确的。然而,对于您想要跟踪的活动类型,我会将类型TAB_USAGE
更改为:
export type FocusPeriod = {
startTime: string,
endTime: string
}
export type TAB_USAGE = {
tabId: number;
index?: number;
active?: boolean; //we're using active instead of highlighted
url?: string; //notice url is now optional
startTime: string;
endTime?: string;
focus?: Array<FocusPeriod>; //storing multiple focus events of a tab
};
因为一个人会经常在选项卡之间切换,并且特定选项卡会有多个焦点时段。还要注意,url
现在是可选的,因为我们将收听.onActivated
事件,其中url
可能在回调中不可用。
现在,为了跟踪选项卡之间的切换,我将使用.onActivated
事件而不是.onHighlighted
事件。请注意active
选项卡和highlighted
选项卡之间的区别。
活动选项卡始终高亮显示。每个窗口只有一个活动选项卡。在同一窗口中可以有多个高亮显示的选项卡。但是,所有突出显示的选项卡都不处于活动状态。示例:选择一个选项卡,按住Shift键,然后选择另一个选项卡。最后单击的选项卡将成为该窗口的活动选项卡,但它们之间的所有选项卡(包括两个限制选项卡(现在都会高亮显示。
.onActivated
事件上的侦听器可以这样添加:
chrome.tabs.onActivated.addListener(
(activeInfo: object) => {
const previousActiveTabIndex = currentPages.findIndex((page) => page.active);
if(previousActiveTabIndex !== -1) {
currentPages[previousActiveTabIndex].active = false;
const focusLength = currentPages[previousActiveTabIndex].focus.length;
currentPages[previousActiveTabIndex].focus[focusLength - 1].endTime = new Date().toISOString();
}
const newActiveTabIndex = currentPages.findIndex((page) => page.tabId === activeInfo.tabId);
if(newActiveTabIndex > 0) {
currentPages[newActiveTabIndex].active = true;
currentPages[newActiveTabIndex].focus.push({
startTime: new Date().toISOString(),
endTime: ''
});
}
else {
currentPages = [
..currentPages,
{
tabId: activeInfo.tabId;
active: true;
startTime: new Date().toISOString();
focus: [{ startTime: new Date().toISOString(), endTime: '' }];
}
]
}
}
)
如果你只对跟踪用户实际访问的选项卡感兴趣,那么上面的代码对你来说应该很好。尽管在某些情况下,我们使用Cmd+Click
或Ctrl+Click
在新选项卡中打开url,这不会使新创建的选项卡处于活动状态。如果用户从未选择该选项卡,那么即使用户由于以下条件关闭了该选项卡,您也将无法跟踪它:.onRemoved
事件处理程序函数中的if (tabExists)
。对于这些情况,我们应该添加.onCreated
事件处理程序。
chrome.tabs.onCreated.addListener(
(tab: Tab) => {
const tabIndex = currentPages.findIndex((page) => page.tabId === tab.id);
if(tabIndex === -1) {
currentPages = [
..currentPages,
{
tabId: tab.id;
startTime: new Date().toISOString();
focus: [];
}
]
}
}
)
到目前为止还不错。我们添加了上面提到的事件处理程序。但在触发.onActivated
或.onCreated
事件时,不能保证会有url。因此,当更新选项卡的url时,就会触发.onUpdated
事件。这就是我们需要稍微更改代码的原因。只有当tabExisting.url
存在(不是null、undefined或''(时,我们才会向visitedPages
添加条目;
最后,为了在安装扩展时从所有窗口获得所有选项卡(初始化(,我们应该添加另一个事件处理程序,如下所示:
chrome.runtime.onInstalled.addListener((details) => {
if(['install', 'chrome_update'].includes(details.reason)) {
chrome.windows.getAll((windows: Window[]) => {
windows.forEach(window => {
chrome.tabs.getAllInWindow(window.id, (tabs: Tab[]) => {
tabs.forEach(tab => {
currentPages = [
..currentPages,
{
tabId: tab.id;
startTime: new Date().toISOString();
focus: [];
url: tab.url;
}
]
});
});
chrome.tabs.query({active: true, windowId: window.id}, (tab: Tab) => {
const tabIndex = currentPages.findIndex((page) => page.tabId === tab.id);
if(tabIndex > 0) {
currentPages[tabIndex - 1].active = true;
}
});
});
});
}
else if(details.reason == 'update') {
//do whatever necessary
}
});
可以有许多正确的方法来实现这一点。我想我会这样做。如果有什么不清楚的地方,请评论。