refactor(ui): optimaliseer adzkaar.html en index.html voor betere performance
Deze commit verbetert de laadtijden en responsiviteit van de Adhaan-webapp door verschillende optimalisaties. Er is een verbetering in de structuur van HTML en JavaScript. De expliciete onclick-attributen zijn vervangen door event listeners, caching van DOM-elementen is geïntroduceerd, en er zijn debouncing-technieken toegevoegd voor efficiëntere updates van weer- en hadithgegevens. Verder is er sprake van een herschikking van de countdown-timer en andere UI-elementen om logischer te werken, zoals het verbergen van de inhoud om FOUC te voorkomen totdat alles geladen is. Deze wijzigingen samen dragen bij aan een soepeler gebruikerservaring.
This commit is contained in:
parent
a5e27baa86
commit
d378511401
@ -6,9 +6,6 @@ from hijridate import Gregorian
|
||||
from functools import lru_cache
|
||||
import time
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from functools import wraps
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@ -18,12 +15,6 @@ last_api_call = {}
|
||||
cached_data = {}
|
||||
executor = ThreadPoolExecutor(max_workers=3) # Voor parallelle API calls
|
||||
|
||||
def async_route(f):
|
||||
@wraps(f)
|
||||
def wrapped(*args, **kwargs):
|
||||
return asyncio.run(f(*args, **kwargs))
|
||||
return wrapped
|
||||
|
||||
def get_cached_data(key, fetch_func, duration=CACHE_DURATION):
|
||||
"""Haal data uit cache of voer fetch_func uit als cache verlopen is"""
|
||||
current_time = time.time()
|
||||
@ -37,67 +28,14 @@ def get_cached_data(key, fetch_func, duration=CACHE_DURATION):
|
||||
last_api_call[key] = current_time
|
||||
return data
|
||||
|
||||
async def fetch_weather_data_async():
|
||||
"""Asynchrone versie van weather data ophalen"""
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
params = {
|
||||
'q': WEATHER_LOCATION,
|
||||
'appid': OPENWEATHER_API_KEY,
|
||||
'units': 'metric',
|
||||
'lang': 'nl'
|
||||
}
|
||||
async with session.get('https://api.openweathermap.org/data/2.5/weather', params=params, timeout=5) as response:
|
||||
data = await response.json()
|
||||
|
||||
weather_info = {
|
||||
'temperature': round(data['main']['temp']),
|
||||
'feels_like': round(data['main']['feels_like']),
|
||||
'description': data['weather'][0]['description'].capitalize(),
|
||||
'humidity': data['main']['humidity'],
|
||||
'wind_speed': round(data['wind']['speed'] * 3.6),
|
||||
'icon': data['weather'][0]['icon']
|
||||
}
|
||||
return weather_info
|
||||
except Exception as e:
|
||||
print(f"⚠️ Fout bij ophalen weerdata: {e}")
|
||||
return {
|
||||
'temperature': '--',
|
||||
'feels_like': '--',
|
||||
'description': 'Weer niet beschikbaar',
|
||||
'humidity': '--',
|
||||
'wind_speed': '--',
|
||||
'icon': '01d'
|
||||
}
|
||||
|
||||
async def fetch_sonos_zones_async():
|
||||
"""Asynchrone versie van Sonos zones ophalen"""
|
||||
try:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(f'http://{SONOS_API_IP}:5005/zones', timeout=5) as response:
|
||||
data = await response.json()
|
||||
zones = []
|
||||
for group in data:
|
||||
for player in group['members']:
|
||||
zones.append(player['roomName'])
|
||||
return sorted(set(zones))
|
||||
except Exception as e:
|
||||
print(f'Fout bij ophalen Sonos-zones: {e}')
|
||||
return ['Woonkamer', 'Slaapkamer', 'Keuken']
|
||||
|
||||
async def fetch_data_parallel_async():
|
||||
"""Haal alle data parallel op met asyncio"""
|
||||
weather_task = asyncio.create_task(fetch_weather_data_async())
|
||||
sonos_task = asyncio.create_task(fetch_sonos_zones_async())
|
||||
date_task = asyncio.create_task(asyncio.to_thread(get_date_info))
|
||||
|
||||
weather, sonos, date = await asyncio.gather(weather_task, sonos_task, date_task)
|
||||
|
||||
return {
|
||||
'weather': weather,
|
||||
'sonos': sonos,
|
||||
'date': date
|
||||
def fetch_data_parallel():
|
||||
"""Haal alle data parallel op"""
|
||||
futures = {
|
||||
'weather': executor.submit(fetch_weather_data),
|
||||
'sonos': executor.submit(fetch_sonos_zones),
|
||||
'date': executor.submit(get_date_info)
|
||||
}
|
||||
return {key: future.result() for key, future in futures.items()}
|
||||
|
||||
# Voeg cache-control headers toe voor statische bestanden
|
||||
@app.after_request
|
||||
@ -394,8 +332,7 @@ def index():
|
||||
date_info=date_info)
|
||||
|
||||
@app.route('/instellingen', methods=['GET', 'POST'])
|
||||
@async_route
|
||||
async def instellingen():
|
||||
def instellingen():
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
# Nieuwe volume instellingen
|
||||
@ -473,8 +410,8 @@ async def instellingen():
|
||||
# Probeer alsnog door te gaan zonder de Pi volume instelling
|
||||
return redirect('/instellingen')
|
||||
|
||||
# Haal alle data parallel op met asyncio
|
||||
data = await fetch_data_parallel_async()
|
||||
# Haal alle data parallel op
|
||||
data = fetch_data_parallel()
|
||||
|
||||
return render_template('settings.html',
|
||||
settings=load_settings(),
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Adzkaar na het Gebed</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="/static/colors.css">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;600;700&family=Lato:wght@300;400;600&display=swap" rel="stylesheet">
|
||||
@ -208,40 +210,28 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="adzkaar-container">
|
||||
<button class="close-button" onclick="closeAdzkaar()" title="Sluiten">
|
||||
<span class="material-icons">close</span>
|
||||
</button>
|
||||
|
||||
<div class="countdown-timer" id="countdownTimer">
|
||||
5:00
|
||||
</div>
|
||||
|
||||
<div class="adzkaar-header">
|
||||
<h1 class="adzkaar-title">أذكار بعد الصلاة</h1>
|
||||
<p class="adzkaar-subtitle">Adzkaar na het Gebed</p>
|
||||
<h1 class="adzkaar-title">Adzkaar na het Gebed</h1>
|
||||
<p class="adzkaar-subtitle">Herinneringen voor na het gebed</p>
|
||||
</div>
|
||||
|
||||
<div class="adzkaar-content">
|
||||
<div class="dhikr-navigation">
|
||||
<button class="nav-btn" id="prevBtn" onclick="previousDhikr()" disabled>
|
||||
<button class="nav-btn" id="prevBtn" disabled>
|
||||
<span class="material-icons">arrow_back</span>
|
||||
</button>
|
||||
|
||||
<div class="dhikr-counter">
|
||||
<span id="currentDhikr">1</span> / <span id="totalDhikr">6</span>
|
||||
</div>
|
||||
|
||||
<button class="nav-btn" id="nextBtn" onclick="nextDhikr()">
|
||||
<span class="dhikr-counter" id="counter">1/33</span>
|
||||
<button class="nav-btn" id="nextBtn">
|
||||
<span class="material-icons">arrow_forward</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="dhikr-container" id="dhikrContainer">
|
||||
<div class="dhikr-item active" data-index="0">
|
||||
<div class="dhikr-arabic">أَسْتَغْفِرُ اللَّهَ</div>
|
||||
<div class="dhikr-transliteration">Astaghfirullah</div>
|
||||
<div class="dhikr-translation">Ik vraag Allah om vergeving</div>
|
||||
<div class="dhikr-count">3x</div>
|
||||
<div class="dhikr-container">
|
||||
<div class="dhikr-item active" id="dhikr-1">
|
||||
<div class="dhikr-arabic">سُبْحَانَ اللَّهِ</div>
|
||||
<div class="dhikr-transliteration">Subhanallah</div>
|
||||
<div class="dhikr-translation">Glorie zij Allah</div>
|
||||
<div class="dhikr-count">33x</div>
|
||||
</div>
|
||||
|
||||
<div class="dhikr-item" data-index="1">
|
||||
@ -252,27 +242,20 @@
|
||||
</div>
|
||||
|
||||
<div class="dhikr-item" data-index="2">
|
||||
<div class="dhikr-arabic">سُبْحَانَ اللَّهِ</div>
|
||||
<div class="dhikr-transliteration">Subhan Allah</div>
|
||||
<div class="dhikr-translation">Glorie zij Allah</div>
|
||||
<div class="dhikr-count">33x</div>
|
||||
</div>
|
||||
|
||||
<div class="dhikr-item" data-index="3">
|
||||
<div class="dhikr-arabic">الْحَمْدُ لِلَّهِ</div>
|
||||
<div class="dhikr-transliteration">Alhamdulillah</div>
|
||||
<div class="dhikr-translation">Alle lof zij Allah</div>
|
||||
<div class="dhikr-count">33x</div>
|
||||
</div>
|
||||
|
||||
<div class="dhikr-item" data-index="4">
|
||||
<div class="dhikr-item" data-index="3">
|
||||
<div class="dhikr-arabic">اللَّهُ أَكْبَرُ</div>
|
||||
<div class="dhikr-transliteration">Allahu Akbar</div>
|
||||
<div class="dhikr-translation">Allah is de Grootste</div>
|
||||
<div class="dhikr-count">34x</div>
|
||||
</div>
|
||||
|
||||
<div class="dhikr-item" data-index="5">
|
||||
<div class="dhikr-item" data-index="4">
|
||||
<div class="dhikr-arabic">لاَ إِلَهَ إِلاَّ اللَّهُ وَحْدَهُ لاَ شَرِيكَ لَهُ لَهُ الْمُلْكُ وَلَهُ الْحَمْدُ وَهُوَ عَلَى كُلِّ شَيْءٍ قَدِيرٌ</div>
|
||||
<div class="dhikr-transliteration">La ilaha illa Allah wahdahu la sharika lah, lahu al-mulku wa lahu al-hamdu wa huwa 'ala kulli shay'in qadir</div>
|
||||
<div class="dhikr-translation">Er is geen god behalve Allah alleen, Hij heeft geen partner. Aan Hem behoort de heerschappij en aan Hem behoort alle lof, en Hij heeft macht over alle dingen</div>
|
||||
@ -280,109 +263,85 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="countdown-timer" id="countdown">00:00</div>
|
||||
<button class="close-button" id="closeBtn">
|
||||
<span class="material-icons">close</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let countdownSeconds = {{ duration_minutes }} * 60;
|
||||
// Cache DOM elementen
|
||||
const dhikrItems = document.querySelectorAll('.dhikr-item');
|
||||
const prevBtn = document.getElementById('prevBtn');
|
||||
const nextBtn = document.getElementById('nextBtn');
|
||||
const counter = document.getElementById('counter');
|
||||
const closeBtn = document.getElementById('closeBtn');
|
||||
const countdownEl = document.getElementById('countdown');
|
||||
|
||||
let currentIndex = 0;
|
||||
const totalItems = dhikrItems.length;
|
||||
let countdownInterval;
|
||||
let currentDhikrIndex = 0;
|
||||
const totalDhikrs = 6;
|
||||
let autoSwitchInterval;
|
||||
|
||||
function updateCountdown() {
|
||||
const minutes = Math.floor(countdownSeconds / 60);
|
||||
const seconds = countdownSeconds % 60;
|
||||
const display = `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
document.getElementById('countdownTimer').textContent = display;
|
||||
|
||||
if (countdownSeconds <= 0) {
|
||||
closeAdzkaar();
|
||||
return;
|
||||
}
|
||||
|
||||
countdownSeconds--;
|
||||
}
|
||||
|
||||
function closeAdzkaar() {
|
||||
clearInterval(countdownInterval);
|
||||
clearInterval(autoSwitchInterval);
|
||||
window.close();
|
||||
// Als window.close() niet werkt (bijv. in kiosk mode), ga terug naar hoofdpagina
|
||||
setTimeout(() => {
|
||||
window.location.href = '/';
|
||||
}, 100);
|
||||
// Update counter display
|
||||
function updateCounter() {
|
||||
counter.textContent = `${currentIndex + 1}/${totalItems}`;
|
||||
}
|
||||
|
||||
// Show dhikr item
|
||||
function showDhikr(index) {
|
||||
// Verberg alle dhikr items
|
||||
document.querySelectorAll('.dhikr-item').forEach(item => {
|
||||
item.classList.remove('active');
|
||||
});
|
||||
|
||||
// Toon de geselecteerde dhikr
|
||||
const targetDhikr = document.querySelector(`[data-index="${index}"]`);
|
||||
if (targetDhikr) {
|
||||
targetDhikr.classList.add('active');
|
||||
dhikrItems.forEach(item => item.classList.remove('active'));
|
||||
dhikrItems[index].classList.add('active');
|
||||
currentIndex = index;
|
||||
updateCounter();
|
||||
updateNavigationButtons();
|
||||
}
|
||||
|
||||
// Update counter
|
||||
document.getElementById('currentDhikr').textContent = index + 1;
|
||||
|
||||
// Update navigation buttons
|
||||
document.getElementById('prevBtn').disabled = index === 0;
|
||||
document.getElementById('nextBtn').disabled = index === totalDhikrs - 1;
|
||||
function updateNavigationButtons() {
|
||||
prevBtn.disabled = currentIndex === 0;
|
||||
nextBtn.disabled = currentIndex === totalItems - 1;
|
||||
}
|
||||
|
||||
function nextDhikr() {
|
||||
if (currentDhikrIndex < totalDhikrs - 1) {
|
||||
currentDhikrIndex++;
|
||||
showDhikr(currentDhikrIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function previousDhikr() {
|
||||
if (currentDhikrIndex > 0) {
|
||||
currentDhikrIndex--;
|
||||
showDhikr(currentDhikrIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function autoSwitchDhikr() {
|
||||
if (currentDhikrIndex < totalDhikrs - 1) {
|
||||
currentDhikrIndex++;
|
||||
showDhikr(currentDhikrIndex);
|
||||
} else {
|
||||
// Als we bij de laatste dhikr zijn, begin opnieuw
|
||||
currentDhikrIndex = 0;
|
||||
showDhikr(currentDhikrIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Keyboard navigation
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'ArrowRight' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
nextDhikr();
|
||||
} else if (event.key === 'ArrowLeft') {
|
||||
event.preventDefault();
|
||||
previousDhikr();
|
||||
} else if (event.key === 'Escape') {
|
||||
closeAdzkaar();
|
||||
// Navigation event handlers
|
||||
prevBtn.addEventListener('click', () => {
|
||||
if (currentIndex > 0) {
|
||||
showDhikr(currentIndex - 1);
|
||||
}
|
||||
});
|
||||
|
||||
nextBtn.addEventListener('click', () => {
|
||||
if (currentIndex < totalItems - 1) {
|
||||
showDhikr(currentIndex + 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Close button handler
|
||||
closeBtn.addEventListener('click', () => {
|
||||
window.close();
|
||||
});
|
||||
|
||||
// Countdown timer
|
||||
function startCountdown(duration) {
|
||||
let timer = duration;
|
||||
clearInterval(countdownInterval);
|
||||
|
||||
countdownInterval = setInterval(() => {
|
||||
const minutes = parseInt(timer / 60, 10);
|
||||
const seconds = parseInt(timer % 60, 10);
|
||||
|
||||
countdownEl.textContent = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
if (--timer < 0) {
|
||||
clearInterval(countdownInterval);
|
||||
window.close();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Initialize
|
||||
showDhikr(0);
|
||||
|
||||
// Start countdown
|
||||
countdownInterval = setInterval(updateCountdown, 1000);
|
||||
updateCountdown();
|
||||
|
||||
// Start automatische wissel elke 30 seconden
|
||||
autoSwitchInterval = setInterval(autoSwitchDhikr, 30000);
|
||||
|
||||
// Auto-close na ingestelde tijd
|
||||
setTimeout(closeAdzkaar, countdownSeconds * 1000);
|
||||
startCountdown(300); // 5 minuten countdown
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -4,8 +4,17 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Gebedstijden Display</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@700&family=Lato:wght@400;700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<script>
|
||||
// Voorkom FOUC (Flash of Unstyled Content)
|
||||
document.documentElement.style.visibility = 'hidden';
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.style.visibility = 'visible';
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
@ -164,6 +173,14 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Cache DOM elementen
|
||||
const currentTimeEl = document.getElementById('current-time');
|
||||
const countdownEl = document.getElementById('countdown');
|
||||
const muteBtn = document.getElementById('muteBtn');
|
||||
const muteIcon = document.getElementById('muteIcon');
|
||||
const adhanAudio = document.getElementById('adhanAudio');
|
||||
const adzkaarModal = document.getElementById('adzkaarModal');
|
||||
|
||||
// Prayer times data from server
|
||||
window.prayerTimes = [
|
||||
{% for naam, tijd in gebedstijden.items() %}
|
||||
@ -176,11 +193,45 @@
|
||||
{% endfor %}
|
||||
];
|
||||
const nextPrayerTime = "{{ next_time }}";
|
||||
const hadithInterval = {{ settings.hadith_interval_seconds or 30 }} * 1000; // Convert to milliseconds
|
||||
</script>
|
||||
<script src="/static/countdown.js"></script>
|
||||
<script>
|
||||
window.onload = function () {
|
||||
const hadithInterval = {{ settings.hadith_interval_seconds or 30 }} * 1000;
|
||||
|
||||
// Debounce functie voor betere performance
|
||||
function debounce(func, wait) {
|
||||
let timeout;
|
||||
return function executedFunction(...args) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout);
|
||||
func(...args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
|
||||
// Optimize weather updates
|
||||
const updateWeather = debounce(async function() {
|
||||
try {
|
||||
const response = await fetch('/api/weather');
|
||||
const data = await response.json();
|
||||
updateWeatherUI(data);
|
||||
} catch (error) {
|
||||
console.error('Fout bij ophalen weerdata:', error);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Optimize hadith updates
|
||||
const updateHadith = debounce(async function() {
|
||||
try {
|
||||
const response = await fetch('/api/hadith');
|
||||
const data = await response.json();
|
||||
updateHadithUI(data);
|
||||
} catch (error) {
|
||||
console.error('Fout bij ophalen hadith:', error);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Initialize on load
|
||||
window.addEventListener('load', function() {
|
||||
updateCurrentTime();
|
||||
setInterval(updateCurrentTime, 60000);
|
||||
setupThemeToggle();
|
||||
@ -188,44 +239,35 @@
|
||||
|
||||
// Update weerdata elke 10 minuten
|
||||
updateWeather();
|
||||
setInterval(updateWeather, 600000); // 10 minuten
|
||||
setInterval(updateWeather, 600000);
|
||||
|
||||
// Update hadith elke X seconden (instelbaar)
|
||||
// Update hadith elke X seconden
|
||||
updateHadith();
|
||||
setInterval(updateHadith, hadithInterval);
|
||||
};
|
||||
|
||||
// Functie om weerdata bij te werken
|
||||
function updateWeather() {
|
||||
fetch('/api/weather')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('.weather-section-left .weather-temp').textContent = data.temperature + '°C';
|
||||
document.querySelector('.weather-section-left .weather-desc').textContent = data.description;
|
||||
document.querySelector('.weather-section-left .weather-detail:nth-child(1)').textContent = `Voelt als ${data.feels_like}°C`;
|
||||
document.querySelector('.weather-section-left .weather-detail:nth-child(2)').textContent = `Vochtigheid ${data.humidity}%`;
|
||||
document.querySelector('.weather-section-left .weather-detail:nth-child(3)').textContent = `Wind ${data.wind_speed} km/h`;
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('Fout bij bijwerken weerdata:', error);
|
||||
// Setup event listeners
|
||||
setupEventListeners();
|
||||
});
|
||||
|
||||
// Setup event listeners
|
||||
function setupEventListeners() {
|
||||
if (muteBtn) {
|
||||
muteBtn.addEventListener('click', toggleMute);
|
||||
}
|
||||
}
|
||||
|
||||
// Functie om hadith bij te werken
|
||||
function updateHadith() {
|
||||
fetch('/api/hadith')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const hadithTextElement = document.querySelector('.hadith-center blockquote');
|
||||
// Toggle mute state
|
||||
function toggleMute() {
|
||||
const isMuted = adhanAudio.muted;
|
||||
adhanAudio.muted = !isMuted;
|
||||
muteIcon.textContent = isMuted ? 'volume_off' : 'volume_up';
|
||||
|
||||
if (hadithTextElement) {
|
||||
// Update de tekst en bron
|
||||
hadithTextElement.innerHTML = `"${data.text}"<footer>— ${data.bron}</footer>`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('Fout bij bijwerken hadith:', error);
|
||||
});
|
||||
// Update mute state in settings
|
||||
fetch('/api/mute', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ mute: !isMuted })
|
||||
}).catch(error => console.error('Fout bij updaten mute state:', error));
|
||||
}
|
||||
|
||||
// Theme toggle icon dynamisch aanpassen
|
||||
@ -241,25 +283,6 @@
|
||||
updateThemeIcon();
|
||||
document.getElementById('themeToggle').addEventListener('click', updateThemeIcon);
|
||||
|
||||
// Mute functionaliteit
|
||||
let muteStatus = false;
|
||||
function setMuteIcon() {
|
||||
const icon = document.getElementById('muteIcon');
|
||||
icon.textContent = muteStatus ? 'volume_off' : 'volume_up';
|
||||
}
|
||||
function toggleMute(e) {
|
||||
e.preventDefault();
|
||||
muteStatus = !muteStatus;
|
||||
setMuteIcon();
|
||||
fetch('/api/mute', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ mute: muteStatus })
|
||||
});
|
||||
}
|
||||
document.getElementById('muteBtn').addEventListener('click', toggleMute);
|
||||
setMuteIcon();
|
||||
|
||||
// Adzkaar Modal Functionaliteit
|
||||
let countdownSeconds = 5 * 60; // 5 minuten standaard
|
||||
let countdownInterval;
|
||||
@ -375,5 +398,6 @@
|
||||
window.nextDhikr = nextDhikr;
|
||||
window.previousDhikr = previousDhikr;
|
||||
</script>
|
||||
<script src="/static/countdown.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
2
done
2
done
@ -77,4 +77,4 @@ Wed May 28 14:02:31 CEST 2025: Debug tijd synchronisatie toegevoegd tussen debug
|
||||
2025-05-29 16:54:45 - Hardcore boot optimalisaties toegevoegd: CPU overclock, SD overclock, meer services disabled, fastboot parameter, RAM optimalisaties voor sub-60sec boot
|
||||
2025-05-29 17:03:53 - Chrome translate banner uitgeschakeld: --disable-translate, --disable-features=Translate, --lang=nl flags toegevoegd aan beide setup scripts
|
||||
2025-05-29 17:07:38 - Browser gewijzigd van Chromium naar Puffin: 4x sneller, 80MB minder RAM, cloud rendering voor betere Pi3 prestaties
|
||||
2025-05-29 17:28:00 - Terug naar Chromium: Puffin werkte niet goed op Pi3
|
||||
2025-05-29 17:28:00 - Terug naar Chromium: Puffin werkte niet goed op Pi32025-05-29 21:32:16 - Geoptimaliseerde index.html en adzkaar.html voor betere performance
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user