mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Restructure code and documentation
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
import { API_BASE_URL } from "../core/config";
|
||||||
|
import { showLogin } from "../navigation";
|
||||||
|
import type { Headers, User } from "../core/types";
|
||||||
|
import { clearAlerts } from "./auth";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current authenticated user information
|
||||||
|
* @type {User | null}
|
||||||
|
*/
|
||||||
|
export let currentUser: User | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT authentication token
|
||||||
|
* @type {string | null}
|
||||||
|
*/
|
||||||
|
export let authToken: string | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the current user to the values provided.
|
||||||
|
* @param token The authentication JWT token.
|
||||||
|
* @param user The current authenticated user.
|
||||||
|
*/
|
||||||
|
export function setUser(token: string, user: User) {
|
||||||
|
authToken = token
|
||||||
|
currentUser = user
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates authentication headers for API requests
|
||||||
|
* @param {boolean} json - Whether to include JSON content type header
|
||||||
|
* @returns {Headers} Headers object with authentication and content type
|
||||||
|
*/
|
||||||
|
export function getAuthHeaders(json: boolean = true): Headers {
|
||||||
|
const headers: Headers = {};
|
||||||
|
|
||||||
|
if (json) {
|
||||||
|
headers["Content-Type"] = "application/json";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authToken) {
|
||||||
|
headers['Authorization'] = `Bearer ${authToken}`;
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks authentication status on page load
|
||||||
|
*/
|
||||||
|
export async function checkAuthStatus(): Promise<void> {
|
||||||
|
// For JWT, we don't have a persistent token on page load
|
||||||
|
// So we'll just show the login form
|
||||||
|
showLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs out the current user and clears session data
|
||||||
|
*/
|
||||||
|
export async function logout(): Promise<void> {
|
||||||
|
try {
|
||||||
|
await fetch(`${API_BASE_URL}/logout`, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: getAuthHeaders()
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Logout error:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentUser = null;
|
||||||
|
authToken = null;
|
||||||
|
showLogin();
|
||||||
|
clearAlerts();
|
||||||
|
}
|
||||||
@@ -5,90 +5,14 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { loadMessages } from "./chat";
|
import { initializeProfile } from "../userPanel/profile/profile";
|
||||||
import { initializeProfile } from "./profile";
|
import type { ErrorResponse, LoginResponse, LoginRequest, RegisterRequest } from "../core/types";
|
||||||
import type { Headers, ErrorResponse, User, LoginResponse, LoginRequest, RegisterRequest } from "./types";
|
import { API_BASE_URL } from "../core/config";
|
||||||
import { API_BASE_URL } from "./config";
|
import { loadChat, showLogin, showRegister } from "../navigation";
|
||||||
|
import { setUser } from "./api";
|
||||||
/**
|
|
||||||
* Current authenticated user information
|
|
||||||
* @type {User | null}
|
|
||||||
*/
|
|
||||||
export let currentUser: User | null = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JWT authentication token
|
|
||||||
* @type {string | null}
|
|
||||||
*/
|
|
||||||
export let authToken: string | null = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates authentication headers for API requests
|
|
||||||
* @param {boolean} json - Whether to include JSON content type header
|
|
||||||
* @returns {Headers} Headers object with authentication and content type
|
|
||||||
* @function getAuthHeaders
|
|
||||||
* @example
|
|
||||||
* const headers = getAuthHeaders();
|
|
||||||
* fetch('/api/endpoint', { headers });
|
|
||||||
*/
|
|
||||||
export function getAuthHeaders(json: boolean = true): Headers {
|
|
||||||
const headers: Headers = {};
|
|
||||||
|
|
||||||
if (json) {
|
|
||||||
headers["Content-Type"] = "application/json";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authToken) {
|
|
||||||
headers['Authorization'] = `Bearer ${authToken}`;
|
|
||||||
}
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the login form and hides other interfaces
|
|
||||||
* @function showLogin
|
|
||||||
* @example
|
|
||||||
* showLogin();
|
|
||||||
*/
|
|
||||||
export function showLogin(): void {
|
|
||||||
document.getElementById('login-form')!.style.display = 'flex';
|
|
||||||
document.getElementById('register-form')!.style.display = 'none';
|
|
||||||
document.getElementById('chat-interface')!.style.display = 'none';
|
|
||||||
clearAlerts();
|
|
||||||
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the registration form and hides other interfaces
|
|
||||||
* @function showRegister
|
|
||||||
* @example
|
|
||||||
* showRegister();
|
|
||||||
*/
|
|
||||||
export function showRegister(): void {
|
|
||||||
document.getElementById('login-form')!.style.display = 'none';
|
|
||||||
document.getElementById('register-form')!.style.display = 'flex';
|
|
||||||
document.getElementById('chat-interface')!.style.display = 'none';
|
|
||||||
clearAlerts();
|
|
||||||
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows the chat interface and hides authentication forms
|
|
||||||
* @function showChat
|
|
||||||
* @example
|
|
||||||
* showChat();
|
|
||||||
*/
|
|
||||||
export function showChat(): void {
|
|
||||||
document.getElementById('login-form')!.style.display = 'none';
|
|
||||||
document.getElementById('register-form')!.style.display = 'none';
|
|
||||||
document.getElementById('chat-interface')!.style.display = 'block';
|
|
||||||
loadMessages();
|
|
||||||
document.getElementById("electron-title-bar")!.classList.remove("color-surface");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all alert messages from authentication forms
|
* Clears all alert messages from authentication forms
|
||||||
* @function clearAlerts
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export function clearAlerts(): void {
|
export function clearAlerts(): void {
|
||||||
@@ -101,9 +25,6 @@ export function clearAlerts(): void {
|
|||||||
* @param {string} containerId - ID of the container to show the alert in
|
* @param {string} containerId - ID of the container to show the alert in
|
||||||
* @param {string} message - Alert message to display
|
* @param {string} message - Alert message to display
|
||||||
* @param {'success' | 'danger'} type - Type of alert (success or danger)
|
* @param {'success' | 'danger'} type - Type of alert (success or danger)
|
||||||
* @function showAlert
|
|
||||||
* @example
|
|
||||||
* showAlert('login-alerts', 'Login successful!', 'success');
|
|
||||||
*/
|
*/
|
||||||
export function showAlert(containerId: string, message: string, type: "success" | "danger" = 'danger'): void {
|
export function showAlert(containerId: string, message: string, type: "success" | "danger" = 'danger'): void {
|
||||||
const container = document.getElementById(containerId)!;
|
const container = document.getElementById(containerId)!;
|
||||||
@@ -115,10 +36,7 @@ export function showAlert(containerId: string, message: string, type: "success"
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles login form submission
|
* Handles login form submission
|
||||||
* @async
|
|
||||||
* @function handleLogin
|
|
||||||
* @param {Event} e - Form submission event
|
* @param {Event} e - Form submission event
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
async function handleLogin(e: Event): Promise<void> {
|
async function handleLogin(e: Event): Promise<void> {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -151,10 +69,8 @@ async function handleLogin(e: Event): Promise<void> {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data: LoginResponse = await response.json();
|
const data: LoginResponse = await response.json();
|
||||||
// Store the JWT token
|
// Store the JWT token
|
||||||
authToken = data.token;
|
setUser(data.token, data.user)
|
||||||
currentUser = data.user;
|
loadChat();
|
||||||
showChat();
|
|
||||||
loadMessages(); // Start loading messages
|
|
||||||
initializeProfile(); // Initialize profile after login
|
initializeProfile(); // Initialize profile after login
|
||||||
} else {
|
} else {
|
||||||
const data: ErrorResponse = await response.json();
|
const data: ErrorResponse = await response.json();
|
||||||
@@ -167,8 +83,6 @@ async function handleLogin(e: Event): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles registration form submission
|
* Handles registration form submission
|
||||||
* @async
|
|
||||||
* @function handleRegister
|
|
||||||
* @param {Event} e - Form submission event
|
* @param {Event} e - Form submission event
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -234,72 +148,15 @@ async function handleRegister(e: Event): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs out the current user and clears session data
|
* Initializes authentication functionality
|
||||||
* @async
|
|
||||||
* @function logout
|
|
||||||
* @example
|
|
||||||
* await logout();
|
|
||||||
*/
|
|
||||||
export async function logout(): Promise<void> {
|
|
||||||
try {
|
|
||||||
await fetch(`${API_BASE_URL}/logout`, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: getAuthHeaders()
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Logout error:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentUser = null;
|
|
||||||
authToken = null;
|
|
||||||
showLogin();
|
|
||||||
clearAlerts();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the chat interface and initializes messaging
|
|
||||||
* @function loadChat
|
|
||||||
* @example
|
|
||||||
* loadChat();
|
|
||||||
*/
|
|
||||||
export function loadChat(): void {
|
|
||||||
showChat();
|
|
||||||
loadMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks authentication status on page load
|
|
||||||
* @async
|
|
||||||
* @function checkAuthStatus
|
|
||||||
* @example
|
|
||||||
* await checkAuthStatus();
|
|
||||||
*/
|
|
||||||
export async function checkAuthStatus(): Promise<void> {
|
|
||||||
// For JWT, we don't have a persistent token on page load
|
|
||||||
// So we'll just show the login form
|
|
||||||
showLogin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up authentication form event listeners
|
|
||||||
* @function setupAuthForms
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupAuthForms(): void {
|
function init(): void {
|
||||||
document.getElementById('login-form-element')!.addEventListener('submit', handleLogin);
|
document.getElementById('login-form-element')!.addEventListener('submit', handleLogin);
|
||||||
document.getElementById('register-form-element')!.addEventListener('submit', handleRegister);
|
document.getElementById('register-form-element')!.addEventListener('submit', handleRegister);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes links
|
|
||||||
* @function setupLinks
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
function setupLinks(): void {
|
|
||||||
document.getElementById("login-link")!.addEventListener("click", showLogin);
|
document.getElementById("login-link")!.addEventListener("click", showLogin);
|
||||||
document.getElementById("register-link")!.addEventListener("click", showRegister);
|
document.getElementById("register-link")!.addEventListener("click", showRegister);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize authentication forms
|
init();
|
||||||
setupAuthForms();
|
|
||||||
setupLinks();
|
|
||||||
@@ -5,22 +5,19 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getAuthHeaders, currentUser, authToken } from "./auth";
|
import { API_BASE_URL } from "../core/config";
|
||||||
import { API_BASE_URL } from "./config";
|
import { websocket } from "../websocket";
|
||||||
import { websocket } from "./websocket";
|
import type { Message, Messages, WebSocketMessage } from "../core/types";
|
||||||
import type { Message, Messages, WebSocketMessage } from "./types";
|
import { formatTime } from "../utils/utils";
|
||||||
import { formatTime } from "./utils/utils";
|
import { show as showContextMenu } from "./contextMenu";
|
||||||
import { show as showContextMenu } from "./message-context-menu";
|
import { show as showUserProfileDialog } from "./profileDialog";
|
||||||
import { show as showUserProfileDialog } from "./user-profile-dialog";
|
import defaultAvatar from "../resources/images/default-avatar.png";
|
||||||
import defaultAvatar from "./images/default-avatar.png";
|
import { authToken, currentUser, getAuthHeaders } from "../auth/api";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new message to the chat interface
|
* Adds a new message to the chat interface
|
||||||
* @param {Message} message - Message object to display
|
* @param {Message} message - Message object to display
|
||||||
* @param {boolean} isAuthor - Whether the current user is the message author
|
* @param {boolean} isAuthor - Whether the current user is the message author
|
||||||
* @function addMessage
|
|
||||||
* @example
|
|
||||||
* addMessage(messageData, messageData.username === currentUser.username);
|
|
||||||
*/
|
*/
|
||||||
export function addMessage(message: Message, isAuthor: boolean): void {
|
export function addMessage(message: Message, isAuthor: boolean): void {
|
||||||
const messagesContainer = document.querySelector('.chat-messages') as HTMLElement;
|
const messagesContainer = document.querySelector('.chat-messages') as HTMLElement;
|
||||||
@@ -127,9 +124,6 @@ export function addMessage(message: Message, isAuthor: boolean): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads chat messages from the server
|
* Loads chat messages from the server
|
||||||
* @function loadMessages
|
|
||||||
* @example
|
|
||||||
* loadMessages();
|
|
||||||
*/
|
*/
|
||||||
export function loadMessages(): void {
|
export function loadMessages(): void {
|
||||||
fetch(`${API_BASE_URL}/get_messages`, {
|
fetch(`${API_BASE_URL}/get_messages`, {
|
||||||
@@ -158,9 +152,6 @@ export function loadMessages(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message via WebSocket
|
* Sends a message via WebSocket
|
||||||
* @function sendMessage
|
|
||||||
* @example
|
|
||||||
* sendMessage();
|
|
||||||
*/
|
*/
|
||||||
export function sendMessage(): void {
|
export function sendMessage(): void {
|
||||||
const input = document.querySelector('.message-input') as HTMLInputElement;
|
const input = document.querySelector('.message-input') as HTMLInputElement;
|
||||||
@@ -202,7 +193,6 @@ document.getElementById('message-form')!.addEventListener('submit', (e) => {
|
|||||||
/**
|
/**
|
||||||
* Updates an existing message in the chat interface
|
* Updates an existing message in the chat interface
|
||||||
* @param {Message} message - Updated message object
|
* @param {Message} message - Updated message object
|
||||||
* @function updateMessage
|
|
||||||
*/
|
*/
|
||||||
export function updateMessage(message: Message): void {
|
export function updateMessage(message: Message): void {
|
||||||
const messageElement = document.querySelector(`[data-id="${message.id}"]`) as HTMLElement;
|
const messageElement = document.querySelector(`[data-id="${message.id}"]`) as HTMLElement;
|
||||||
@@ -227,7 +217,6 @@ export function updateMessage(message: Message): void {
|
|||||||
/**
|
/**
|
||||||
* Removes a message from the chat interface
|
* Removes a message from the chat interface
|
||||||
* @param {number} messageId - ID of the message to remove
|
* @param {number} messageId - ID of the message to remove
|
||||||
* @function removeMessage
|
|
||||||
*/
|
*/
|
||||||
export function removeMessage(messageId: number): void {
|
export function removeMessage(messageId: number): void {
|
||||||
const messageElement = document.querySelector(`[data-id="${messageId}"]`) as HTMLElement;
|
const messageElement = document.querySelector(`[data-id="${messageId}"]`) as HTMLElement;
|
||||||
@@ -239,7 +228,6 @@ export function removeMessage(messageId: number): void {
|
|||||||
/**
|
/**
|
||||||
* Handles WebSocket message updates
|
* Handles WebSocket message updates
|
||||||
* @param {WebSocketMessage} response - WebSocket response
|
* @param {WebSocketMessage} response - WebSocket response
|
||||||
* @function handleWebSocketMessage
|
|
||||||
*/
|
*/
|
||||||
export function handleWebSocketMessage(response: WebSocketMessage): void {
|
export function handleWebSocketMessage(response: WebSocketMessage): void {
|
||||||
switch (response.type) {
|
switch (response.type) {
|
||||||
@@ -5,13 +5,13 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { currentUser, authToken } from "./auth";
|
import { websocket } from "../websocket";
|
||||||
import { websocket } from "./websocket";
|
import type { Message, WebSocketMessage } from "../core/types";
|
||||||
import type { Message, WebSocketMessage } from "./types";
|
import { showSuccess, showError } from "../utils/notification";
|
||||||
import { showSuccess, showError } from "./utils/notification";
|
import { delay } from "../utils/utils";
|
||||||
import { delay } from "./utils/utils";
|
|
||||||
import type { Dialog } from "mdui/components/dialog";
|
import type { Dialog } from "mdui/components/dialog";
|
||||||
import type { TextField } from "mdui/components/text-field";
|
import type { TextField } from "mdui/components/text-field";
|
||||||
|
import { currentUser, authToken } from "../auth/api";
|
||||||
|
|
||||||
|
|
||||||
let menu = document.getElementById("message-context-menu")!;
|
let menu = document.getElementById("message-context-menu")!;
|
||||||
@@ -83,7 +83,7 @@ export function show(message: Message, x: number, y: number): void {
|
|||||||
const deleteItem = menu.querySelector('[data-action="delete"]') as HTMLElement;
|
const deleteItem = menu.querySelector('[data-action="delete"]') as HTMLElement;
|
||||||
|
|
||||||
const isAuthor = message.username === currentUser?.username;
|
const isAuthor = message.username === currentUser?.username;
|
||||||
const isOwner = !!currentUser?.admin;
|
const isOwner = currentUser?.admin;
|
||||||
|
|
||||||
editItem.style.display = isAuthor ? 'flex' : 'none';
|
editItem.style.display = isAuthor ? 'flex' : 'none';
|
||||||
deleteItem.style.display = (isAuthor || isOwner) ? 'flex' : 'none';
|
deleteItem.style.display = (isAuthor || isOwner) ? 'flex' : 'none';
|
||||||
@@ -5,12 +5,12 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getAuthHeaders, currentUser } from "./auth";
|
import { getAuthHeaders, currentUser } from "../auth/api";
|
||||||
import { API_BASE_URL } from "./config";
|
import { API_BASE_URL } from "../core/config";
|
||||||
import type { UserProfile } from "./types";
|
import type { UserProfile } from "../core/types";
|
||||||
import { showError, showSuccess } from "./utils/notification";
|
import { showError, showSuccess } from "../utils/notification";
|
||||||
import { formatTime } from "./utils/utils";
|
import { formatTime } from "../utils/utils";
|
||||||
import defaultAvatar from "./images/default-avatar.png";
|
import defaultAvatar from "../resources/images/default-avatar.png";
|
||||||
|
|
||||||
|
|
||||||
let dialog = document.getElementById("user-profile-dialog")!;
|
let dialog = document.getElementById("user-profile-dialog")!;
|
||||||
@@ -7,21 +7,18 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Base API endpoint for all backend requests
|
* Base API endpoint for all backend requests
|
||||||
* @type {string}
|
|
||||||
* @constant
|
* @constant
|
||||||
*/
|
*/
|
||||||
export const API_BASE_URL: string = '/api';
|
export const API_BASE_URL = `${location.host || "https://fromchat.toolbox-io.ru"}/api`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Full API URL including hostname and port for WebSocket connections
|
* Full API URL including hostname and port for WebSocket connections
|
||||||
* @type {string}
|
|
||||||
* @constant
|
* @constant
|
||||||
*/
|
*/
|
||||||
export const API_FULL_BASE_URL: string = `${location.host}/api`;
|
export const API_WS_BASE_URL = `${location.host || "fromchat.toolbox-io.ru"}/api`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application name displayed in UI and document title
|
* Application name displayed in UI and document title
|
||||||
* @type {string}
|
|
||||||
* @constant
|
* @constant
|
||||||
*/
|
*/
|
||||||
export const PRODUCT_NAME: string = "FromChat";
|
export const PRODUCT_NAME = "FromChat";
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { showLogin } from "./auth";
|
import { showLogin } from "../navigation";
|
||||||
import { PRODUCT_NAME } from "./config";
|
import { PRODUCT_NAME } from "./config";
|
||||||
|
|
||||||
showLogin();
|
showLogin();
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Electron-specific code
|
||||||
|
* @description This module initializes Electron-specific functionality.
|
||||||
|
* @author denis0001-dev
|
||||||
|
* @version 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
import "../../electron.d.ts";
|
import "../../electron.d.ts";
|
||||||
import { PRODUCT_NAME } from "../config.ts";
|
import { PRODUCT_NAME } from "../core/config.ts";
|
||||||
|
|
||||||
if (window.electronInterface !== undefined) {
|
if (window.electronInterface !== undefined) {
|
||||||
console.log("Running in Electron");
|
console.log("Running in Electron");
|
||||||
|
|||||||
@@ -5,15 +5,15 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './css/style.scss';
|
import './resources/css/style.scss';
|
||||||
import "mdui/mdui.css";
|
import "mdui/mdui.css";
|
||||||
|
|
||||||
import "./utils/material";
|
import "./utils/material";
|
||||||
import "./chat";
|
import "./chat/chat";
|
||||||
import "./settings";
|
import "./userPanel/settings";
|
||||||
import "./leftpanel";
|
import "./userPanel/leftpanel";
|
||||||
import "./init";
|
import "./core/init";
|
||||||
import "./profile";
|
import "./userPanel/profile/profile";
|
||||||
import "./message-context-menu";
|
import "./chat/contextMenu";
|
||||||
import "./user-profile-dialog";
|
import "./chat/profileDialog";
|
||||||
import "./electron/electron";
|
import "./electron/electron";
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { clearAlerts } from "./auth/auth";
|
||||||
|
import { loadMessages } from "./chat/chat";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the login form and hides other interfaces.
|
||||||
|
*/
|
||||||
|
export function showLogin(): void {
|
||||||
|
document.getElementById('login-form')!.style.display = 'flex';
|
||||||
|
document.getElementById('register-form')!.style.display = 'none';
|
||||||
|
document.getElementById('chat-interface')!.style.display = 'none';
|
||||||
|
clearAlerts();
|
||||||
|
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the registration form and hides other interfaces.
|
||||||
|
*/
|
||||||
|
export function showRegister(): void {
|
||||||
|
document.getElementById('login-form')!.style.display = 'none';
|
||||||
|
document.getElementById('register-form')!.style.display = 'flex';
|
||||||
|
document.getElementById('chat-interface')!.style.display = 'none';
|
||||||
|
clearAlerts();
|
||||||
|
document.getElementById("electron-title-bar")!.classList.add("color-surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the chat interface and hides authentication forms.
|
||||||
|
*/
|
||||||
|
export function showChat(): void {
|
||||||
|
document.getElementById('login-form')!.style.display = 'none';
|
||||||
|
document.getElementById('register-form')!.style.display = 'none';
|
||||||
|
document.getElementById('chat-interface')!.style.display = 'block';
|
||||||
|
loadMessages();
|
||||||
|
document.getElementById("electron-title-bar")!.classList.remove("color-surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the chat interface and initializes messaging.
|
||||||
|
*/
|
||||||
|
export function loadChat(): void {
|
||||||
|
showChat();
|
||||||
|
loadMessages();
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@@ -20,7 +20,6 @@ const dialogClose = document.getElementById("profile-dialog-close")!;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up chat collapse functionality
|
* Sets up chat collapse functionality
|
||||||
* @function setupChatCollapse
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupChatCollapse(): void {
|
function setupChatCollapse(): void {
|
||||||
@@ -32,7 +31,6 @@ function setupChatCollapse(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up chat switching functionality
|
* Sets up chat switching functionality
|
||||||
* @function setupChatSwitching
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupChatSwitching(): void {
|
function setupChatSwitching(): void {
|
||||||
@@ -51,7 +49,6 @@ function setupChatSwitching(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up profile dialog functionality
|
* Sets up profile dialog functionality
|
||||||
* @function setupProfileDialog
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupProfileDialog(): void {
|
function setupProfileDialog(): void {
|
||||||
@@ -5,14 +5,13 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getAuthHeaders } from '../auth';
|
import { getAuthHeaders } from '../../auth/api';
|
||||||
import type { ProfileData, UploadResponse } from './types';
|
import type { ProfileData, UploadResponse } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads user profile data from the server
|
* Loads user profile data from the server
|
||||||
* @async
|
* @async
|
||||||
* @function loadProfile
|
* @returns User profile data or null if failed
|
||||||
* @returns {Promise<ProfileData | null>} User profile data or null if failed
|
|
||||||
* @example
|
* @example
|
||||||
* const profile = await loadProfile();
|
* const profile = await loadProfile();
|
||||||
* if (profile) {
|
* if (profile) {
|
||||||
@@ -38,8 +37,6 @@ export async function loadProfile(): Promise<ProfileData | null> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Uploads a profile picture to the server
|
* Uploads a profile picture to the server
|
||||||
* @async
|
|
||||||
* @function uploadProfilePicture
|
|
||||||
* @param {Blob} file - The image file to upload
|
* @param {Blob} file - The image file to upload
|
||||||
* @returns {Promise<UploadResponse | null>} Upload response with URL or null if failed
|
* @returns {Promise<UploadResponse | null>} Upload response with URL or null if failed
|
||||||
* @example
|
* @example
|
||||||
@@ -47,7 +44,7 @@ export async function loadProfile(): Promise<ProfileData | null> {
|
|||||||
* const file = fileInput.files[0];
|
* const file = fileInput.files[0];
|
||||||
* const result = await uploadProfilePicture(file);
|
* const result = await uploadProfilePicture(file);
|
||||||
* if (result) {
|
* if (result) {
|
||||||
* console.log('Uploaded to:', result.profile_picture_url);
|
* console.log('Uploaded to:', result.profile_picture_url);
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export async function uploadProfilePicture(file: Blob): Promise<UploadResponse | null> {
|
export async function uploadProfilePicture(file: Blob): Promise<UploadResponse | null> {
|
||||||
@@ -73,8 +70,6 @@ export async function uploadProfilePicture(file: Blob): Promise<UploadResponse |
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates user profile information
|
* Updates user profile information
|
||||||
* @async
|
|
||||||
* @function updateProfile
|
|
||||||
* @param {Partial<ProfileData>} data - Profile data to update
|
* @param {Partial<ProfileData>} data - Profile data to update
|
||||||
* @returns {Promise<boolean>} True if update was successful, false otherwise
|
* @returns {Promise<boolean>} True if update was successful, false otherwise
|
||||||
* @example
|
* @example
|
||||||
@@ -103,8 +98,6 @@ export async function updateProfile(data: Partial<ProfileData>): Promise<boolean
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates user bio
|
* Updates user bio
|
||||||
* @async
|
|
||||||
* @function updateBio
|
|
||||||
* @param {string} bio - New bio text
|
* @param {string} bio - New bio text
|
||||||
* @returns {Promise<boolean>} True if update was successful, false otherwise
|
* @returns {Promise<boolean>} True if update was successful, false otherwise
|
||||||
* @example
|
* @example
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import { updateProfile } from './api';
|
import { updateProfile } from './api';
|
||||||
import { loadProfile } from './api';
|
import { loadProfile } from './api';
|
||||||
import { showSuccess, showError } from '../utils/notification';
|
import { showSuccess, showError } from '../../utils/notification';
|
||||||
import type { TextField } from 'mdui/components/text-field';
|
import type { TextField } from 'mdui/components/text-field';
|
||||||
|
|
||||||
let profileForm = document.getElementById('profile-form')!;
|
let profileForm = document.getElementById('profile-form')!;
|
||||||
@@ -23,9 +23,6 @@ let isInitialized = false;
|
|||||||
/**
|
/**
|
||||||
* Sets the username field value
|
* Sets the username field value
|
||||||
* @param {string} value - The username value to set
|
* @param {string} value - The username value to set
|
||||||
* @function setUsernameValue
|
|
||||||
* @example
|
|
||||||
* setUsernameValue('John Doe');
|
|
||||||
*/
|
*/
|
||||||
export function setUsernameValue(value: string): void {
|
export function setUsernameValue(value: string): void {
|
||||||
if (nicknameField && nicknameField.value !== undefined) {
|
if (nicknameField && nicknameField.value !== undefined) {
|
||||||
@@ -36,9 +33,6 @@ export function setUsernameValue(value: string): void {
|
|||||||
/**
|
/**
|
||||||
* Sets the description field value
|
* Sets the description field value
|
||||||
* @param {string} value - The description value to set
|
* @param {string} value - The description value to set
|
||||||
* @function setDescriptionValue
|
|
||||||
* @example
|
|
||||||
* setDescriptionValue('Software Developer');
|
|
||||||
*/
|
*/
|
||||||
export function setDescriptionValue(value: string): void {
|
export function setDescriptionValue(value: string): void {
|
||||||
if (descriptionField && descriptionField.value !== undefined) {
|
if (descriptionField && descriptionField.value !== undefined) {
|
||||||
@@ -49,10 +43,6 @@ export function setDescriptionValue(value: string): void {
|
|||||||
/**
|
/**
|
||||||
* Gets the current username field value
|
* Gets the current username field value
|
||||||
* @returns {string} The current username value
|
* @returns {string} The current username value
|
||||||
* @function getUsernameValue
|
|
||||||
* @example
|
|
||||||
* const username = getUsernameValue();
|
|
||||||
* console.log('Current username:', username);
|
|
||||||
*/
|
*/
|
||||||
export function getUsernameValue(): string {
|
export function getUsernameValue(): string {
|
||||||
if (nicknameField && nicknameField.value !== undefined) {
|
if (nicknameField && nicknameField.value !== undefined) {
|
||||||
@@ -64,10 +54,6 @@ export function getUsernameValue(): string {
|
|||||||
/**
|
/**
|
||||||
* Gets the current description field value
|
* Gets the current description field value
|
||||||
* @returns {string} The current description value
|
* @returns {string} The current description value
|
||||||
* @function getDescriptionValue
|
|
||||||
* @example
|
|
||||||
* const description = getDescriptionValue();
|
|
||||||
* console.log('Current description:', description);
|
|
||||||
*/
|
*/
|
||||||
export function getDescriptionValue(): string {
|
export function getDescriptionValue(): string {
|
||||||
if (descriptionField && descriptionField.value !== undefined) {
|
if (descriptionField && descriptionField.value !== undefined) {
|
||||||
@@ -78,10 +64,6 @@ export function getDescriptionValue(): string {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads profile data from the server and populates the form fields
|
* Loads profile data from the server and populates the form fields
|
||||||
* @async
|
|
||||||
* @function loadProfileData
|
|
||||||
* @example
|
|
||||||
* await loadProfileData();
|
|
||||||
*/
|
*/
|
||||||
export async function loadProfileData(): Promise<void> {
|
export async function loadProfileData(): Promise<void> {
|
||||||
const userData = await loadProfile();
|
const userData = await loadProfile();
|
||||||
@@ -97,8 +79,6 @@ export async function loadProfileData(): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles profile form submission
|
* Handles profile form submission
|
||||||
* @async
|
|
||||||
* @function handleFormSubmission
|
|
||||||
* @param {Event} e - Form submission event
|
* @param {Event} e - Form submission event
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -124,7 +104,6 @@ async function handleFormSubmission(e: Event): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up form submission handler
|
* Sets up form submission handler
|
||||||
* @function setupFormHandler
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupFormHandler(): void {
|
function setupFormHandler(): void {
|
||||||
@@ -142,9 +121,6 @@ function setupFormHandler(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes profile editor functionality
|
* Initializes profile editor functionality
|
||||||
* @function initializeProfileEditor
|
|
||||||
* @example
|
|
||||||
* initializeProfileEditor();
|
|
||||||
*/
|
*/
|
||||||
export function initializeProfileEditor(): void {
|
export function initializeProfileEditor(): void {
|
||||||
setupFormHandler();
|
setupFormHandler();
|
||||||
+1
-18
@@ -5,7 +5,7 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Size2D } from "../types";
|
import type { Size2D } from "../../core/types";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image cropper class for circular profile picture cropping
|
* Image cropper class for circular profile picture cropping
|
||||||
@@ -63,7 +63,6 @@ export class ImageCropper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up mouse and touch event listeners
|
* Sets up mouse and touch event listeners
|
||||||
* @function setupEventListeners
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private setupEventListeners(): void {
|
private setupEventListeners(): void {
|
||||||
@@ -78,7 +77,6 @@ export class ImageCropper {
|
|||||||
/**
|
/**
|
||||||
* Handles mouse down events
|
* Handles mouse down events
|
||||||
* @param {MouseEvent} e - Mouse event
|
* @param {MouseEvent} e - Mouse event
|
||||||
* @function onMouseDown
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onMouseDown(e: MouseEvent): void {
|
private onMouseDown(e: MouseEvent): void {
|
||||||
@@ -89,7 +87,6 @@ export class ImageCropper {
|
|||||||
/**
|
/**
|
||||||
* Handles mouse move events during dragging
|
* Handles mouse move events during dragging
|
||||||
* @param {MouseEvent} e - Mouse event
|
* @param {MouseEvent} e - Mouse event
|
||||||
* @function onMouseMove
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onMouseMove(e: MouseEvent): void {
|
private onMouseMove(e: MouseEvent): void {
|
||||||
@@ -107,7 +104,6 @@ export class ImageCropper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles mouse up events
|
* Handles mouse up events
|
||||||
* @function onMouseUp
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onMouseUp(): void {
|
private onMouseUp(): void {
|
||||||
@@ -117,7 +113,6 @@ export class ImageCropper {
|
|||||||
/**
|
/**
|
||||||
* Handles touch start events
|
* Handles touch start events
|
||||||
* @param {TouchEvent} e - Touch event
|
* @param {TouchEvent} e - Touch event
|
||||||
* @function onTouchStart
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onTouchStart(e: TouchEvent): void {
|
private onTouchStart(e: TouchEvent): void {
|
||||||
@@ -130,7 +125,6 @@ export class ImageCropper {
|
|||||||
/**
|
/**
|
||||||
* Handles touch move events during dragging
|
* Handles touch move events during dragging
|
||||||
* @param {TouchEvent} e - Touch event
|
* @param {TouchEvent} e - Touch event
|
||||||
* @function onTouchMove
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onTouchMove(e: TouchEvent): void {
|
private onTouchMove(e: TouchEvent): void {
|
||||||
@@ -150,7 +144,6 @@ export class ImageCropper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles touch end events
|
* Handles touch end events
|
||||||
* @function onTouchEnd
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private onTouchEnd(): void {
|
private onTouchEnd(): void {
|
||||||
@@ -161,9 +154,6 @@ export class ImageCropper {
|
|||||||
* Loads an image file for cropping
|
* Loads an image file for cropping
|
||||||
* @param {File} file - Image file to load
|
* @param {File} file - Image file to load
|
||||||
* @returns {Promise<void>} Promise that resolves when image is loaded
|
* @returns {Promise<void>} Promise that resolves when image is loaded
|
||||||
* @async
|
|
||||||
* @example
|
|
||||||
* await cropper.loadImage(fileInput.files[0]);
|
|
||||||
*/
|
*/
|
||||||
loadImage(file: File): Promise<void> {
|
loadImage(file: File): Promise<void> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@@ -178,7 +168,6 @@ export class ImageCropper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the image with circular crop overlay
|
* Renders the image with circular crop overlay
|
||||||
* @function render
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private render(): void {
|
private render(): void {
|
||||||
@@ -216,9 +205,6 @@ export class ImageCropper {
|
|||||||
/**
|
/**
|
||||||
* Gets the cropped image as a data URL
|
* Gets the cropped image as a data URL
|
||||||
* @returns {string} Data URL of the cropped image
|
* @returns {string} Data URL of the cropped image
|
||||||
* @example
|
|
||||||
* const croppedImage = cropper.getCroppedImage();
|
|
||||||
* // Use croppedImage as src for an img element
|
|
||||||
*/
|
*/
|
||||||
getCroppedImage(): string {
|
getCroppedImage(): string {
|
||||||
return this.canvas.toDataURL('image/jpeg', 0.8);
|
return this.canvas.toDataURL('image/jpeg', 0.8);
|
||||||
@@ -226,9 +212,6 @@ export class ImageCropper {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the cropper and removes the canvas from DOM
|
* Destroys the cropper and removes the canvas from DOM
|
||||||
* @function destroy
|
|
||||||
* @example
|
|
||||||
* cropper.destroy();
|
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
if (this.canvas.parentNode) {
|
if (this.canvas.parentNode) {
|
||||||
@@ -6,9 +6,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Dialog } from "mdui/components/dialog";
|
import type { Dialog } from "mdui/components/dialog";
|
||||||
import { loadProfileData } from './profile/editor';
|
import { loadProfileData } from './editor';
|
||||||
import { loadProfilePicture, initializeProfileUpload } from "./profile/upload";
|
import { loadProfilePicture, initializeProfileUpload } from "./upload";
|
||||||
import { initializeProfileEditor } from './profile/editor';
|
import { initializeProfileEditor } from './editor';
|
||||||
|
|
||||||
// Handle profile form submission
|
// Handle profile form submission
|
||||||
const form = document.getElementById("profile-form")!;
|
const form = document.getElementById("profile-form")!;
|
||||||
@@ -24,10 +24,6 @@ form.addEventListener("submit", async (e) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes profile functionality after user login
|
* Initializes profile functionality after user login
|
||||||
* @function initializeProfile
|
|
||||||
* @example
|
|
||||||
* // Called after successful authentication
|
|
||||||
* initializeProfile();
|
|
||||||
*/
|
*/
|
||||||
export function initializeProfile(): void {
|
export function initializeProfile(): void {
|
||||||
// Initialize profile modules
|
// Initialize profile modules
|
||||||
@@ -6,10 +6,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Dialog } from "mdui/components/dialog";
|
import type { Dialog } from "mdui/components/dialog";
|
||||||
import { ImageCropper } from './image-cropper';
|
import { ImageCropper } from './imageCropper';
|
||||||
import { uploadProfilePicture } from './api';
|
import { uploadProfilePicture } from './api';
|
||||||
import { loadProfile } from './api';
|
import { loadProfile } from './api';
|
||||||
import { showSuccess, showError } from '../utils/notification';
|
import { showSuccess, showError } from '../../utils/notification';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global image cropper instance
|
* Global image cropper instance
|
||||||
@@ -33,8 +33,6 @@ let cropperArea = document.getElementById('cropper-area')!;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the image cropper with the selected file
|
* Opens the image cropper with the selected file
|
||||||
* @async
|
|
||||||
* @function openCropper
|
|
||||||
* @param {File} file - The image file to crop
|
* @param {File} file - The image file to crop
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -54,7 +52,6 @@ async function openCropper(file: File): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the image cropper and cleans up resources
|
* Closes the image cropper and cleans up resources
|
||||||
* @function closeCropper
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function closeCropper(): void {
|
function closeCropper(): void {
|
||||||
@@ -69,8 +66,6 @@ function closeCropper(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the cropped image and uploads it to the server
|
* Saves the cropped image and uploads it to the server
|
||||||
* @async
|
|
||||||
* @function saveCroppedImage
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
async function saveCroppedImage(): Promise<void> {
|
async function saveCroppedImage(): Promise<void> {
|
||||||
@@ -87,7 +82,7 @@ async function saveCroppedImage(): Promise<void> {
|
|||||||
if (result) {
|
if (result) {
|
||||||
// Update profile picture display
|
// Update profile picture display
|
||||||
const profilePicture = document.getElementById('profile-picture') as HTMLImageElement;
|
const profilePicture = document.getElementById('profile-picture') as HTMLImageElement;
|
||||||
profilePicture.src = result.profile_picture_url + '?t=' + Date.now(); // Cache bust
|
profilePicture.src = `${result.profile_picture_url}?t=${Date.now()}`; // Cache bust
|
||||||
|
|
||||||
// Close cropper
|
// Close cropper
|
||||||
closeCropper();
|
closeCropper();
|
||||||
@@ -101,7 +96,6 @@ async function saveCroppedImage(): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up event listeners for upload functionality
|
* Sets up event listeners for upload functionality
|
||||||
* @function setupEventListeners
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupEventListeners(): void {
|
function setupEventListeners(): void {
|
||||||
@@ -136,9 +130,6 @@ function setupEventListeners(): void {
|
|||||||
/**
|
/**
|
||||||
* Loads and displays the user's profile picture
|
* Loads and displays the user's profile picture
|
||||||
* @async
|
* @async
|
||||||
* @function loadProfilePicture
|
|
||||||
* @example
|
|
||||||
* await loadProfilePicture();
|
|
||||||
*/
|
*/
|
||||||
export async function loadProfilePicture(): Promise<void> {
|
export async function loadProfilePicture(): Promise<void> {
|
||||||
const userData = await loadProfile();
|
const userData = await loadProfile();
|
||||||
@@ -154,9 +145,6 @@ export async function loadProfilePicture(): Promise<void> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes profile upload functionality
|
* Initializes profile upload functionality
|
||||||
* @function initializeProfileUpload
|
|
||||||
* @example
|
|
||||||
* initializeProfileUpload();
|
|
||||||
*/
|
*/
|
||||||
export function initializeProfileUpload(): void {
|
export function initializeProfileUpload(): void {
|
||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
@@ -32,7 +32,6 @@ const panelMapping = {
|
|||||||
/**
|
/**
|
||||||
* Handles click events on settings list items
|
* Handles click events on settings list items
|
||||||
* @param {Element} item - The clicked list item element
|
* @param {Element} item - The clicked list item element
|
||||||
* @function handleListItemClick
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function handleListItemClick(item: Element): void {
|
function handleListItemClick(item: Element): void {
|
||||||
@@ -58,7 +57,6 @@ function handleListItemClick(item: Element): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up click listeners for all settings list items
|
* Sets up click listeners for all settings list items
|
||||||
* @function setupSettingsNavigation
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupSettingsNavigation(): void {
|
function setupSettingsNavigation(): void {
|
||||||
@@ -70,7 +68,6 @@ function setupSettingsNavigation(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets settings dialog to show the first panel
|
* Resets settings dialog to show the first panel
|
||||||
* @function resetToFirstPanel
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function resetToFirstPanel(): void {
|
function resetToFirstPanel(): void {
|
||||||
@@ -86,7 +83,6 @@ function resetToFirstPanel(): void {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up dialog event listeners
|
* Sets up dialog event listeners
|
||||||
* @function setupDialogListeners
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function setupDialogListeners(): void {
|
function setupDialogListeners(): void {
|
||||||
@@ -15,7 +15,6 @@ export type NotificationType = 'success' | 'error';
|
|||||||
* Shows a notification with the specified message and type
|
* Shows a notification with the specified message and type
|
||||||
* @param {string} message - The message to display
|
* @param {string} message - The message to display
|
||||||
* @param {NotificationType} type - The type of notification (success or error)
|
* @param {NotificationType} type - The type of notification (success or error)
|
||||||
* @function showNotification
|
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function showNotification(message: string, type: NotificationType): void {
|
function showNotification(message: string, type: NotificationType): void {
|
||||||
@@ -49,9 +48,6 @@ function showNotification(message: string, type: NotificationType): void {
|
|||||||
/**
|
/**
|
||||||
* Shows a success notification
|
* Shows a success notification
|
||||||
* @param {string} message - The success message to display
|
* @param {string} message - The success message to display
|
||||||
* @function showSuccess
|
|
||||||
* @example
|
|
||||||
* showSuccess('Profile updated successfully!');
|
|
||||||
*/
|
*/
|
||||||
export function showSuccess(message: string): void {
|
export function showSuccess(message: string): void {
|
||||||
showNotification(message, 'success');
|
showNotification(message, 'success');
|
||||||
@@ -60,9 +56,6 @@ export function showSuccess(message: string): void {
|
|||||||
/**
|
/**
|
||||||
* Shows an error notification
|
* Shows an error notification
|
||||||
* @param {string} message - The error message to display
|
* @param {string} message - The error message to display
|
||||||
* @function showError
|
|
||||||
* @example
|
|
||||||
* showError('Failed to update profile');
|
|
||||||
*/
|
*/
|
||||||
export function showError(message: string): void {
|
export function showError(message: string): void {
|
||||||
showNotification(message, 'error');
|
showNotification(message, 'error');
|
||||||
|
|||||||
+21
-15
@@ -5,14 +5,12 @@
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { handleWebSocketMessage } from "./chat";
|
import { handleWebSocketMessage } from "./chat/chat";
|
||||||
import { API_FULL_BASE_URL } from "./config";
|
import { API_WS_BASE_URL } from "./core/config";
|
||||||
import type { WebSocketMessage } from "./types";
|
|
||||||
import { delay } from "./utils/utils";
|
import { delay } from "./utils/utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new WebSocket connection to the chat server
|
* Creates a new WebSocket connection to the chat server
|
||||||
* @function create
|
|
||||||
* @returns {WebSocket} New WebSocket instance
|
* @returns {WebSocket} New WebSocket instance
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@@ -22,7 +20,7 @@ function create(): WebSocket {
|
|||||||
prefix = "wss://";
|
prefix = "wss://";
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WebSocket(`${prefix}${API_FULL_BASE_URL}/chat/ws`);
|
return new WebSocket(`${prefix}${API_WS_BASE_URL}/chat/ws`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -31,16 +29,14 @@ function create(): WebSocket {
|
|||||||
*/
|
*/
|
||||||
export let websocket: WebSocket = create();
|
export let websocket: WebSocket = create();
|
||||||
|
|
||||||
// --------------
|
/**
|
||||||
// Initialization
|
* This function will wait 3 seconds and them attempts to reconnect the WebSocket.
|
||||||
// --------------
|
* If it fails, tries again in an endless loop until the connection is established
|
||||||
|
* again.
|
||||||
websocket.addEventListener("message", (e) => {
|
*
|
||||||
const message: WebSocketMessage = JSON.parse(e.data);
|
* @private
|
||||||
handleWebSocketMessage(message);
|
*/
|
||||||
});
|
async function onError() {
|
||||||
|
|
||||||
websocket.addEventListener("error", async () => {
|
|
||||||
console.warn("WebSocket disconnected, retrying in 3 seconds...");
|
console.warn("WebSocket disconnected, retrying in 3 seconds...");
|
||||||
await delay(3000);
|
await delay(3000);
|
||||||
websocket = create();
|
websocket = create();
|
||||||
@@ -52,4 +48,14 @@ websocket.addEventListener("error", async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
websocket.addEventListener("open", listener);
|
websocket.addEventListener("open", listener);
|
||||||
|
websocket.addEventListener("error", onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Initialization
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
websocket.addEventListener("message", (e) => {
|
||||||
|
handleWebSocketMessage(JSON.parse(e.data));
|
||||||
});
|
});
|
||||||
|
websocket.addEventListener("error", onError);
|
||||||
Reference in New Issue
Block a user