有許多即時通訊軟體會顯示當前用戶的上線狀態,甚至會自動檢測用戶是否狀態為「離開」,像是:Microsoft Teams、Discord 等。若要使用 Web 技術實現自動檢測這件事情,第一個想到的可能是使用 Page Visibility API 來檢測「頁面是可見的還是隱藏的」,進而判斷是否要讓用戶呈現「離開」狀態。但如果使用者離開的定義是 使用者鎖定畫面或長時間沒有操作,這用 Page Visibility API 是無法精準判斷的,因為頁面的隱藏有可能是 最小化、切換分頁、鎖定畫面等情境 。如果要精準判斷鎖定畫面或是長時間沒有操作,可以考慮使用 Idle Detection API。

什麼是 Idle Detection API?

Idle Detection API 是 Chrome 在 94 版中添加的 API,該 API 可以檢測用戶是否處於閒置狀態,包含:是否鎖定畫面、使用者是否沒有跟鍵盤、滑鼠、螢幕互動等。這對於即時通訊軟體而言可說是非常有用的 API,即使用戶切換分頁、最小化視窗,只要還在操作就不會被判定是「離開」。

注意:該 API 目前只在 Chromium 系列的瀏覽器有支援,Firefox、Safari 因隱私和安全等考量並沒有跟進。詳細資訊可以參考「Chrome 94添加存在隱私爭議的閒置偵測API,Firefox和Safari不跟進」文章。也因為只有部分瀏覽器有支援,建議可以在程式碼中檢查該 API 是否可用,檢查的判斷式為:if ('IdleDetector' in window) { ... }。

使用 Idle Detection API

下方是一段 Idle Detection API 的範例程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
async function detect(func) {
const controller = new AbortController();
const signal = controller.signal;

if (!'IdleDetector' in window) {
throw new Error('Browser does not support idle detection.');
}

// 向用戶提出權限許可
const permission = await IdleDetector.requestPermission();
if (permission !== 'granted') {
throw new Error('Idle detection permission denied.');
}

const idleDetector = new IdleDetector();
// 當使用者長時間未操作或鎖定畫面時,會觸發此事件
idleDetector.addEventListener('change', () => {
const userState = idleDetector.userState; // active or idle
const screenState = idleDetector.screenState; // locked or unlocked
func({ userState, screenState });
});

await idleDetector.start({
// 設置閒置門檻為 60 秒
threshold: 60 * 1000,
signal,
});

return function() {
controller.abort();
};
}

async function main() {
const unsubscribe = await detect(({ userState, screenState }) => {
console.log(`User state: ${userState}, Screen state: ${screenState}`);
});

// 要停止偵測時,可以調用該 function
// unsubscribe();
}

main();

當執行 IdleDetector.requestPermission() 時,瀏覽器會彈出下方權限許可畫面,用戶需要點擊「允許」才能夠使用 Idle Detection API:

Request idle detector permission

當用戶允許後,就會開始檢測。由於 threshold 設置為 60 秒,當用戶閒置 60 秒時,會在 Console 印出狀態為 idle:

User state idle

當用戶重新使用時,會在 Console 印出狀態為 active:

User state active

如果用戶鎖定畫面,會在 Console 印出狀態為 locked:

Screen state locked

如果用戶解除鎖定畫面,會在 Console 印出狀態為 unlocked:

Screen state unlocked

用 DevTool 模擬

Chrome 推出 Idle Detection API 的同時,也在 DevTool 新增了模擬閒置事件。可以透過「Sensors」分頁找到「Emulate Idle Detector state」區塊,在這裡可以針對四種情境進行切換:

Chrome dev tool idle detector

結論

透過 Idle Detection API 可以更精準地判斷使用者是否處於閒置狀態,不過該 API 現在只有 Chromium 系列瀏覽器有支援,這對於需要同時支援多種瀏覽器的應用程式來說仍然需要用 Page Visibility API 當作 Fallback。