5 Commits

Author SHA1 Message Date
CodeDevMLH
d97f017e32 fix: Update checksum and timestamp for version 1.1.0.0 in manifest 2025-12-16 01:40:56 +01:00
CodeDevMLH
29c6255904 fix: Update imageUrl in manifest to correct logo path 2025-12-16 01:40:23 +01:00
CodeDevMLH
baa1ddde66 fix: Update README for clarity and correct repository links 2025-12-16 01:37:40 +01:00
CodeDevMLH
93f09f42cf fix: Update source URLs in manifest for version downloads 2025-12-16 01:28:10 +01:00
CodeDevMLH
25a0be221b feat: Bump version to 1.1.0.0 and add advanced configuration options for seasonal effects
Enhanced JavaScript files for autumn, christmas, easter, fireworks, halloween, hearts, santa, snowfall, snowflakes, and snowstorm to support configuration options via window.SeasonalsPluginConfig.

Added automatic theme selection based on date in README.md.
2025-12-16 01:26:27 +01:00
22 changed files with 775 additions and 87 deletions

View File

@@ -21,12 +21,7 @@ public class SeasonalsController : ControllerBase
[Produces("application/json")] [Produces("application/json")]
public ActionResult<object> GetConfig() public ActionResult<object> GetConfig()
{ {
var config = Plugin.Instance?.Configuration; return Plugin.Instance?.Configuration ?? new object();
return new
{
selectedSeason = config?.SelectedSeason ?? "none",
automateSeasonSelection = config?.AutomateSeasonSelection ?? true
};
} }
/// <summary> /// <summary>

View File

@@ -14,6 +14,17 @@ public class PluginConfiguration : BasePluginConfiguration
{ {
SelectedSeason = "none"; SelectedSeason = "none";
AutomateSeasonSelection = true; AutomateSeasonSelection = true;
Autumn = new AutumnOptions();
Snowflakes = new SnowflakesOptions();
Snowfall = new SnowfallOptions();
Snowstorm = new SnowstormOptions();
Fireworks = new FireworksOptions();
Halloween = new HalloweenOptions();
Hearts = new HeartsOptions();
Christmas = new ChristmasOptions();
Santa = new SantaOptions();
Easter = new EasterOptions();
} }
/// <summary> /// <summary>
@@ -25,4 +36,118 @@ public class PluginConfiguration : BasePluginConfiguration
/// Gets or sets a value indicating whether to automate season selection. /// Gets or sets a value indicating whether to automate season selection.
/// </summary> /// </summary>
public bool AutomateSeasonSelection { get; set; } public bool AutomateSeasonSelection { get; set; }
public AutumnOptions Autumn { get; set; }
public SnowflakesOptions Snowflakes { get; set; }
public SnowfallOptions Snowfall { get; set; }
public SnowstormOptions Snowstorm { get; set; }
public FireworksOptions Fireworks { get; set; }
public HalloweenOptions Halloween { get; set; }
public HeartsOptions Hearts { get; set; }
public ChristmasOptions Christmas { get; set; }
public SantaOptions Santa { get; set; }
public EasterOptions Easter { get; set; }
}
public class AutumnOptions
{
public int LeafCount { get; set; } = 25;
public bool EnableAutumn { get; set; } = true;
public bool EnableRandomLeaves { get; set; } = true;
public bool EnableRandomLeavesMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
public bool EnableRotation { get; set; } = false;
}
public class SnowflakesOptions
{
public int SnowflakeCount { get; set; } = 25;
public bool EnableSnowflakes { get; set; } = true;
public bool EnableRandomSnowflakes { get; set; } = true;
public bool EnableRandomSnowflakesMobile { get; set; } = false;
public bool EnableColoredSnowflakes { get; set; } = true;
public bool EnableDifferentDuration { get; set; } = true;
}
public class SnowfallOptions
{
public int SnowflakesCount { get; set; } = 500;
public int SnowflakesCountMobile { get; set; } = 250;
public double Speed { get; set; } = 3;
public bool EnableSnowfall { get; set; } = true;
}
public class SnowstormOptions
{
public int SnowflakesCount { get; set; } = 500;
public int SnowflakesCountMobile { get; set; } = 250;
public double Speed { get; set; } = 6;
public bool EnableSnowstorm { get; set; } = true;
public double HorizontalWind { get; set; } = 4;
public double VerticalVariation { get; set; } = 2;
}
public class FireworksOptions
{
public int ParticleCount { get; set; } = 50;
public int LaunchInterval { get; set; } = 3200;
public bool EnableFireworks { get; set; } = true;
public bool ScrollFireworks { get; set; } = true;
public int MinFireworks { get; set; } = 3;
public int MaxFireworks { get; set; } = 6;
}
public class HalloweenOptions
{
public int SymbolCount { get; set; } = 25;
public bool EnableHalloween { get; set; } = true;
public bool EnableRandomSymbols { get; set; } = true;
public bool EnableRandomSymbolsMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}
public class HeartsOptions
{
public int SymbolCount { get; set; } = 25;
public bool EnableHearts { get; set; } = true;
public bool EnableRandomSymbols { get; set; } = true;
public bool EnableRandomSymbolsMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}
public class ChristmasOptions
{
public int SymbolCount { get; set; } = 25;
public bool EnableChristmas { get; set; } = true;
public bool EnableRandomChristmas { get; set; } = true;
public bool EnableRandomChristmasMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}
public class SantaOptions
{
public int SnowflakesCount { get; set; } = 500;
public int SnowflakesCountMobile { get; set; } = 250;
public double SantaSpeed { get; set; } = 10;
public double SantaSpeedMobile { get; set; } = 8;
public bool EnableSanta { get; set; } = true;
public double SnowFallSpeed { get; set; } = 3;
public double MaxSantaRestTime { get; set; } = 8;
public double MinSantaRestTime { get; set; } = 3;
public double MaxPresentFallSpeed { get; set; } = 5;
public double MinPresentFallSpeed { get; set; } = 2;
}
public class EasterOptions
{
public int EggCount { get; set; } = 20;
public bool EnableEaster { get; set; } = true;
public bool EnableRandomEaster { get; set; } = true;
public bool EnableRandomEasterMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
public bool EnableBunny { get; set; } = true;
public int BunnyDuration { get; set; } = 12000;
public int HopHeight { get; set; } = 12;
public int MinBunnyRestTime { get; set; } = 2000;
public int MaxBunnyRestTime { get; set; } = 5000;
} }

View File

