62 lines
2.8 KiB
TypeScript
62 lines
2.8 KiB
TypeScript
/**
|
|
* <map-privacy-panel> — privacy settings dropdown for rMaps.
|
|
* Dispatches 'precision-change' and 'ghost-toggle' CustomEvents.
|
|
*/
|
|
|
|
import type { PrecisionLevel, PrivacySettings } from "./map-sync";
|
|
|
|
const PRECISION_LABELS: Record<PrecisionLevel, string> = {
|
|
exact: "Exact",
|
|
building: "~50m (Building)",
|
|
area: "~500m (Area)",
|
|
approximate: "~5km (Approximate)",
|
|
};
|
|
|
|
class MapPrivacyPanel extends HTMLElement {
|
|
private _settings: PrivacySettings = { precision: "exact", ghostMode: false };
|
|
|
|
static get observedAttributes() { return ["precision", "ghost"]; }
|
|
|
|
get settings(): PrivacySettings { return this._settings; }
|
|
set settings(v: PrivacySettings) { this._settings = v; this.render(); }
|
|
|
|
attributeChangedCallback() {
|
|
this._settings.precision = (this.getAttribute("precision") as PrecisionLevel) || "exact";
|
|
this._settings.ghostMode = this.getAttribute("ghost") === "true";
|
|
this.render();
|
|
}
|
|
|
|
connectedCallback() { this.render(); }
|
|
|
|
private render() {
|
|
this.innerHTML = `
|
|
<div style="font-size:12px;font-weight:600;color:var(--rs-text-secondary);margin-bottom:8px;">Privacy Settings</div>
|
|
<label style="font-size:12px;color:var(--rs-text-secondary);display:block;margin-bottom:6px;">Location Precision</label>
|
|
<select id="precision-select" style="width:100%;padding:6px 8px;border-radius:6px;border:1px solid var(--rs-border);background:var(--rs-input-bg);color:var(--rs-text-primary);font-size:12px;margin-bottom:10px;">
|
|
${(["exact", "building", "area", "approximate"] as PrecisionLevel[]).map(p =>
|
|
`<option value="${p}" ${this._settings.precision === p ? "selected" : ""}>${PRECISION_LABELS[p]}</option>`
|
|
).join("")}
|
|
</select>
|
|
<label style="display:flex;align-items:center;gap:8px;font-size:12px;color:var(--rs-text-secondary);cursor:pointer;">
|
|
<input type="checkbox" id="ghost-toggle" ${this._settings.ghostMode ? "checked" : ""} style="accent-color:#8b5cf6;">
|
|
<span>\u{1F47B} Ghost Mode</span>
|
|
</label>
|
|
<div style="font-size:10px;color:var(--rs-text-muted);margin-top:4px;line-height:1.4;">
|
|
Ghost mode hides your location from all participants and stops GPS tracking.
|
|
</div>
|
|
`;
|
|
|
|
this.querySelector("#precision-select")?.addEventListener("change", (e) => {
|
|
this._settings.precision = (e.target as HTMLSelectElement).value as PrecisionLevel;
|
|
this.dispatchEvent(new CustomEvent("precision-change", { detail: this._settings.precision, bubbles: true, composed: true }));
|
|
});
|
|
this.querySelector("#ghost-toggle")?.addEventListener("change", () => {
|
|
this._settings.ghostMode = !this._settings.ghostMode;
|
|
this.dispatchEvent(new CustomEvent("ghost-toggle", { detail: this._settings.ghostMode, bubbles: true, composed: true }));
|
|
});
|
|
}
|
|
}
|
|
|
|
customElements.define("map-privacy-panel", MapPrivacyPanel);
|
|
export { MapPrivacyPanel };
|