Compare commits

...

3 commits

Author SHA1 Message Date
Kristjan ESPERANTO
6a84961a36
chore: release v1.1.0 2025-03-25 19:22:51 +01:00
Kristjan ESPERANTO
07eed1bf3e
Add example config files 2025-03-25 19:17:49 +01:00
Kristjan ESPERANTO
2ccd56ef36
feat: Add individual rotation time for each page (#88) 2025-03-25 19:13:37 +01:00
8 changed files with 200 additions and 57 deletions

View file

@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.1.0](https://github.com/edward-shen/MMM-pages/compare/v1.0.1...v1.1.0) - 2025-03-25 - Feature Release
### Added
- feat: Add individual rotation time for each page (#88)
- docs: Add example configuration files in directory `example_configs`
## [1.0.1](https://github.com/edward-shen/MMM-pages/compare/v1.0.0...v1.0.1) - 2025-03-23 - Maintenance Release
### Changed

View file

@ -12,6 +12,7 @@ Module.register('MMM-pages', {
hiddenPages: {},
animationTime: 1000,
rotationTime: 0,
timings: { default: 0 },
rotationFirstPage: 0, // Keep for compatibility
rotationHomePage: 0,
rotationDelay: 10000,
@ -48,12 +49,17 @@ Module.register('MMM-pages', {
}
if (this.config.rotationFirstPage) {
Log.warn('[MMM-pages] The config option "rotationFirstPage" is deprecated. Please used "rotationHomePage" instead.');
Log.warn('[MMM-pages] The config option "rotationFirstPage" is deprecated. Please use "rotationHomePage" instead.');
this.config.rotationHomePage = this.config.rotationFirstPage;
}
if (this.config.rotationTime) {
Log.warn('[MMM-pages] The config option "rotationTime" is deprecated. Please use "timings" instead.');
this.config.timings.default = this.config.rotationTime;
}
// Disable rotation if an invalid input is given
this.config.rotationTime = Math.max(this.config.rotationTime, 0);
this.config.timings.default = Math.max(this.config.timings.default, 0);
this.config.rotationDelay = Math.max(this.config.rotationDelay, 0);
this.config.rotationHomePage = Math.max(this.config.rotationHomePage, 0);
@ -221,11 +227,15 @@ Module.register('MMM-pages', {
* @param {number} delay the delay, in milliseconds.
*/
resetTimerWithDelay(delay) {
if (this.config.rotationTime > 0) {
if (this.config.timings.default > 0 || Object.keys(this.config.timings).length > 1) {
// This timer is the auto rotate function.
clearInterval(this.timer);
// This is delay timer after manually updating.
clearInterval(this.delayTimer);
let currentRotationTime = this.config.timings.default;
if (this.config.timings[this.curPage]) {
currentRotationTime = this.config.timings[this.curPage];
}
const self = this;
this.delayTimer = setTimeout(() => {
@ -235,7 +245,7 @@ Module.register('MMM-pages', {
// message, so we need to trigger it for ourselves.
self.sendNotification('PAGE_INCREMENT');
self.notificationReceived('PAGE_INCREMENT');
}, self.config.rotationTime);
}, currentRotationTime);
}, delay);
} else if (this.config.rotationHomePage > 0) {
// This timer is the auto rotate function.

View file

@ -59,7 +59,7 @@ To use this module, add a configuration to the modules array in the `config/conf
There are two ways to configure this module: Using the module names or using class names. The module name based configuration is easier to use, but has the limitation that you can only use one instance of each module. So if you want to use multiple instances of the same module, you have to use the class based configuration.
*Note*: Some of the module names used in the following examples are fictitious.
*Note*: You can find complete configuration example files for both module name and class based configurations in the [example_configs](example_configs) directory.
### Module name based configuration
@ -71,10 +71,13 @@ The first element of the array is the first page, the second element is the seco
{
module: "MMM-pages",
config: {
rotationTime: 1000 * 20, // rotate every 20 seconds
timings: {
default: 5000, // rotate every 5 seconds
0: 20000 // page 0 rotates every 20 seconds
},
modules: [
["newsfeed"], // page 1
["calendar", "compliments"], // page 2
["newsfeed"], // page 0
["calendar", "compliments"], // page 1
],
fixed: [ // modules that are always shown
"clock",
@ -84,11 +87,11 @@ The first element of the array is the first page, the second element is the seco
hiddenPages: { // modules that are only shown on specific pages
"screenSaver": [
"clock",
"MMM-SomeBackgroundImageModule"
"MMM-BackgroundSlideshow"
],
"admin": [
"MMM-ShowMeSystemStatsModule",
"MMM-AnOnScreenMenuModule"
"MMM-SystemMonitor",
"MMM-OnScreenMenu"
]
}
}
@ -103,11 +106,14 @@ Instead of using the module name, you can also use a class name for each page. T
{
module: "MMM-pages",
config: {
rotationTime: 1000 * 20, // rotate every 20 seconds
timings: {
default: 20000, // rotate every 20 seconds
2: 30000 // page 2 rotates every 30 seconds
},
modules: [
["page0"], // class name for page 0
["page1"], // class name for page 1
["page2"], // class name for page 2
["page3"], // class name for page 3
],
fixed: ["fixed_page"],
hiddenPages: {
@ -121,15 +127,23 @@ Instead of using the module name, you can also use a class name for each page. T
You have to add the class name to the config of the module you want to show on a specific page. You can even add more than one class name to show a module instance on multiple pages.
```js
{ // newsfeed on page 1
{ // newsfeed on page 0
module: "newsfeed",
classes: "page0",
position: "...",
config: {
...
}
},
{ // first calendar instance on page 1
module: "calendar",
classes: "page1",
position: "...",
config: {
...
}
},
{ // first calendar instance on page 2
{ // second calendar instance on page 2
module: "calendar",
classes: "page2",
position: "...",
@ -137,17 +151,9 @@ You have to add the class name to the config of the module you want to show on a
...
}
},
{ // second calendar instance on page 3
module: "calendar",
classes: "page3",
position: "...",
config: {
...
}
},
{ // this compliments instance appears on page 1 and 3
{ // this compliments instance appears on page 0 and 2
module: "compliments",
classes: "page1 page3",
classes: "page0 page2",
position: "...",
config: {
...
@ -158,14 +164,15 @@ You have to add the class name to the config of the module you want to show on a
### Configuration options
| Option | Type | Default Value | Description |
| --- | --- | --- | --- |
| Option | Type | Default Value | Description |
| ------------------- | -------------------------- | ------------------------ | ----------- |
| `modules` | `[[String...]...]` | `[]` | A 2D String array of what each module should be on which page. Note that all entries must take their class name (e.g. this module's class name is `MMM-pages`, while the default modules may just have `newsfeed`, without the `MMM-` prefix. |
| `fixed` | `[String...]` | `["MMM-page-indicator"]` | Which modules should show up all the time. |
| `excludes` | *NA* | *NA* | **Deprecated**. Use `fixed` instead. |
| `hiddenPages` | `{String: [String...]...}` | `{}` | An Object defining special `hiddenPages` which are not available on the normal page rotation and only accessible via a notification. Modules defined in `fixed` are ignored and need to be also added if you wish to have them on any hidden page. |
| `animationTime` | `int` | `1000` | Fading animation time. Set to `0` for instant change. Value is in milliseconds (1 second = 1000 milliseconds). |
| `rotationTime` | `int` | `0` | Time, in milliseconds, between automatic page changes. |
| `rotationTime` | *NA* | *NA* | **Deprecated**. Use `timings` instead. |
| `timings` | `object` | `{ default: 0 }` | An object whose keys define the rotation time of the pages in milliseconds. <br>Example, where each page is 3 seconds, except page 3 which is 20 seconds:<br>`{ default: 3000, 2: 20000 }`<br>If a page is not defined, it will use the `default` value. <br> *Note:* Remember that the numbering starts at 0, so the first page is `0`, the second page is `1`, and so forth. |
| `rotationDelay` | `int` | `10000` | Time, in milliseconds, of how long should a manual page change linger before returning to automatic page changing. In other words, how long should the timer wait for after you manually change a page. This does include the animation time, so you may wish to increase it by a few seconds or so to account for the animation time. |
| `rotationHomePage` | `int` | `0` | Time, in milliseconds, before automatically returning to the home page. If a home page is not set, this returns to the leftmost page instead. |
| `rotationFirstPage` | *NA* | *NA* | **Deprecated**. Use `rotationHomePage` instead. |

View file

@ -13,11 +13,13 @@ const config = [
Log: 'readonly',
MM: 'readonly',
Module: 'readonly',
module: 'readonly',
},
},
rules: {
'@stylistic/brace-style': ['error', '1tbs', { allowSingleLine: true }],
'@stylistic/comma-dangle': ['error', 'only-multiline'],
'@stylistic/max-statements-per-line': ['error', { max: 2 }],
'@stylistic/semi': ['error', 'always'],
'object-shorthand': ['error', 'always']
},

View file

@ -0,0 +1,60 @@
/*
* This is an example configuration file for the MMM-pages module.
*
* Since it uses only default modules besides MMM-pages, it is a good starting
* point for your configuration. You can add more modules if you want.
*
* It shows how to configure the module with class names. Checkout the
* "Class based configuration" section in the README.
*
*/
let config = {
modules: [
{
module: 'MMM-pages',
config: {
timings: {
default: 5000,
2: 20000
},
modules: [
['page0'],
['page1'],
['page2'],
]
}
},
{
module: 'compliments',
classes: 'page0 page1 page2',
position: 'top_bar',
config: {
compliments: {
anytime: ['Test MMM-pages: Class based configuration'],
}
}
},
{
module: 'clock',
classes: 'page1',
position: 'bottom_bar'
},
{
module: 'newsfeed',
classes: 'page2',
position: 'middle_center',
config: {
feeds: [
{
title: 'New York Times',
url: 'https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
}
]
}
},
]
};
/** ************* DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== 'undefined') { module.exports = config; }

View file

@ -0,0 +1,57 @@
/*
* This is an example configuration file for the MMM-pages module.
*
* Since it uses only default modules besides MMM-pages, it is a good starting
* point for your configuration. You can add more modules if you want.
*
* It shows how to configure the module with module names. Checkout the
* "Module name based configuration" section in the README.
*
*/
let config = {
modules: [
{
module: 'MMM-pages',
config: {
timings: {
default: 5000,
2: 20000
},
modules: [
['compliments'],
['clock'],
['newsfeed'],
]
}
},
{
module: 'compliments',
position: 'top_bar',
config: {
compliments: {
anytime: ['Test MMM-pages: Module name based configuration'],
}
}
},
{
module: 'clock',
position: 'top_bar'
},
{
module: 'newsfeed',
position: 'middle_center',
config: {
feeds: [
{
title: 'New York Times',
url: 'https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
}
]
}
},
]
};
/** ************* DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== 'undefined') { module.exports = config; }

56
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "mmm-pages",
"version": "1.0.1",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "mmm-pages",
"version": "1.0.1",
"version": "1.1.0",
"license": "MIT",
"devDependencies": {
"@eslint/js": "^9.23.0",
@ -339,9 +339,9 @@
}
},
"node_modules/@types/estree": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
"dev": true,
"license": "MIT"
},
@ -353,14 +353,14 @@
"license": "MIT"
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz",
"integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz",
"integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0"
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -371,9 +371,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz",
"integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz",
"integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==",
"dev": true,
"license": "MIT",
"engines": {
@ -385,14 +385,14 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz",
"integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz",
"integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/visitor-keys": "8.27.0",
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/visitor-keys": "8.28.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
@ -412,16 +412,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz",
"integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz",
"integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.27.0",
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/typescript-estree": "8.27.0"
"@typescript-eslint/scope-manager": "8.28.0",
"@typescript-eslint/types": "8.28.0",
"@typescript-eslint/typescript-estree": "8.28.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -436,13 +436,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.27.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz",
"integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==",
"version": "8.28.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz",
"integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.27.0",
"@typescript-eslint/types": "8.28.0",
"eslint-visitor-keys": "^4.2.0"
},
"engines": {

View file

@ -1,6 +1,6 @@
{
"name": "mmm-pages",
"version": "1.0.1",
"version": "1.1.0",
"description": "Add pages to your MagicMirror².",
"main": "MMM-pages.js",
"repository": {