206 lines
6.8 KiB
JavaScript
206 lines
6.8 KiB
JavaScript
// friends, DM list, and friend request logic
|
|
|
|
async function loadFriends() {
|
|
try {
|
|
const res = await fetch(`${API_URL}/friends`, {
|
|
headers: { 'Authorization': `Bearer ${token}` }
|
|
});
|
|
|
|
if (res.ok) {
|
|
friends = await res.json();
|
|
// seed lastSeen for each DM
|
|
friends.forEach(f => {
|
|
const key = conversationKey('d', f.id);
|
|
if (!lastSeen[key]) lastSeen[key] = Date.now();
|
|
});
|
|
displayFriends();
|
|
displayDMList();
|
|
|
|
// Update Service Worker with friends list for background notifications
|
|
updateServiceWorkerFriends();
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading friends:', error);
|
|
}
|
|
}
|
|
|
|
async function loadFriendRequests() {
|
|
try {
|
|
const res = await fetch(`${API_URL}/friend-requests`, {
|
|
headers: { 'Authorization': `Bearer ${token}` }
|
|
});
|
|
|
|
if (res.ok) {
|
|
const requests = await res.json();
|
|
displayFriendRequests(requests);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error loading friend requests:', error);
|
|
}
|
|
}
|
|
|
|
function displayFriends() {
|
|
friendsList.innerHTML = '';
|
|
if (friends.length === 0) {
|
|
friendsList.innerHTML = '<div class="empty-state">No friends yet. Add some!</div>';
|
|
return;
|
|
}
|
|
friends.forEach(friend => {
|
|
const friendEl = document.createElement('div');
|
|
friendEl.className = 'friend-item';
|
|
let av = friend.avatar_url ? `<img class="msg-avatar" src="${friend.avatar_url}" alt="av"/>` : '';
|
|
|
|
// Generate badge HTML if user has a system badge
|
|
let badgeHtml = '';
|
|
if (friend.badge) {
|
|
const badgeClass = friend.badge.toLowerCase().replace(/\s+/g, '-');
|
|
badgeHtml = `<span class="user-badge ${badgeClass}">${friend.badge}</span>`;
|
|
}
|
|
|
|
friendEl.innerHTML = `${av}<span>@${friend.username}</span>${badgeHtml}`;
|
|
friendEl.onclick = () => selectDM(friend.id, friend.username);
|
|
friendsList.appendChild(friendEl);
|
|
});
|
|
}
|
|
|
|
function displayDMList() {
|
|
dmList.innerHTML = '';
|
|
if (friends.length === 0) {
|
|
dmList.innerHTML = '<div class="empty-state">No friends</div>';
|
|
return;
|
|
}
|
|
friends.forEach(friend => {
|
|
const userEl = document.createElement('div');
|
|
userEl.className = 'dm-user';
|
|
userEl.setAttribute('data-user-id', friend.id);
|
|
let av = friend.avatar_url ? `<img class="msg-avatar" src="${friend.avatar_url}" alt="av"/>` : '';
|
|
|
|
// Generate badge HTML if user has a system badge
|
|
let badgeHtml = '';
|
|
if (friend.badge) {
|
|
const badgeClass = friend.badge.toLowerCase().replace(/\s+/g, '-');
|
|
badgeHtml = `<span class="user-badge ${badgeClass}">${friend.badge}</span>`;
|
|
}
|
|
|
|
userEl.innerHTML = `${av}<span>@${friend.username}</span>${badgeHtml}`;
|
|
const count = unreadCounts[conversationKey('d', friend.id)];
|
|
if (count) {
|
|
const badge = document.createElement('span');
|
|
badge.className = 'unread-badge';
|
|
badge.textContent = count;
|
|
userEl.appendChild(badge);
|
|
}
|
|
userEl.onclick = () => selectDM(friend.id, friend.username);
|
|
dmList.appendChild(userEl);
|
|
});
|
|
}
|
|
|
|
function displayFriendRequests(requests) {
|
|
friendRequestsList.innerHTML = '';
|
|
if (requests.length === 0) {
|
|
friendRequestsList.innerHTML = '<div class="empty-state">No pending requests</div>';
|
|
return;
|
|
}
|
|
requests.forEach(req => {
|
|
const reqEl = document.createElement('div');
|
|
reqEl.className = 'friend-request-item';
|
|
reqEl.innerHTML = `
|
|
<span>@${req.username}</span>
|
|
<div class="request-actions">
|
|
<button class="accept-btn" onclick="respondFriendRequest(${req.id}, 'accept')">✓</button>
|
|
<button class="reject-btn" onclick="respondFriendRequest(${req.id}, 'reject')">✗</button>
|
|
</div>
|
|
`;
|
|
friendRequestsList.appendChild(reqEl);
|
|
});
|
|
}
|
|
|
|
function displayAddFriendModal() {
|
|
modalError.textContent = '';
|
|
modalError.className = 'modal-error';
|
|
friendUsernameInput.value = '';
|
|
friendUsernameInput.focus();
|
|
}
|
|
|
|
async function sendFriendRequest(username) {
|
|
if (!username || !username.trim()) {
|
|
modalError.textContent = 'Please enter a username';
|
|
modalError.className = 'modal-error show';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(`${API_URL}/friend-request`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({ username: username.trim() })
|
|
});
|
|
|
|
const data = await res.json();
|
|
|
|
if (res.ok) {
|
|
modalError.textContent = 'Friend request sent!';
|
|
modalError.className = 'modal-error show success';
|
|
friendUsernameInput.value = '';
|
|
setTimeout(() => {
|
|
addFriendModal.style.display = 'none';
|
|
loadFriendRequests();
|
|
}, 1000);
|
|
} else {
|
|
modalError.textContent = data.error || 'Error sending request';
|
|
modalError.className = 'modal-error show';
|
|
}
|
|
} catch (error) {
|
|
modalError.textContent = 'Error: ' + error.message;
|
|
modalError.className = 'modal-error show';
|
|
}
|
|
}
|
|
|
|
async function respondFriendRequest(requestId, action) {
|
|
try {
|
|
const res = await fetch(`${API_URL}/friend-request/${requestId}`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({ action: action })
|
|
});
|
|
|
|
if (res.ok) {
|
|
loadFriends();
|
|
loadFriendRequests();
|
|
}
|
|
} catch (error) {
|
|
console.error('Error responding to friend request:', error);
|
|
}
|
|
}
|
|
|
|
// event hooks for friend UI
|
|
function initFriendListeners() {
|
|
addFriendBtn.addEventListener('click', () => {
|
|
displayAddFriendModal();
|
|
addFriendModal.style.display = 'flex';
|
|
});
|
|
closeModal.addEventListener('click', () => {
|
|
addFriendModal.style.display = 'none';
|
|
});
|
|
addFriendModal.addEventListener('click', (e) => {
|
|
if (e.target === addFriendModal) {
|
|
addFriendModal.style.display = 'none';
|
|
}
|
|
});
|
|
modalAddBtn.addEventListener('click', () => {
|
|
sendFriendRequest(friendUsernameInput.value);
|
|
});
|
|
friendUsernameInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
sendFriendRequest(friendUsernameInput.value);
|
|
}
|
|
});
|
|
}
|