Implements new icon features, better favicon support and generative

This commit is contained in:
Alicia Sykes 2021-06-21 19:31:13 +01:00
parent 4b3d20f43f
commit b4b9d29170
2 changed files with 24 additions and 7 deletions

View File

@ -11,7 +11,7 @@
tabIndex="-1" tabIndex="-1"
> >
<label :for="`collapsible-${uniqueKey}`" class="lbl-toggle" tabindex="-1"> <label :for="`collapsible-${uniqueKey}`" class="lbl-toggle" tabindex="-1">
<Icon v-if="icon" :icon="icon" size="small" class="section-icon" /> <Icon v-if="icon" :icon="icon" size="small" :url="title" class="section-icon" />
<h3>{{ title }}</h3> <h3>{{ title }}</h3>
</label> </label>
<div class="collapsible-content"> <div class="collapsible-content">

View File

@ -11,9 +11,11 @@
<script> <script>
import BrokenImage from '@/assets/interface-icons/broken-icon.svg'; import BrokenImage from '@/assets/interface-icons/broken-icon.svg';
import ErrorHandler from '@/utils/ErrorHandler'; import ErrorHandler from '@/utils/ErrorHandler';
import { faviconApi as defaultFaviconApi, faviconApiEndpoints } from '@/utils/defaults';
export default { export default {
name: 'Icon', name: 'Icon',
inject: ['config'],
props: { props: {
icon: String, // Path to icon asset icon: String, // Path to icon asset
url: String, // Used for fetching the favicon url: String, // Used for fetching the favicon
@ -33,6 +35,7 @@ export default {
data() { data() {
return { return {
broken: false, broken: false,
// faviconApi: this.config.appConfig.faviconApi || defaultFaviconApi,
}; };
}, },
methods: { methods: {
@ -51,26 +54,36 @@ export default {
}, },
/* Get favicon URL, for items which use the favicon as their icon */ /* Get favicon URL, for items which use the favicon as their icon */
getFavicon(fullUrl) { getFavicon(fullUrl) {
const isLocalIP = /(127\.)|(192\.168\.)|(10\.)|(172\.1[6-9]\.)|(172\.2[0-9]\.)|(172\.3[0-1]\.)|(::1$)|([fF][cCdD])|(localhost)/; if (this.shouldUseDefaultFavicon(fullUrl)) { // Check if we should use local icon
if (isLocalIP.test(fullUrl)) { // Check if using a local IP format or localhost
const urlParts = fullUrl.split('/'); const urlParts = fullUrl.split('/');
// For locally running services, use the default path for favicon
if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/favicon.ico`; if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/favicon.ico`;
} else if (fullUrl.includes('http')) { } else if (fullUrl.includes('http')) { // Service is running publicly
// For publicly accessible sites, a more reliable method is using Google's API const host = this.getHostName(fullUrl);
return `https://s2.googleusercontent.com/s2/favicons?domain=${fullUrl}`; const faviconApi = this.config.appConfig.faviconApi || defaultFaviconApi;
const endpoint = faviconApiEndpoints[faviconApi];
return endpoint.replace('$URL', host);
} }
return ''; return '';
}, },
/* If using favicon for icon, and if service is running locally (determined by local IP) */
/* or if user prefers local favicon, then return true */
shouldUseDefaultFavicon(fullUrl) {
const isLocalIP = /(127\.)|(192\.168\.)|(10\.)|(172\.1[6-9]\.)|(172\.2[0-9]\.)|(172\.3[0-1]\.)|(::1$)|([fF][cCdD])|(localhost)/;
return (isLocalIP.test(fullUrl) || this.config.appConfig.faviconApi === 'local');
},
getLocalImagePath(img) { getLocalImagePath(img) {
return `/item-icons/${img}`; return `/item-icons/${img}`;
}, },
getGenerativeIcon(url) {
return `https://ipsicon.io/${this.getHostName(url)}.svg`;
},
/* Checks if the icon is from a local image, remote URL, SVG or font-awesome */ /* Checks if the icon is from a local image, remote URL, SVG or font-awesome */
getIconPath(img, url) { getIconPath(img, url) {
switch (this.determineImageType(img)) { switch (this.determineImageType(img)) {
case 'url': return img; case 'url': return img;
case 'img': return this.getLocalImagePath(img); case 'img': return this.getLocalImagePath(img);
case 'favicon': return this.getFavicon(url); case 'favicon': return this.getFavicon(url);
case 'generative': return this.getGenerativeIcon(url);
case 'svg': return img; case 'svg': return img;
default: return ''; default: return '';
} }
@ -84,9 +97,13 @@ export default {
else if (this.isImage(img)) imgType = 'img'; else if (this.isImage(img)) imgType = 'img';
else if (img.includes('fa-')) imgType = 'font-awesome'; else if (img.includes('fa-')) imgType = 'font-awesome';
else if (img === 'favicon') imgType = 'favicon'; else if (img === 'favicon') imgType = 'favicon';
else if (img === 'generative') imgType = 'generative';
else imgType = 'none'; else imgType = 'none';
return imgType; return imgType;
}, },
getHostName(url) {
try { return new URL(url).hostname; } catch (e) { return url; }
},
/* Called when the path to the image cannot be resolved */ /* Called when the path to the image cannot be resolved */
imageNotFound() { imageNotFound() {
this.broken = true; this.broken = true;