Add Spring, Summer, and Carnival options to plugin configuration and UI

This commit is contained in:
CodeDevMLH
2026-02-19 03:18:39 +01:00
parent 92d9e1a9ad
commit 4c168a5ec2
3 changed files with 235 additions and 7 deletions

View File

@@ -28,6 +28,9 @@ public class PluginConfiguration : BasePluginConfiguration
Santa = new SantaOptions(); Santa = new SantaOptions();
Easter = new EasterOptions(); Easter = new EasterOptions();
Resurrection = new ResurrectionOptions(); Resurrection = new ResurrectionOptions();
Spring = new SpringOptions();
Summer = new SummerOptions();
Carnival = new CarnivalOptions();
} }
/// <summary> /// <summary>
@@ -53,7 +56,7 @@ public class PluginConfiguration : BasePluginConfiguration
/// <summary> /// <summary>
/// Gets or sets the seasonal rules configuration as JSON. /// Gets or sets the seasonal rules configuration as JSON.
/// </summary> /// </summary>
public string SeasonalRules { get; set; } = "[{\"Name\":\"New Year Fireworks\",\"StartDay\":28,\"StartMonth\":12,\"EndDay\":5,\"EndMonth\":1,\"Theme\":\"fireworks\"},{\"Name\":\"Valentine's Day\",\"StartDay\":10,\"StartMonth\":2,\"EndDay\":18,\"EndMonth\":2,\"Theme\":\"hearts\"},{\"Name\":\"Santa\",\"StartDay\":22,\"StartMonth\":12,\"EndDay\":27,\"EndMonth\":12,\"Theme\":\"santa\"},{\"Name\":\"Snowflakes (December)\",\"StartDay\":1,\"StartMonth\":12,\"EndDay\":31,\"EndMonth\":12,\"Theme\":\"snowflakes\"},{\"Name\":\"Snowfall (January)\",\"StartDay\":1,\"StartMonth\":1,\"EndDay\":31,\"EndMonth\":1,\"Theme\":\"snowfall\"},{\"Name\":\"Snowfall (February)\",\"StartDay\":1,\"StartMonth\":2,\"EndDay\":29,\"EndMonth\":2,\"Theme\":\"snowfall\"},{\"Name\":\"Easter\",\"StartDay\":25,\"StartMonth\":3,\"EndDay\":25,\"EndMonth\":4,\"Theme\":\"easter\"},{\"Name\":\"Halloween\",\"StartDay\":24,\"StartMonth\":10,\"EndDay\":5,\"EndMonth\":11,\"Theme\":\"halloween\"},{\"Name\":\"Autumn\",\"StartDay\":1,\"StartMonth\":9,\"EndDay\":30,\"EndMonth\":11,\"Theme\":\"autumn\"}]"; public string SeasonalRules { get; set; } = "[{\"Name\":\"New Year Fireworks\",\"StartDay\":28,\"StartMonth\":12,\"EndDay\":5,\"EndMonth\":1,\"Theme\":\"fireworks\"},{\"Name\":\"Carnival\",\"StartDay\":19,\"StartMonth\":2,\"EndDay\":28,\"EndMonth\":2,\"Theme\":\"carnival\"},{\"Name\":\"Valentine's Day\",\"StartDay\":10,\"StartMonth\":2,\"EndDay\":18,\"EndMonth\":2,\"Theme\":\"hearts\"},{\"Name\":\"Spring\",\"StartDay\":1,\"StartMonth\":3,\"EndDay\":31,\"EndMonth\":5,\"Theme\":\"spring\"},{\"Name\":\"Summer\",\"StartDay\":1,\"StartMonth\":6,\"EndDay\":31,\"EndMonth\":8,\"Theme\":\"summer\"},{\"Name\":\"Santa\",\"StartDay\":22,\"StartMonth\":12,\"EndDay\":27,\"EndMonth\":12,\"Theme\":\"santa\"},{\"Name\":\"Snowflakes (December)\",\"StartDay\":1,\"StartMonth\":12,\"EndDay\":31,\"EndMonth\":12,\"Theme\":\"snowflakes\"},{\"Name\":\"Snowfall (January)\",\"StartDay\":1,\"StartMonth\":1,\"EndDay\":31,\"EndMonth\":1,\"Theme\":\"snowfall\"},{\"Name\":\"Snowfall (February)\",\"StartDay\":1,\"StartMonth\":2,\"EndDay\":29,\"EndMonth\":2,\"Theme\":\"snowfall\"},{\"Name\":\"Easter\",\"StartDay\":25,\"StartMonth\":3,\"EndDay\":25,\"EndMonth\":4,\"Theme\":\"easter\"},{\"Name\":\"Halloween\",\"StartDay\":24,\"StartMonth\":10,\"EndDay\":5,\"EndMonth\":11,\"Theme\":\"halloween\"},{\"Name\":\"Autumn\",\"StartDay\":1,\"StartMonth\":9,\"EndDay\":30,\"EndMonth\":11,\"Theme\":\"autumn\"}]";
/// <summary> /// <summary>
/// Gets or sets the Seasonals options. /// Gets or sets the Seasonals options.
@@ -69,6 +72,9 @@ public class PluginConfiguration : BasePluginConfiguration
public SantaOptions Santa { get; set; } public SantaOptions Santa { get; set; }
public EasterOptions Easter { get; set; } public EasterOptions Easter { get; set; }
public ResurrectionOptions Resurrection { get; set; } public ResurrectionOptions Resurrection { get; set; }
public SpringOptions Spring { get; set; }
public SummerOptions Summer { get; set; }
public CarnivalOptions Carnival { get; set; }
} }
public class AutumnOptions public class AutumnOptions
@@ -182,3 +188,34 @@ public class ResurrectionOptions
public bool EnableRandomSymbolsMobile { get; set; } = false; public bool EnableRandomSymbolsMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true; public bool EnableDifferentDuration { get; set; } = true;
} }
public class SpringOptions
{
public int PetalCount { get; set; } = 25;
public int PollenCount { get; set; } = 15;
public int LadybugCount { get; set; } = 5;
public int SunbeamCount { get; set; } = 5;
public bool EnableSpring { get; set; } = true;
public bool EnableRandomSpring { get; set; } = true;
public bool EnableRandomSpringMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}
public class SummerOptions
{
public int BubbleCount { get; set; } = 20;
public int DustCount { get; set; } = 50;
public bool EnableSummer { get; set; } = true;
public bool EnableRandomSummer { get; set; } = true;
public bool EnableRandomSummerMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}
public class CarnivalOptions
{
public int ObjectCount { get; set; } = 25;
public bool EnableCarnival { get; set; } = true;
public bool EnableRandomCarnival { get; set; } = true;
public bool EnableRandomCarnivalMobile { get; set; } = false;
public bool EnableDifferentDuration { get; set; } = true;
}

