dynamic favicon that indicates if an entry is running (#4038)

This commit is contained in:
Kevin Papst
2023-05-21 15:40:45 +02:00
committed by GitHub
parent 2664d6117f
commit 7ab0a8cea1
9 changed files with 49 additions and 11 deletions

View File

@@ -13,7 +13,8 @@ As announced in the [README](README.md) I only support the latest available rele
## Reporting a Vulnerability ## Reporting a Vulnerability
Please read the [Bughunter](https://www.kimai.org/documentation/bughunter.html) documentation before posting. Please read the [Bughunter](https://www.kimai.org/documentation/bughunter.html) documentation before posting.
You can report any security related vulnerability in the [advisory section at GitHub](https://github.com/kimai/kimai/security/advisories) or via email to kpapst@gmx.net. You can report any security related vulnerability in the [advisory section at GitHub](https://github.com/kimai/kimai/security/advisories)
or via email to [support@kimai.org](mailto:support@kimai.org).
I will work as fast as I can to fix the problem and publish a bugfix release / security update. I will work as fast as I can to fix the problem and publish a bugfix release / security update.
Depending on the size of the required fixes, this might take a couple of hours or a couple of days. Depending on the size of the required fixes, this might take a couple of hours or a couple of days.
@@ -22,3 +23,5 @@ You can expect that your message will be answered ASAP.
You will be mentioned in the release notes if your issue is valid. You will be mentioned in the release notes if your issue is valid.
I am grateful for any (discrete) disclosure of vulnerabilities! I am grateful for any (discrete) disclosure of vulnerabilities!
Please note: if you are asking for money, I will not reply. I receive these scam messages every day...

View File

@@ -18,6 +18,7 @@ export default class KimaiActiveRecords extends KimaiPlugin {
super(); super();
this._selector = '.ticktac-menu'; this._selector = '.ticktac-menu';
this._selectorEmpty = '.ticktac-menu-empty'; this._selectorEmpty = '.ticktac-menu-empty';
this._favIconUrl = null;
} }
/** /**
@@ -52,8 +53,6 @@ export default class KimaiActiveRecords extends KimaiPlugin {
// handle duration in the visible UI // handle duration in the visible UI
this._updateBrowserTitle = !!this.getConfiguration('updateBrowserTitle'); this._updateBrowserTitle = !!this.getConfiguration('updateBrowserTitle');
// deactivated direct duration update, becuase it is unclear
// this._updateDuration();
const handle = () => { const handle = () => {
this._updateDuration(); this._updateDuration();
}; };
@@ -77,6 +76,10 @@ export default class KimaiActiveRecords extends KimaiPlugin {
// needs to search in document, to find all running entries, both in "ticktac" and listing pages // needs to search in document, to find all running entries, both in "ticktac" and listing pages
const activeRecords = document.querySelectorAll('[data-since]:not([data-since=""])'); const activeRecords = document.querySelectorAll('[data-since]:not([data-since=""])');
if (this._updateBrowserTitle) {
this._changeFavicon(activeRecords.length > 0);
}
if (activeRecords.length === 0) { if (activeRecords.length === 0) {
if (this._updateBrowserTitle) { if (this._updateBrowserTitle) {
if (document.body.dataset['title'] === undefined) { if (document.body.dataset['title'] === undefined) {
@@ -195,4 +198,36 @@ export default class KimaiActiveRecords extends KimaiPlugin {
}); });
} }
/**
* @param {boolean} running
* @private
*/
_changeFavicon(running)
{
const canvas = document.createElement('canvas');
const orig = document.getElementById('favicon');
if (this._favIconUrl === null) {
this._favIconUrl = orig.href;
}
const link = orig.cloneNode(true);
if (canvas.getContext && link) {
const ratio = window.devicePixelRatio;
const img = document.createElement('img');
canvas.height = canvas.width = 16 * ratio;
img.onload = function () {
const ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, canvas.width, canvas.height);
if (running) {
const width = 5.5 * ratio;
ctx.fillStyle = 'rgb(182,57,57)';
ctx.fillRect((canvas.width / 2) - (width / 2), (canvas.height / 2) - (width / 2), width, width);
}
link.href = canvas.toDataURL('image/png');
orig.remove();
document.head.appendChild(link);
};
img.src = this._favIconUrl;
}
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
"app": { "app": {
"js": [ "js": [
"/build/runtime.f0079159.js", "/build/runtime.f0079159.js",
"/build/app.70a820f6.js" "/build/app.f0378e96.js"
], ],
"css": [ "css": [
"/build/app.2005c135.css" "/build/app.2005c135.css"
@@ -63,7 +63,7 @@
}, },
"integrity": { "integrity": {
"/build/runtime.f0079159.js": "sha384-H22sAW1aTvyIPqvHOvGXWSWTxf0y6mptp+MsVmyXCfjx/WJjBbhX9gbUZ+qIuihV", "/build/runtime.f0079159.js": "sha384-H22sAW1aTvyIPqvHOvGXWSWTxf0y6mptp+MsVmyXCfjx/WJjBbhX9gbUZ+qIuihV",
"/build/app.70a820f6.js": "sha384-WKz8wOwY8EYT1ncPkMRnEE3q5LnP76keOZxTD410dXpsowUktUg+vWUqDhVXwLat", "/build/app.f0378e96.js": "sha384-ohZkuGMYJFa1nD/JJb1XJy6CYfqk/ubIo9QuY3yYJFg7NEG+0U93+YIIvUnCm2xm",
"/build/app.2005c135.css": "sha384-mXP2EO6K1kvUNEFBxLHjXlgkfWSFtyLC1rFhhX5qMbpOHvZrl8Ny1zP03ToPkF6d", "/build/app.2005c135.css": "sha384-mXP2EO6K1kvUNEFBxLHjXlgkfWSFtyLC1rFhhX5qMbpOHvZrl8Ny1zP03ToPkF6d",
"/build/export-pdf.d367a32e.js": "sha384-Z5baqnzjI636nYFs4g63ViIKBZKRW4Jhv/7PQmTEQlqhfA7eK0vUMUtiyy0R5A9u", "/build/export-pdf.d367a32e.js": "sha384-Z5baqnzjI636nYFs4g63ViIKBZKRW4Jhv/7PQmTEQlqhfA7eK0vUMUtiyy0R5A9u",
"/build/export-pdf.d8a6c23b.css": "sha384-ztepocHE4rnGE9eKZ4kL6jTKaePUyiwiB9TjJjstjpf/ckcKg1HedrEOOk/8ElJg", "/build/export-pdf.d8a6c23b.css": "sha384-ztepocHE4rnGE9eKZ4kL6jTKaePUyiwiB9TjJjstjpf/ckcKg1HedrEOOk/8ElJg",

View File

@@ -1,6 +1,6 @@
{ {
"build/app.css": "/build/app.2005c135.css", "build/app.css": "/build/app.2005c135.css",
"build/app.js": "/build/app.70a820f6.js", "build/app.js": "/build/app.f0378e96.js",
"build/export-pdf.css": "/build/export-pdf.d8a6c23b.css", "build/export-pdf.css": "/build/export-pdf.d8a6c23b.css",
"build/export-pdf.js": "/build/export-pdf.d367a32e.js", "build/export-pdf.js": "/build/export-pdf.d367a32e.js",
"build/invoice.css": "/build/invoice.5bea118e.css", "build/invoice.css": "/build/invoice.5bea118e.css",

View File

@@ -17,11 +17,11 @@ class Constants
/** /**
* The current release version * The current release version
*/ */
public const VERSION = '2.0.22'; public const VERSION = '2.0.23';
/** /**
* The current release: major * 10000 + minor * 100 + patch * The current release: major * 10000 + minor * 100 + patch
*/ */
public const VERSION_ID = 20022; public const VERSION_ID = 20023;
/** /**
* The software name * The software name
*/ */

View File

@@ -1,4 +1,4 @@
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}"> <link id="favicon" rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
<link rel="icon" type="image/png" href="{{ asset('favicon-16x16.png') }}" sizes="16x16"> <link rel="icon" type="image/png" href="{{ asset('favicon-16x16.png') }}" sizes="16x16">
<link rel="icon" type="image/png" href="{{ asset('favicon-32x32.png') }}" sizes="32x32"> <link rel="icon" type="image/png" href="{{ asset('favicon-32x32.png') }}" sizes="32x32">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}"> <link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">