'use strict'; // ---- Family Chat extras: a GIF picker (kept family-friendly by the hub; phones never contact the GIF service) and sharing a place (your location, or a place you search for). // The Chat list also shows Signal conversations, labelled, when Signal is available on this screen. async function chGifOn() { if (ch.gifOn === undefined) { try { ch.gifOn = !!(await chApi('/gif/status')).enabled; ch.gifBy = (await chApi('/gif/status')).provider; } catch { ch.gifOn = false; } } return ch.gifOn; } function chGifPicker() { const to = ch.cur, by = ch.gifBy === 'giphy' ? 'GIPHY' : 'Tenor'; const el = openSheet('GIF', 'Family-friendly only', `
Powered by ${by}
`); el.querySelector('.sheet').classList.add('wide'); let next = '', q = '', busy = false; const load = async more => { if (busy) return; busy = true; el.querySelector('#gpe').textContent = ''; try { const r = await chApi('/gif?q=' + encodeURIComponent(q) + (more && next ? '&pos=' + encodeURIComponent(next) : '')); next = r.next || ''; const g = el.querySelector('#gpg'); if (!more) g.innerHTML = ''; g.insertAdjacentHTML('beforeend', r.items.map(x => ``).join('')); if (!more && !r.items.length) el.querySelector('#gpe').textContent = 'Nothing found. Try another word.'; el.querySelector('#gpm').hidden = !next; } catch (e) { el.querySelector('#gpe').textContent = e.message; } busy = false; }; el.querySelector('#gpf').onsubmit = e => { e.preventDefault(); q = el.querySelector('#gpq').value.trim(); next = ''; load(false); }; el.querySelector('#gpm').onclick = () => load(true); el.querySelector('#gpg').onclick = async e => { const b = e.target.closest('.gifc'); if (!b || b.disabled) return; b.disabled = true; b.style.opacity = '.5'; try { await chPost('/gif/send', { conv: to, url: b.dataset.u, title: b.dataset.t }); closeSheet(); } catch (er) { b.disabled = false; b.style.opacity = ''; el.querySelector('#gpe').textContent = er.message; } }; load(false); } function chPlacePicker() { const to = ch.cur, el = openSheet('Share a place', '', `Your phone asks first. This sends where you are right now, once; it does not keep following you.
`); const send = async (title, sub, lat, lng) => { try { await chPost('/send', { conv: to, share: { kind: 'place', title, sub, lat, lng } }); closeSheet(); } catch (e) { el.querySelector('#ple').textContent = e.message; } }; el.querySelector('#plme').onclick = () => { if (!navigator.geolocation) { el.querySelector('#ple').textContent = 'This browser cannot share a location here. Search for the place instead.'; return; } el.querySelector('#plmm').textContent = 'Finding you…'; navigator.geolocation.getCurrentPosition(p => send('My location', `${p.coords.latitude.toFixed(4)}, ${p.coords.longitude.toFixed(4)}`, p.coords.latitude, p.coords.longitude), e => { el.querySelector('#plmm').textContent = e.code === 1 ? 'Location is blocked. Allow it for this site in your browser settings, or search for the place instead.' : 'Could not find your location. Search for the place instead.'; }, { enableHighAccuracy: true, timeout: 12000, maximumAge: 30000 }); }; el.querySelector('#plf').onsubmit = async e => { e.preventDefault(); const q = el.querySelector('#plq').value.trim(), box = el.querySelector('#plr'); el.querySelector('#ple').textContent = ''; if (q.length < 3) { el.querySelector('#ple').textContent = 'Type at least three letters.'; return; } box.innerHTML = '