This repository has been archived by the owner on Jan 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.user.js
117 lines (98 loc) · 3.74 KB
/
index.user.js
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// ==UserScript==
// @name SteamPTP
// @icon https://raw.githubusercontent.com/octoman90/SteamPTP/master/assets/icon48.png
// @version 0.2.1
// @description A Chrome extension that displays total playtime and playtime percentage for each game in Steam profiles
// @author man90 (https://github.com/octoman90)
// @namespace https://github.com/octoman90/SteamPTP/
// @updateURL https://github.com/octoman90/SteamPTP/raw/master/index.user.js
// @downloadURL https://github.com/octoman90/SteamPTP/raw/master/index.user.js
// @supportURL https://github.com/octoman90/SteamPTP/issues
// @license GPL-3.0
// @match *://steamcommunity.com/id/*/games/?tab=all*
// @match *://steamcommunity.com/profiles/*/games/?tab=all*
// @grant none
// @run-at idle
// ==/UserScript==
(() => {
"use strict"
// Function that takes a list of game card elements and outputs
// a list of playtimes as numbers and the sum
function parseAndCalc(playtimeElements) {
const parsedPlaytimes = playtimeElements
.map(el => {
const str = el.childNodes[1]?.textContent
// This here is the main reason why this script
// won't work for non-English interfaces
const inMinutes = /minutes/i.test(str)
return parseFloat(str.replaceAll(",", "")) / (inMinutes ? 60 : 1)
})
return {
playtimes: parsedPlaytimes,
total: parsedPlaytimes.reduce((acc, val) => acc + val),
}
}
// Function that adds playtime percentage to a given game card
function injectPercentage(element, playtime, total) {
const percentage = (playtime / total * 100).toFixed(1)
if (0 === parseFloat(percentage)) {
return
}
element.innerHTML += ` (${percentage}%)`
}
// Function that adds a total playtime text to the page
function injectTotal(total) {
if (total < 1) {
return
}
const totalElement = document.createElement("div")
totalElement.innerText = `Total: ${total.toFixed(0).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} hours`
totalElement.style.marginRight = "1rem"
totalElement.style.placeSelf = "center end"
const nextElement = document.querySelector("[class^=gameslistapp_PrivacySettingsLink], [class^=gameslistapp_BothOwnedFilter]")
const bar = nextElement.parentNode
bar.style.gridTemplateColumns = "auto 1fr auto auto"
bar.style.gridTemplateAreas = "\"search totalPlaytime bothOwned sort\""
bar.insertBefore(totalElement, nextElement)
}
// Main function that gathers all game cards on the page
// And launches the processing
function processPlaytimes() {
// Find playtime elements
const playtimeH5s = [...document.querySelectorAll("[class^=gameslistitems_Hours]")]
const { playtimes, total } = parseAndCalc(playtimeH5s)
// Add playtime percentages
playtimeH5s.forEach((el, i) => {
injectPercentage(el, playtimes[i], total)
})
injectTotal(total)
}
// Observer catches the app adding game cards
// If there's a pause of at least 100ms the processing function is fired
// It would be nicer to process them card by card whenever one gets added
// but I CBA to hack into React apps any farther
let t = null
const observer = new MutationObserver((mutationList, observer) => {
for (const mutation of mutationList) {
for (const node of mutation.addedNodes) {
if (!node.className?.startsWith("gameslistitems_GamesListItemContainer")) {
continue
}
if (t) {
clearTimeout(t)
}
t = setTimeout(() => {
observer.disconnect()
processPlaytimes()
// There may be a problem if it takes the browser more than 100ms
// to add the next card, but it works for me
}, 100)
}
}
})
observer.observe(document.querySelector("#application_root"), {
attributes: false,
childList: true,
subtree: true,
})
})()