Basit Anlatım (Herkes İçin)
Şu anda ne sorun var?
- Ana şube "Kaç şarkıda bir anons çalsın?" ayarını değiştiriyor (örn: 10 → 15 şarkı)
- Ana şube anons sistemini tamamen kapatıyor (spot_enabled = false)
- Şubeler ve ana şube player'ları eski ayarı kullanmaya devam ediyor
- Değişiklik için sayfa yenileme (F5) gerekiyor
- 10 şube var? 10 yerde F5 basmak gerekiyor!
Ne yapacağız?
- Ana şube ayarı değiştirdiğinde → Tüm şubeler otomatik algılayacak
- Sayfa yenileme yok! Arka planda sessizce güncellenir
- 3 dinamik ayar: Çalma Aralığı, Aktif/Pasif, Global Kapatma
- 30 saniyede bir kontrol eder (hafif, server'ı yormaz)
Örnek Senaryo 1:
Ana şube "10 şarkıda bir" ayarını "15 şarkıda bir" yapar. 30 saniye içinde tüm şubeler yeni ayarı alır. Kimsenin sayfa yenilemesine gerek kalmaz!
Örnek Senaryo 2:
Ana şube "Anons Sistemi"ni kapatır (spot_enabled → false). 30 saniye içinde tüm şubelerdeki player'lar otomatik durur. Şube kendisi açamaz, sadece ana şube kontrol eder!
Üç Seviyeli Kontrol Sistemi
Seviye 1: Ana Şube Global Kontrol (spot_enabled)
Tüm sistemi kapatma/açma yetkisi
- ✅
spot_enabled = true→ Sistem açık, şubeler çalabilir - ❌
spot_enabled = false→ Sistem kapalı, hiçbir şube çalamaz! - 🔒 Sadece ana şube değiştirebilir
Seviye 2: Şube Lokal Kontrol (spot_is_paused)
Her şube kendi player'ını durdurabilir
- ✅
spot_is_paused = false→ Bu şubede çalar (ana şube açıksa) - ⏸️
spot_is_paused = true→ Bu şubede durur (geçici) - 🔓 Her şube kendi durumunu değiştirebilir
- ⚠️ Ana şube kapatırsa → Şube açamaz!
Seviye 3: Çalma Aralığı (spot_songs_between)
Kaç şarkıda bir anons çalacak?
- 🎵
spot_songs_between = 10→ Her 10 şarkıda bir - 📊 Ana şube değiştirir, tüm şubeler uyar
- 🔄 Değişince sayaç sıfırlanır
Öncelik Mantığı:
if (!spot_enabled) {
// ❌ Ana şube kapattı → HİÇBİR ŞUBE ÇALAMAZ!
return SPOT_DISABLED;
}
if (spot_is_paused) {
// ⏸️ Bu şube kendi durdurdu → Bu şubede çalmaz
return SPOT_PAUSED;
}
// ✅ Her şey OK → Normal çalış
playSpotsEvery(spot_songs_between);
Teknik Detaylar (Geliştiriciler İçin)
Mevcut Sistem (Sorunlu)
Player Init (spot-player.js:50-68)
async function init() {
loadCounter(); // localStorage'dan sayaç yükle
await fetchSettings(); // API'den ayarları ÇEK (1 kez!)
}
async function fetchSettings() {
const data = await fetch('/api/spot/settings').json();
state.songsBetween = data.songs_between || 10; // ← Bir kez ayarlanıyor!
state.enabled = data.enabled; // ← Bir kez!
state.isPaused = data.spot_is_paused; // ← Bir kez!
// ❌ SORUN: Ayarlar değişse bile player tekrar kontrol etmiyor
}
Sorun: Player init sırasında ayarları 1 kez alıyor, bir daha kontrol etmiyor!
Yeni Sistem (Çözüm)
1. Database: Settings Version Ekle
Dosya: Modules/Muzibu/database/migrations/tenant/YYYY_MM_DD_add_spot_settings_version.php
Schema::table('muzibu_corporate_accounts', function (Blueprint $table) {
$table->unsignedInteger('spot_settings_version')->default(1)
->after('spot_is_paused')
->comment('Ayarlar her değiştiğinde artırılır');
});
2. Controller: Version'ı Artır (3 Durum İçin)
Dosya: Modules/Muzibu/app/Http/Controllers/Front/CorporateFrontController.php:1726
public function updateSpotSettings(Request $request)
{
// ... (mevcut kod)
// ✅ YENİ: 3 ayar değişimini de izle
$versionUpdated = false;
if ($request->has('spot_enabled')) {
$data['spot_enabled'] = (bool) $request->spot_enabled;
$versionUpdated = true; // Ana şube global kapatma!
}
if ($request->has('spot_songs_between')) {
$data['spot_songs_between'] = max(1, min(100, (int) $request->spot_songs_between));
$versionUpdated = true; // Çalma aralığı değişti!
}
// ⚠️ NOT: spot_is_paused şube bazlı, version artırMAZ! (lokal ayar)
// Version'ı artır
if ($versionUpdated) {
$data['spot_settings_version'] = DB::raw('spot_settings_version + 1');
}
$account->update($data);
return response()->json([
'success' => true,
'settings' => [
'spot_enabled' => $account->spot_enabled,
'spot_songs_between' => $account->spot_songs_between,
'spot_settings_version' => $account->fresh()->spot_settings_version // ✅ Yeni değer!
]
]);
}
3. API: Version Bilgisini Ekle
Dosya: Modules/Muzibu/app/Http/Controllers/Api/SpotController.php
public function settings(Request $request)
{
// ... (mevcut kod)
// ✅ effectiveEnabled: Ana şube + şube kontrolü
$effectiveEnabled = $parentAccount->spot_enabled && !$account->spot_is_paused;
return response()->json([
'enabled' => $effectiveEnabled, // Efektif durum
'spot_enabled' => $parentAccount->spot_enabled, // ✅ YENİ: Ana şube global
'spot_is_paused' => $account->spot_is_paused, // Şube lokal
'songs_between' => $parentAccount->spot_songs_between ?? 10,
'corporate_id' => $parentAccount->id,
'branch_id' => $account->id,
'spot_settings_version' => $parentAccount->spot_settings_version ?? 1, // ✅ Version!
]);
}
4. JavaScript: Periyodik Kontrol + 3 Seviye
Dosya: public/themes/muzibu/js/player/features/spot-player.js:20-40
const state = {
enabled: false, // Efektif durum (global && !paused)
spotEnabled: true, // ✅ YENİ: Ana şube global
isPaused: false, // Şube lokal
songsBetween: 10,
songsPlayed: 0,
currentVersion: 1, // ✅ Version
checkInterval: null, // Interval ID
};
async function init() {
await fetchSettings();
// ✅ Her 30 saniyede bir ayarları kontrol et
state.checkInterval = setInterval(checkSettingsUpdate, 30000);
}
// ✅ YENİ: Ayarlar değişmiş mi kontrol et
async function checkSettingsUpdate() {
try {
const response = await fetch('/api/spot/settings');
const data = await response.json();
// Version farklıysa güncelle!
if (data.spot_settings_version !== state.currentVersion) {
console.log('🎙️ SpotPlayer: Settings updated! Refreshing...');
// ✅ 3 seviyeyi güncelle
state.songsBetween = data.songs_between || 10;
state.spotEnabled = data.spot_enabled; // ✅ Ana şube global
state.isPaused = data.spot_is_paused; // Şube lokal
state.enabled = data.enabled; // Efektif (global && !paused)
state.currentVersion = data.spot_settings_version;
// Sayacı sıfırla (yeni aralık için)
resetCounter();
// ✅ UI'ı güncelle (Alpine.js event)
window.dispatchEvent(new CustomEvent('spot-settings-updated', {
detail: {
songsBetween: state.songsBetween,
spotEnabled: state.spotEnabled, // ✅ Global durum
isPaused: state.isPaused, // Lokal durum
enabled: state.enabled // Efektif durum
}
}));
}
} catch (e) {
console.error('🎙️ SpotPlayer: Failed to check settings', e);
}
}
5. Alpine.js: UI Senkronizasyonu (3 Seviye)
Dosya: Player footer'daki anons toggle component
<div x-data="{
spotEnabled: true, // UI state (efektif durum)
globalDisabled: false, // ✅ YENİ: Ana şube kapattı mı?
init() {
// ✅ YENİ: Spot settings update event'ini dinle
window.addEventListener('spot-settings-updated', (e) => {
// Ana şube global kapatma kontrolü
this.globalDisabled = !e.detail.spotEnabled;
// Efektif durum (global açık && lokal açık)
this.spotEnabled = e.detail.enabled;
console.log('🎨 UI: Spot settings updated!', {
global: e.detail.spotEnabled,
paused: e.detail.isPaused,
effective: e.detail.enabled
});
});
// Başlangıç senkronizasyonu
const syncState = () => {
if (window.MuzibuSpotPlayer) {
this.spotEnabled = window.MuzibuSpotPlayer.isEnabled()
&& !window.MuzibuSpotPlayer.isPaused();
}
};
setTimeout(syncState, 500);
},
toggle() {
// ✅ Ana şube kapattıysa toggle edemez!
if (this.globalDisabled) {
console.warn('🚫 Ana şube spot sistemini kapattı!');
return;
}
// Optimistic UI
this.spotEnabled = !this.spotEnabled;
// API çağır (spot_is_paused toggle)
if (window.MuzibuSpotPlayer) {
window.MuzibuSpotPlayer.togglePause().then(result => {
if (!result.success) {
this.spotEnabled = !this.spotEnabled;
}
}).catch(() => {
this.spotEnabled = !this.spotEnabled;
});
}
}
}">
<!-- Anons toggle UI -->
<div @click="toggle()" class="flex items-center gap-2 cursor-pointer"
:class="globalDisabled && 'opacity-50 cursor-not-allowed'">
<i class="fas text-[10px]"
:class="spotEnabled ? 'fa-bullhorn text-white/50' : 'fa-ban text-red-400/80'"></i>
<span class="text-xs" x-text="spotEnabled ? 'Anonslar aktif' : 'Anonslar durduruldu'"></span>
<div class="w-2.5 h-2.5 rounded-sm"
:class="spotEnabled ? 'bg-green-400/60' : 'bg-red-400/60'"></div>
</div>
<!-- ⚠️ Ana şube kapattıysa uyarı -->
<div x-show="globalDisabled" class="text-[10px] text-amber-400 mt-1">
<i class="fas fa-lock mr-1"></i>Ana şube tarafından kapatıldı
</div>
</div>
Çözüm Seçenekleri
| Çözüm | Avantajlar | Dezavantajlar | Öneri |
|---|---|---|---|
|
Seçildi Settings Version + Polling |
• Basit implementasyon • Ek teknoloji yok • Hafif (30s polling) • Laravel cache entegre • 3 seviye kontrol destekler |
• Gerçek zamanlı değil (30s gecikme) • Minimal API yükü |
|
| WebSocket/Pusher |
• Anında güncelleme • Gerçek zamanlı • Polling yok |
• Pusher ücreti • Server konfigürasyonu • Karmaşık implementasyon |
|
| Redis Pub/Sub |
• Hafif • Laravel entegre |
• Yine polling gerekir • Settings version'dan farkı yok |
Uygulama Adımları
Migration Oluştur ve Çalıştır
Database'e spot_settings_version field ekle
php artisan make:migration add_spot_settings_version_to_corporate_accounts --path=Modules/Muzibu/database/migrations/tenant
php artisan tenants:migrate
Controller'ı Güncelle (3 Seviye İçin)
CorporateFrontController::updateSpotSettings() - Version artırma ekle (spot_enabled + spot_songs_between)
API'ye Version ve Global Durum Ekle
SpotController::settings() - Version + spot_enabled bilgisi ekle
JavaScript Polling + 3 Seviye Ekle
spot-player.js - checkSettingsUpdate() + spotEnabled/isPaused/enabled state'leri
Alpine Component Güncelle (Global Kontrol)
Anons toggle component - globalDisabled kontrolü + event listener
Test Et (3 Senaryo)
- • Çalma aralığı değiştir → 30s içinde tüm şubeler güncellenir
- • Ana şube sistemi kapat → 30s içinde tüm şubeler durur
- • Şube kendini durdur → Sadece o şube durur (diğerleri çalar)
Önemli Notlar
-
30 Saniye Gecikme:
Bu normal ve kabul edilebilir. Anons sistemi için gerçek zamanlı olması kritik değil.
-
localStorage Temizleme:
Version değişince localStorage'daki sayaç sıfırlanır (yeni aralık için).
-
Server Yükü:
30 saniyede 1 API çağrısı = saatte 120 istek = hafif (cache'lenebilir).
-
3 Seviye Kontrol:
Global (spot_enabled), Lokal (spot_is_paused), Aralık (spot_songs_between) - Hepsi dinamik!
-
Version Mantığı:
Sadece
spot_enabledvespot_songs_betweendeğişiminde version artar.spot_is_pausedlokal olduğu için version artırmaz.