1// cloudManager.js 2import { sendDiscordEvent } from './utils/sendDiscordEvent.js'; 3import { sendDiscordError } from './utils/sendDiscordError.js'; 4import { showCloudJokeModal } from './cloudJokeModal.js'; 5// Cloud tiles: the whole world at zoom 2 (16 tiles, fetched the first time the 6// layer is shown), plus the tiles covering the view when zoomed in closer. 7const CLOUD_TILES = { 8 globalLevel: 2, 9 maxLevel: 7, 10 maxTiles: 24, 11 alpha: 0.99, 12 credit: 'Clouds: OpenWeatherMap', 13}; 14 15export class CloudCoverManager { 16 constructor(globe, apiKey) { 17 this.globe = globe; 18 this.apiKey = apiKey; 19 this.cloudLayer = null; 20 this.cloudsEnabled = false; 21 this.provider = 'openweathermap'; 22 this.hasLoggedDiscovery = false; 23 this.init(); 24 } 25 26 init() { 27 if (this.provider === 'openweathermap') { 28 this.addOpenWeatherClouds(); 29 } 30 this.setupToggleButton(); 31 } 32 33 addOpenWeatherClouds() { 34 try { 35 // Nothing is fetched until the layer is shown. 36 this.cloudLayer = this.globe.setTileOverlay({ 37 ...CLOUD_TILES, 38 url: `https://tile.openweathermap.org/map/clouds_new/{z}/{x}/{y}.png?appid=${this.apiKey}`, 39 show: false, 40 }); 41 console.log('â OpenWeatherMap Cloud cover layer loaded'); 42 } catch (error) { 43 console.error('Failed to load cloud cover:', error); 44 sendDiscordError("Cloud API Failure", error, { provider: 'OpenWeatherMap' }); 45 } 46 } 47 48 toggle() { 49 if (!this.cloudLayer) return; 50 if (!this.cloudsEnabled) { 51 showCloudJokeModal(); 52 } 53 this.cloudsEnabled = !this.cloudsEnabled; 54 this.cloudLayer.show = this.cloudsEnabled; 55 56 if (this.cloudsEnabled && !this.hasLoggedDiscovery) { 57 sendDiscordEvent( 58 "âï¸ Feature Discovered: Clouds", 59 "A user toggled the Cloud Cover layer for the first time this session.", 60 { provider: this.provider } 61 ); 62 this.hasLoggedDiscovery = true; 63 } 64 65 const btn = document.getElementById('cloudToggle'); 66 if (btn) { 67 btn.setAttribute('aria-pressed', this.cloudsEnabled); 68 btn.title = this.cloudsEnabled ? 'Hide Cloud Cover' : 'Show Cloud Cover'; 69 } 70 } 71 72 setupToggleButton() { 73 const btn = document.getElementById('cloudToggle'); 74 if (btn) { 75 btn.addEventListener('click', () => this.toggle()); 76 } 77 } 78}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.