feature: add a map

This commit is contained in:
Andy Burke 2026-01-15 20:53:57 -08:00
parent 19afb7f9fa
commit 32ed2dfd33
23 changed files with 29839 additions and 130 deletions

View file

@ -1,8 +1,19 @@
<script>
APP.on("channels_updated", ({ channels }) => {
const channel_list = document.getElementById("channel-list");
if ( !channel_list ) {
return;
}
channel_list.innerHTML = "";
for (const channel of channels.sort((lhs, rhs) => lhs.name.localeCompare(rhs.name))) {
if ( !document.body.dataset.channel ) {
document.body.dataset.channel = APP.user?.meta?.chat?.last_channel ?? channel.id;
if ( APP.view === 'chat' ) {
window.location.hash = '/chat/channel/' + document.body.dataset.channel;
}
}
channel_list.insertAdjacentHTML(
"beforeend",
`<li id="channel-selector-${channel.id}" class="channel" data-channel-selector-for="${channel.id}"><a href="#/channel/${channel.id}/chat">${channel.name}</a></li>`,
@ -10,6 +21,36 @@
}
});
APP.on( 'view_changed', ( { previous, view, channel_id } ) => {
if (document.body.dataset.channel !== channel_id) {
const previous_channel = typeof document.body.dataset.channel === 'string' ? document.body.dataset.channel : undefined;
if ( channel_id ) {
document.body.dataset.channel = channel_id;
}
else {
delete document.body.dataset.channel;
}
const target_channel_id = channel_id ?? this.CHANNELS.CHANNEL_LIST[0]?.id;
// TODO: allow a different default than chat
const hash_target = `/${ view ? view : 'chat' }` + ( target_channel_id ? `/channel/${ target_channel_id }` : '' );
if ( window.location.hash?.slice( 1 ) !== hash_target ) {
if ( previous_channel !== target_channel_id ) {
this._emit( 'channel_changed', {
previous: previous_channel,
channel_id: target_channel_id
});
}
window.location.hash = hash_target;
}
}
});
function update_channel_indicators(event) {
document
.querySelectorAll("[data-channel-selector-for]")
@ -77,20 +118,25 @@
}
});
APP.on( 'view_changed', ( {view} ) => {
if ( !view === 'chat' ) {
return;
}
APP.on( 'view_changed', ( {previous, view} ) => {
const sidebar_dynamic_container = document.getElementById( 'sidebar-dynamic-container');
if ( !sidebar_dynamic_container ) {
console.error( 'could not get #sidebar-dynamic-container' );
return;
}
if ( view !== 'chat' && previous === 'chat' ) {
sidebar_dynamic_container.innerHTML = '';
delete document.body.dataset.channel;
return;
}
else if ( view !== 'chat' ) {
return;
}
const template = document.getElementById( 'channel-list-template');
sidebar_dynamic_container.innerHTML = template.innerHTML.trim();
APP.CHANNELS.update();
APP.CHANNELS.update(true);
});
</script>
<style>

55
public/tabs/map/map.html Normal file
View file

@ -0,0 +1,55 @@
<link rel="stylesheet" href="/js/external/leaflet/leaflet.css"/>
<script src="/js/external/leaflet/leaflet.js"></script>
<script type="module">
var map = L.map('map').setView([33.88,-118.13], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}).addTo(map);
APP.on( "view_changed", ({ view }) => {
if ( view === 'map' ) {
map.invalidateSize();
}
});
</script>
<style>
#map-tab .tab-content {
overflow: hidden;
}
#map {
position: absolute;
top: 4em;
left: 4em;
right: 4em;
bottom: 4em;
}
@media screen and (max-width: 640px) {
#map {
top: 1em;
left: 1em;
right: 1em;
bottom: 1em;
}
}
</style>
<div id="map-tab" class="tab">
<input
type="radio"
name="top-level-tabs"
id="map-tab-tab-input"
class="tab-switch"
data-view="map"
/>
<label for="map-tab-tab-input" class="tab-label"
><div class="icon map-pin"></div>
<div class="label">Map</div>
</label>
<div class="tab-content">
<div id="map"></div>
</div>
</div>

View file

@ -13,6 +13,7 @@
tab_switch.addEventListener("input", (event) => {
const tab_selector = event.target;
const view = tab_selector.dataset.view;
if (view) {
window.location.hash = `/${view}${ document.body.dataset.channel ? `/channel/${ document.body.dataset.channel }` : '' }`;
}
@ -134,4 +135,5 @@
<!-- #include file="./blurbs/blurbs.html" -->
<!-- #include file="./forum/forum.html" -->
<!-- #include file="./essays/essays.html" -->
<!-- #include file="./map/map.html" -->
</div>