Initial TafsirQuran app with Gitea CI/CD deploy to k3s.
build-and-deploy / deploy (push) Successful in 10m50s

Blazor UI + ASP.NET API + Postgres; push to main builds images and rolls out namespace tafsirquran.
This commit is contained in:
2026-10-09 21:50:37 +03:30
commit 7f06856f45
124 changed files with 4729 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
window.tqStorage = {
get: (key) => localStorage.getItem(key),
set: (key, value) => localStorage.setItem(key, value),
remove: (key) => localStorage.removeItem(key)
};
window.tqAudio = {
_handlers: new WeakMap(),
bind: (audio, dotnet) => {
if (!audio) return;
const onTime = () => dotnet.invokeMethodAsync('OnTime', audio.currentTime || 0, audio.duration || 0, !audio.paused);
const onPause = () => dotnet.invokeMethodAsync('OnPaused', audio.currentTime || 0);
const onEnded = () => dotnet.invokeMethodAsync('OnPaused', audio.currentTime || 0);
audio.addEventListener('timeupdate', onTime);
audio.addEventListener('pause', onPause);
audio.addEventListener('ended', onEnded);
audio.addEventListener('loadedmetadata', onTime);
window.tqAudio._handlers.set(audio, { onTime, onPause, onEnded, dotnet });
window.addEventListener('pagehide', () => {
if (!audio.paused) {
dotnet.invokeMethodAsync('OnPaused', audio.currentTime || 0);
}
});
},
unbind: (audio) => {
const h = window.tqAudio._handlers.get(audio);
if (!h || !audio) return;
audio.removeEventListener('timeupdate', h.onTime);
audio.removeEventListener('pause', h.onPause);
audio.removeEventListener('ended', h.onEnded);
window.tqAudio._handlers.delete(audio);
},
load: async (audio, src, position) => {
if (!audio) return;
audio.src = src;
audio.load();
const seek = () => {
if (position && !Number.isNaN(position)) {
try { audio.currentTime = position; } catch (_) { /* ignore */ }
}
};
audio.addEventListener('loadedmetadata', seek, { once: true });
},
toggle: async (audio) => {
if (!audio) return false;
if (audio.paused) {
await audio.play();
return true;
}
audio.pause();
return false;
},
seek: (audio, value) => {
if (!audio) return;
audio.currentTime = Number(value) || 0;
}
};