Release 2.30.0 (#3673)

## [2.30.0] - 2025-01-01

Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel,
@KristjanESPERANTO, @rejas, @sdetweil.

> ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum
version is `v20.18.1`

### Added

- [core] Add wayland and windows start options to `package.json` (#3594)
- [docs] Add step for npm publishing in release process (#3595)
- [core] Add GitHub workflow to run spellcheck a few days before each
release (#3623)
- [core] Add test flag to `index.html` to pass to module js for test
mode detection (needed by #3630)
- [core] Add export on animation names (#3644)
- [compliments] Add support for refreshing remote compliments file, and
test cases (#3630)
- [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9
(#3586)
- [linter] Re-activate `eslint-plugin-package-json` to lint
`package.json` (#3643)
- [linter] Add linting for markdown files (#3646)
- [linter] Add some handy ESLint rules.
- [calendar] Add ability to display end date for full date events, where
end is not same day (showEnd=true) (#3650)
- [core] Add text to the config.js.sample file about the locale variable
(#3654, #3655)
- [core] Add fetch timeout for all node_helpers (thru undici, forces
node 20.18.1 minimum) to help on slower systems. (#3660) (3661)

### Changed

- [core] Run code style checks in workflow only once (#3648)
- [core] Fix animations export #3644 only on server side (#3649)
- [core] Use project URL in fallback config (#3656)
- [core] Fix Access Denied crash writing js/positions.js (on synology
nas) #3651. new message, MM starts, but no modules showing (#3652)
- [linter] Switch to 'npx' for lint-staged in pre-commit hook (#3658)

### Removed

- [tests] Remove `node-pty` and `drivelist` from rebuilded test (#3575)
- [deps] Remove `@eslint/js` dependency. Already installed with `eslint`
in deep (#3636)

### Updated

- [repo] Reactivate `stale.yaml` as GitHub action to mark issues as
stale after 60 days and close them 7 days later (if no activity) (#3577,
#3580, #3581)
- [core] Update electron dependency to v32 (test electron rebuild) and
all other dependencies too (#3657)
- [tests] All test configs have been updated to allow full external
access, allowing for easier debugging (especially when running as a
container)
- [core] Run and test with node 23 (#3588)
- [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in
`dep-review.yaml` (#3659)

### Fixed

- [updatenotification] Fix pm2 using detection when pm2 script is inside
or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628)
- [core] Fix loading node_helper of modules: avoid black screen, display
errors and continue loading with next module (#3578)
- [weather] Change default value for weatherEndpoint of provider
openweathermap to "/onecall" (#3574)
- [tests] Fix electron tests with mock dates, the mock on server side
was missing (#3597)
- [tests] Fix testcases with hard coded Date.now (#3597)
- [core] Fix missing `basePath` where `location.host` is used (#3613)
- [compliments] croner library changed filenames used in latest version
(#3624)
- [linter] Fix ESLint ignore pattern which caused that default modules
not to be linted (#3632)
- [core] Fix module path in case of sub/sub folder is used and use
path.resolve for resolve `moduleFolder` and `defaultModuleFolder` in
app.js (#3653)
- [calendar] Update to resolve issues #3098 #3144 #3351 #3422 #3443
#3467 #3537 related to timezone changes
- [calendar] Fix #3267 (styles array), also fixes event with both exdate
AND recurrence(and testcase)
- [calendar] Fix showEndsOnlyWithDuration not working, #3598, applies
ONLY to full day events
- [calendar] Fix showEnd for Full Day events (#3602)
- [tests] Suppress "module is not defined" in e2e tests (#3647)
- [calendar] Fix #3267 (styles array, really this time!)
- [core] Fix #3662 js/positions.js created incorrectly

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Michael Teeuw <michael@xonaymedia.nl>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Karsten Hassel <hassel@gmx.de>
Co-authored-by: Ross Younger <crazyscot@gmail.com>
Co-authored-by: Veeck <github@veeck.de>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: jkriegshauser <joshuakr@nvidia.com>
Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com>
Co-authored-by: vppencilsharpener <tim.pray@gmail.com>
Co-authored-by: veeck <michael.veeck@nebenan.de>
Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com>
Co-authored-by: Brian O'Connor <btoconnor@users.noreply.github.com>
Co-authored-by: WallysWellies <59727507+WallysWellies@users.noreply.github.com>
Co-authored-by: Jason Stieber <jrstieber@gmail.com>
Co-authored-by: jargordon <50050429+jargordon@users.noreply.github.com>
Co-authored-by: Daniel <32464403+dkallen78@users.noreply.github.com>
Co-authored-by: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com>
Co-authored-by: Panagiotis Skias <panagiotis.skias@gmail.com>
Co-authored-by: Marc Landis <dirk.rettschlag@gmail.com>
Co-authored-by: HeikoGr <20295490+HeikoGr@users.noreply.github.com>
Co-authored-by: Pedro Lamas <pedrolamas@gmail.com>
Co-authored-by: veeck <gitkraken@veeck.de>
This commit is contained in:
sam detweiler
2025-01-01 08:27:27 -06:00
committed by GitHub
parent 94c3c699e8
commit c24de64d77
145 changed files with 4895 additions and 1915 deletions

View File

@@ -12,6 +12,7 @@ Module.register("compliments", {
},
updateInterval: 30000,
remoteFile: null,
remoteFileRefreshInterval: 0,
fadeSpeed: 4000,
morningStartTime: 3,
morningEndTime: 12,
@@ -20,6 +21,9 @@ Module.register("compliments", {
random: true,
specialDayUnique: false
},
urlSuffix: "",
compliments_new: null,
refreshMinimumDelay: 15 * 60 * 60 * 1000, // 15 minutes
lastIndexUsed: -1,
// Set currentweather from module
currentWeatherType: "",
@@ -41,6 +45,22 @@ Module.register("compliments", {
const response = await this.loadComplimentFile();
this.config.compliments = JSON.parse(response);
this.updateDom();
if (this.config.remoteFileRefreshInterval !== 0) {
if ((this.config.remoteFileRefreshInterval >= this.refreshMinimumDelay) || window.mmTestMode === "true") {
setInterval(async () => {
const response = await this.loadComplimentFile();
if (response) {
this.compliments_new = JSON.parse(response);
}
else {
Log.error(`${this.name} remoteFile refresh failed`);
}
},
this.config.remoteFileRefreshInterval);
} else {
Log.error(`${this.name} remoteFileRefreshInterval less than minimum`);
}
}
}
let minute_sync_delay = 1;
// loop thru all the configured when events
@@ -185,8 +205,18 @@ Module.register("compliments", {
async loadComplimentFile () {
const isRemote = this.config.remoteFile.indexOf("http://") === 0 || this.config.remoteFile.indexOf("https://") === 0,
url = isRemote ? this.config.remoteFile : this.file(this.config.remoteFile);
const response = await fetch(url);
return await response.text();
// because we may be fetching the same url,
// we need to force the server to not give us the cached result
// create an extra property (ignored by the server handler) just so the url string is different
// that will never be the same, using the ms value of date
if (isRemote && this.config.remoteFileRefreshInterval !== 0) this.urlSuffix = `?dummy=${Date.now()}`;
//
try {
const response = await fetch(url + this.urlSuffix);
return await response.text();
} catch (error) {
Log.info(`${this.name} fetch failed error=`, error);
}
},
/**
@@ -236,6 +266,27 @@ Module.register("compliments", {
compliment.lastElementChild.remove();
wrapper.appendChild(compliment);
}
// if a new set of compliments was loaded from the refresh task
// we do this here to make sure no other function is using the compliments list
if (this.compliments_new) {
// use them
if (JSON.stringify(this.config.compliments) !== JSON.stringify(this.compliments_new)) {
// only reset if the contents changes
this.config.compliments = this.compliments_new;
// reset the index
this.lastIndexUsed = -1;
}
// clear new file list so we don't waste cycles comparing between refreshes
this.compliments_new = null;
}
// only in test mode
if (window.mmTestMode === "true") {
// check for (undocumented) remoteFile2 to test new file load
if (this.config.remoteFile2 !== null && this.config.remoteFileRefreshInterval !== 0) {
// switch the file so that next time it will be loaded from a changed file
this.config.remoteFile = this.config.remoteFile2;
}
}
return wrapper;
},