diff --git a/MMM-RandomPhoto.css b/MMM-RandomPhoto.css
index b53ec0e..be66c28 100644
--- a/MMM-RandomPhoto.css
+++ b/MMM-RandomPhoto.css
@@ -1,8 +1,8 @@
:root {
- --randomphoto-blur-value: 0px;
+ --_randomPhoto-blur-value: 0px;
}
-#randomPhoto img {
+#_randomPhoto img {
opacity: 0;
position: absolute;;
top: 0;
@@ -12,39 +12,39 @@
object-fit: cover;
}
-#randomPhoto img.grayscale {
+#_randomPhoto img.grayscale {
filter: grayscale(100%);
}
-#randomPhoto img.blur {
+#_randomPhoto img.blur {
filter: blur(var(--randomphoto-blur-value));
}
-#randomPhotoIcon {
+#_randomPhotoIcon {
position: absolute;
}
-#randomPhotoIcon.rpitop {
+#_randomPhotoIcon.rpitop {
top: 5px;
}
-#randomPhotoIcon.rpibottom {
+#_randomPhotoIcon.rpibottom {
bottom: 5px;
}
-#randomPhotoIcon.rpiright {
+#_randomPhotoIcon.rpiright {
right: 10px;
}
-#randomPhotoIcon.rpileft {
+#_randomPhotoIcon.rpileft {
left: 10px;
}
-#randomPhotoIcon i {
+#_randomPhotoIcon i {
opacity: 1;
}
-#randomPhotoIcon i.rpihidden {
+#_randomPhotoIcon i.rpihidden {
opacity: 0;
}
diff --git a/MMM-RandomPhoto.js b/MMM-RandomPhoto.js
index a403906..0e53c0b 100644
--- a/MMM-RandomPhoto.js
+++ b/MMM-RandomPhoto.js
@@ -1,5 +1,5 @@
/* global Module */
-
+
/* MagicMirror²
* Module: MMM-RandomPhoto
*
@@ -13,7 +13,8 @@ Module.register("MMM-RandomPhoto",{
opacity: 0.3,
animationSpeed: 500,
updateInterval: 60,
- imageRepository: "picsum", // Select the image repository source. One of "picsum" (default / fallback), "localdirectory" or "nextcloud" (currently broken because of CORS bug in nextcloud)
+ imageRepository: "picsum", // Select the image repository source. One of "picsum" (default / fallback), "localdirectory" or "nextcloud" (currently broken because of CORS bug in nextcloud)
+ config : '-',
repositoryConfig: {
// if imageRepository = "picsum" -> "path", "username" and "password" are ignored and can be left empty
// if imageRepository = "nextcloud"
@@ -39,7 +40,10 @@ Module.register("MMM-RandomPhoto",{
showStatusIcon: true,
statusIconMode: "show", // one of: "show" (default / fallback) or "fade"
statusIconPosition: "top_right", // one of: "top_right" (default / fallback), "top_left", "bottom_right" or "bottom_left"
- },
+ },
+ imgID1: "",
+ imgID2: "",
+ statusIconID:"",
start: function() {
this.updateTimer = null;
@@ -48,8 +52,10 @@ Module.register("MMM-RandomPhoto",{
this.running = false;
this.nextcloud = false;
- this.localdirectory = false;
-
+ this.localdirectory = false;
+ this.imgID1 = this.config.id + "randomPhoto-placeholder1"
+ this.imgID2 = this.config.id + "randomPhoto-placeholder2"
+ this.statusIconID = this.config.id +"randomPhotoStatusIcon"
this.config.imageRepository = this.config.imageRepository.toLowerCase();
if (this.config.imageRepository === "nextcloud") {
this.nextcloud = true;
@@ -73,7 +79,7 @@ Module.register("MMM-RandomPhoto",{
fetchImageList: function() {
if (typeof this.config.repositoryConfig.path !== "undefined" && this.config.repositoryConfig.path !== null) {
- this.sendSocketNotification('FETCH_IMAGE_LIST');
+ this.sendSocketNotification('FETCH_IMAGE_LIST',{ id: this.config.id });
} else {
Log.error("[" + this.name + "] Trying to use 'nextcloud' or 'localdirectory' but did not specify any 'config.repositoryConfig.path'.");
}
@@ -107,7 +113,7 @@ Module.register("MMM-RandomPhoto",{
if (self.localdirectory || self.nextcloud) {
if (self.imageList && self.imageList.length > 0) {
- url = "/" + this.name + "/images/" + this.returnImageFromList(mode);
+ url = "/" + this.name + "/images/"+this.config.id+'/' + this.returnImageFromList(mode);
jQuery.ajax({
method: "GET",
@@ -155,16 +161,16 @@ Module.register("MMM-RandomPhoto",{
var self = this;
var img = $('
').attr('src', url);
img.on('load', function() {
- $('#randomPhoto-placeholder1').attr('src', url).animate({
+ $('#'+self.imgID1).attr('src', url).animate({
opacity: self.config.opacity
}, self.config.animationSpeed, function() {
- $(this).attr('id', 'randomPhoto-placeholder2');
+ $(this).attr('id', self.imgID2);
});
- $('#randomPhoto-placeholder2').animate({
+ $('#'+self.imgID2).animate({
opacity: 0
}, self.config.animationSpeed, function() {
- $(this).attr('id', 'randomPhoto-placeholder1');
+ $(this).attr('id', self.imgID1);
});
});
},
@@ -200,7 +206,7 @@ Module.register("MMM-RandomPhoto",{
loadIcon: function(navigate="none") {
var self = this;
- const statusIcon = document.getElementById("randomPhotoStatusIcon");
+ const statusIcon = document.getElementById(self.statusIconID);
let currentIndex = -1;
let iconloadInProgress = false;
@@ -294,12 +300,12 @@ Module.register("MMM-RandomPhoto",{
getDom: function() {
var wrapper = document.createElement("div");
- wrapper.id = "randomPhoto";
+ wrapper.id = this.config.id+"randomPhoto";
var img1 = document.createElement("img");
- img1.id = "randomPhoto-placeholder1";
+ img1.id = this.imgID1;
var img2 = document.createElement("img");
- img2.id = "randomPhoto-placeholder2";
+ img2.id = this.imgID2;
// Only apply grayscale / blur css classes if we are NOT using picsum, as picsum is doing it via URL parameters
if (this.nextcloud || this.localdirectory) {
@@ -310,8 +316,8 @@ Module.register("MMM-RandomPhoto",{
if (this.config.blur) {
img1.classList.add("blur");
img2.classList.add("blur");
- img1.style.setProperty("--randomphoto-blur-value", this.config.blurAmount + "px");
- img2.style.setProperty("--randomphoto-blur-value", this.config.blurAmount + "px");
+ img1.style.setProperty("--"+this.config.id+"randomphoto-blur-value", this.config.blurAmount + "px");
+ img2.style.setProperty("--"+this.config.id+"randomphoto-blur-value", this.config.blurAmount + "px");
}
}
@@ -324,12 +330,12 @@ Module.register("MMM-RandomPhoto",{
this.config.statusIconPosition = 'top_right';
}
var statusIconObject = document.createElement("span");
- statusIconObject.id = "randomPhotoIcon";
+ statusIconObject.id = this.config.id+"blurandomPhotoIcon";
statusIconObject.classList.add("dimmed");
this.config.statusIconPosition.split("_").forEach(function(extractedName) {
statusIconObject.classList.add("rpi" + extractedName);
});
- statusIconObject.innerHTML = '';
+ statusIconObject.innerHTML = '';
wrapper.appendChild(statusIconObject);
}
return wrapper;
@@ -359,6 +365,7 @@ Module.register("MMM-RandomPhoto",{
}
}
}
+
if (notification === "RANDOMPHOTO_NEXT") {
// Don't call the pause or resume functions here, so we can actually work with both states ("paused" and "active"), so independent of what "this.running" is set to
clearTimeout(this.updateTimer);
@@ -395,8 +402,8 @@ Module.register("MMM-RandomPhoto",{
socketNotificationReceived: function(notification, payload) {
//Log.log("["+ this.name + "] received a '" + notification + "' with payload: " + payload);
//console.dir(payload);
- if (notification === "IMAGE_LIST") {
- this.imageList = payload;
+ if (notification === "IMAGE_LIST" && payload.id === this.config.id) {
+ this.imageList = payload.data;
// After we now received the image list, go ahead and display them (only when not starting as hidden)
if(!this.config.startHidden) {
this.resumeImageLoading(true);
diff --git a/README.md b/README.md
index 3a13c11..41c8096 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,7 @@ The entry in `config.js` can include the following options:
| Option | Description
|-----------------------|------------
| `imageRepository` | *Optional* - The image source.
**Type:** `string`
**Allowed:** `picsum`, `nextcloud`, `localdirectory`
**Default:** `picsum`
+| `id` | *Optional* - the unique id of this instance, defaults to '_'
see the section on ****multiple instances*** below on how to use this property
| `repositoryConfig` | *Optional* - The configuration block for the selected image repository. See below.
**Type:** `Object`
| `random` | *Optional* - Should the images be shown at random? Has **NO** effect when `imageRepository` is set to `picsum`, as it is forced there.
**Type:** `boolean`
**Default:** `true`
| `width` | *Optional* - The width of the image in px. Only used when `imageRepository` is set to `picsum`
**Type:** `int`
**Default:** `1920`
@@ -134,7 +135,25 @@ Thinking about implementing the following things:
- possibility to show the EXIF comment from each image on screen (target selectable)
- ...
+## Using multiple instances
+This module uses content ids to do the transitions between images. These were hard coded before, preventing multiple instances from working.
+now you can use an ID in the config for each instance and the content ids will include that value.
+now you need to create updated css values that include the id for each instance
+
+to do that follow these steps
+1. copy all the MMM-RandomPhoto.css lines to custom.css
+2. mass change the default id value '_' to whatever value you set in the id for an instance
+3. replace the one _ in the :root section at the top
+```
+:root {
+ --_randomPhoto-blur-value: 0px;
+}
+```
+4. repeat steps 1 and 2 for each additional instance
+
+for example: if the config id value is 'foo', then the info in the css file needs to change from #_random to #foorandom
and
+ --_random... to --foorandom...
## Dependencies
- [jQuery](https://www.npmjs.com/package/jquery) (installed via `npm install`)
diff --git a/node_helper.js b/node_helper.js
index bc9c32d..d5ede04 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -6,16 +6,16 @@ const Log = require("logger");
const NodeHelper = require("node_helper");
module.exports = NodeHelper.create({
-
+ config: {},
+ imageList: {},
start: function() {
var self = this;
this.nextcloud = false;
this.localdirectory = false;
- this.imageList = [];
- this.expressApp.get("/" + this.name + "/images/:randomImageName", async function(request, response) {
- var imageBase64Encoded = await self.fetchEncodedImage(decodeURIComponent(request.params.randomImageName));
+ this.expressApp.get("/" + this.name + "/images/:id/:randomImageName", async function(request, response) {
+ var imageBase64Encoded = await self.fetchEncodedImage(decodeURIComponent(request.params.randomImageName, request.params.id));
response.send(imageBase64Encoded);
});
},
@@ -24,24 +24,28 @@ module.exports = NodeHelper.create({
socketNotificationReceived: function(notification, payload) {
//console.log("["+ this.name + "] received a '" + notification + "' with payload: " + payload);
if (notification === "SET_CONFIG") {
- this.config = payload;
- if (this.config.imageRepository === "nextcloud") {
+ this.imageList[payload.id]=[]
+ this.config[payload.id] = payload;
+ if (this.config[payload.id].imageRepository === "nextcloud") {
+
this.nextcloud = true;
- } else if (this.config.imageRepository === "localdirectory") {
+ } else if (this.config[payload.id].imageRepository === "localdirectory") {
this.localdirectory = true;
}
}
if (notification === "FETCH_IMAGE_LIST") {
- if (this.config.imageRepository === "nextcloud") {
- this.fetchNextcloudImageList();
+ if (this.imageList[payload.id] === undefined)
+ this.imageList[payload.id]
+ if (this.config[payload.id].imageRepository === "nextcloud") {
+ this.fetchNextcloudImageList(this.config[payload.id]);
}
- if (this.config.imageRepository === "localdirectory") {
- this.fetchLocalImageList();
+ if (this.config[payload.id].imageRepository === "localdirectory") {
+ this.fetchLocalImageList(this.config[payload.id]);
}
}
},
- fetchLocalImageDirectory: function(path) {
+ fetchLocalImageDirectory: function(path,config) {
var self = this;
// Validate path
@@ -50,7 +54,7 @@ module.exports = NodeHelper.create({
return false;
}
- const excludePattern = self.config.repositoryConfig.exclude?.map(pattern => new RegExp(pattern));
+ const excludePattern = config.repositoryConfig.exclude?.map(pattern => new RegExp(pattern));
var fileList = fs.readdirSync(path, { withFileTypes: true });
if (fileList.length > 0) {
@@ -59,38 +63,38 @@ module.exports = NodeHelper.create({
if (fileList[f].isFile()) {
//TODO: add mime type check here
- self.imageList.push(encodeURIComponent(path + "/" + fileList[f].name));
+ self.imageList[config.id].push(encodeURIComponent(path + "/" + fileList[f].name));
}
- if ((self.config.repositoryConfig.recursive === true) && fileList[f].isDirectory()) {
- self.fetchLocalImageDirectory(path + "/" + fileList[f].name);
+ if ((config.repositoryConfig.recursive === true) && fileList[f].isDirectory()) {
+ self.fetchLocalImageDirectory(path + "/" + fileList[f].name,config);
}
}
return;
}
},
- fetchLocalImageList: function() {
+ fetchLocalImageList: function(config) {
var self = this;
- var path = self.config.repositoryConfig.path;
+ var path = config.repositoryConfig.path;
- self.imageList = [];
- self.fetchLocalImageDirectory(path);
+ self.imageList[config.id] = [];
+ self.fetchLocalImageDirectory(path,config);
- self.sendSocketNotification("IMAGE_LIST", self.imageList);
+ self.sendSocketNotification("IMAGE_LIST", { data: self.imageList[config.id], id: config.id });
return false;
},
- fetchNextcloudImageList: function() {
+ fetchNextcloudImageList: function(config) {
var self = this;
var imageList = [];
- var path = self.config.repositoryConfig.path;
+ var path = config.repositoryConfig.path;
const urlParts = new URL(path);
const requestOptions = {
method: "PROPFIND",
headers: {
- "Authorization": "Basic " + new Buffer.from(this.config.repositoryConfig.username + ":" + this.config.repositoryConfig.password).toString("base64")
+ "Authorization": "Basic " + new Buffer.from(config.repositoryConfig.username + ":" + config.repositoryConfig.password).toString("base64")
}
};
https.get(path, requestOptions, function(response) {
@@ -107,7 +111,7 @@ module.exports = NodeHelper.create({
imageList[index] = encodeURIComponent(item.replace("href>" + urlParts.pathname, ""));
//console.log("[" + self.name + "] Found entry: " + imageList[index]);
});
- self.sendSocketNotification("IMAGE_LIST", imageList);
+ self.sendSocketNotification("IMAGE_LIST", { data: imageList, id: config.id });
return;
} else {
console.log("[" + this.name + "] WARNING: did not get any images from nextcloud url");
@@ -122,8 +126,9 @@ module.exports = NodeHelper.create({
},
- fetchEncodedImage: async function(passedImageName) {
+ fetchEncodedImage: async function(passedImageName,id) {
var self = this;
+ config=this.config[id]
return new Promise(function(resolve, reject) {
var fullImagePath = passedImageName;
@@ -138,10 +143,10 @@ module.exports = NodeHelper.create({
const requestOptions = {
method: "GET",
headers: {
- "Authorization": "Basic " + new Buffer.from(self.config.repositoryConfig.username + ":" + self.config.repositoryConfig.password).toString("base64")
+ "Authorization": "Basic " + new Buffer.from(self.config.repositoryConfig.username + ":" + config.repositoryConfig.password).toString("base64")
}
};
- https.get(self.config.repositoryConfig.path + fullImagePath, requestOptions, (response) => {
+ https.get(config.repositoryConfig.path + fullImagePath, requestOptions, (response) => {
response.setEncoding('base64');
var fileEncoded = "data:" + response.headers["content-type"] + ";base64,";
response.on("data", (data) => { fileEncoded += data; });