View File

@@ -62,14 +62,13 @@
<option value="halloween">Halloween</option> <option value="halloween">Halloween</option>
<option value="hearts">Hearts</option> <option value="hearts">Hearts</option>
<option value="christmas">Christmas</option> <option value="christmas">Christmas</option>
<option value="santa">Santa</option> <option value="santa">Santa (flying santa & snowfall)</option>
<option value="autumn">Autumn</option> <option value="autumn">Autumn (falling leaves)</option>
<option value="easter">Easter</option> <option value="easter">Easter</option>
<option value="resurrection">Resurrection</option> <option value="resurrection">Resurrection</option>
<option value="summer" disabled>Summer (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="summer">Summer (Bubbles)</option>
<option value="spring" disabled>Spring (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="spring">Spring</option>
<option value="oktoberfest" disabled>Oktoberfest (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="carnival">Carnival (Confetti)</option>
<option value="carnival" disabled>Carnival (not implemented yet. Please commit ideas in a issue or PR)</option>
<option value="championships" disabled>European/World Championships (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="championships" disabled>European/World Championships (not implemented yet. Please commit ideas in a issue or PR)</option>
<option value="patrick" disabled>St. Patrick's Day (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="patrick" disabled>St. Patrick's Day (not implemented yet. Please commit ideas in a issue or PR)</option>
<option value="thanksgiving" disabled>Thanksgiving (not implemented yet. Please commit ideas in a issue or PR)</option> <option value="thanksgiving" disabled>Thanksgiving (not implemented yet. Please commit ideas in a issue or PR)</option>
@@ -576,6 +575,140 @@
<div class="fieldDescription">Randomize the movement speed.</div> <div class="fieldDescription">Randomize the movement speed.</div>
</div> </div>
</details> </details>
<hr style="max-width: 800px; margin: 1em 0;">
<details>
<summary>Spring</summary>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableSpring" name="EnableSpring" type="checkbox" is="emby-checkbox" />
<span>Enable Spring Seasonal</span>
</label>
<div class="fieldDescription">Enable the Spring theme in general (e.g. for automation).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomSpring" name="EnableRandomSpring" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Sakura Petals</span>
</label>
<div class="fieldDescription">Displays additional Sakura petals falling across the screen.</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomSpringMobile" name="EnableRandomSpringMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Sakura Petals on Mobile</span>
</label>
<div class="fieldDescription">Displays additional Sakura petals falling across the screen on mobile devices. Warning: High values may affect performance.</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SpringPetalCount">Sakura Petal Count</label>
<input is="emby-input" type="number" id="SpringPetalCount" name="SpringPetalCount" />
<div class="fieldDescription">Number of additional Sakura petals (if enabled).</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SpringPollenCount">Pollen Count</label>
<input is="emby-input" type="number" id="SpringPollenCount" name="SpringPollenCount" />
<div class="fieldDescription">Number of pollen particles (if enabled).</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SpringLadybugCount">Ladybug Count</label>
<input is="emby-input" type="number" id="SpringLadybugCount" name="SpringLadybugCount" />
<div class="fieldDescription">Number of ladybugs.</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SpringSunbeamCount">Sunbeam Count</label>
<input is="emby-input" type="number" id="SpringSunbeamCount" name="SpringSunbeamCount" />
<div class="fieldDescription">Number of sunbeams (if enabled).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationSpring" name="EnableDifferentDurationSpring" type="checkbox" is="emby-checkbox" />
<span>Enable Different Falling Speed</span>
</label>
<div class="fieldDescription">Randomize the falling speed of petals.</div>
</div>
</details>
<hr style="max-width: 800px; margin: 1em 0;">
<details>
<summary>Summer</summary>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableSummer" name="EnableSummer" type="checkbox" is="emby-checkbox" />
<span>Enable Summer Seasonal</span>
</label>
<div class="fieldDescription">Enable the Summer theme in general (e.g. for automation).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomSummer" name="EnableRandomSummer" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Bubbles and Dust</span>
</label>
<div class="fieldDescription">Displays additional bubbles and dust particles rising across the screen.</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomSummerMobile" name="EnableRandomSummerMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Bubbles and Dust on Mobile</span>
</label>
<div class="fieldDescription">Displays additional bubbles and dust particles rising across the screen on mobile devices. Warning: High values may affect performance.</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SummerBubbleCount">Bubbles Count</label>
<input is="emby-input" type="number" id="SummerBubbleCount" name="SummerBubbleCount" />
<div class="fieldDescription">Number of bubbles (if enabled).</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="SummerDustCount">Dust Count</label>
<input is="emby-input" type="number" id="SummerDustCount" name="SummerDustCount" />
<div class="fieldDescription">Number of dust particles (if enabled).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationSummer" name="EnableDifferentDurationSummer" type="checkbox" is="emby-checkbox" />
<span>Enable Different Rising Speed</span>
</label>
<div class="fieldDescription">Randomize the rising speed of bubbles.</div>
</div>
</details>
<hr style="max-width: 800px; margin: 1em 0;">
<details>
<summary>Carnival</summary>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableCarnival" name="EnableCarnival" type="checkbox" is="emby-checkbox" />
<span>Enable Carnival Seasonal</span>
</label>
<div class="fieldDescription">Enable the Carnival theme in general (e.g. for automation).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomCarnival" name="EnableRandomCarnival" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Confetti</span>
</label>
<div class="fieldDescription">Displays additional confetti falling and fluttering across the screen.</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableRandomCarnivalMobile" name="EnableRandomCarnivalMobile" type="checkbox" is="emby-checkbox" />
<span>Enable Additional Random Confetti on Mobile</span>
</label>
<div class="fieldDescription">Displays additional confetti falling and fluttering across the screen on mobile devices. Warning: High values may affect performance.</div>
</div>
<div class="inputContainer">
<label class="inputLabel" for="CarnivalObjectCount">Confetti Count</label>
<input is="emby-input" type="number" id="CarnivalObjectCount" name="CarnivalObjectCount" />
<div class="fieldDescription">Number of additional confetti pieces (if enabled).</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label class="emby-checkbox-label">
<input id="EnableDifferentDurationCarnival" name="EnableDifferentDurationCarnival" type="checkbox" is="emby-checkbox" />
<span>Enable Different Falling Speed</span>
</label>
<div class="fieldDescription">Randomize the falling speed of confetti.</div>
</div>
</details>
</div> </div>
<div style="background-color: rgba(255, 255, 255, 0.05); border-left: 4px solid #00a4dc; border-radius: 4px; padding: 1em 1.5em; margin: 1.5em 0; display: flex; align-items: center; gap: 1em;"> <div style="background-color: rgba(255, 255, 255, 0.05); border-left: 4px solid #00a4dc; border-radius: 4px; padding: 1em 1.5em; margin: 1.5em 0; display: flex; align-items: center; gap: 1em;">
@@ -755,6 +888,9 @@
' <option value="autumn">Autumn</option>' + ' <option value="autumn">Autumn</option>' +
' <option value="easter">Easter</option>' + ' <option value="easter">Easter</option>' +
' <option value="resurrection">Resurrection</option>' + ' <option value="resurrection">Resurrection</option>' +
' <option value="spring">Spring</option>' +
' <option value="summer">Summer</option>' +
' <option value="carnival">Carnival</option>' +
' </select>' + ' </select>' +
' </div>' + ' </div>' +
'</div>'; '</div>';
@@ -927,6 +1063,31 @@
document.querySelector('#EnableRandomResurrectionMobile').checked = config.Resurrection.EnableRandomSymbolsMobile; document.querySelector('#EnableRandomResurrectionMobile').checked = config.Resurrection.EnableRandomSymbolsMobile;
document.querySelector('#EnableDifferentDurationResurrection').checked = config.Resurrection.EnableDifferentDuration; document.querySelector('#EnableDifferentDurationResurrection').checked = config.Resurrection.EnableDifferentDuration;
// Spring
document.querySelector('#EnableSpring').checked = config.Spring.EnableSpring;
document.querySelector('#SpringPetalCount').value = config.Spring.PetalCount;
document.querySelector('#SpringPollenCount').value = config.Spring.PollenCount;
document.querySelector('#SpringLadybugCount').value = config.Spring.LadybugCount;
document.querySelector('#SpringSunbeamCount').value = config.Spring.SunbeamCount;
document.querySelector('#EnableRandomSpring').checked = config.Spring.EnableRandomSpring;
document.querySelector('#EnableRandomSpringMobile').checked = config.Spring.EnableRandomSpringMobile;
document.querySelector('#EnableDifferentDurationSpring').checked = config.Spring.EnableDifferentDuration;
// Summer
document.querySelector('#EnableSummer').checked = config.Summer.EnableSummer;
document.querySelector('#SummerBubbleCount').value = config.Summer.BubbleCount;
document.querySelector('#SummerDustCount').value = config.Summer.DustCount;
document.querySelector('#EnableRandomSummer').checked = config.Summer.EnableRandomSummer;
document.querySelector('#EnableRandomSummerMobile').checked = config.Summer.EnableRandomSummerMobile;
document.querySelector('#EnableDifferentDurationSummer').checked = config.Summer.EnableDifferentDuration;
// Carnival
document.querySelector('#EnableCarnival').checked = config.Carnival.EnableCarnival;
document.querySelector('#CarnivalObjectCount').value = config.Carnival.ObjectCount;
document.querySelector('#EnableRandomCarnival').checked = config.Carnival.EnableRandomCarnival;
document.querySelector('#EnableRandomCarnivalMobile').checked = config.Carnival.EnableRandomCarnivalMobile;
document.querySelector('#EnableDifferentDurationCarnival').checked = config.Carnival.EnableDifferentDuration;
Dashboard.hideLoadingMsg(); Dashboard.hideLoadingMsg();
}); });
}); });
@@ -1034,6 +1195,31 @@
config.Resurrection.EnableRandomSymbolsMobile = document.querySelector('#EnableRandomResurrectionMobile').checked; config.Resurrection.EnableRandomSymbolsMobile = document.querySelector('#EnableRandomResurrectionMobile').checked;
config.Resurrection.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationResurrection').checked; config.Resurrection.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationResurrection').checked;
// Spring
config.Spring.EnableSpring = document.querySelector('#EnableSpring').checked;
config.Spring.PetalCount = parseInt(document.querySelector('#SpringPetalCount').value);
config.Spring.PollenCount = parseInt(document.querySelector('#SpringPollenCount').value);
config.Spring.LadybugCount = parseInt(document.querySelector('#SpringLadybugCount').value);
config.Spring.SunbeamCount = parseInt(document.querySelector('#SpringSunbeamCount').value);
config.Spring.EnableRandomSpring = document.querySelector('#EnableRandomSpring').checked;
config.Spring.EnableRandomSpringMobile = document.querySelector('#EnableRandomSpringMobile').checked;
config.Spring.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationSpring').checked;
// Summer
config.Summer.EnableSummer = document.querySelector('#EnableSummer').checked;
config.Summer.BubbleCount = parseInt(document.querySelector('#SummerBubbleCount').value);
config.Summer.DustCount = parseInt(document.querySelector('#SummerDustCount').value);
config.Summer.EnableRandomSummer = document.querySelector('#EnableRandomSummer').checked;
config.Summer.EnableRandomSummerMobile = document.querySelector('#EnableRandomSummerMobile').checked;
config.Summer.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationSummer').checked;
// Carnival
config.Carnival.EnableCarnival = document.querySelector('#EnableCarnival').checked;
config.Carnival.ObjectCount = parseInt(document.querySelector('#CarnivalObjectCount').value);
config.Carnival.EnableRandomCarnival = document.querySelector('#EnableRandomCarnival').checked;
config.Carnival.EnableRandomCarnivalMobile = document.querySelector('#EnableRandomCarnivalMobile').checked;
config.Carnival.EnableDifferentDuration = document.querySelector('#EnableDifferentDurationCarnival').checked;
ApiClient.updatePluginConfiguration(SeasonalsConfigPage.pluginUniqueId, config).then(function (result) { ApiClient.updatePluginConfiguration(SeasonalsConfigPage.pluginUniqueId, config).then(function (result) {
Dashboard.processPluginConfigurationUpdateResult(result); Dashboard.processPluginConfigurationUpdateResult(result);
}); });

View File

@@ -68,6 +68,11 @@ const ThemeConfigs = {
js: '../Seasonals/Resources/spring.js', js: '../Seasonals/Resources/spring.js',
containerClass: 'spring-container' containerClass: 'spring-container'
}, },
carnival: {
css: '../Seasonals/Resources/carnival.css',
js: '../Seasonals/Resources/carnival.js',
containerClass: 'carnival-container'
},
none: { none: {
containerClass: 'none' containerClass: 'none'
}, },