feat(debug): debug mode tijdsynchronisatie toegevoegd
De commit introduceert een debug tijdsynchronisatie tussen de cron script, de hoofdpagina en de Flask API. Deze functies maken het mogelijk om de huidige tijd te simuleren met een instelbare offset voor testdoeleinden. Het volume en de gebedstijden passen zich nu aan op basis van deze debug tijd indien actief. Debugger gebruikers kunnen via de nieuwe '/api/debug-time' endpoint de tijd aanpassen. De wijzigingen verbeteren de testbaarheid van de applicatie en zorgen ervoor dat gebedsafroepen en volumebepaling correct functioneren onder simulatieomstandigheden.
This commit is contained in:
parent
f3cbd6e910
commit
c212ec4987
@ -4,9 +4,10 @@ import time
|
||||
|
||||
SETTINGS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settings.json')
|
||||
VUMG_API = 'https://www.vumg.nl/?rest_route=/dpt/v1/prayertime&filter=today'
|
||||
SONOS_API_IP = '192.168.0.114' # Pas aan indien nodig
|
||||
SONOS_API_IP = '192.168.0.114' # IP van Raspberry Pi waar Sonos API draait
|
||||
LOG_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'adhan_cron.log')
|
||||
LAST_PLAYED_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'last_played.json')
|
||||
FLASK_API_URL = 'http://localhost:80' # Flask app URL
|
||||
|
||||
def logregel(message):
|
||||
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
@ -15,13 +16,32 @@ def logregel(message):
|
||||
with open(LOG_PATH, 'a') as log:
|
||||
log.write(log_message + '\n')
|
||||
|
||||
def get_current_time():
|
||||
"""Haal de huidige tijd op, gebruik debug tijd als actief"""
|
||||
try:
|
||||
# Probeer debug tijd API
|
||||
response = requests.get(f'{FLASK_API_URL}/api/debug-time', timeout=3)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get('success') and data.get('debug_active'):
|
||||
debug_time = data.get('current_time_display', '')
|
||||
logregel(f"🔧 CRON gebruikt debug tijd: {debug_time}")
|
||||
return debug_time
|
||||
except Exception as e:
|
||||
logregel(f"Debug tijd API niet beschikbaar: {e}")
|
||||
|
||||
# Fallback naar normale tijd
|
||||
normal_time = datetime.now().strftime('%H:%M')
|
||||
return normal_time
|
||||
|
||||
def get_current_volume(settings):
|
||||
"""Bepaal het juiste volume op basis van de huidige tijd"""
|
||||
# Fallback naar oude volume als nieuwe instellingen niet bestaan
|
||||
if 'volume_day' not in settings or 'volume_night' not in settings:
|
||||
return settings.get('volume', 30)
|
||||
|
||||
current_time = datetime.now().strftime('%H:%M')
|
||||
# Gebruik debug tijd als beschikbaar
|
||||
current_time = get_current_time()
|
||||
night_start = settings.get('night_start', '20:00')
|
||||
day_start = settings.get('day_start', '07:00')
|
||||
|
||||
@ -38,11 +58,11 @@ def get_current_volume(settings):
|
||||
|
||||
if is_night:
|
||||
volume = settings.get('volume_night', settings.get('volume', 30) // 2)
|
||||
logregel(f"🌙 Avond volume gebruikt: {volume}")
|
||||
logregel(f"🌙 Avond volume gebruikt: {volume} (tijd: {current_time})")
|
||||
return volume
|
||||
else:
|
||||
volume = settings.get('volume_day', settings.get('volume', 30))
|
||||
logregel(f"☀️ Dag volume gebruikt: {volume}")
|
||||
logregel(f"☀️ Dag volume gebruikt: {volume} (tijd: {current_time})")
|
||||
return volume
|
||||
|
||||
def apply_prayer_offsets(gebedstijden, settings):
|
||||
@ -145,7 +165,8 @@ def play_sonos_clip(zone, audio_clip, volume, prayer_name):
|
||||
logregel(f"❌ FOUT Sonos {zone} {prayer_name}: {e}")
|
||||
return False
|
||||
|
||||
now = datetime.now().strftime('%H:%M')
|
||||
# Gebruik debug tijd als beschikbaar
|
||||
now = get_current_time()
|
||||
logregel(f"CRON gestart, huidige tijd: {now}")
|
||||
|
||||
# Laad settings
|
||||
|
||||
@ -22,7 +22,11 @@ SETTINGS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'settin
|
||||
HADITHS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'hadiths.json')
|
||||
VUMG_API = 'https://www.vumg.nl/?rest_route=/dpt/v1/prayertime&filter=today'
|
||||
CLIPS_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'static', 'clips')
|
||||
SONOS_API_IP = '192.168.0.114' # IP van host waar Sonos API draait
|
||||
SONOS_API_IP = '192.168.0.114' # IP van Raspberry Pi waar Sonos API draait
|
||||
|
||||
# Globale variabelen
|
||||
debug_time_offset = 0 # Offset in seconden voor debug mode
|
||||
debug_mode_active = False
|
||||
|
||||
def fetch_weather_data():
|
||||
"""Haalt weersinformatie op voor de geconfigureerde locatie"""
|
||||
@ -77,13 +81,20 @@ def load_settings():
|
||||
|
||||
def get_current_volume(settings):
|
||||
"""Bepaal het juiste volume op basis van de huidige tijd"""
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Fallback naar oude volume als nieuwe instellingen niet bestaan
|
||||
if 'volume_day' not in settings or 'volume_night' not in settings:
|
||||
return settings.get('volume', 30)
|
||||
|
||||
current_time = datetime.now().strftime('%H:%M')
|
||||
# Gebruik debug tijd als actief
|
||||
global debug_mode_active, debug_time_offset
|
||||
if debug_mode_active:
|
||||
current_time = (datetime.now() + timedelta(seconds=debug_time_offset)).strftime('%H:%M')
|
||||
print(f"🔧 Volume bepaling gebruikt debug tijd: {current_time}")
|
||||
else:
|
||||
current_time = datetime.now().strftime('%H:%M')
|
||||
|
||||
night_start = settings.get('night_start', '20:00')
|
||||
day_start = settings.get('day_start', '07:00')
|
||||
|
||||
@ -99,9 +110,13 @@ def get_current_volume(settings):
|
||||
is_night = current_minutes >= night_minutes and current_minutes < day_minutes
|
||||
|
||||
if is_night:
|
||||
return settings.get('volume_night', settings.get('volume', 30) // 2)
|
||||
volume = settings.get('volume_night', settings.get('volume', 30) // 2)
|
||||
print(f"🌙 Avond volume gebruikt: {volume} (tijd: {current_time})")
|
||||
return volume
|
||||
else:
|
||||
return settings.get('volume_day', settings.get('volume', 30))
|
||||
volume = settings.get('volume_day', settings.get('volume', 30))
|
||||
print(f"☀️ Dag volume gebruikt: {volume} (tijd: {current_time})")
|
||||
return volume
|
||||
|
||||
def apply_prayer_offsets(gebedstijden, settings):
|
||||
"""Pas offsets toe op gebedstijden"""
|
||||
@ -644,5 +659,73 @@ def trigger_adzkaar():
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/debug-time', methods=['GET', 'POST'])
|
||||
def debug_time():
|
||||
"""API endpoint voor debug tijd beheer"""
|
||||
global debug_time_offset, debug_mode_active
|
||||
|
||||
if flask_request.method == 'POST':
|
||||
# Check of debug mode is ingeschakeld voor POST requests
|
||||
settings = load_settings()
|
||||
if not settings.get('debug_mode', False):
|
||||
return jsonify({'success': False, 'error': 'Debug mode is niet ingeschakeld'}), 403
|
||||
|
||||
try:
|
||||
data = flask_request.get_json()
|
||||
action = data.get('action')
|
||||
|
||||
if action == 'set_offset':
|
||||
debug_time_offset = data.get('offset', 0)
|
||||
debug_mode_active = True
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Debug tijd offset ingesteld op {debug_time_offset} seconden',
|
||||
'offset': debug_time_offset,
|
||||
'debug_active': debug_mode_active
|
||||
})
|
||||
|
||||
elif action == 'reset':
|
||||
debug_time_offset = 0
|
||||
debug_mode_active = False
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': 'Debug tijd gereset naar echte tijd',
|
||||
'offset': debug_time_offset,
|
||||
'debug_active': debug_mode_active
|
||||
})
|
||||
|
||||
elif action == 'adjust':
|
||||
adjustment = data.get('seconds', 0)
|
||||
debug_time_offset += adjustment
|
||||
debug_mode_active = True
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'message': f'Debug tijd aangepast met {adjustment} seconden',
|
||||
'offset': debug_time_offset,
|
||||
'debug_active': debug_mode_active
|
||||
})
|
||||
|
||||
else:
|
||||
return jsonify({'success': False, 'error': 'Onbekende actie'}), 400
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
else: # GET request - altijd beschikbaar voor cron script
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
current_time = datetime.now()
|
||||
if debug_mode_active:
|
||||
current_time += timedelta(seconds=debug_time_offset)
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'current_time': current_time.strftime('%H:%M:%S'),
|
||||
'current_time_display': current_time.strftime('%H:%M'),
|
||||
'offset': debug_time_offset,
|
||||
'debug_active': debug_mode_active,
|
||||
'real_time': datetime.now().strftime('%H:%M:%S')
|
||||
})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=80)
|
||||
@ -12,3 +12,4 @@ Mon May 26 18:17:57 CEST 2025: Tijdzone probleem opgelost - Container gebruikt n
|
||||
2025-05-28 03:37:57 - Light theme kleuren gerepareerd: teksten nu zichtbaar in light mode, accent kleuren aangepast voor betere contrast
|
||||
2025-05-28 03:49:24 - Adzkaar fullscreen functionaliteit geïmplementeerd: nieuwe /adzkaar route, instellingen, debug knoppen, automatische trigger na gebedstijden, Nederlandse/Arabische dhikr content
|
||||
2025-05-28 03:55:38 - Adzkaar scherm verbeterd naar kaart-voor-kaart weergave met navigatie knoppen en toetsenbord besturing
|
||||
Wed May 28 14:09:12 CEST 2025: Sonos debug tijd synchronisatie geïmplementeerd - get_current_volume functie en cron script gebruiken nu debug tijd API, volume bepaling werkt correct in debug mode
|
||||
|
||||
@ -1,10 +1,31 @@
|
||||
function updateCurrentTime() {
|
||||
const now = new Date();
|
||||
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById("current-time").textContent = timeStr;
|
||||
// Check eerst of debug mode actief is
|
||||
fetch('/api/debug-time')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.debug_active) {
|
||||
// Gebruik debug tijd
|
||||
document.getElementById("current-time").textContent = data.current_time_display;
|
||||
console.log(`🔧 Debug tijd actief: ${data.current_time_display} (offset: ${data.offset}s)`);
|
||||
} else {
|
||||
// Gebruik normale tijd
|
||||
const now = new Date();
|
||||
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById("current-time").textContent = timeStr;
|
||||
}
|
||||
|
||||
// Update datum informatie elke minuut
|
||||
updateDateInfo();
|
||||
// Update datum informatie elke minuut
|
||||
updateDateInfo();
|
||||
})
|
||||
.catch(error => {
|
||||
// Fallback naar normale tijd bij fout
|
||||
const now = new Date();
|
||||
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById("current-time").textContent = timeStr;
|
||||
|
||||
// Update datum informatie elke minuut
|
||||
updateDateInfo();
|
||||
});
|
||||
}
|
||||
|
||||
function updateDateInfo() {
|
||||
@ -33,28 +54,69 @@ let isNextDayPrayer = false;
|
||||
function startCountdowns(times, names) {
|
||||
prayerTimes = times;
|
||||
prayerNames = names;
|
||||
const nextPrayer = getNextPrayer();
|
||||
currentPrayerIndex = nextPrayer.index;
|
||||
isNextDayPrayer = nextPrayer.isNextDay;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
|
||||
getNextPrayer().then(nextPrayer => {
|
||||
currentPrayerIndex = nextPrayer.index;
|
||||
isNextDayPrayer = nextPrayer.isNextDay;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
}).catch(error => {
|
||||
console.log('Fout bij bepalen volgende gebed:', error);
|
||||
// Fallback
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = false;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
});
|
||||
}
|
||||
|
||||
function getNextPrayer() {
|
||||
const now = new Date();
|
||||
const currentTime = now.getHours() * 60 + now.getMinutes(); // Huidige tijd in minuten
|
||||
// Gebruik debug tijd als actief
|
||||
return fetch('/api/debug-time')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
let currentTime;
|
||||
|
||||
// Zoek naar volgende gebed vandaag
|
||||
for (let i = 0; i < prayerTimes.length; i++) {
|
||||
const [h, m] = prayerTimes[i].split(":");
|
||||
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
|
||||
if (data.success && data.debug_active) {
|
||||
// Gebruik debug tijd
|
||||
const debugTime = data.current_time_display;
|
||||
const [h, m] = debugTime.split(":");
|
||||
currentTime = parseInt(h) * 60 + parseInt(m);
|
||||
console.log(`🔧 Debug tijd gebruikt voor countdown: ${debugTime}`);
|
||||
} else {
|
||||
// Gebruik normale tijd
|
||||
const now = new Date();
|
||||
currentTime = now.getHours() * 60 + now.getMinutes();
|
||||
}
|
||||
|
||||
if (prayerTimeMinutes > currentTime) {
|
||||
return { index: i, isNextDay: false };
|
||||
}
|
||||
}
|
||||
// Zoek naar volgende gebed vandaag
|
||||
for (let i = 0; i < prayerTimes.length; i++) {
|
||||
const [h, m] = prayerTimes[i].split(":");
|
||||
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
|
||||
|
||||
// Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen
|
||||
return { index: 0, isNextDay: true };
|
||||
if (prayerTimeMinutes > currentTime) {
|
||||
return { index: i, isNextDay: false };
|
||||
}
|
||||
}
|
||||
|
||||
// Alle gebeden van vandaag zijn voorbij, volgende is eerste gebed van morgen
|
||||
return { index: 0, isNextDay: true };
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('Fout bij ophalen debug tijd, gebruik normale tijd:', error);
|
||||
// Fallback naar normale tijd
|
||||
const now = new Date();
|
||||
const currentTime = now.getHours() * 60 + now.getMinutes();
|
||||
|
||||
for (let i = 0; i < prayerTimes.length; i++) {
|
||||
const [h, m] = prayerTimes[i].split(":");
|
||||
const prayerTimeMinutes = parseInt(h) * 60 + parseInt(m);
|
||||
|
||||
if (prayerTimeMinutes > currentTime) {
|
||||
return { index: i, isNextDay: false };
|
||||
}
|
||||
}
|
||||
|
||||
return { index: 0, isNextDay: true };
|
||||
});
|
||||
}
|
||||
|
||||
function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
|
||||
@ -74,55 +136,119 @@ function startCountdown(targetTimeStr, prayerName, isNextDay = false) {
|
||||
document.querySelector('.huidig-gebed-bottom .naam').textContent = displayName;
|
||||
|
||||
function update() {
|
||||
const now = new Date();
|
||||
let diff = Math.floor((target - now) / 1000);
|
||||
// Gebruik debug tijd als actief
|
||||
fetch('/api/debug-time')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
let now;
|
||||
|
||||
if (diff <= 0) {
|
||||
// Speel adhaan af via browser
|
||||
const audio = document.getElementById('adhanAudio');
|
||||
if (audio) audio.play();
|
||||
|
||||
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
|
||||
setTimeout(() => {
|
||||
triggerAdzkaarScreen(displayName);
|
||||
}, 3000);
|
||||
|
||||
// Ga naar volgende gebed
|
||||
if (isNextDayPrayer) {
|
||||
// We waren aan het wachten op het eerste gebed van de nieuwe dag
|
||||
// Nu gaan we naar het tweede gebed van vandaag (nieuwe dag)
|
||||
currentPrayerIndex = 1;
|
||||
isNextDayPrayer = false;
|
||||
|
||||
if (currentPrayerIndex < prayerTimes.length) {
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
|
||||
if (data.success && data.debug_active) {
|
||||
// Gebruik debug tijd
|
||||
const debugTime = data.current_time;
|
||||
const [h, m, s] = debugTime.split(":");
|
||||
now = new Date();
|
||||
now.setHours(parseInt(h), parseInt(m), parseInt(s), 0);
|
||||
} else {
|
||||
// Dit zou niet moeten gebeuren, maar veiligheidshalve
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
|
||||
}
|
||||
} else {
|
||||
// Normaal doorgang naar volgende gebed
|
||||
currentPrayerIndex++;
|
||||
|
||||
if (currentPrayerIndex >= prayerTimes.length) {
|
||||
// Alle gebeden van vandaag zijn klaar, ga naar eerste gebed van morgen
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
// Gebruik normale tijd
|
||||
now = new Date();
|
||||
}
|
||||
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let diff = Math.floor((target - now) / 1000);
|
||||
|
||||
// Toon countdown
|
||||
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
|
||||
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
|
||||
const s = String(diff % 60).padStart(2, '0');
|
||||
if (diff <= 0) {
|
||||
// Speel adhaan af via browser
|
||||
const audio = document.getElementById('adhanAudio');
|
||||
if (audio) audio.play();
|
||||
|
||||
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
|
||||
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
|
||||
setTimeout(() => {
|
||||
triggerAdzkaarScreen(displayName);
|
||||
}, 3000);
|
||||
|
||||
// Ga naar volgende gebed
|
||||
if (isNextDayPrayer) {
|
||||
// We waren aan het wachten op het eerste gebed van de nieuwe dag
|
||||
// Nu gaan we naar het tweede gebed van vandaag (nieuwe dag)
|
||||
currentPrayerIndex = 1;
|
||||
isNextDayPrayer = false;
|
||||
|
||||
if (currentPrayerIndex < prayerTimes.length) {
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
|
||||
} else {
|
||||
// Dit zou niet moeten gebeuren, maar veiligheidshalve
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
|
||||
}
|
||||
} else {
|
||||
// Normaal doorgang naar volgende gebed
|
||||
currentPrayerIndex++;
|
||||
|
||||
if (currentPrayerIndex >= prayerTimes.length) {
|
||||
// Alle gebeden van vandaag zijn klaar, ga naar eerste gebed van morgen
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
}
|
||||
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Toon countdown
|
||||
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
|
||||
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
|
||||
const s = String(diff % 60).padStart(2, '0');
|
||||
|
||||
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
|
||||
})
|
||||
.catch(error => {
|
||||
// Fallback naar normale tijd
|
||||
const now = new Date();
|
||||
let diff = Math.floor((target - now) / 1000);
|
||||
|
||||
if (diff <= 0) {
|
||||
// Speel adhaan af via browser
|
||||
const audio = document.getElementById('adhanAudio');
|
||||
if (audio) audio.play();
|
||||
|
||||
// Trigger Adzkaar scherm na 3 seconden (geef adhaan tijd om te starten)
|
||||
setTimeout(() => {
|
||||
triggerAdzkaarScreen(displayName);
|
||||
}, 3000);
|
||||
|
||||
// Ga naar volgende gebed
|
||||
if (isNextDayPrayer) {
|
||||
currentPrayerIndex = 1;
|
||||
isNextDayPrayer = false;
|
||||
|
||||
if (currentPrayerIndex < prayerTimes.length) {
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], false);
|
||||
} else {
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], true);
|
||||
}
|
||||
} else {
|
||||
currentPrayerIndex++;
|
||||
|
||||
if (currentPrayerIndex >= prayerTimes.length) {
|
||||
currentPrayerIndex = 0;
|
||||
isNextDayPrayer = true;
|
||||
}
|
||||
|
||||
startCountdown(prayerTimes[currentPrayerIndex], prayerNames[currentPrayerIndex], isNextDayPrayer);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Toon countdown
|
||||
const h = String(Math.floor(diff / 3600)).padStart(2, '0');
|
||||
const m = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
|
||||
const s = String(diff % 60).padStart(2, '0');
|
||||
|
||||
document.getElementById("countdown").textContent = `${h}:${m}:${s}`;
|
||||
});
|
||||
}
|
||||
|
||||
update();
|
||||
@ -159,18 +285,13 @@ function triggerAdzkaarScreen(prayerName) {
|
||||
if (data.success) {
|
||||
console.log(`📿 Adzkaar scherm wordt getoond na ${prayerName}`);
|
||||
|
||||
// Open Adzkaar scherm in fullscreen
|
||||
// In kiosk mode proberen we een nieuw venster te openen
|
||||
const adzkaarWindow = window.open(
|
||||
data.url,
|
||||
'adzkaar',
|
||||
'fullscreen=yes,scrollbars=no,resizable=no,toolbar=no,menubar=no,status=no'
|
||||
);
|
||||
|
||||
// Als window.open niet werkt (bijv. popup blocker), navigeer naar de pagina
|
||||
if (!adzkaarWindow) {
|
||||
console.log('📿 Popup geblokkeerd, navigeren naar Adzkaar pagina...');
|
||||
window.location.href = data.url;
|
||||
// Toon Adzkaar modal in plaats van nieuwe pagina
|
||||
if (window.showAdzkaarModal) {
|
||||
// Gebruik de duur uit de API response of standaard 5 minuten
|
||||
const durationMinutes = data.duration_minutes || 5;
|
||||
window.showAdzkaarModal(durationMinutes);
|
||||
} else {
|
||||
console.log('📿 Adzkaar modal functie niet beschikbaar');
|
||||
}
|
||||
} else {
|
||||
console.log(`📿 Adzkaar niet getoond: ${data.error}`);
|
||||
|
||||
@ -1400,3 +1400,211 @@ html.dark .hadith-center {
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adzkaar Modal Styles */
|
||||
.adzkaar-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 10000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.adzkaar-container {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: var(--primary-gradient);
|
||||
color: var(--white);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.adzkaar-header {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.adzkaar-title {
|
||||
font-family: 'Cairo', sans-serif;
|
||||
font-size: 3.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1rem;
|
||||
text-shadow: var(--text-shadow);
|
||||
}
|
||||
|
||||
.adzkaar-subtitle {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 1.5rem;
|
||||
opacity: 0.9;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.adzkaar-content {
|
||||
max-width: 900px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dhikr-container {
|
||||
position: relative;
|
||||
min-height: 400px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dhikr-item {
|
||||
display: none;
|
||||
background: var(--white-10);
|
||||
border-radius: 15px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid var(--white-20);
|
||||
transition: all 0.3s ease;
|
||||
max-width: 800px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.dhikr-item.active {
|
||||
display: block;
|
||||
background: var(--white-15);
|
||||
border: 1px solid var(--white-30);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
.dhikr-arabic {
|
||||
font-family: 'Cairo', sans-serif;
|
||||
font-size: 2.2rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
direction: rtl;
|
||||
line-height: 1.6;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.dhikr-transliteration {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 1.3rem;
|
||||
font-style: italic;
|
||||
margin-bottom: 1rem;
|
||||
opacity: 0.8;
|
||||
color: var(--text-muted-dark);
|
||||
}
|
||||
|
||||
.dhikr-translation {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 1.2rem;
|
||||
color: var(--text-muted-dark);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.dhikr-count {
|
||||
display: inline-block;
|
||||
background: var(--white-20);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 20px;
|
||||
font-size: 0.9rem;
|
||||
margin-top: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.countdown-timer {
|
||||
position: fixed;
|
||||
top: 2rem;
|
||||
right: 2rem;
|
||||
background: var(--black-50);
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 10px;
|
||||
font-family: 'Cairo', sans-serif;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.close-button {
|
||||
position: fixed;
|
||||
top: 2rem;
|
||||
left: 2rem;
|
||||
background: var(--white-20);
|
||||
border: none;
|
||||
color: var(--white);
|
||||
padding: 0.8rem;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
font-size: 1.5rem;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.close-button:hover {
|
||||
background: var(--white-30);
|
||||
}
|
||||
|
||||
.dhikr-navigation {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.nav-btn {
|
||||
background: var(--white-20);
|
||||
border: none;
|
||||
color: var(--white);
|
||||
font-size: 2rem;
|
||||
cursor: pointer;
|
||||
margin: 0 2rem;
|
||||
padding: 1rem;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-btn:hover:not(:disabled) {
|
||||
background: var(--white-30);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.nav-btn:disabled {
|
||||
opacity: 0.3;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.dhikr-counter {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 600;
|
||||
background: var(--black-30);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.adzkaar-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.dhikr-arabic {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.dhikr-transliteration {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.dhikr-translation {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.dhikr-item {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,17 +302,29 @@
|
||||
}
|
||||
|
||||
function updateDebugDisplay() {
|
||||
const debugTime = getDebugTime();
|
||||
const timeStr = debugTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById('currentDebugTime').textContent = timeStr;
|
||||
fetch('/api/debug-time')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
document.getElementById('currentDebugTime').textContent = data.current_time_display;
|
||||
|
||||
// Update status
|
||||
const statusElement = document.getElementById('debugStatus');
|
||||
statusElement.textContent = isDebugMode ? 'Debug Mode Actief' : 'Normaal';
|
||||
statusElement.style.color = isDebugMode ? '#ff6b6b' : '#00ff00';
|
||||
// Update status
|
||||
const statusElement = document.getElementById('debugStatus');
|
||||
statusElement.textContent = data.debug_active ? 'Debug Mode Actief' : 'Normaal';
|
||||
statusElement.style.color = data.debug_active ? '#ff6b6b' : '#00ff00';
|
||||
|
||||
// Check voor gebedstijd
|
||||
checkPrayerTime(timeStr);
|
||||
// Check voor gebedstijd
|
||||
checkPrayerTime(data.current_time_display);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log('Fout bij ophalen debug tijd:', error);
|
||||
// Fallback naar normale tijd
|
||||
const now = new Date();
|
||||
const timeStr = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById('currentDebugTime').textContent = timeStr;
|
||||
document.getElementById('debugStatus').textContent = 'Normaal';
|
||||
});
|
||||
}
|
||||
|
||||
function checkPrayerTime(currentTime) {
|
||||
@ -384,20 +396,41 @@
|
||||
const targetTime = new Date();
|
||||
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
|
||||
|
||||
debugTimeOffset = Math.floor((targetTime - now) / 1000);
|
||||
isDebugMode = true;
|
||||
const offsetSeconds = Math.floor((targetTime - now) / 1000);
|
||||
|
||||
log(`⏰ Tijd handmatig ingesteld op ${timeInput.value}`);
|
||||
updateDebugDisplay();
|
||||
fetch('/api/debug-time', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'set_offset', offset: offsetSeconds })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
log(`⏰ ${data.message}`);
|
||||
updateDebugDisplay();
|
||||
} else {
|
||||
log(`❌ Fout: ${data.error}`);
|
||||
}
|
||||
})
|
||||
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
|
||||
}
|
||||
|
||||
function adjustTime(seconds) {
|
||||
debugTimeOffset += seconds;
|
||||
isDebugMode = true;
|
||||
|
||||
const sign = seconds > 0 ? '+' : '';
|
||||
log(`⏰ Tijd aangepast: ${sign}${seconds} seconden`);
|
||||
updateDebugDisplay();
|
||||
fetch('/api/debug-time', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'adjust', seconds: seconds })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
log(`⏰ ${data.message}`);
|
||||
updateDebugDisplay();
|
||||
} else {
|
||||
log(`❌ Fout: ${data.error}`);
|
||||
}
|
||||
})
|
||||
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
|
||||
}
|
||||
|
||||
function setTimeToPrayer(prayerTime, offsetMinutes) {
|
||||
@ -407,12 +440,24 @@
|
||||
targetTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
|
||||
targetTime.setTime(targetTime.getTime() + (offsetMinutes * 60 * 1000));
|
||||
|
||||
debugTimeOffset = Math.floor((targetTime - now) / 1000);
|
||||
isDebugMode = true;
|
||||
const offsetSeconds = Math.floor((targetTime - now) / 1000);
|
||||
|
||||
const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
|
||||
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
|
||||
updateDebugDisplay();
|
||||
fetch('/api/debug-time', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'set_offset', offset: offsetSeconds })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
const offsetText = offsetMinutes === 0 ? 'exact' : `${offsetMinutes} min ervoor`;
|
||||
log(`🕌 Tijd ingesteld op ${prayerTime} (${offsetText})`);
|
||||
updateDebugDisplay();
|
||||
} else {
|
||||
log(`❌ Fout: ${data.error}`);
|
||||
}
|
||||
})
|
||||
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
|
||||
}
|
||||
|
||||
function setTimeToNextPrayer(offsetMinutes) {
|
||||
@ -433,10 +478,21 @@
|
||||
}
|
||||
|
||||
function resetTime() {
|
||||
debugTimeOffset = 0;
|
||||
isDebugMode = false;
|
||||
log(`🔄 Tijd gereset naar echte tijd`);
|
||||
updateDebugDisplay();
|
||||
fetch('/api/debug-time', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ action: 'reset' })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
log(`🔄 ${data.message}`);
|
||||
updateDebugDisplay();
|
||||
} else {
|
||||
log(`❌ Fout: ${data.error}`);
|
||||
}
|
||||
})
|
||||
.catch(error => log(`❌ Netwerk fout: ${error.message}`));
|
||||
}
|
||||
|
||||
function checkSonosStatus() {
|
||||
|
||||
@ -85,6 +85,84 @@
|
||||
|
||||
<audio id="adhanAudio" src="/static/clips/{{ settings['audio_clip'] }}" preload="auto"></audio>
|
||||
|
||||
<!-- Adzkaar Modal -->
|
||||
<div id="adzkaarModal" class="adzkaar-modal" style="display: none;">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div class="adzkaar-content">
|
||||
<div class="dhikr-navigation">
|
||||
<button class="nav-btn" id="prevBtn" onclick="previousDhikr()" 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="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>
|
||||
|
||||
<div class="dhikr-item" data-index="1">
|
||||
<div class="dhikr-arabic">اللَّهُمَّ أَنْتَ السَّلاَمُ وَمِنْكَ السَّلاَمُ تَبَارَكْتَ يَا ذَا الْجَلاَلِ وَالإِكْرَامِ</div>
|
||||
<div class="dhikr-transliteration">Allahumma anta as-salamu wa minka as-salamu, tabarakta ya dhal-jalali wal-ikram</div>
|
||||
<div class="dhikr-translation">O Allah, U bent de Vrede en van U komt de vrede. Gezegend bent U, O Bezitter van Majesteit en Eer</div>
|
||||
<div class="dhikr-count">1x</div>
|
||||
</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-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-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>
|
||||
<div class="dhikr-count">1x</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Prayer times data from server
|
||||
window.prayerTimes = [
|
||||
@ -181,6 +259,121 @@
|
||||
}
|
||||
document.getElementById('muteBtn').addEventListener('click', toggleMute);
|
||||
setMuteIcon();
|
||||
|
||||
// Adzkaar Modal Functionaliteit
|
||||
let countdownSeconds = 5 * 60; // 5 minuten standaard
|
||||
let countdownInterval;
|
||||
let currentDhikrIndex = 0;
|
||||
const totalDhikrs = 6;
|
||||
let autoSwitchInterval;
|
||||
|
||||
function showAdzkaarModal(durationMinutes = 5) {
|
||||
countdownSeconds = durationMinutes * 60;
|
||||
currentDhikrIndex = 0;
|
||||
|
||||
// Toon modal
|
||||
document.getElementById('adzkaarModal').style.display = 'flex';
|
||||
|
||||
// Reset dhikr display
|
||||
showDhikr(0);
|
||||
|
||||
// Start countdown
|
||||
countdownInterval = setInterval(updateAdzkaarCountdown, 1000);
|
||||
updateAdzkaarCountdown();
|
||||
|
||||
// Start automatische wissel elke 30 seconden
|
||||
autoSwitchInterval = setInterval(autoSwitchDhikr, 30000);
|
||||
|
||||
// Auto-close na ingestelde tijd
|
||||
setTimeout(closeAdzkaar, countdownSeconds * 1000);
|
||||
}
|
||||
|
||||
function updateAdzkaarCountdown() {
|
||||
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);
|
||||
document.getElementById('adzkaarModal').style.display = 'none';
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
// 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 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 voor modal
|
||||
document.addEventListener('keydown', function(event) {
|
||||
const modal = document.getElementById('adzkaarModal');
|
||||
if (modal.style.display === 'flex') {
|
||||
if (event.key === 'ArrowRight' || event.key === ' ') {
|
||||
event.preventDefault();
|
||||
nextDhikr();
|
||||
} else if (event.key === 'ArrowLeft') {
|
||||
event.preventDefault();
|
||||
previousDhikr();
|
||||
} else if (event.key === 'Escape') {
|
||||
closeAdzkaar();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Maak functies globaal beschikbaar
|
||||
window.showAdzkaarModal = showAdzkaarModal;
|
||||
window.closeAdzkaar = closeAdzkaar;
|
||||
window.nextDhikr = nextDhikr;
|
||||
window.previousDhikr = previousDhikr;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
3
done
3
done
@ -62,3 +62,6 @@ Wed May 28 08:02:50 CEST 2025: Countdown gerepareerd - JavaScript aangepast om h
|
||||
Wed May 28 08:35:42 CEST 2025: Hadith auto-update gerepareerd - JavaScript selector aangepast van .hadith-section naar .hadith-center voor nieuwe layout
|
||||
Wed May 28 08:37:45 CEST 2025: Hadith interval instelbaar gemaakt - nieuwe setting hadith_interval_seconds toegevoegd aan settings.json, settings.html en app.py, JavaScript gebruikt nu variabele interval
|
||||
Wed May 28 08:39:34 CEST 2025: Settings pagina georganiseerd in tabbladen - 4 tabs: Audio & Volume, Gebedstijden, Functies, Systeem. Inclusief CSS styling en JavaScript functionaliteit met localStorage voor actieve tab
|
||||
Wed May 28 13:43:52 CEST 2025: Bevestigd dat Adzkaar scherm wordt geopend in nieuwe pagina bij gebedstijd
|
||||
Wed May 28 13:46:26 CEST 2025: Adzkaar aangepast van nieuwe pagina naar fullscreen modal in hoofdpagina
|
||||
Wed May 28 14:02:31 CEST 2025: Debug tijd synchronisatie toegevoegd tussen debug pagina en hoofdpagina
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user