Left-Right Balance for Strava [Updated]

Shows your Left/Right balance under the analysis section on Strava.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Left-Right Balance for Strava [Updated]
// @namespace    typpi.online
// @description  Shows your Left/Right balance under the analysis section on Strava.
// @version      2.9
// @include      https://www.strava.com/activities/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=strava.com
// @author       Nick2bad4u
// @license      UnLicense
// @grant        none
// @homepageURL  https://github.com/Nick2bad4u/UserStyles
// ==/UserScript==

/**
 * URL of the script to be loaded from the CDN.
 * This script is hosted on jsDelivr and is part of the UserStyles repository.
 *
 * @constant {string}
 */
const SCRIPT_URL = 'https://cdn.jsdelivr.net/gh/Nick2bad4u/UserStyles@main/strava-balance/Strava-AddBalance.js';
// Cache expiration time set to 24 hours in milliseconds
const CACHE_EXPIRE_TIME = 24 * 60 * 60 * 1000;
// Key used to store the last fetch time of the script in localStorage
const CACHE_LAST_FETCH_TIME_KEY = 'stravaBalanceScriptFetchTime';
// Key used to store the cached script in localStorage
const CACHED_SCRIPT_KEY = 'stravaBalanceScript';

//SCRIPT_BALANCE_ELEMENT.src="https://dmwnz.github.io/lrbalance4strava/addbal.js";

/**
 * Determines if the cache has expired based on the last fetch time and the cache expiration time.
 *
 * @param {number} CACHE_LAST_FETCH_TIME - The timestamp of the last fetch.
 * @param {number} CACHE_EXPIRE_TIME - The duration in milliseconds after which the cache is considered expired.
 * @returns {boolean} - Returns true if the cache is expired, otherwise false.
 */
const isCacheExpired = (CACHE_LAST_FETCH_TIME, CACHE_EXPIRE_TIME) => {
	const CURRENT_TIME = Date.now();
	return !CACHE_LAST_FETCH_TIME || CURRENT_TIME - CACHE_LAST_FETCH_TIME > CACHE_EXPIRE_TIME;
};

/**
 * Immediately Invoked Function Expression (IIFE) to load and execute the Strava balance script.
 * It checks the cache for the script and fetches it from the network if the cache is expired.
 */
function loadStravaBalanceScript() {
	const CACHED_SCRIPT = localStorage.getItem(CACHED_SCRIPT_KEY) || '';
	const CACHE_LAST_FETCH_TIME = localStorage.getItem(CACHE_LAST_FETCH_TIME_KEY) || '0';

	const CACHE_EXPIRED = isCacheExpired(Number(CACHE_LAST_FETCH_TIME) || 0, CACHE_EXPIRE_TIME);
	if (CACHED_SCRIPT && !CACHE_EXPIRED) {
		loadScriptFromCache(CACHED_SCRIPT);
		console.log('Strava balance script loaded from cache and executed successfully.');
	} else {
		fetchAndCacheScript();
	}
}

/**
 * Loads and executes the provided script from the cache.
 *
 * @param {string} script - The script content to be executed.
 */
function loadScriptFromCache(script) {
	let SCRIPT_BALANCE_ELEMENT = document.querySelector('script[data-source="stravaBalanceScript"]');
	if (!SCRIPT_BALANCE_ELEMENT) {
		SCRIPT_BALANCE_ELEMENT = document.createElement('script');
		SCRIPT_BALANCE_ELEMENT.type = 'module';
		SCRIPT_BALANCE_ELEMENT.setAttribute('data-source', 'stravaBalanceScript');
		document.body.appendChild(SCRIPT_BALANCE_ELEMENT);
	}
	SCRIPT_BALANCE_ELEMENT.text = script;
}

function fetchAndCacheScript() {
	const CONTROLLER = new AbortController();
	const TIMEOUT_ID = setTimeout(() => CONTROLLER.abort(), 10000); // 10 seconds timeout
	fetch(SCRIPT_URL, { signal: CONTROLLER.signal })
		.then((SCRIPT_URL_RESPONSE) => {
			clearTimeout(TIMEOUT_ID);
			if (!SCRIPT_URL_RESPONSE.ok) {
				throw new Error(`HTTP error! status: ${SCRIPT_URL_RESPONSE.status} while fetching ${SCRIPT_URL}`);
			}
			return SCRIPT_URL_RESPONSE.text();
		})
		.then((SCRIPT_URL_RESPONSE_DATA) => {
			localStorage.setItem(CACHED_SCRIPT_KEY, SCRIPT_URL_RESPONSE_DATA);
			localStorage.setItem(CACHE_LAST_FETCH_TIME_KEY, Date.now().toString());
			loadScriptFromCache(SCRIPT_URL_RESPONSE_DATA);
			console.log('Strava balance script loaded from network and executed successfully.');
		})
		.catch((error) => {
			if (error.name === 'AbortError') {
				console.error('Fetch request timed out after 10 seconds');
			} else {
				console.error(`Error fetching script from ${SCRIPT_URL}:`, error);
			}
		});
}

(function () {
	loadStravaBalanceScript();
})();