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">
|
||||
<option value="hentai" selected>🎭 Hentai</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>
|
||||
</select>
|
||||
</div>
|
||||
|
|
@ -1307,24 +1310,69 @@
|
|||
<script src="src/core/game.js"></script>
|
||||
<script>
|
||||
// Theme switching functionality
|
||||
function applyTheme(theme) {
|
||||
async function applyTheme(theme) {
|
||||
console.log('Applying theme:', theme);
|
||||
const characterSides = document.querySelectorAll('.character-side');
|
||||
|
||||
characterSides.forEach((element, index) => {
|
||||
if (theme === 'none') {
|
||||
if (theme === 'none') {
|
||||
characterSides.forEach(element => {
|
||||
element.style.display = 'none';
|
||||
} else {
|
||||
element.style.display = 'block';
|
||||
|
||||
// Map element positions to image numbers
|
||||
});
|
||||
localStorage.setItem('selectedTheme', theme);
|
||||
return;
|
||||
}
|
||||
|
||||
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 imageNumber = imageNumbers[index];
|
||||
|
||||
if (imageNumber) {
|
||||
const imagePath = `assets/${theme}/${imageNumber}.png`;
|
||||
element.style.backgroundImage = `url('${imagePath}')`;
|
||||
}
|
||||
imageNames = imageNumbers.map(num => `${num}.png`);
|
||||
} else if (theme === 'BBC') {
|
||||
// BBC directory image names
|
||||
imageNames = [
|
||||
'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);
|
||||
}
|
||||
|
||||
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
|
||||
function initializeThemeDropdown() {
|
||||
async function initializeThemeDropdown() {
|
||||
const themeDropdown = document.getElementById('theme-dropdown');
|
||||
if (themeDropdown) {
|
||||
// Load saved theme preference
|
||||
const savedTheme = localStorage.getItem('selectedTheme') || 'hentai';
|
||||
themeDropdown.value = savedTheme;
|
||||
applyTheme(savedTheme);
|
||||
|
||||
// Apply the saved theme (refreshes library theme with new random images)
|
||||
await applyTheme(savedTheme);
|
||||
|
||||
// Handle theme changes
|
||||
themeDropdown.addEventListener('change', (e) => {
|
||||
applyTheme(e.target.value);
|
||||
themeDropdown.addEventListener('change', async (e) => {
|
||||
await applyTheme(e.target.value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2990,7 +2990,9 @@ class TaskChallengeGame {
|
|||
document.body.classList.remove(...oldThemeClasses);
|
||||
|
||||
// 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');
|
||||
themeLink.id = 'dynamic-theme';
|
||||
themeLink.rel = 'stylesheet';
|
||||
|
|
|
|||
Loading…
Reference in New Issue