Adds fallback options for when icon servers are down

This commit is contained in:
Alicia Sykes 2021-11-10 17:48:36 +00:00
parent 14ef52ccf3
commit 8d1b57c34e
3 changed files with 25 additions and 5 deletions

View File

@ -80,7 +80,7 @@ sections:
---
## Generative Icons
To uses a unique and programmatically generated icon for a given service just set `icon: generative`. This is particularly useful when you have a lot of similar services with a different IP or port, and no specific icon. These icons are generated with [DiceBear](https://avatars.dicebear.com/), and use a hash of the services domain/ ip for entropy, so each domain will always have the same icon.
To uses a unique and programmatically generated icon for a given service just set `icon: generative`. This is particularly useful when you have a lot of similar services with a different IP or port, and no specific icon. These icons are generated with [DiceBear](https://avatars.dicebear.com/) (or [Evatar](https://evatar.io/) for fallback), and use a hash of the services domain/ ip for entropy, so each domain will have a unique icon.
<p align="center">
<img width="500" src="https://i.ibb.co/b2pC2CL/generative-icons-2.png" />

View File

@ -49,12 +49,14 @@ export default {
},
/* Gets the icon path, dependent on icon type */
iconPath: function iconPath() {
if (this.broken) return this.getFallbackIcon();
return this.getIconPath(this.icon, this.url);
},
},
data() {
return {
broken: false, // If true, was unable to resolve icon
attemptedFallback: false,
};
},
methods: {
@ -94,12 +96,12 @@ export default {
},
/* Get favicon URL, for items which use the favicon as their icon */
getFavicon(fullUrl, specificApi) {
if (this.shouldUseDefaultFavicon(fullUrl)) { // Check if we should use local icon
const faviconApi = specificApi || this.appConfig.faviconApi || defaultFaviconApi;
if (this.shouldUseDefaultFavicon(fullUrl) || faviconApi === 'local') { // Check if we should use local icon
const urlParts = fullUrl.split('/');
if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/${iconCdns.faviconName}`;
} else if (fullUrl.includes('http')) { // Service is running publicly
const host = this.getHostName(fullUrl);
const faviconApi = specificApi || this.appConfig.faviconApi || defaultFaviconApi;
const endpoint = faviconApiEndpoints[faviconApi];
return endpoint.replace('$URL', host);
}
@ -130,9 +132,9 @@ export default {
return `${iconCdns.localPath}/${img}`;
},
/* Formats the URL for fetching the generative icons */
getGenerativeIcon(url) {
getGenerativeIcon(url, cdn) {
const host = encodeURI(url) || Math.random().toString();
return iconCdns.generative.replace('{icon}', asciiHash(host));
return (cdn || iconCdns.generative).replace('{icon}', asciiHash(host));
},
/* Returns the SVG path content */
getSimpleIcon(img) {
@ -187,6 +189,23 @@ export default {
this.broken = true;
ErrorHandler(`The path to '${this.icon}' could not be resolved`);
},
/* Called when initial icon has resulted in 404. Attempts to find new icon */
getFallbackIcon() {
if (this.attemptedFallback) return undefined; // If this is second attempt, then give up
const { iconType } = this;
const markAsSttempted = () => {
this.broken = false;
this.attemptedFallback = true;
};
if (iconType.includes('favicon')) { // Specify fallback for favicon-based icons
markAsSttempted();
return this.getFavicon(this.url, 'local');
} else if (iconType === 'generative') {
markAsSttempted();
return this.getGenerativeIcon(this.url, iconCdns.generativeFallback);
}
return undefined;
},
},
};
</script>

View File

@ -184,6 +184,7 @@ module.exports = {
mdi: 'https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.min.css',
si: 'https://unpkg.com/simple-icons@v5/icons',
generative: 'https://avatars.dicebear.com/api/identicon/{icon}.svg',
generativeFallback: 'https://evatar.io/{icon}',
localPath: './item-icons',
faviconName: 'favicon.ico',
homeLabIcons: 'https://raw.githubusercontent.com/WalkxCode/dashboard-icons/master/png/{icon}.png',