@@ -33,9 +33,357 @@
</select> </select>
<div class="fieldDescription">The season to display if automation is disabled.</div> <div class="fieldDescription">The season to display if automation is disabled.</div>
</div> </div>
<div is="emby-collapse" title="Advanced Configuration">
<div class="collapseContent">
<h3>Autumn</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableAutumn" name="EnableAutumn" type="checkbox" is="emby-checkbox" />
<span>Enable Autumn</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="AutumnLeafCount">Leaf Count</label>
<input is="emby-input" type="number" id="AutumnLeafCount" name="AutumnLeafCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomLeaves" name="EnableRandomLeaves" type="checkbox" is="emby-checkbox" />
<span>Enable Random Leaves</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomLeavesMobile" name="EnableRandomLeavesMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Leaves on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationAutumn" name="EnableDifferentDurationAutumn" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRotation" name="EnableRotation" type="checkbox" is="emby-checkbox" />
<span>Enable Rotation</span>
</label>
</div>
<h3>Snowflakes</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableSnowflakes" name="EnableSnowflakes" type="checkbox" is="emby-checkbox" />
<span>Enable Snowflakes</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowflakesCount">Snowflake Count</label>
<input is="emby-input" type="number" id="SnowflakesCount" name="SnowflakesCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomSnowflakes" name="EnableRandomSnowflakes" type="checkbox" is="emby-checkbox" />
<span>Enable Random Snowflakes</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomSnowflakesMobile" name="EnableRandomSnowflakesMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Snowflakes on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableColoredSnowflakes" name="EnableColoredSnowflakes" type="checkbox" is="emby-checkbox" />
<span>Enable Colored Snowflakes</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationSnowflakes" name="EnableDifferentDurationSnowflakes" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<h3>Snowfall</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableSnowfall" name="EnableSnowfall" type="checkbox" is="emby-checkbox" />
<span>Enable Snowfall</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowfallCount">Snowflake Count</label>
<input is="emby-input" type="number" id="SnowfallCount" name="SnowfallCount" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowfallCountMobile">Snowflake Count (Mobile)</label>
<input is="emby-input" type="number" id="SnowfallCountMobile" name="SnowfallCountMobile" />
<div class="fieldDescription">Warning: High values may affect performance</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowfallSpeed">Speed</label>
<input is="emby-input" type="number" id="SnowfallSpeed" name="SnowfallSpeed" step="0.1" />
</div>
<h3>Snowstorm</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableSnowstorm" name="EnableSnowstorm" type="checkbox" is="emby-checkbox" />
<span>Enable Snowstorm</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowstormCount">Snowflake Count</label>
<input is="emby-input" type="number" id="SnowstormCount" name="SnowstormCount" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowstormCountMobile">Snowflake Count (Mobile)</label>
<input is="emby-input" type="number" id="SnowstormCountMobile" name="SnowstormCountMobile" />
<div class="fieldDescription">Warning: High values may affect performance</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowstormSpeed">Speed</label>
<input is="emby-input" type="number" id="SnowstormSpeed" name="SnowstormSpeed" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowstormHorizontalWind">Horizontal Wind</label>
<input is="emby-input" type="number" id="SnowstormHorizontalWind" name="SnowstormHorizontalWind" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SnowstormVerticalVariation">Vertical Variation</label>
<input is="emby-input" type="number" id="SnowstormVerticalVariation" name="SnowstormVerticalVariation" step="0.1" />
</div>
<h3>Fireworks</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableFireworks" name="EnableFireworks" type="checkbox" is="emby-checkbox" />
<span>Enable Fireworks</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="FireworksParticles">Particle Count</label>
<input is="emby-input" type="number" id="FireworksParticles" name="FireworksParticles" />
<div class="fieldDescription">Warning: High values may affect performance</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="FireworksInterval">Launch Interval (ms)</label>
<input is="emby-input" type="number" id="FireworksInterval" name="FireworksInterval" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="ScrollFireworks" name="ScrollFireworks" type="checkbox" is="emby-checkbox" />
<span>Scroll Fireworks</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="MinFireworks">Min Fireworks</label>
<input is="emby-input" type="number" id="MinFireworks" name="MinFireworks" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MaxFireworks">Max Fireworks</label>
<input is="emby-input" type="number" id="MaxFireworks" name="MaxFireworks" />
</div>
<h3>Halloween</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableHalloween" name="EnableHalloween" type="checkbox" is="emby-checkbox" />
<span>Enable Halloween</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="HalloweenCount">Symbol Count</label>
<input is="emby-input" type="number" id="HalloweenCount" name="HalloweenCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomHalloween" name="EnableRandomHalloween" type="checkbox" is="emby-checkbox" />
<span>Enable Random Symbols</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomHalloweenMobile" name="EnableRandomHalloweenMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Symbols on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationHalloween" name="EnableDifferentDurationHalloween" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<h3>Hearts</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableHearts" name="EnableHearts" type="checkbox" is="emby-checkbox" />
<span>Enable Hearts</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="HeartsCount">Symbol Count</label>
<input is="emby-input" type="number" id="HeartsCount" name="HeartsCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomHearts" name="EnableRandomHearts" type="checkbox" is="emby-checkbox" />
<span>Enable Random Symbols</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomHeartsMobile" name="EnableRandomHeartsMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Symbols on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationHearts" name="EnableDifferentDurationHearts" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<h3>Christmas</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableChristmas" name="EnableChristmas" type="checkbox" is="emby-checkbox" />
<span>Enable Christmas</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="ChristmasCount">Symbol Count</label>
<input is="emby-input" type="number" id="ChristmasCount" name="ChristmasCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomChristmas" name="EnableRandomChristmas" type="checkbox" is="emby-checkbox" />
<span>Enable Random Christmas</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomChristmasMobile" name="EnableRandomChristmasMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Christmas on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationChristmas" name="EnableDifferentDurationChristmas" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<h3>Santa</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableSanta" name="EnableSanta" type="checkbox" is="emby-checkbox" />
<span>Enable Santa</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SantaSnowflakes">Snowflakes Count</label>
<input is="emby-input" type="number" id="SantaSnowflakes" name="SantaSnowflakes" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SantaSnowflakesMobile">Snowflakes Count (Mobile)</label>
<input is="emby-input" type="number" id="SantaSnowflakesMobile" name="SantaSnowflakesMobile" />
<div class="fieldDescription">Warning: High values may affect performance</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SantaSpeed">Santa Speed (seconds)</label>
<input is="emby-input" type="number" id="SantaSpeed" name="SantaSpeed" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SantaSpeedMobile">Santa Speed Mobile (seconds)</label>
<input is="emby-input" type="number" id="SantaSpeedMobile" name="SantaSpeedMobile" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="SantaSnowFallSpeed">Snowfall Speed</label>
<input is="emby-input" type="number" id="SantaSnowFallSpeed" name="SantaSnowFallSpeed" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MaxSantaRestTime">Max Santa Rest Time (seconds)</label>
<input is="emby-input" type="number" id="MaxSantaRestTime" name="MaxSantaRestTime" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MinSantaRestTime">Min Santa Rest Time (seconds)</label>
<input is="emby-input" type="number" id="MinSantaRestTime" name="MinSantaRestTime" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MaxPresentFallSpeed">Max Present Fall Speed (seconds)</label>
<input is="emby-input" type="number" id="MaxPresentFallSpeed" name="MaxPresentFallSpeed" step="0.1" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MinPresentFallSpeed">Min Present Fall Speed (seconds)</label>
<input is="emby-input" type="number" id="MinPresentFallSpeed" name="MinPresentFallSpeed" step="0.1" />
</div>
<h3>Easter</h3>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableEaster" name="EnableEaster" type="checkbox" is="emby-checkbox" />
<span>Enable Easter</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="EasterEggCount">Egg Count</label>
<input is="emby-input" type="number" id="EasterEggCount" name="EasterEggCount" />
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomEaster" name="EnableRandomEaster" type="checkbox" is="emby-checkbox" />
<span>Enable Random Easter</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableRandomEasterMobile" name="EnableRandomEasterMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Random Easter on Mobile (Warning: High values may affect performance)</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationEaster" name="EnableDifferentDurationEaster" type="checkbox" is="emby-checkbox" />
<span>Enable Different Duration</span>
</label>
</div>
<div class="checkboxContainer">
<label class="emby-checkbox-label">
<input id="EasterBunny" name="EasterBunny" type="checkbox" is="emby-checkbox" />
<span>Enable Bunny</span>
</label>
</div>
<div class="inputContainer">
<label class="inputLabel" for="BunnyDuration">Bunny Duration (ms)</label>
<input is="emby-input" type="number" id="BunnyDuration" name="BunnyDuration" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="HopHeight">Hop Height (px)</label>
<input is="emby-input" type="number" id="HopHeight" name="HopHeight" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MinBunnyRestTime">Min Bunny Rest Time (ms)</label>
<input is="emby-input" type="number" id="MinBunnyRestTime" name="MinBunnyRestTime" />
</div>
<div class="inputContainer">
<label class="inputLabel" for="MaxBunnyRestTime">Max Bunny Rest Time (ms)</label>
<input is="emby-input" type="number" id="MaxBunnyRestTime" name="MaxBunnyRestTime" />
</div>
</div>
</div>
<div> <div>
<button is="emby-button" type="submit" class="raised button-submit block emby-button"> <button is="emby-button" type="submit" class="raised button-submit block emby-button">
<span>Save</span> <span>${Save}</span>
</button>
<button is="emby-button" type="button" class="raised button-cancel block btnCancel" onclick="history.back();">
<span>${ButtonCancel}</span>
</button> </button>
<div class="fieldDescription" style="margin-top: 1em;">Please reload the page (F5) after saving for changes to take effect.</div> <div class="fieldDescription" style="margin-top: 1em;">Please reload the page (F5) after saving for changes to take effect.</div>
</div> </div>
@@ -53,6 +401,91 @@
ApiClient.getPluginConfiguration(SeasonalsConfig.pluginUniqueId).then(function (config) { ApiClient.getPluginConfiguration(SeasonalsConfig.pluginUniqueId).then(function (config) {
document.querySelector('#SelectedSeason').value = config.SelectedSeason; document.querySelector('#SelectedSeason').value = config.SelectedSeason;
document.querySelector('#AutomateSeasonSelection').checked = config.AutomateSeasonSelection; document.querySelector('#AutomateSeasonSelection').checked = config.AutomateSeasonSelection;
// Advanced Config
// Autumn
document.querySelector('#EnableAutumn').checked = config.Autumn.EnableAutumn;
document.querySelector('#AutumnLeafCount').value = config.Autumn.LeafCount;
document.querySelector('#EnableRandomLeaves').checked = config.Autumn.EnableRandomLeaves;
document.querySelector('#EnableRandomLeavesMobile').checked = config.Autumn.EnableRandomLeavesMobile;
document.querySelector('#EnableDifferentDurationAutumn').checked = config.Autumn.EnableDifferentDuration;
document.querySelector('#EnableRotation').checked = config.Autumn.EnableRotation;
// Snowflakes
document.querySelector('#SnowflakesCount').value = config.Snowflakes.SnowflakeCount;
document.querySelector('#EnableSnowflakes').checked = config.Snowflakes.EnableSnowflakes;
document.querySelector('#EnableRandomSnowflakes').checked = config.Snowflakes.EnableRandomSnowflakes;
document.querySelector('#EnableRandomSnowflakesMobile').checked = config.Snowflakes.EnableRandomSnowflakesMobile;
document.querySelector('#EnableColoredSnowflakes').checked = config.Snowflakes.EnableColoredSnowflakes;
document.querySelector('#EnableDifferentDurationSnowflakes').checked = config.Snowflakes.EnableDifferentDuration;
// Snowfall
document.querySelector('#EnableSnowfall').checked = config.Snowfall.EnableSnowfall;
document.querySelector('#SnowfallCount').value = config.Snowfall.SnowflakesCount;
document.querySelector('#SnowfallCountMobile').value = config.Snowfall.SnowflakesCountMobile;
document.querySelector('#SnowfallSpeed').value = config.Snowfall.Speed;
// Snowstorm
document.querySelector('#EnableSnowstorm').checked = config.Snowstorm.EnableSnowstorm;
document.querySelector('#SnowstormCount').value = config.Snowstorm.SnowflakesCount;
document.querySelector('#SnowstormCountMobile').value = config.Snowstorm.SnowflakesCountMobile;
document.querySelector('#SnowstormSpeed').value = config.Snowstorm.Speed;
document.querySelector('#SnowstormHorizontalWind').value = config.Snowstorm.HorizontalWind;
document.querySelector('#SnowstormVerticalVariation').value = config.Snowstorm.VerticalVariation;
// Fireworks
document.querySelector('#EnableFireworks').checked = config.Fireworks.EnableFireworks;
document.querySelector('#FireworksParticles').value = config.Fireworks.ParticleCount;
document.querySelector('#FireworksInterval').value = config.Fireworks.LaunchInterval;
document.querySelector('#ScrollFireworks').checked = config.Fireworks.ScrollFireworks;
document.querySelector('#MinFireworks').value = config.Fireworks.MinFireworks;
document.querySelector('#MaxFireworks').value = config.Fireworks.MaxFireworks;
// Halloween
document.querySelector('#EnableHalloween').checked = config.Halloween.EnableHalloween;
document.querySelector('#HalloweenCount').value = config.Halloween.SymbolCount;
document.querySelector('#EnableRandomHalloween').checked = config.Halloween.EnableRandomSymbols;
document.querySelector('#EnableRandomHalloweenMobile').checked = config.Halloween.EnableRandomSymbolsMobile;
document.querySelector('#EnableDifferentDurationHalloween').checked = config.Halloween.EnableDifferentDuration;
// Hearts
document.querySelector('#EnableHearts').checked = config.Hearts.EnableHearts;
document.querySelector('#HeartsCount').value = config.Hearts.SymbolCount;
document.querySelector('#EnableRandomHearts').checked = config.Hearts.EnableRandomSymbols;
document.querySelector('#EnableRandomHeartsMobile').checked = config.Hearts.EnableRandomSymbolsMobile;
document.querySelector('#EnableDifferentDurationHearts').checked = config.Hearts.EnableDifferentDuration;
// Christmas
document.querySelector('#EnableChristmas').checked = config.Christmas.EnableChristmas;
document.querySelector('#ChristmasCount').value = config.Christmas.SymbolCount;
document.querySelector('#EnableRandomChristmas').checked = config.Christmas.EnableRandomChristmas;
document.querySelector('#EnableRandomChristmasMobile').checked = config.Christmas.EnableRandomChristmasMobile;
document.querySelector('#EnableDifferentDurationChristmas').checked = config.Christmas.EnableDifferentDuration;
// Santa
document.querySelector('#EnableSanta').checked = config.Santa.EnableSanta;
document.querySelector('#SantaSnowflakes').value = config.Santa.SnowflakesCount;
document.querySelector('#SantaSnowflakesMobile').value = config.Santa.SnowflakesCountMobile;
document.querySelector('#SantaSpeed').value = config.Santa.SantaSpeed;
document.querySelector('#SantaSpeedMobile').value = config.Santa.SantaSpeedMobile;
document.querySelector('#SantaSnowFallSpeed').value = config.Santa.SnowFallSpeed;
document.querySelector('#MaxSantaRestTime').value = config.Santa.MaxSantaRestTime;
document.querySelector('#MinSantaRestTime').value = config.Santa.MinSantaRestTime;
document.querySelector('#MaxPresentFallSpeed').value = config.Santa.MaxPresentFallSpeed;
document.querySelector('#MinPresentFallSpeed').value = config.Santa.MinPresentFallSpeed;
// Easter
document.querySelector('#EnableEaster').checked = config.Easter.EnableEaster;
document.querySelector('#EasterEggCount').value = config.Easter.EggCount;
document.querySelector('#EnableRandomEaster').checked = config.Easter.EnableRandomEaster;
document.querySelector('#EnableRandomEasterMobile').checked = config.Easter.EnableRandomEasterMobile;
document.querySelector('#EnableDifferentDurationEaster').checked = config.Easter.EnableDifferentDuration;
document.querySelector('#EasterBunny').checked = config.Easter.EnableBunny;
document.querySelector('#BunnyDuration').value = config.Easter.BunnyDuration;
document.querySelector('#HopHeight').value = config.Easter.HopHeight;
document.querySelector('#MinBunnyRestTime').value = config.Easter.MinBunnyRestTime;
document.querySelector('#MaxBunnyRestTime').value = config.Easter.MaxBunnyRestTime;
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
}); });
@@ -63,6 +496,91 @@
ApiClient.getPluginConfiguration(SeasonalsConfig.pluginUniqueId).then(function (config) { ApiClient.getPluginConfiguration(SeasonalsConfig.pluginUniqueId).then(function (config) {
config.SelectedSeason = document.querySelector('#SelectedSeason').value; config.SelectedSeason = document.querySelector('#SelectedSeason').value;
config.AutomateSeasonSelection = document.querySelector('#AutomateSeasonSelection').checked; config.AutomateSeasonSelection = document.querySelector('#AutomateSeasonSelection').checked;
// Advanced Config
// Autumn
config.Autumn.EnableAutumn = document.querySelector('#EnableAutumn').checked;
config.Autumn.LeafCount = parseInt(document.querySelector('#AutumnLeafCount').value);
config.Autumn.EnableRandomLeaves = document.querySelector('#EnableRandomLeaves').checked;
config.Autumn.EnableRandomLeavesMobile = document.querySelector('#EnableRandomLeavesMobile').checked;
config.Autumn.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationAutumn').checked;
config.Autumn.EnableRotation = document.querySelector('#EnableRotation').checked;
// Snowflakes
config.Snowflakes.SnowflakeCount = parseInt(document.querySelector('#SnowflakesCount').value);
config.Snowflakes.EnableSnowflakes = document.querySelector('#EnableSnowflakes').checked;
config.Snowflakes.EnableRandomSnowflakes = document.querySelector('#EnableRandomSnowflakes').checked;
config.Snowflakes.EnableRandomSnowflakesMobile = document.querySelector('#EnableRandomSnowflakesMobile').checked;
config.Snowflakes.EnableColoredSnowflakes = document.querySelector('#EnableColoredSnowflakes').checked;
config.Snowflakes.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationSnowflakes').checked;
// Snowfall
config.Snowfall.EnableSnowfall = document.querySelector('#EnableSnowfall').checked;
config.Snowfall.SnowflakesCount = parseInt(document.querySelector('#SnowfallCount').value);
config.Snowfall.SnowflakesCountMobile = parseInt(document.querySelector('#SnowfallCountMobile').value);
config.Snowfall.Speed = parseFloat(document.querySelector('#SnowfallSpeed').value);
// Snowstorm
config.Snowstorm.EnableSnowstorm = document.querySelector('#EnableSnowstorm').checked;
config.Snowstorm.SnowflakesCount = parseInt(document.querySelector('#SnowstormCount').value);
config.Snowstorm.SnowflakesCountMobile = parseInt(document.querySelector('#SnowstormCountMobile').value);
config.Snowstorm.Speed = parseFloat(document.querySelector('#SnowstormSpeed').value);
config.Snowstorm.HorizontalWind = parseFloat(document.querySelector('#SnowstormHorizontalWind').value);
config.Snowstorm.VerticalVariation = parseFloat(document.querySelector('#SnowstormVerticalVariation').value);
// Fireworks
config.Fireworks.EnableFireworks = document.querySelector('#EnableFireworks').checked;
config.Fireworks.ParticleCount = parseInt(document.querySelector('#FireworksParticles').value);
config.Fireworks.LaunchInterval = parseInt(document.querySelector('#FireworksInterval').value);
config.Fireworks.ScrollFireworks = document.querySelector('#ScrollFireworks').checked;
config.Fireworks.MinFireworks = parseInt(document.querySelector('#MinFireworks').value);
config.Fireworks.MaxFireworks = parseInt(document.querySelector('#MaxFireworks').value);
// Halloween
config.Halloween.EnableHalloween = document.querySelector('#EnableHalloween').checked;
config.Halloween.SymbolCount = parseInt(document.querySelector('#HalloweenCount').value);
config.Halloween.EnableRandomSymbols = document.querySelector('#EnableRandomHalloween').checked;
config.Halloween.EnableRandomSymbolsMobile = document.querySelector('#EnableRandomHalloweenMobile').checked;
config.Halloween.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationHalloween').checked;
// Hearts
config.Hearts.EnableHearts = document.querySelector('#EnableHearts').checked;
config.Hearts.SymbolCount = parseInt(document.querySelector('#HeartsCount').value);
config.Hearts.EnableRandomSymbols = document.querySelector('#EnableRandomHearts').checked;
config.Hearts.EnableRandomSymbolsMobile = document.querySelector('#EnableRandomHeartsMobile').checked;
config.Hearts.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationHearts').checked;
// Christmas
config.Christmas.EnableChristmas = document.querySelector('#EnableChristmas').checked;
config.Christmas.SymbolCount = parseInt(document.querySelector('#ChristmasCount').value);
config.Christmas.EnableRandomChristmas = document.querySelector('#EnableRandomChristmas').checked;
config.Christmas.EnableRandomChristmasMobile = document.querySelector('#EnableRandomChristmasMobile').checked;
config.Christmas.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationChristmas').checked;
// Santa
config.Santa.EnableSanta = document.querySelector('#EnableSanta').checked;
config.Santa.SnowflakesCount = parseInt(document.querySelector('#SantaSnowflakes').value);
config.Santa.SnowflakesCountMobile = parseInt(document.querySelector('#SantaSnowflakesMobile').value);
config.Santa.SantaSpeed = parseFloat(document.querySelector('#SantaSpeed').value);
config.Santa.SantaSpeedMobile = parseFloat(document.querySelector('#SantaSpeedMobile').value);
config.Santa.SnowFallSpeed = parseFloat(document.querySelector('#SantaSnowFallSpeed').value);
config.Santa.MaxSantaRestTime = parseFloat(document.querySelector('#MaxSantaRestTime').value);
config.Santa.MinSantaRestTime = parseFloat(document.querySelector('#MinSantaRestTime').value);
config.Santa.MaxPresentFallSpeed = parseFloat(document.querySelector('#MaxPresentFallSpeed').value);
config.Santa.MinPresentFallSpeed = parseFloat(document.querySelector('#MinPresentFallSpeed').value);
// Easter
config.Easter.EnableEaster = document.querySelector('#EnableEaster').checked;
config.Easter.EggCount = parseInt(document.querySelector('#EasterEggCount').value);
config.Easter.EnableRandomEaster = document.querySelector('#EnableRandomEaster').checked;
config.Easter.EnableRandomEasterMobile = document.querySelector('#EnableRandomEasterMobile').checked;
config.Easter.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationEaster').checked;
config.Easter.EnableBunny = document.querySelector('#EasterBunny').checked;
config.Easter.BunnyDuration = parseInt(document.querySelector('#BunnyDuration').value);
config.Easter.HopHeight = parseInt(document.querySelector('#HopHeight').value);
config.Easter.MinBunnyRestTime = parseInt(document.querySelector('#MinBunnyRestTime').value);
config.Easter.MaxBunnyRestTime = parseInt(document.querySelector('#MaxBunnyRestTime').value);
ApiClient.updatePluginConfiguration(SeasonalsConfig.pluginUniqueId, config).then(function (result) { ApiClient.updatePluginConfiguration(SeasonalsConfig.pluginUniqueId, config).then(function (result) {
Dashboard.processPluginConfigurationUpdateResult(result); Dashboard.processPluginConfigurationUpdateResult(result);
}); });

View File

@@ -12,7 +12,7 @@
<!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> --> <!-- <TreatWarningsAsErrors>false</TreatWarningsAsErrors> -->
<Title>Jellyfin Seasonals Plugin</Title> <Title>Jellyfin Seasonals Plugin</Title>
<Authors>CodeDevMLH</Authors> <Authors>CodeDevMLH</Authors>
<Version>1.0.0.0</Version> <Version>1.1.0.0</Version>
<RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-seasonals</RepositoryUrl> <RepositoryUrl>https://github.com/CodeDevMLH/jellyfin-plugin-seasonals</RepositoryUrl>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,9 +1,11 @@
const leaves = true; // enable/disable leaves const config = window.SeasonalsPluginConfig?.autumn || {};
const randomLeaves = true; // enable random leaves
const randomLeavesMobile = false; // enable random leaves on mobile devices const leaves = config.enableAutumn !== undefined ? config.enableAutumn : true; // enable/disable leaves
const enableDiffrentDuration = true; // enable different duration for the random leaves const randomLeaves = config.enableRandomLeaves !== undefined ? config.enableRandomLeaves : true; // enable random leaves
const enableRotation = false; // enable/disable leaf rotation const randomLeavesMobile = config.enableRandomLeavesMobile !== undefined ? config.enableRandomLeavesMobile : false; // enable random leaves on mobile devices (Warning: High values may affect performance)
const leafCount = 25; // count of random extra leaves const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different duration for the random leaves
const enableRotation = config.enableRotation !== undefined ? config.enableRotation : false; // enable/disable leaf rotation
const leafCount = config.leafCount || 25; // count of random extra leaves
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,8 +1,10 @@
const christmas = true; // enable/disable christmas const config = window.SeasonalsPluginConfig?.christmas || {};
const randomChristmas = true; // enable random Christmas
const randomChristmasMobile = false; // enable random Christmas on mobile devices const christmas = config.enableChristmas !== undefined ? config.enableChristmas : true; // enable/disable christmas
const enableDiffrentDuration = true; // enable different duration for the random Christmas symbols const randomChristmas = config.enableRandomChristmas !== undefined ? config.enableRandomChristmas : true; // enable random Christmas
const christmasCount = 25; // count of random extra christmas const randomChristmasMobile = config.enableRandomChristmasMobile !== undefined ? config.enableRandomChristmasMobile : false; // enable random Christmas on mobile devices (Warning: High values may affect performance)
const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different duration for the random Christmas symbols
const christmasCount = config.symbolCount || 25; // count of random extra christmas
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,14 +1,16 @@
const easter = true; // enable/disable easter const config = window.SeasonalsPluginConfig?.easter || {};
const randomEaster = true; // enable random easter
const randomEasterMobile = false; // enable random easter on mobile devices
const enableDiffrentDuration = true; // enable different duration for the random easter
const easterEggCount = 20; // count of random extra easter
const bunny = true; // enable/disable hopping bunny const easter = config.enableEaster !== undefined ? config.enableEaster : true; // enable/disable easter
const bunnyDuration = 12000; // duration of the bunny animation in ms const randomEaster = config.enableRandomEaster !== undefined ? config.enableRandomEaster : true; // enable random easter
const hopHeight = 12; // height of the bunny hops in px const randomEasterMobile = config.enableRandomEasterMobile !== undefined ? config.enableRandomEasterMobile : false; // enable random easter on mobile devices (Warning: High values may affect performance)
const minBunnyRestTime = 2000; // minimum time the bunny rests in ms const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different duration for the random easter
const maxBunnyRestTime = 5000; // maximum time the bunny rests in ms const easterEggCount = config.eggCount || 20; // count of random extra easter
const bunny = config.enableBunny !== undefined ? config.enableBunny : true; // enable/disable hopping bunny
const bunnyDuration = config.bunnyDuration || 12000; // duration of the bunny animation in ms
const hopHeight = config.hopHeight || 12; // height of the bunny hops in px
const minBunnyRestTime = config.minBunnyRestTime || 2000; // minimum time the bunny rests in ms
const maxBunnyRestTime = config.maxBunnyRestTime || 5000; // maximum time the bunny rests in ms
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,9 +1,11 @@
const fireworks = true; // enable/disable fireworks const config = window.SeasonalsPluginConfig?.fireworks || {};
const scrollFireworks = true; // enable fireworks to scroll with page content
const particlesPerFirework = 50; // count of particles per firework const fireworks = config.enableFireworks !== undefined ? config.enableFireworks : true; // enable/disable fireworks
const minFireworks = 3; // minimum number of simultaneous fireworks const scrollFireworks = config.scrollFireworks !== undefined ? config.scrollFireworks : true; // enable fireworks to scroll with page content
const maxFireworks = 6; // maximum number of simultaneous fireworks const particlesPerFirework = config.particleCount || 50; // count of particles per firework (Warning: High values may affect performance)
const intervalOfFireworks = 3200; // interval for the fireworks in milliseconds const minFireworks = config.minFireworks || 3; // minimum number of simultaneous fireworks
const maxFireworks = config.maxFireworks || 6; // maximum number of simultaneous fireworks
const intervalOfFireworks = config.launchInterval || 3200; // interval for the fireworks in milliseconds
// array of color palettes for the fireworks // array of color palettes for the fireworks
const colorPalettes = [ const colorPalettes = [

View File

@@ -1,8 +1,10 @@
const halloween = true; // enable/disable halloween const config = window.SeasonalsPluginConfig?.halloween || {};
const randomSymbols = true; // enable more random symbols
const randomSymbolsMobile = false; // enable random symbols on mobile devices const halloween = config.enableHalloween !== undefined ? config.enableHalloween : true; // enable/disable halloween
const enableDiffrentDuration = true; // enable different duration for the random halloween symbols const randomSymbols = config.enableRandomSymbols !== undefined ? config.enableRandomSymbols : true; // enable more random symbols
const halloweenCount = 25; // count of random extra symbols const randomSymbolsMobile = config.enableRandomSymbolsMobile !== undefined ? config.enableRandomSymbolsMobile : false; // enable random symbols on mobile devices (Warning: High values may affect performance)
const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different duration for the random halloween symbols
const halloweenCount = config.symbolCount || 25; // count of random extra symbols
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,8 +1,10 @@
const hearts = true; // enable/disable hearts const config = window.SeasonalsPluginConfig?.hearts || {};
const randomSymbols = true; // enable more random symbols
const randomSymbolsMobile = false; // enable random symbols on mobile devices const hearts = config.enableHearts !== undefined ? config.enableHearts : true; // enable/disable hearts
const enableDiffrentDuration = true; // enable different animation duration for random symbols const randomSymbols = config.enableRandomSymbols !== undefined ? config.enableRandomSymbols : true; // enable more random symbols
const heartsCount = 25; // count of random extra symbols const randomSymbolsMobile = config.enableRandomSymbolsMobile !== undefined ? config.enableRandomSymbolsMobile : false; // enable random symbols on mobile devices (Warning: High values may affect performance)
const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different animation duration for random symbols
const heartsCount = config.symbolCount || 25; // count of random extra symbols
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,13 +1,15 @@
const santaIsFlying = true; // enable/disable santa const config = window.SeasonalsPluginConfig?.santa || {};
let snowflakesCount = 500; // count of snowflakes (recommended values: 300-600)
const snowflakesCountMobile = 250; // count of snowflakes on mobile devices const santaIsFlying = config.enableSanta !== undefined ? config.enableSanta : true; // enable/disable santa
const snowFallSpeed = 3; // speed of snowfall (recommended values: 0-5) let snowflakesCount = config.snowflakesCount || 500; // count of snowflakes (recommended values: 300-600)
const santaSpeed = 10; // speed of santa in seconds (recommended values: 5000-15000) const snowflakesCountMobile = config.snowflakesCountMobile || 250; // count of snowflakes on mobile devices (Warning: High values may affect performance)
const santaSpeedMobile = 8; // speed of santa on mobile devices in seconds const snowFallSpeed = config.snowFallSpeed || 3; // speed of snowfall (recommended values: 0-5)
const maxSantaRestTime = 8; // maximum time santa rests in seconds const santaSpeed = config.santaSpeed || 10; // speed of santa in seconds (recommended values: 5000-15000)
const minSantaRestTime = 3; // minimum time santa rests in seconds const santaSpeedMobile = config.santaSpeedMobile || 8; // speed of santa on mobile devices in seconds
const maxPresentFallSpeed = 5; // maximum speed of falling presents in seconds const maxSantaRestTime = config.maxSantaRestTime || 8; // maximum time santa rests in seconds
const minPresentFallSpeed = 2; // minimum speed of falling presents in seconds const minSantaRestTime = config.minSantaRestTime || 3; // minimum time santa rests in seconds
const maxPresentFallSpeed = config.maxPresentFallSpeed || 5; // maximum speed of falling presents in seconds
const minPresentFallSpeed = config.minPresentFallSpeed || 2; // minimum speed of falling presents in seconds
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages
let isMobile = false; // flag to detect mobile devices let isMobile = false; // flag to detect mobile devices

View File

@@ -161,6 +161,7 @@ async function initializeTheme() {
const config = await response.json(); const config = await response.json();
automateThemeSelection = config.automateSeasonSelection; automateThemeSelection = config.automateSeasonSelection;
defaultTheme = config.selectedSeason; defaultTheme = config.selectedSeason;
window.SeasonalsPluginConfig = config;
} else { } else {
console.error('Failed to fetch Seasonals config'); console.error('Failed to fetch Seasonals config');
} }

View File

@@ -1,7 +1,9 @@
const snowfall = true; // enable/disable snowfall const config = window.SeasonalsPluginConfig?.snowfall || {};
let snowflakesCount = 500; // count of snowflakes (recommended values: 300-600)
const snowflakesCountMobile = 250; // count of snowflakes on mobile devices const snowfall = config.enableSnowfall !== undefined ? config.enableSnowfall : true; // enable/disable snowfall
const snowFallSpeed = 3; // speed of snowfall (recommended values: 0-5) let snowflakesCount = config.snowflakesCount || 500; // count of snowflakes (recommended values: 300-600)
const snowflakesCountMobile = config.snowflakesCountMobile || 250; // count of snowflakes on mobile devices (Warning: High values may affect performance)
const snowFallSpeed = config.speed || 3; // speed of snowfall (recommended values: 0-5)
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,9 +1,11 @@
const snowflakes = true; // enable/disable snowflakes const config = window.SeasonalsPluginConfig?.snowflakes || {};
const randomSnowflakes = true; // enable random Snowflakes
const randomSnowflakesMobile = false; // enable random Snowflakes on mobile devices const snowflakes = config.enableSnowflakes !== undefined ? config.enableSnowflakes : true; // enable/disable snowflakes
const enableColoredSnowflakes = true; // enable colored snowflakes on mobile devices const randomSnowflakes = config.enableRandomSnowflakes !== undefined ? config.enableRandomSnowflakes : true; // enable random Snowflakes
const enableDiffrentDuration = true; // enable different animation duration for random symbols const randomSnowflakesMobile = config.enableRandomSnowflakesMobile !== undefined ? config.enableRandomSnowflakesMobile : false; // enable random Snowflakes on mobile devices (Warning: High values may affect performance)
const snowflakeCount = 25; // count of random extra snowflakes const enableColoredSnowflakes = config.enableColoredSnowflakes !== undefined ? config.enableColoredSnowflakes : true; // enable colored snowflakes on mobile devices
const enableDiffrentDuration = config.enableDifferentDuration !== undefined ? config.enableDifferentDuration : true; // enable different animation duration for random symbols
const snowflakeCount = config.snowflakeCount || 25; // count of random extra snowflakes
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -1,9 +1,11 @@
const snowstorm = true; // enable/disable snowstorm const config = window.SeasonalsPluginConfig?.snowstorm || {};
let snowflakesCount = 500; // count of snowflakes (recommended values: 300-600)
const snowflakesCountMobile = 250; // count of snowflakes on mobile devices const snowstorm = config.enableSnowstorm !== undefined ? config.enableSnowstorm : true; // enable/disable snowstorm
const snowFallSpeed = 6; // speed of snowfall (recommended values: 4-8) let snowflakesCount = config.snowflakesCount || 500; // count of snowflakes (recommended values: 300-600)
const horizontalWind = 4; // horizontal wind speed (recommended value: 4) const snowflakesCountMobile = config.snowflakesCountMobile || 250; // count of snowflakes on mobile devices (Warning: High values may affect performance)
const verticalVariation = 2; // vertical variation (recommended value: 2) const snowFallSpeed = config.speed || 6; // speed of snowfall (recommended values: 4-8)
const horizontalWind = config.horizontalWind || 4; // horizontal wind speed (recommended value: 4)
const verticalVariation = config.verticalVariation || 2; // vertical variation (recommended value: 2)
let msgPrinted = false; // flag to prevent multiple console messages let msgPrinted = false; // flag to prevent multiple console messages

View File

@@ -2,7 +2,9 @@
Jellyfin Seasonals is a plugin that adds seasonal themes to your Jellyfin web interface. Depending on the configuration, it automatically selects a theme based on the current date or allows you to manually set a default theme. Jellyfin Seasonals is a plugin that adds seasonal themes to your Jellyfin web interface. Depending on the configuration, it automatically selects a theme based on the current date or allows you to manually set a default theme.
This plugin is based on my manual mod (see the `manual` branch), which builds up on the awesome work of [BobHasNoSoul-jellyfin-mods](https://github.com/BobHasNoSoul/jellyfin-mods). This plugin is based on my manual mod (see the [legacy branch](https://github.com/CodeDevMLH/Jellyfin-Seasonals/tree/legacy)), which builds up on the awesome work of [BobHasNoSoul-jellyfin-mods](https://github.com/BobHasNoSoul/jellyfin-mods).
![logo](https://raw.githubusercontent.com/CodeDevMLH/Jellyfin-Seasonals/refs/heads/main/logo.png)
--- ---
@@ -13,13 +15,13 @@ This plugin is based on my manual mod (see the `manual` branch), which builds up
- [Overview](#overview) - [Overview](#overview)
- [Installation](#installation) - [Installation](#installation)
- [Usage](#usage) - [Usage](#usage)
- [Automatic Theme Selection](#automatic-theme-selection)
- [Build Process](#build-process) - [Build Process](#build-process)
- [Contributing](#contributing) - [Contributing](#contributing)
- [Legacy Manual Installation](#legacy-manual-installation) - [Legacy Manual Installation](#legacy-manual-installation)
- [Installation](#installation-1) - [Installation](#installation-1)
- [Theme Settings](#theme-settings) - [Usage](#usage-1)
- [Additional Directory: Separate Single Seasonals](#additional-directory-separate-single-seasonals) - [Additional Directory: Separate Single Seasonals](#additional-directory-separate-single-seasonals)
- [Troubleshooting](#troubleshooting)
--- ---
@@ -63,18 +65,20 @@ This plugin is based on my manual mod (see the `manual` branch), which builds up
## Installation ## Installation
This plugin is based on Jellyfin Version `10.11.x`
To install this plugin, you will first need to add the repository in Jellyfin. To install this plugin, you will first need to add the repository in Jellyfin.
1. Open your Jellyfin Dashboard. 1. Open your Jellyfin Dashboard.
2. Navigate to **Plugins** > **Repositories**. 2. Navigate to **Plugins** > **Manage Repositories**.
3. Click the **+** sign to add a new repository. 3. Click the **+ New Repository** button to add a new repository.
4. Enter a name (e.g., "Seasonals") and paste the following URL into the 'Repository URL' field: 4. Enter a name (e.g., "Seasonals") and paste the following URL into the 'Repository URL' field:
```bash ```bash
https://raw.githubusercontent.com/CodeDevMLH/jellyfin-plugin-seasonals/main/manifest.json https://raw.githubusercontent.com/CodeDevMLH/Jellyfin-Seasonals/refs/heads/main/manifest.json
``` ```
5. Click **Save**. 5. Click **Add**.
6. Go to the **Catalog** tab at the top. 6. Go to the **Available** tab at the top.
7. Under **General**, find the **Seasonals** plugin. 7. Find the **Seasonals** plugin (Under **General**)
8. Click on it and select **Install**. 8. Click on it and select **Install**.
9. **Restart your Jellyfin server.** 9. **Restart your Jellyfin server.**
10. **You may need to refresh your browser page** (F5 or Ctrl+R) to see the changes. 10. **You may need to refresh your browser page** (F5 or Ctrl+R) to see the changes.
@@ -91,6 +95,23 @@ After installation and restart:
4. **Save** your settings. 4. **Save** your settings.
5. **Reload your browser page** (F5 or Ctrl+R) to see the changes. 5. **Reload your browser page** (F5 or Ctrl+R) to see the changes.
## Automatic Theme Selection
If automatic selection is enabled, the following themes are applied based on the date. Specific holiday events take precedence over general seasonal themes.:
| Theme | Active Period | Description |
| :--- | :--- | :--- |
| **`santa`** | Dec 22 Dec 27 | Christmas theme |
| **`fireworks`** | Dec 28 Jan 05 | New Year's celebration |
| **`hearts`** | Feb 10 Feb 18 | Valentine's Day |
| **`easter`** | Mar 25 Apr 25 | Easter theme |
| **`halloween`** | Oct 24 Nov 05 | Halloween theme |
| **`snowflakes`** | December (Remainder) | General December winter theme |
| **`snowfall`** | January & February | General winter theme (outside of holidays) |
| **`autumn`** | Sep, Oct, Nov | Fall theme (when not Halloween) |
| **`none`** | All other dates | Default appearance |
> **Note:** Holiday themes (like `santa` or `fireworks`) override monthly seasonal themes (like `snowflakes`).
## Build Process ## Build Process
If you want to build the plugin yourself: If you want to build the plugin yourself:
@@ -127,7 +148,7 @@ Feel free to contribute to this project by creating pull requests or reporting i
<script src="seasonals/seasonals.js"></script> <script src="seasonals/seasonals.js"></script>
``` ```
2. **Deploy Files** 2. **Deploy Files**
Place the seasonals folder (including seasonals.js, CSS, and additional JavaScript files for each theme [this one](https://github.com/CodeDevMLH/Jellyfin-Seasonals/tree/main/seasonals)) inside the Jellyfin web server directory (labeld with "web"). Place the seasonals folder (including seasonals.js, CSS, and additional JavaScript files for each theme [this one](https://github.com/CodeDevMLH/Jellyfin-Seasonals/tree/legacy/seasonals)) inside the Jellyfin web server directory (labeld with "web").
3. **Configure Themes** 3. **Configure Themes**
Customize the theme-configs.js file to modify or add new themes. The default configuration is shown below: Customize the theme-configs.js file to modify or add new themes. The default configuration is shown below:

View File

@@ -6,7 +6,7 @@
"compilationOptions": {}, "compilationOptions": {},
"targets": { "targets": {
".NETCoreApp,Version=v9.0": { ".NETCoreApp,Version=v9.0": {
"Jellyfin.Plugin.Seasonals/1.0.0.0": { "Jellyfin.Plugin.Seasonals/1.1.0.0": {
"dependencies": { "dependencies": {
"Jellyfin.Controller": "10.11.0", "Jellyfin.Controller": "10.11.0",
"Jellyfin.Model": "10.11.0" "Jellyfin.Model": "10.11.0"
@@ -363,7 +363,7 @@
} }
}, },
"libraries": { "libraries": {
"Jellyfin.Plugin.Seasonals/1.0.0.0": { "Jellyfin.Plugin.Seasonals/1.1.0.0": {
"type": "project", "type": "project",
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""

View File

@@ -1,7 +1,7 @@
--- ---
name: "Seasonals" name: "Seasonals"
guid: "ef1e863f-cbb0-4e47-9f23-f0cbb1826ad4" guid: "ef1e863f-cbb0-4e47-9f23-f0cbb1826ad4"
version: "1.0.0.0" version: "1.1.0.0"
targetAbi: "10.11.0.0" targetAbi: "10.11.0.0"
framework: "net9.0" framework: "net9.0"
overview: "Seasonal effects for Jellyfin" overview: "Seasonal effects for Jellyfin"
@@ -12,4 +12,4 @@ owner: "CodeDevMLH"
artifacts: artifacts:
- "Jellyfin.Plugin.Seasonals.dll" - "Jellyfin.Plugin.Seasonals.dll"
changelog: > changelog: >
Initial release Added Advanced Configuration UI for customizing individual seasonal effects.

View File

@@ -6,13 +6,21 @@
"overview": "Seasonal effects for Jellyfin", "overview": "Seasonal effects for Jellyfin",
"owner": "CodeDevMLH", "owner": "CodeDevMLH",
"category": "General", "category": "General",
"imageUrl": "", "imageUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/raw/branch/main/logo.png",
"versions": [ "versions": [
{
"version": "1.1.0.0",
"changelog": "Added Advanced Configuration UI for customizing individual seasonal effects.",
"targetAbi": "10.11.0.0",
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/releases/download/v1.1.0.0/Jellyfin.Plugin.Seasonals.zip",
"checksum": "efc26cf0d09b313c52c089fc43df12ab",
"timestamp": "2025-12-16T00:22:10Z"
},
{ {
"version": "1.0.0.0", "version": "1.0.0.0",
"changelog": "Initial release", "changelog": "Initial release",
"targetAbi": "10.11.0.0", "targetAbi": "10.11.0.0",
"sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/raw/branch/main/bin/Publish/Jellyfin.Plugin.Seasonals.zip", "sourceUrl": "https://git.mahom03-spacecloud.de/CodeDevMLH/Jellyfin-Seasonals-Plugin/releases/download/v1.0.0.0/Jellyfin.Plugin.Seasonals.zip",
"checksum": "be6d06a959b3e18e5058a6d8fb6d800c", "checksum": "be6d06a959b3e18e5058a6d8fb6d800c",
"timestamp": "2025-12-15T15:33:15Z" "timestamp": "2025-12-15T15:33:15Z"
} }