Zakkir — مواقيت الصلاة وأذكار
+1
-1
| { | ||
| "manifest_version": 3, | ||
| "name": "Zakkir", | ||
| "version": "1.3.8", | ||
| "version": "1.4.0", | ||
| "description": "Prayer times + Azkar (Hisn al-Muslim) in your toolbar.", | ||
@@ -6,0 +6,0 @@ "permissions": [ |
+140
-0
@@ -932,1 +932,141 @@ /* ===== MINIMAL THEMES (no gradients) ===== */ | ||
| .loc-adv[open] summary { color: var(--ink); } | ||
| /* ===== Monthly schedule ===== */ | ||
| .sched-head { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: space-between; | ||
| gap: 8px; | ||
| margin: 4px 0 10px; | ||
| } | ||
| .sched-title { text-align: center; flex: 1; } | ||
| .sched-month { font-weight: 700; color: var(--ink); font-size: 15px; } | ||
| .sched-hijri { font-size: 11px; color: var(--muted); margin-top: 2px; } | ||
| .sched-mode { | ||
| display: flex; | ||
| gap: 4px; | ||
| padding: 3px; | ||
| margin: 6px 0 8px; | ||
| background: color-mix(in oklab, var(--ink) 6%, transparent); | ||
| border-radius: 8px; | ||
| } | ||
| .sched-mode-btn { | ||
| flex: 1; | ||
| padding: 6px 8px; | ||
| font-size: 11px; | ||
| font-weight: 600; | ||
| border: 0; | ||
| background: transparent; | ||
| color: var(--muted); | ||
| border-radius: 6px; | ||
| cursor: pointer; | ||
| } | ||
| .sched-mode-btn.active { | ||
| background: var(--card, var(--bg)); | ||
| color: var(--ink); | ||
| box-shadow: 0 1px 2px rgba(0,0,0,0.08); | ||
| } | ||
| .sched-table td.d.h-primary b { color: var(--ink); } | ||
| .sched-table-wrap { | ||
| border: 1px solid var(--line); | ||
| border-radius: 10px; | ||
| overflow: hidden; | ||
| background: var(--surface); | ||
| } | ||
| .sched-table { | ||
| width: 100%; | ||
| border-collapse: collapse; | ||
| font-size: 11.5px; | ||
| } | ||
| .sched-table thead th { | ||
| position: sticky; | ||
| top: 0; | ||
| background: var(--surface-2); | ||
| color: var(--muted); | ||
| font-weight: 600; | ||
| text-align: left; | ||
| padding: 6px 6px; | ||
| border-bottom: 1px solid var(--line); | ||
| font-size: 10.5px; | ||
| text-transform: uppercase; | ||
| letter-spacing: 0.04em; | ||
| } | ||
| .sched-table tbody td { | ||
| padding: 5px 6px; | ||
| border-bottom: 1px solid var(--line); | ||
| color: var(--ink); | ||
| white-space: nowrap; | ||
| } | ||
| .sched-table tbody tr:last-child td { border-bottom: 0; } | ||
| .sched-table td.d { color: var(--muted); } | ||
| .sched-table td.d b { color: var(--ink); margin-right: 4px; } | ||
| .sched-table td.d .wd { font-size: 10px; opacity: 0.75; } | ||
| .sched-table tr.today td { background: color-mix(in oklab, var(--accent) 12%, transparent); } | ||
| .sched-table tr.today td.d b { color: var(--accent); } | ||
| .sched-table td.h { | ||
| color: var(--muted); | ||
| font-size: 10.5px; | ||
| white-space: nowrap; | ||
| } | ||
| .sched-table td.h b { color: var(--ink); margin-right: 3px; font-weight: 600; } | ||
| .sched-table td.h .hy { opacity: 0.7; margin-left: 3px; font-size: 9.5px; } | ||
| .sched-table tr.hijri-rollover td { border-top: 1px solid color-mix(in oklab, var(--accent) 55%, transparent); } | ||
| .sched-table tr.hijri-rollover td.h { color: var(--accent); } | ||
| .sched-table tr.hijri-event td.h { color: var(--accent); } | ||
| .sched-table tr.hijri-event td { background: color-mix(in oklab, var(--accent) 5%, transparent); } | ||
| .sched-event { | ||
| display: inline-block; | ||
| margin-left: 4px; | ||
| color: var(--accent); | ||
| font-size: 10px; | ||
| cursor: help; | ||
| } | ||
| /* Sunnah fasting (Mon/Thu) — distinct green tint, separate from accent */ | ||
| .sched-table tr.sunnah-fast td { | ||
| background: color-mix(in oklab, #16a34a 10%, transparent); | ||
| } | ||
| .sched-table tr.sunnah-fast td:first-child { | ||
| box-shadow: inset 3px 0 0 color-mix(in oklab, #16a34a 70%, transparent); | ||
| } | ||
| .sched-table tr.sunnah-fast.today td { | ||
| background: color-mix(in oklab, #16a34a 14%, color-mix(in oklab, var(--accent) 10%, transparent)); | ||
| } | ||
| .sched-fast { | ||
| display: inline-block; | ||
| margin-left: 5px; | ||
| padding: 1px 5px; | ||
| border-radius: 6px; | ||
| background: color-mix(in oklab, #16a34a 22%, transparent); | ||
| color: #16a34a; | ||
| font-size: 9px; | ||
| font-weight: 600; | ||
| letter-spacing: 0.3px; | ||
| vertical-align: middle; | ||
| cursor: help; | ||
| } | ||
| .sched-msg { | ||
| padding: 14px; | ||
| text-align: center; | ||
| color: var(--muted); | ||
| font-size: 12px; | ||
| } | ||
| .sched-msg.subtle { padding: 6px; font-size: 10.5px; } | ||
| .sched-foot { | ||
| display: flex; | ||
| justify-content: space-between; | ||
| align-items: center; | ||
| gap: 8px; | ||
| margin-top: 10px; | ||
| font-size: 11px; | ||
| color: var(--muted); | ||
| } | ||
| .sched-csv { | ||
| background: transparent; | ||
| border: 1px solid var(--line); | ||
| color: var(--ink); | ||
| border-radius: 8px; | ||
| padding: 5px 10px; | ||
| font-size: 11px; | ||
| cursor: pointer; | ||
| } | ||
| .sched-csv:hover { border-color: var(--accent); color: var(--accent); } |
+329
-2
@@ -12,3 +12,3 @@ // Azkar Extension — Prayer Times + Azkar (Hisn al-Muslim) | ||
| popupH: 580, | ||
| theme: "dark", | ||
| theme: "rosepine-d", | ||
| palette: "default", | ||
@@ -45,2 +45,8 @@ city: "Cairo", | ||
| prayerCache: null, | ||
| // Monthly schedule view | ||
| scheduleMonth: null, // "YYYY-MM"; null = current month | ||
| scheduleDateMode: "g", // "g" = Gregorian column, "h" = Hijri column | ||
| scheduleCache: {}, | ||
| // Highlight Mondays & Thursdays (Sunnah fasting days) | ||
| sunnahFastHighlight: true, | ||
| }; | ||
@@ -416,2 +422,3 @@ | ||
| unpin: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3l18 18"/><path d="M12 17v5"/><path d="M9 10.76V6a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v4.76l2 3.24H7l2-3.24Z"/></svg>`, | ||
| cal: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M16 3v4M8 3v4M3 10h18"/></svg>`, | ||
| }; | ||
@@ -430,2 +437,3 @@ | ||
| <button class="icon-btn" id="pinBtn" title="${IS_PINNED ? "Close pinned window" : "Pin (keep open)"}">${IS_PINNED ? icon.unpin : icon.pin}</button> | ||
| <button class="icon-btn" data-go="schedule" title="Monthly schedule">${icon.cal}</button> | ||
| <button class="icon-btn" data-go="settings" title="Settings">${icon.gear}</button> | ||
@@ -719,2 +727,296 @@ </div>`; | ||
| // ---------- Monthly schedule ---------- | ||
| const MONTH_NAMES = ["January","February","March","April","May","June","July","August","September","October","November","December"]; | ||
| // Aladhan calendar endpoint returns times like "04:23 (EET)" — strip suffix. | ||
| function cleanTime(s) { | ||
| if (!s) return "00:00"; | ||
| const m = String(s).match(/^(\d{1,2}):(\d{2})/); | ||
| return m ? `${m[1].padStart(2, "0")}:${m[2]}` : s; | ||
| } | ||
| function currentScheduleYM() { | ||
| if (state.scheduleMonth && /^\d{4}-\d{2}$/.test(state.scheduleMonth)) return state.scheduleMonth; | ||
| const d = new Date(); | ||
| return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; | ||
| } | ||
| function stepScheduleMonth(delta) { | ||
| const [y, m] = currentScheduleYM().split("-").map(Number); | ||
| const d = new Date(y, m - 1 + delta, 1); | ||
| return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}`; | ||
| } | ||
| function scheduleCacheKey(state, ym) { | ||
| const useCoords = state.useCoords && state.lat != null && state.lng != null; | ||
| return useCoords | ||
| ? `v3|coords|${state.lat}|${state.lng}|${state.method}|${ym}` | ||
| : `v3|city|${state.city}|${state.country}|${state.method}|${ym}`; | ||
| } | ||
| // Notable Hijri days — keyed as "hMonthNumber|hDayNumber" | ||
| const HIJRI_EVENTS = { | ||
| "1|1": "Islamic New Year", | ||
| "1|10": "Day of Ashura", | ||
| "3|12": "Mawlid an-Nabi", | ||
| "7|27": "Isra & Mi'raj", | ||
| "8|15": "Mid-Sha'ban", | ||
| "9|1": "1st of Ramadan", | ||
| "9|27": "Laylat al-Qadr (likely)", | ||
| "10|1": "Eid al-Fitr", | ||
| "12|9": "Day of Arafah", | ||
| "12|10": "Eid al-Adha", | ||
| }; | ||
| function hijriEventName(hMonthNum, hDay) { | ||
| return HIJRI_EVENTS[`${Number(hMonthNum)}|${Number(hDay)}`] || ""; | ||
| } | ||
| let _scheduleData = null; // { ym, key, days: [{g, h, timings}], loading, error } | ||
| let _scheduleLoadingKey = null; | ||
| async function fetchMonth(ym) { | ||
| const key = scheduleCacheKey(state, ym); | ||
| const cached = state.scheduleCache?.[key]; | ||
| const fresh = cached && (Date.now() - (cached.fetchedAt || 0) < 24 * 3600 * 1000); | ||
| if (cached) { | ||
| _scheduleData = { ym, key, days: cached.days, error: null, loading: !fresh }; | ||
| } else { | ||
| _scheduleData = { ym, key, days: null, error: null, loading: true }; | ||
| } | ||
| // Always reflect the new _scheduleData in the DOM on the next tick, so | ||
| // a cache hit (fresh or stale) doesn't leave a stale "Loading…" body | ||
| // when fetchMonth is called after the initial render. | ||
| if (state.view === "schedule") { | ||
| Promise.resolve().then(() => { if (state.view === "schedule") patchSchedule(); }); | ||
| } | ||
| if (fresh) return; | ||
| if (_scheduleLoadingKey === key) return; | ||
| _scheduleLoadingKey = key; | ||
| try { | ||
| const [y, m] = ym.split("-").map(Number); | ||
| const useCoords = state.useCoords && state.lat != null && state.lng != null; | ||
| const url = useCoords | ||
| ? `https://api.aladhan.com/v1/calendar/${y}/${m}?latitude=${state.lat}&longitude=${state.lng}&method=${state.method}` | ||
| : `https://api.aladhan.com/v1/calendarByCity/${y}/${m}?city=${encodeURIComponent(state.city)}&country=${encodeURIComponent(state.country)}&method=${state.method}`; | ||
| const r = await fetch(url); | ||
| const j = await r.json(); | ||
| if (!Array.isArray(j?.data)) throw new Error("bad response"); | ||
| const days = j.data.map((d) => { | ||
| const hj = d.date?.hijri; | ||
| return { | ||
| g: d.date?.gregorian?.day || "", | ||
| weekday: d.date?.gregorian?.weekday?.en || "", | ||
| h: hj ? `${hj.day} ${hj.month.en}` : "", | ||
| hDay: hj?.day || "", | ||
| hMonth: hj?.month?.en || "", | ||
| hMonthAr: hj?.month?.ar || "", | ||
| hMonthNum: hj?.month?.number || null, | ||
| hYear: hj?.year || "", | ||
| timings: { | ||
| Fajr: cleanTime(d.timings.Fajr), | ||
| Dhuhr: cleanTime(d.timings.Dhuhr), | ||
| Asr: cleanTime(d.timings.Asr), | ||
| Maghrib: cleanTime(d.timings.Maghrib), | ||
| Isha: cleanTime(d.timings.Isha), | ||
| }, | ||
| }; | ||
| }); | ||
| const entry = { days, fetchedAt: Date.now() }; | ||
| state.scheduleCache = { ...(state.scheduleCache || {}), [key]: entry }; | ||
| storage.set({ scheduleCache: state.scheduleCache }); | ||
| _scheduleData = { ym, key, days, error: null, loading: false }; | ||
| } catch (e) { | ||
| if (_scheduleData) _scheduleData.error = "Failed to load schedule — check your connection."; | ||
| if (_scheduleData) _scheduleData.loading = false; | ||
| if (!_scheduleData?.days) _scheduleData = { ym, key, days: null, error: "Failed to load schedule.", loading: false }; | ||
| } finally { | ||
| _scheduleLoadingKey = null; | ||
| if (state.view === "schedule") patchSchedule(); | ||
| } | ||
| } | ||
| function scheduleHeaderHTML() { | ||
| const ym = currentScheduleYM(); | ||
| const [y, m] = ym.split("-").map(Number); | ||
| const monthName = MONTH_NAMES[m - 1]; | ||
| // Hijri label: derive a range from first/last day so month transitions are visible. | ||
| let hijriLabel = ""; | ||
| const days = _scheduleData?.days || []; | ||
| if (days.length) { | ||
| const first = days[0]; | ||
| const last = days[days.length - 1]; | ||
| if (first?.hMonth && last?.hMonth) { | ||
| if (first.hMonth === last.hMonth && first.hYear === last.hYear) { | ||
| hijriLabel = `${first.hMonth} ${first.hYear} AH`; | ||
| } else { | ||
| const yA = first.hYear, yB = last.hYear; | ||
| hijriLabel = yA === yB | ||
| ? `${first.hMonth} → ${last.hMonth} ${yB} AH` | ||
| : `${first.hMonth} ${yA} → ${last.hMonth} ${yB} AH`; | ||
| } | ||
| } | ||
| } | ||
| const mode = state.scheduleDateMode === "h" ? "h" : "g"; | ||
| return ` | ||
| <div class="sched-head"> | ||
| <button class="icon-btn" id="schedPrev" title="Previous month">${icon.prev}</button> | ||
| <div class="sched-title"> | ||
| <div class="sched-month">${monthName} ${y}</div> | ||
| ${hijriLabel ? `<div class="sched-hijri">${hijriLabel}</div>` : ""} | ||
| </div> | ||
| <button class="icon-btn" id="schedNext" title="Next month">${icon.next}</button> | ||
| </div> | ||
| <div class="sched-mode" role="tablist"> | ||
| <button class="sched-mode-btn ${mode === "g" ? "active" : ""}" data-mode="g" role="tab">Gregorian</button> | ||
| <button class="sched-mode-btn ${mode === "h" ? "active" : ""}" data-mode="h" role="tab">Hijri</button> | ||
| </div>`; | ||
| } | ||
| function scheduleBodyHTML() { | ||
| if (_scheduleData?.error && !_scheduleData?.days) { | ||
| return `<div class="sched-msg">${_scheduleData.error} <button class="loc-btn" id="schedRetry">Retry</button></div>`; | ||
| } | ||
| if (!_scheduleData?.days) { | ||
| return `<div class="sched-msg">Loading schedule…</div>`; | ||
| } | ||
| const mode = state.scheduleDateMode === "h" ? "h" : "g"; | ||
| const ym = currentScheduleYM(); | ||
| const today = new Date(); | ||
| const todayYM = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, "0")}`; | ||
| const todayDay = today.getDate(); | ||
| const isCurrentMonth = ym === todayYM; | ||
| let prevHMonth = null; | ||
| const rows = _scheduleData.days.map((d) => { | ||
| const isToday = isCurrentMonth && parseInt(d.g, 10) === todayDay; | ||
| const rollover = prevHMonth !== null && d.hMonth && d.hMonth !== prevHMonth; | ||
| prevHMonth = d.hMonth || prevHMonth; | ||
| const evt = hijriEventName(d.hMonthNum, d.hDay); | ||
| const wd = (d.weekday || "").toLowerCase(); | ||
| const isSunnahFast = state.sunnahFastHighlight && (wd === "monday" || wd === "thursday"); | ||
| const fastTitle = wd === "monday" ? "Sunnah fast — Monday" : "Sunnah fast — Thursday"; | ||
| const classes = [ | ||
| isToday ? "today" : "", | ||
| rollover ? "hijri-rollover" : "", | ||
| evt ? "hijri-event" : "", | ||
| isSunnahFast ? "sunnah-fast" : "", | ||
| ].filter(Boolean).join(" "); | ||
| const evtBadge = evt ? `<span class="sched-event" title="${evt}">★</span>` : ""; | ||
| const fastBadge = isSunnahFast ? `<span class="sched-fast" title="${fastTitle}">صوم</span>` : ""; | ||
| let dateCell; | ||
| if (mode === "h") { | ||
| const hijriMain = d.hDay | ||
| ? (rollover | ||
| ? `<b>${d.hDay}</b><span class="wd">${d.hMonth} ${d.hYear}</span>` | ||
| : `<b>${d.hDay}</b><span class="wd">${(d.hMonth || "").slice(0, 8)}</span>`) | ||
| : ""; | ||
| dateCell = `<td class="d h-primary">${hijriMain}${evtBadge}${fastBadge}</td>`; | ||
| } else { | ||
| dateCell = `<td class="d"><b>${d.g}</b><span class="wd">${(d.weekday || "").slice(0, 3)}</span>${evtBadge}${fastBadge}</td>`; | ||
| } | ||
| return `<tr class="${classes}"> | ||
| ${dateCell} | ||
| <td>${fmt12(d.timings.Fajr)}</td> | ||
| <td>${fmt12(d.timings.Dhuhr)}</td> | ||
| <td>${fmt12(d.timings.Asr)}</td> | ||
| <td>${fmt12(d.timings.Maghrib)}</td> | ||
| <td>${fmt12(d.timings.Isha)}</td> | ||
| </tr>`; | ||
| }).join(""); | ||
| const dateHeader = mode === "h" ? "Hijri" : "Date"; | ||
| return ` | ||
| <div class="sched-table-wrap"> | ||
| <table class="sched-table"> | ||
| <thead><tr><th>${dateHeader}</th><th>Fajr</th><th>Dhuhr</th><th>Asr</th><th>Maghrib</th><th>Isha</th></tr></thead> | ||
| <tbody>${rows}</tbody> | ||
| </table> | ||
| </div> | ||
| ${_scheduleData.loading ? `<div class="sched-msg subtle">Updating…</div>` : ""}`; | ||
| } | ||
| function scheduleFooterHTML() { | ||
| const useCoords = state.useCoords && state.lat != null && state.lng != null; | ||
| const where = useCoords | ||
| ? (state.locationName || `${Number(state.lat).toFixed(2)}, ${Number(state.lng).toFixed(2)}`) | ||
| : `${state.city}, ${state.country}`; | ||
| const methodName = (METHODS.find(([v]) => v === state.method) || [, `Method ${state.method}`])[1]; | ||
| return ` | ||
| <div class="sched-foot"> | ||
| <span>${where} · ${methodName}</span> | ||
| <button class="sched-csv" id="schedCsv" title="Download CSV">Export CSV</button> | ||
| </div>`; | ||
| } | ||
| function renderSchedule() { | ||
| return ` | ||
| <div class="app"> | ||
| <div class="settings-head"> | ||
| <button class="icon-btn" data-go="home">${icon.back}</button> | ||
| <h1>Schedule</h1> | ||
| <span style="width:30px"></span> | ||
| </div> | ||
| <div id="schedHead">${scheduleHeaderHTML()}</div> | ||
| <div id="schedBody">${scheduleBodyHTML()}</div> | ||
| <div id="schedFoot">${scheduleFooterHTML()}</div> | ||
| </div> | ||
| `; | ||
| } | ||
| function patchSchedule() { | ||
| const head = $("#schedHead"); if (head) setHTML(head, scheduleHeaderHTML()); | ||
| const body = $("#schedBody"); if (body) setHTML(body, scheduleBodyHTML()); | ||
| const foot = $("#schedFoot"); if (foot) setHTML(foot, scheduleFooterHTML()); | ||
| wireSchedule(); | ||
| } | ||
| function downloadScheduleCsv() { | ||
| if (!_scheduleData?.days) return; | ||
| const ym = currentScheduleYM(); | ||
| const header = ["Gregorian", "Weekday", "Hijri", "Hijri Month", "Hijri Year", "Event", "Fajr", "Dhuhr", "Asr", "Maghrib", "Isha"]; | ||
| const rows = _scheduleData.days.map((d) => [ | ||
| `${ym}-${String(d.g).padStart(2, "0")}`, | ||
| d.weekday || "", | ||
| d.hDay || "", | ||
| d.hMonth || "", | ||
| d.hYear || "", | ||
| hijriEventName(d.hMonthNum, d.hDay), | ||
| d.timings.Fajr, d.timings.Dhuhr, d.timings.Asr, d.timings.Maghrib, d.timings.Isha, | ||
| ]); | ||
| const csv = [header, ...rows].map((r) => r.map((c) => `"${String(c).replace(/"/g, '""')}"`).join(",")).join("\n"); | ||
| const blob = new Blob([csv], { type: "text/csv" }); | ||
| const url = URL.createObjectURL(blob); | ||
| const a = document.createElement("a"); | ||
| a.href = url; a.download = `zakkir-schedule-${ym}.csv`; | ||
| document.body.appendChild(a); a.click(); a.remove(); | ||
| setTimeout(() => URL.revokeObjectURL(url), 1000); | ||
| } | ||
| function wireSchedule() { | ||
| const prev = $("#schedPrev"); | ||
| if (prev) prev.addEventListener("click", () => { | ||
| state.scheduleMonth = stepScheduleMonth(-1); | ||
| storage.set({ scheduleMonth: state.scheduleMonth }); | ||
| fetchMonth(state.scheduleMonth); | ||
| patchSchedule(); | ||
| }); | ||
| const next = $("#schedNext"); | ||
| if (next) next.addEventListener("click", () => { | ||
| state.scheduleMonth = stepScheduleMonth(1); | ||
| storage.set({ scheduleMonth: state.scheduleMonth }); | ||
| fetchMonth(state.scheduleMonth); | ||
| patchSchedule(); | ||
| }); | ||
| const retry = $("#schedRetry"); | ||
| if (retry) retry.addEventListener("click", () => { fetchMonth(currentScheduleYM()); patchSchedule(); }); | ||
| const csv = $("#schedCsv"); | ||
| if (csv) csv.addEventListener("click", downloadScheduleCsv); | ||
| document.querySelectorAll(".sched-mode-btn").forEach((btn) => { | ||
| btn.addEventListener("click", () => { | ||
| const mode = btn.getAttribute("data-mode") === "h" ? "h" : "g"; | ||
| if (state.scheduleDateMode === mode) return; | ||
| state.scheduleDateMode = mode; | ||
| storage.set({ scheduleDateMode: mode }); | ||
| patchSchedule(); | ||
| }); | ||
| }); | ||
| } | ||
| function renderSettings() { | ||
@@ -782,3 +1084,11 @@ return ` | ||
| <div class="sec">Schedule</div> | ||
| <div class="row"> | ||
| <label>Highlight Mon/Thu (Sunnah fasting)</label> | ||
| <label class="switch"><input type="checkbox" id="sunnahFastHighlight" ${state.sunnahFastHighlight ? "checked" : ""}/><span></span></label> | ||
| </div> | ||
| <div class="sec">Arabic Font</div> | ||
@@ -877,3 +1187,6 @@ <div class="font-grid"> | ||
| const app = $("#app"); | ||
| setHTML(app, state.view === "settings" ? renderSettings() : renderHome()); | ||
| const html = state.view === "settings" ? renderSettings() | ||
| : state.view === "schedule" ? renderSchedule() | ||
| : renderHome(); | ||
| setHTML(app, html); | ||
| wire(); | ||
@@ -966,2 +1279,11 @@ } | ||
| if (state.view === "schedule") { | ||
| const ym = currentScheduleYM(); | ||
| if (!_scheduleData || _scheduleData.ym !== ym) { | ||
| fetchMonth(ym); | ||
| } | ||
| wireSchedule(); | ||
| } | ||
| // Home interactions | ||
@@ -1220,2 +1542,7 @@ const tap = $("#azkarTap"); | ||
| }); | ||
| const sf = $("#sunnahFastHighlight"); | ||
| if (sf) sf.addEventListener("change", (e) => { | ||
| state.sunnahFastHighlight = e.target.checked; | ||
| storage.set({ sunnahFastHighlight: state.sunnahFastHighlight }); | ||
| }); | ||
| } | ||
@@ -1222,0 +1549,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet