jaynesmax commited on
Commit
2c965a0
·
verified ·
1 Parent(s): ce74250

Upload 2 files

Browse files
Files changed (2) hide show
  1. config.js +3 -0
  2. index.html +21 -6
config.js CHANGED
@@ -28,6 +28,9 @@ window.JM_CONFIG = Object.freeze({
28
  // Web Push (VAPID) — funguo YA UMMA tu. Private key iwe Supabase secrets pekee.
29
  VAPID_PUBLIC_KEY: 'BCgKqA0rqp_xKw90XP0kGwNuTm5nPA1BAOaqiDM3be-lDoeBW7hKRhnEi7sJ8VcCQ5TdJ-6rZ0WVGBGKV7bwfFw',
30
 
 
 
 
31
  // Matangazo (Adsterra). Zima yote kwa kubadilisha kuwa false — hakuna haja ya kugusa index.html.
32
  ADS_ENABLED: true,
33
  });
 
28
  // Web Push (VAPID) — funguo YA UMMA tu. Private key iwe Supabase secrets pekee.
29
  VAPID_PUBLIC_KEY: 'BCgKqA0rqp_xKw90XP0kGwNuTm5nPA1BAOaqiDM3be-lDoeBW7hKRhnEi7sJ8VcCQ5TdJ-6rZ0WVGBGKV7bwfFw',
30
 
31
+ // Onyesha idadi ya walio online juu ya app (false = ficha). Takwimu zinabaki kwenye admin-online.html
32
+ SHOW_ONLINE: true,
33
+
34
  // Matangazo (Adsterra). Zima yote kwa kubadilisha kuwa false — hakuna haja ya kugusa index.html.
35
  ADS_ENABLED: true,
36
  });
index.html CHANGED
@@ -58,6 +58,10 @@
58
  .brand{font-weight:800; font-size:17px;}
59
  .brand span{color:var(--accent);}
60
  .top-icons{display:flex; gap:16px; align-items:center;}
 
 
 
 
61
  .icon-btn{width:22px;height:22px; display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:0.9;}
62
  .search-box{display:none; align-items:center; gap:8px; background:var(--card); border:1px solid var(--border);
63
  border-radius:999px; padding:6px 12px; flex:1; margin-right:10px;}
@@ -1275,6 +1279,7 @@
1275
  <input id="searchInput" placeholder="Tafuta filamu, series...">
1276
  </div>
1277
  <div class="top-icons">
 
1278
  <div class="icon-btn" id="dlTopBtn" data-nav="downloads" title="Downloads" data-i18n-title="tip_downloads" style="position:relative"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v11"/><path d="M7.5 10.5 12 15l4.5-4.5"/><path d="M3 19h18"/></svg><span class="nav-badge" id="dqNavBadge" style="display:none">0</span></div>
1279
  <div class="icon-btn" id="notifBellBtn" title="Notifications" data-i18n-title="tip_notifications" style="position:relative">
1280
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
@@ -11263,16 +11268,26 @@ Router.sync(); // inafungua tab/ukurasa sahihi kulingana na URL (#/live, #/mat
11263
  if (!dev) { dev = (crypto.randomUUID && crypto.randomUUID()) || (Date.now() + '-' + Math.random().toString(36).slice(2)); localStorage.setItem('jm_dev', dev); }
11264
  } catch (_) { return; }
11265
  const platform = ((window.matchMedia && matchMedia('(display-mode: standalone)').matches) || navigator.standalone === true) ? 'pwa' : 'web';
 
 
 
 
 
 
 
 
 
 
11266
  const ping = () => {
11267
- if (document.hidden) return;
11268
- fetch(C.PROFILE_URL + '/rest/v1/rpc/jm_heartbeat', {
11269
- method: 'POST', keepalive: true,
11270
- headers: { apikey: C.PROFILE_KEY, Authorization: 'Bearer ' + C.PROFILE_KEY, 'Content-Type': 'application/json' },
11271
  body: JSON.stringify({ p_dev: dev, p_platform: platform })
11272
  }).catch(() => {});
11273
  };
11274
- ping(); setInterval(ping, 60000);
11275
- document.addEventListener('visibilitychange', () => { if (!document.hidden) ping(); });
 
11276
  } catch (_) {}
11277
  })();
11278
  </script>
 
58
  .brand{font-weight:800; font-size:17px;}
59
  .brand span{color:var(--accent);}
60
  .top-icons{display:flex; gap:16px; align-items:center;}
61
+ .online-pill{display:none; align-items:center; gap:5px; font-size:11px; font-weight:700; padding:4px 9px; border-radius:999px; background:rgba(255,255,255,.08); color:var(--text); white-space:nowrap;}
62
+ .online-pill.on{display:inline-flex;}
63
+ .online-pill i{width:7px; height:7px; border-radius:50%; background:#2ee59d; animation:jmOnlinePulse 1.6s infinite;}
64
+ @keyframes jmOnlinePulse{50%{opacity:.3}}
65
  .icon-btn{width:22px;height:22px; display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:0.9;}
66
  .search-box{display:none; align-items:center; gap:8px; background:var(--card); border:1px solid var(--border);
67
  border-radius:999px; padding:6px 12px; flex:1; margin-right:10px;}
 
1279
  <input id="searchInput" placeholder="Tafuta filamu, series...">
1280
  </div>
1281
  <div class="top-icons">
1282
+ <div class="online-pill" id="onlinePill" title="Online sasa"><i></i><span id="onlineNum">0</span></div>
1283
  <div class="icon-btn" id="dlTopBtn" data-nav="downloads" title="Downloads" data-i18n-title="tip_downloads" style="position:relative"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3v11"/><path d="M7.5 10.5 12 15l4.5-4.5"/><path d="M3 19h18"/></svg><span class="nav-badge" id="dqNavBadge" style="display:none">0</span></div>
1284
  <div class="icon-btn" id="notifBellBtn" title="Notifications" data-i18n-title="tip_notifications" style="position:relative">
1285
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg>
 
11268
  if (!dev) { dev = (crypto.randomUUID && crypto.randomUUID()) || (Date.now() + '-' + Math.random().toString(36).slice(2)); localStorage.setItem('jm_dev', dev); }
11269
  } catch (_) { return; }
11270
  const platform = ((window.matchMedia && matchMedia('(display-mode: standalone)').matches) || navigator.standalone === true) ? 'pwa' : 'web';
11271
+ const H = { apikey: C.PROFILE_KEY, Authorization: 'Bearer ' + C.PROFILE_KEY, 'Content-Type': 'application/json' };
11272
+ const pill = document.getElementById('onlinePill'), num = document.getElementById('onlineNum');
11273
+ const fmt = n => n >= 1000 ? (n / 1000).toFixed(n >= 10000 ? 0 : 1).replace('.0', '') + 'k' : String(n);
11274
+ const loadOnline = () => {
11275
+ if (C.SHOW_ONLINE === false || !pill || document.hidden) return Promise.resolve();
11276
+ return fetch(C.PROFILE_URL + '/rest/v1/rpc/jm_online_stats', { method: 'POST', headers: H, body: '{}' })
11277
+ .then(r => r.ok ? r.json() : null)
11278
+ .then(d => { if (d && typeof d.online_now === 'number' && d.online_now > 0) { num.textContent = fmt(d.online_now); pill.classList.add('on'); } })
11279
+ .catch(() => {});
11280
+ };
11281
  const ping = () => {
11282
+ if (document.hidden) return Promise.resolve();
11283
+ return fetch(C.PROFILE_URL + '/rest/v1/rpc/jm_heartbeat', {
11284
+ method: 'POST', keepalive: true, headers: H,
 
11285
  body: JSON.stringify({ p_dev: dev, p_platform: platform })
11286
  }).catch(() => {});
11287
  };
11288
+ const tick = () => ping().then(loadOnline);
11289
+ tick(); setInterval(tick, 60000);
11290
+ document.addEventListener('visibilitychange', () => { if (!document.hidden) tick(); });
11291
  } catch (_) {}
11292
  })();
11293
  </script>