diff --git a/.gitignore b/.gitignore index 5b669df..ff9c37b 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,4 @@ testem.log # System files .DS_Store Thumbs.db +CLAUDE.md diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..1e9202d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "Webnative.webnative" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0abbfd2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.preferences.autoImportFileExcludePatterns": ["@ionic/angular/common", "@ionic/angular/standalone"] +} diff --git a/CLAUDE.md b/CLAUDE.md index 452f0d9..a00d765 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,35 +1,33 @@ -# chat_app +# chat_app_v2 -Angular 10 / Ionic 5 frontend for the Chatli messaging platform. - -## Stack -- TypeScript, Angular 10, Ionic 5 -- Capacitor for native mobile builds -- JWT-based auth (jwt-decode) -- WebSocket for real-time messaging +Angular 20 / Ionic 8 standalone chat client for the Chatli messaging backend. ## Build & run ```bash +eval "$(mise activate bash)" npm install -npm start # Dev server -npm run build -- --prod # Production build -docker build -t fra/chatapp . && docker run -p 8100:8100 fra/chatapp +npm start # Dev server +npm run build # Production build +npm run lint # ESLint ``` -## Test -```bash -npm test # Karma + Jasmine -npm run e2e # Protractor -npm run lint # TSLint -``` +## Architecture +- Fully standalone components (no NgModules) +- Bootstrap: `bootstrapApplication()` with `provideIonicAngular()` +- Builder: `@angular-devkit/build-angular:application` with `browser` key +- Ionic imports: individual components from `@ionic/angular/standalone` +- Ionicons: `addIcons()` in component constructors +- State: Angular signals (`signal`, `computed`) +- HTTP: `withInterceptors([authInterceptor, errorInterceptor])` ## Backend connection -- REST API: http://localhost:8090/v1 (public), http://localhost:8090/client (auth required) +- REST API: http://localhost:8090/v1 (public), http://localhost:8090/client (auth) - WebSocket: ws://localhost:8090/client/device/:deviceid/user/:userid/ws ## Structure -- `src/app/pages/` — page components (login, signup, chat, main) -- `src/app/services/` — auth, chat, message, storage services -- `src/app/models/` — data models (user, chat, message, participant) -- `src/app/helpers/` — HTTP interceptors (auth token injection, error handling) +- `src/app/pages/` — page components (login, signup, chats, contacts, messages, tabs) +- `src/app/services/` — auth, chat, message, user services +- `src/app/models/` — data models +- `src/app/components/` — reusable components (avatar) - `src/app/guards/` — route guards +- `src/app/interceptors/` — auth + error interceptors diff --git a/src/app/pages/messages/messages.page.ts b/src/app/pages/messages/messages.page.ts index 42f8337..90edf05 100644 --- a/src/app/pages/messages/messages.page.ts +++ b/src/app/pages/messages/messages.page.ts @@ -179,9 +179,8 @@ export class MessagesPage implements OnInit, OnDestroy { this.chatService.getChat({ id: chatId } as Chat).subscribe((chat) => { this.currentChat = chat; - const others = chat.participants ?? []; - this.title = others.length === 1 ? (others[0].username ?? chat.name ?? '') : (chat.name ?? ''); - this.participants = [...others]; + this.title = chat.name ?? ''; + this.participants = [...(chat.participants ?? [])]; const currentUser = this.auth.currentUserValue; if (currentUser) this.participants.push(currentUser); @@ -258,9 +257,8 @@ export class MessagesPage implements OnInit, OnDestroy { const { data } = await modal.onDidDismiss(); if (data) { this.currentChat = data; - const updatedOthers = data.participants ?? []; - this.title = updatedOthers.length === 1 ? (updatedOthers[0].username ?? data.name ?? '') : (data.name ?? ''); - this.participants = [...updatedOthers]; + this.title = data.name ?? ''; + this.participants = [...(data.participants ?? [])]; const currentUser = this.auth.currentUserValue; if (currentUser) this.participants.push(currentUser); }