fuzzyworld

north-star / files / src / features / session / self_profile.ts

self_profile.ts

Blame: the commit that last changed each line · file · history

f32f5e95 2026-03-16 Pavel Safronov1import { normalizeName, normalizeColor, createRandomUserName, createRandomColor } from '../../core/utils';
36d64b37 2026-03-15 Pavel Safronov2
3const NAME_STORAGE_KEY = 'north-star-self-name-v2';
4const COLOR_STORAGE_KEY = 'north-star-self-color';
5
6const resolveInitialSelfName = async () => {
7 const savedName = normalizeName(localStorage.getItem(NAME_STORAGE_KEY));
8 if (savedName) return savedName;
9
10 const generatedName = await createRandomUserName();
11 localStorage.setItem(NAME_STORAGE_KEY, generatedName);
12 return generatedName;
13};
14
15const resolveInitialSelfColor = () => {
16 const savedColor = normalizeColor(localStorage.getItem(COLOR_STORAGE_KEY));
17 if (savedColor) return savedColor;
18
19 const generatedColor = createRandomColor();
20 localStorage.setItem(COLOR_STORAGE_KEY, generatedColor);
21 return generatedColor;
22};
23
24/**
e790982a 2026-03-16 Pavel Safronov25 * Creates the selfFriend object, populates form inputs, and wires
36d64b37 2026-03-15 Pavel Safronov26 * name/color change handlers.
27 *
28 * @param {object} opts
29 * @param {HTMLElement} opts.nameForm
30 * @param {HTMLInputElement} opts.selfNameInput
31 * @param {HTMLInputElement} opts.selfColorInput
e790982a 2026-03-16 Pavel Safronov32 * @param {string} opts.uid - Firebase UID used as friend ID
36d64b37 2026-03-15 Pavel Safronov33 * @param {object} opts.selfPosition - Shared { lat, lon } reference (mutated externally)
34 * @param {function} opts.syncSelf - async () => void, called after name/color changes
35 * @param {function} opts.requestRender - triggers a render frame
e790982a 2026-03-16 Pavel Safronov36 * @returns {{ selfFriend: object }}
36d64b37 2026-03-15 Pavel Safronov37 */
38export async function initSelfProfile({
39 nameForm,
40 selfNameInput,
41 selfColorInput,
42 uid,
43 selfPosition,
44 syncSelf,
45 requestRender
b4e7f682 2026-03-16 Pavel Safronov46}: {
47 nameForm: HTMLElement | null;
48 selfNameInput: HTMLInputElement | null;
49 selfColorInput: HTMLInputElement | null;
50 uid: string;
51 selfPosition: { lat: number; lon: number };
52 syncSelf: () => Promise<void>;
53 requestRender: () => void;
36d64b37 2026-03-15 Pavel Safronov54}) {
55 const initialSelfName = await resolveInitialSelfName();
56 const initialSelfColor = resolveInitialSelfColor();
57
e790982a 2026-03-16 Pavel Safronov58 const selfFriend = {
36d64b37 2026-03-15 Pavel Safronov59 id: uid,
60 name: initialSelfName,
61 color: initialSelfColor,
62 position: selfPosition,
63 timestamp: Date.now()
64 };
65
e790982a 2026-03-16 Pavel Safronov66 if (selfNameInput) selfNameInput.value = selfFriend.name;
67 if (selfColorInput) selfColorInput.value = selfFriend.color;
36d64b37 2026-03-15 Pavel Safronov68
b4e7f682 2026-03-16 Pavel Safronov69 const applySelfName = async (rawName: string) => {
36d64b37 2026-03-15 Pavel Safronov70 const nextName = normalizeName(rawName) || await createRandomUserName();
e790982a 2026-03-16 Pavel Safronov71 if (nextName === selfFriend.name) {
36d64b37 2026-03-15 Pavel Safronov72 if (selfNameInput) selfNameInput.value = nextName;
73 return;
74 }
e790982a 2026-03-16 Pavel Safronov75 selfFriend.name = nextName;
36d64b37 2026-03-15 Pavel Safronov76 localStorage.setItem(NAME_STORAGE_KEY, nextName);
77 if (selfNameInput) selfNameInput.value = nextName;
78 await syncSelf();
79 requestRender();
80 };
81
b4e7f682 2026-03-16 Pavel Safronov82 const applySelfColor = async (rawColor: string) => {
36d64b37 2026-03-15 Pavel Safronov83 const nextColor = normalizeColor(rawColor) || createRandomColor();
e790982a 2026-03-16 Pavel Safronov84 if (nextColor === selfFriend.color) {
36d64b37 2026-03-15 Pavel Safronov85 if (selfColorInput) selfColorInput.value = nextColor;
86 return;
87 }
e790982a 2026-03-16 Pavel Safronov88 selfFriend.color = nextColor;
36d64b37 2026-03-15 Pavel Safronov89 localStorage.setItem(COLOR_STORAGE_KEY, nextColor);
90 if (selfColorInput) selfColorInput.value = nextColor;
91 await syncSelf();
92 requestRender();
93 };
94
95 if (nameForm) {
b4e7f682 2026-03-16 Pavel Safronov96 nameForm.addEventListener('submit', async (event: Event) => {
36d64b37 2026-03-15 Pavel Safronov97 event.preventDefault();
e790982a 2026-03-16 Pavel Safronov98 await applySelfName(selfNameInput ? selfNameInput.value : selfFriend.name);
99 await applySelfColor(selfColorInput ? selfColorInput.value : selfFriend.color);
36d64b37 2026-03-15 Pavel Safronov100 if (selfNameInput) selfNameInput.blur();
101 });
102 }
103
104 if (selfNameInput) {
105 selfNameInput.addEventListener('change', async () => {
106 await applySelfName(selfNameInput.value);
107 });
108 }
109
110 if (selfColorInput) {
111 selfColorInput.addEventListener('change', async () => {
112 await applySelfColor(selfColorInput.value);
113 });
114 }
115
e790982a 2026-03-16 Pavel Safronov116 return { selfFriend };
36d64b37 2026-03-15 Pavel Safronov117}