Add Library theme with user images + fix theme system
New Library Theme Feature: - Added 'Library (Random)' option to theme dropdown - Uses random images from user's linked directories - Fresh random selection on each page load/theme change - Displays 10 random images from personal collection on home screen Theme System Improvements: - Updated applyTheme() to handle async library theme loading - Added applyLibraryTheme() function with proper error handling - Fixed CSS loading to skip image-based themes (library, hentai, etc.) - Improved file path handling for Electron environment - Added fallback to hentai theme when no library images found Enhanced Dropdown: - Added BBC and feet themes with proper image mappings - Added Library theme with folder icon - All 6 theme options now fully functional Result: Personalized home screen using user's own image collection!
This commit is contained in:
parent
37ec5f0f1e
commit
9d94fb8695
193
index.html
193
index.html
|
|
@ -256,6 +256,9 @@
|
||||||
<select id="theme-dropdown" class="theme-dropdown">
|
<select id="theme-dropdown" class="theme-dropdown">
|
||||||
<option value="hentai" selected>🎭 Hentai</option>
|
<option value="hentai" selected>🎭 Hentai</option>
|
||||||
<option value="pornstars">⭐ Pornstars</option>
|
<option value="pornstars">⭐ Pornstars</option>
|
||||||
|
<option value="BBC">🔥 BBC</option>
|
||||||
|
<option value="feet">👣 Feet</option>
|
||||||
|
<option value="library">📂 Library (Random)</option>
|
||||||
<option value="none">🚫 None</option>
|
<option value="none">🚫 None</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1307,24 +1310,69 @@
|
||||||
<script src="src/core/game.js"></script>
|
<script src="src/core/game.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// Theme switching functionality
|
// Theme switching functionality
|
||||||
function applyTheme(theme) {
|
async function applyTheme(theme) {
|
||||||
console.log('Applying theme:', theme);
|
console.log('Applying theme:', theme);
|
||||||
const characterSides = document.querySelectorAll('.character-side');
|
const characterSides = document.querySelectorAll('.character-side');
|
||||||
|
|
||||||
characterSides.forEach((element, index) => {
|
if (theme === 'none') {
|
||||||
if (theme === 'none') {
|
characterSides.forEach(element => {
|
||||||
element.style.display = 'none';
|
element.style.display = 'none';
|
||||||
} else {
|
});
|
||||||
element.style.display = 'block';
|
localStorage.setItem('selectedTheme', theme);
|
||||||
|
return;
|
||||||
// Map element positions to image numbers
|
}
|
||||||
|
|
||||||
|
if (theme === 'library') {
|
||||||
|
// Use random images from user's library
|
||||||
|
await applyLibraryTheme(characterSides);
|
||||||
|
localStorage.setItem('selectedTheme', theme);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle static themes (hentai, pornstars, BBC, feet)
|
||||||
|
characterSides.forEach((element, index) => {
|
||||||
|
element.style.display = 'block';
|
||||||
|
|
||||||
|
// Define image mappings for different themes
|
||||||
|
let imageNames;
|
||||||
|
|
||||||
|
if (theme === 'hentai' || theme === 'pornstars') {
|
||||||
|
// Standard numbering for hentai and pornstars
|
||||||
const imageNumbers = [1, 11, 3, 4, 5, 6, 7, 8, 9, 10];
|
const imageNumbers = [1, 11, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
const imageNumber = imageNumbers[index];
|
imageNames = imageNumbers.map(num => `${num}.png`);
|
||||||
|
} else if (theme === 'BBC') {
|
||||||
if (imageNumber) {
|
// BBC directory image names
|
||||||
const imagePath = `assets/${theme}/${imageNumber}.png`;
|
imageNames = [
|
||||||
element.style.backgroundImage = `url('${imagePath}')`;
|
'18808856_035_d374.png',
|
||||||
}
|
'19086746_049_ba0d.png',
|
||||||
|
'23515083_025_f794.png',
|
||||||
|
'24163996_041_81d6.png',
|
||||||
|
'31015308_126_3792.png',
|
||||||
|
'44141198_113_f31a.png',
|
||||||
|
'60016759_151_ea2b.png',
|
||||||
|
'85835876_037_0c84.png',
|
||||||
|
'99106223_020_819b.png',
|
||||||
|
'99769898_038_0e86.png'
|
||||||
|
];
|
||||||
|
} else if (theme === 'feet') {
|
||||||
|
// Feet directory image names (using first 10)
|
||||||
|
imageNames = [
|
||||||
|
'20931683_001_c8f7.png',
|
||||||
|
'25674071_097_2016.png',
|
||||||
|
'29553632_079_53ec.png',
|
||||||
|
'30818412_002_8cbf.png',
|
||||||
|
'40352681_083_bec8.png',
|
||||||
|
'46780885_029_b8a2.png',
|
||||||
|
'47594084_126_51a7.png',
|
||||||
|
'67258313_065_60f1.png',
|
||||||
|
'79150090_035_3c99.png',
|
||||||
|
'80350346_043_3e8a.png'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageNames && imageNames[index]) {
|
||||||
|
const imagePath = `assets/${theme}/${imageNames[index]}`;
|
||||||
|
element.style.backgroundImage = `url('${imagePath}')`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1332,18 +1380,129 @@
|
||||||
localStorage.setItem('selectedTheme', theme);
|
localStorage.setItem('selectedTheme', theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function applyLibraryTheme(characterSides) {
|
||||||
|
console.log('Applying library theme with random images...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get images from user's linked directories (same way as lib-image-gallery)
|
||||||
|
const linkedDirs = JSON.parse(localStorage.getItem('linkedImageDirectories') || '[]');
|
||||||
|
let allImages = [];
|
||||||
|
|
||||||
|
if (window.electronAPI && linkedDirs.length > 0) {
|
||||||
|
const imageExtensions = /\.(jpg|jpeg|png|gif|webp|bmp)$/i;
|
||||||
|
|
||||||
|
// Load images from all linked directories
|
||||||
|
for (const dir of linkedDirs) {
|
||||||
|
try {
|
||||||
|
let files = [];
|
||||||
|
if (window.electronAPI.readDirectory) {
|
||||||
|
const filesPromise = window.electronAPI.readDirectory(dir.path);
|
||||||
|
|
||||||
|
if (filesPromise && typeof filesPromise.then === 'function') {
|
||||||
|
files = await filesPromise;
|
||||||
|
} else if (Array.isArray(filesPromise)) {
|
||||||
|
files = filesPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (files && files.length > 0) {
|
||||||
|
const imageFiles = files.filter(file => {
|
||||||
|
const fileName = typeof file === 'object' ? file.name : file;
|
||||||
|
return imageExtensions.test(fileName);
|
||||||
|
});
|
||||||
|
|
||||||
|
const dirImages = imageFiles.map(file => {
|
||||||
|
if (typeof file === 'object' && file.name && file.path) {
|
||||||
|
return { path: file.path, name: file.name };
|
||||||
|
} else {
|
||||||
|
const fileName = typeof file === 'object' ? file.name : file;
|
||||||
|
const fullPath = window.electronAPI.pathJoin ?
|
||||||
|
window.electronAPI.pathJoin(dir.path, fileName) :
|
||||||
|
`${dir.path}\\${fileName}`;
|
||||||
|
return { path: fullPath, name: fileName };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
allImages = allImages.concat(dirImages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn(`Error loading images from ${dir.path}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`📂 Found ${allImages.length} images in user library`);
|
||||||
|
|
||||||
|
if (allImages.length === 0) {
|
||||||
|
// No images available - show placeholder or fall back to hentai theme
|
||||||
|
console.log('No library images found, falling back to hentai theme');
|
||||||
|
characterSides.forEach((element, index) => {
|
||||||
|
element.style.display = 'block';
|
||||||
|
// Fallback to hentai theme
|
||||||
|
const imageNumbers = [1, 11, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
const imageNumber = imageNumbers[index];
|
||||||
|
if (imageNumber) {
|
||||||
|
const imagePath = `assets/hentai/${imageNumber}.png`;
|
||||||
|
element.style.backgroundImage = `url('${imagePath}')`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly select images for each character panel
|
||||||
|
characterSides.forEach((element, index) => {
|
||||||
|
element.style.display = 'block';
|
||||||
|
|
||||||
|
// Get a random image
|
||||||
|
const randomIndex = Math.floor(Math.random() * allImages.length);
|
||||||
|
const randomImage = allImages[randomIndex];
|
||||||
|
|
||||||
|
if (randomImage) {
|
||||||
|
// Use different approaches for file paths based on environment
|
||||||
|
let imageUrl;
|
||||||
|
if (window.electronAPI) {
|
||||||
|
// In Electron, use the path as-is (Electron handles file protocol internally)
|
||||||
|
imageUrl = randomImage.path;
|
||||||
|
} else {
|
||||||
|
// In browser, use file protocol (though this may not work due to security restrictions)
|
||||||
|
const cleanPath = randomImage.path.replace(/\\/g, '/');
|
||||||
|
imageUrl = `file:///${cleanPath}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.style.backgroundImage = `url('${imageUrl}')`;
|
||||||
|
console.log(`📸 Panel ${index + 1}: Using ${randomImage.name} from ${imageUrl}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error applying library theme:', error);
|
||||||
|
// Fallback to hentai theme on error
|
||||||
|
characterSides.forEach((element, index) => {
|
||||||
|
element.style.display = 'block';
|
||||||
|
const imageNumbers = [1, 11, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
const imageNumber = imageNumbers[index];
|
||||||
|
if (imageNumber) {
|
||||||
|
const imagePath = `assets/hentai/${imageNumber}.png`;
|
||||||
|
element.style.backgroundImage = `url('${imagePath}')`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize theme dropdown functionality
|
// Initialize theme dropdown functionality
|
||||||
function initializeThemeDropdown() {
|
async function initializeThemeDropdown() {
|
||||||
const themeDropdown = document.getElementById('theme-dropdown');
|
const themeDropdown = document.getElementById('theme-dropdown');
|
||||||
if (themeDropdown) {
|
if (themeDropdown) {
|
||||||
// Load saved theme preference
|
// Load saved theme preference
|
||||||
const savedTheme = localStorage.getItem('selectedTheme') || 'hentai';
|
const savedTheme = localStorage.getItem('selectedTheme') || 'hentai';
|
||||||
themeDropdown.value = savedTheme;
|
themeDropdown.value = savedTheme;
|
||||||
applyTheme(savedTheme);
|
|
||||||
|
// Apply the saved theme (refreshes library theme with new random images)
|
||||||
|
await applyTheme(savedTheme);
|
||||||
|
|
||||||
// Handle theme changes
|
// Handle theme changes
|
||||||
themeDropdown.addEventListener('change', (e) => {
|
themeDropdown.addEventListener('change', async (e) => {
|
||||||
applyTheme(e.target.value);
|
await applyTheme(e.target.value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2990,7 +2990,9 @@ class TaskChallengeGame {
|
||||||
document.body.classList.remove(...oldThemeClasses);
|
document.body.classList.remove(...oldThemeClasses);
|
||||||
|
|
||||||
// Load the appropriate theme CSS file
|
// Load the appropriate theme CSS file
|
||||||
if (themeName && themeName !== 'balanced-purple') {
|
// Skip CSS loading for themes that only change background images
|
||||||
|
const imageBGThemes = ['library', 'hentai', 'pornstars', 'BBC', 'feet', 'none'];
|
||||||
|
if (themeName && themeName !== 'balanced-purple' && !imageBGThemes.includes(themeName)) {
|
||||||
const themeLink = document.createElement('link');
|
const themeLink = document.createElement('link');
|
||||||
themeLink.id = 'dynamic-theme';
|
themeLink.id = 'dynamic-theme';
|
||||||
themeLink.rel = 'stylesheet';
|
themeLink.rel = 'stylesheet';
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue