Start implementing direct messaging and continued developing the chatnav
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import {Routes} from '@angular/router';
|
||||
import {SignIn} from './signin/signin';
|
||||
import {Chat} from './chat/chat';
|
||||
import {Dm} from './chat/dm/dm';
|
||||
|
||||
export const routes: Routes = [
|
||||
{ path: 'signin', component: SignIn },
|
||||
{ path: 'chat', component: Chat },
|
||||
{path: 'signin', component: SignIn},
|
||||
{
|
||||
path: 'chat', component: Chat, children: [
|
||||
{path: 'dm/:chatid', component: Dm},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<tui-loader size="xl"/>
|
||||
</main>
|
||||
} @else {
|
||||
<main id="layout">
|
||||
<main id="layout" tuiGroup [collapsed]="true">
|
||||
<aside id="chatnav">
|
||||
<aside>
|
||||
<tui-segmented id="mode_switcher">
|
||||
@@ -30,8 +30,9 @@
|
||||
|
||||
<main id="content">
|
||||
<div id="content_tint">
|
||||
{{serviceManager.currentSession()|json}}
|
||||
<router-outlet/>
|
||||
@defer (when serviceManager.chatsStatus() != LoadStatus.loading) {
|
||||
<router-outlet/>
|
||||
}
|
||||
</div>
|
||||
</main>
|
||||
</main>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#layout {
|
||||
display: grid;
|
||||
grid-template-columns: 20% 80%;
|
||||
grid-template-columns: 350px minmax(0, 1fr);
|
||||
height: 100svh;
|
||||
|
||||
#chatnav {
|
||||
display: grid;
|
||||
grid-template-columns: 25% 75%;
|
||||
grid-template-columns: 70px minmax(0, 1fr);
|
||||
|
||||
aside {
|
||||
padding: 15px;
|
||||
@@ -36,18 +36,22 @@
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 25px;
|
||||
padding-top: 65px;
|
||||
background: var(--tui-background-base-alt);
|
||||
border-radius: 20px 0 0 20px;
|
||||
margin: 10px 0 10px 10px;
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
padding: 10px 10px 10px 0;
|
||||
|
||||
#content_tint {
|
||||
border-radius: 0 20px 20px 0;
|
||||
height: 100%;
|
||||
border-radius: 20px;
|
||||
background: var(--tui-background-base-alt);
|
||||
background: var(--tui-background-neutral-2);
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {Component, inject, OnInit} from '@angular/core';
|
||||
import {RouterOutlet} from '@angular/router';
|
||||
import {TuiSegmented} from '@taiga-ui/kit';
|
||||
import {TuiButton, TuiIcon, TuiLoader} from '@taiga-ui/core';
|
||||
import {TuiAppearance, TuiButton, TuiGroup, TuiIcon, TuiLoader} from '@taiga-ui/core';
|
||||
import {SessionManager} from '@chatenium/chatenium-sdk/services/sessionManager';
|
||||
import {ServiceManager} from '../service-manager';
|
||||
import {LoadStatus, ServiceManager} from '../service-manager';
|
||||
import {IndexedDB} from '../storage/indexed-db';
|
||||
import {DmList} from './dm-list/dm-list';
|
||||
import {JsonPipe} from '@angular/common';
|
||||
@@ -17,7 +17,9 @@ import {JsonPipe} from '@angular/common';
|
||||
TuiButton,
|
||||
TuiLoader,
|
||||
DmList,
|
||||
JsonPipe
|
||||
JsonPipe,
|
||||
TuiAppearance,
|
||||
TuiGroup
|
||||
],
|
||||
templateUrl: './chat.html',
|
||||
styleUrl: './chat.scss',
|
||||
@@ -31,4 +33,6 @@ export class Chat implements OnInit {
|
||||
this.serviceManager.currentSession.set(await this.serviceManager.sessionManager.loadPreferredSession())
|
||||
})
|
||||
}
|
||||
|
||||
protected readonly LoadStatus = LoadStatus;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
@for (chat of chats(); track chat.chatid) {
|
||||
{{chat.chatid}}
|
||||
<button tuiButton appearance="secondary" iconStart="@tui.mail-plus">
|
||||
{{"chat.chatnav.dmList.newChat"|translate}}
|
||||
</button>
|
||||
|
||||
@for (chat of serviceManager.chats(); track chat.chatid) {
|
||||
<button tuiButton [appearance]="router.url == '/chat/dm/' + chat.chatid ? 'primary' : 'flat'" [routerLink]="'/chat/dm/' + chat.chatid">
|
||||
<oimg [src]="chat.pfp" height="35px" width="35px" [radius]="10"></oimg>
|
||||
<div class="info">
|
||||
@if (chat.displayName == "") {
|
||||
<span>{{'@'+chat.username}}</span>
|
||||
} @else {
|
||||
<span>{{chat.displayName}}</span>
|
||||
}
|
||||
@if (chat.latestMessage) {
|
||||
<span class="latest_message">
|
||||
@if (chat.latestMessage.isAuthor) {
|
||||
{{"chat.chatnav.dmList.messageBox.latestMessage.you"|translate}}
|
||||
}
|
||||
{{chat.latestMessage.message}}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
font-weight: 600;
|
||||
|
||||
.info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: start;
|
||||
|
||||
.latest_message {
|
||||
margin-top: -5px;
|
||||
font-size: 12px;
|
||||
opacity: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,19 @@ import {Component, inject, input, OnInit, signal} from '@angular/core';
|
||||
import {ChatService} from '@chatenium/chatenium-sdk/services/chatService';
|
||||
import {IndexedDB} from '../../storage/indexed-db';
|
||||
import {Chat} from '@chatenium/chatenium-sdk/domain/chatService.schema';
|
||||
import {JsonPipe} from '@angular/common';
|
||||
import {TuiButton} from '@taiga-ui/core';
|
||||
import {Oimg} from '../elements/oimg/oimg';
|
||||
import {Router, RouterLink} from '@angular/router';
|
||||
import {TranslatePipe} from '@ngx-translate/core';
|
||||
import {LoadStatus, ServiceManager} from '../../service-manager';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dm-list',
|
||||
imports: [
|
||||
JsonPipe
|
||||
TuiButton,
|
||||
Oimg,
|
||||
RouterLink,
|
||||
TranslatePipe
|
||||
],
|
||||
templateUrl: './dm-list.html',
|
||||
styleUrl: './dm-list.scss',
|
||||
@@ -17,19 +24,17 @@ export class DmList implements OnInit {
|
||||
token = input<string>("")
|
||||
|
||||
indexedDb = inject(IndexedDB)
|
||||
|
||||
service: ChatService | null = null
|
||||
chats = signal<Chat[]>([])
|
||||
chatsStatus = 0
|
||||
router = inject(Router)
|
||||
serviceManager = inject(ServiceManager)
|
||||
|
||||
async ngOnInit() {
|
||||
this.service = new ChatService(this.userid(), this.token(), this.indexedDb.getApi(), () => {})
|
||||
this.serviceManager.chatService = new ChatService(this.userid(), this.token(), this.indexedDb.getApi(), () => {})
|
||||
try {
|
||||
this.chats.set(await this.service.get())
|
||||
this.chatsStatus = 1
|
||||
this.serviceManager.chats.set(await this.serviceManager.chatService.get())
|
||||
this.serviceManager.chatsStatus.set(LoadStatus.loaded)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.chatsStatus = 2
|
||||
this.serviceManager.chatsStatus.set(LoadStatus.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
src/app/chat/dm/dm.html
Normal file
27
src/app/chat/dm/dm.html
Normal file
@@ -0,0 +1,27 @@
|
||||
@defer (when store) {
|
||||
<navbar>
|
||||
<div class="items-left">
|
||||
<oimg [src]="store.chatData.pfp" height="50px" width="50px" [radius]="15"></oimg>
|
||||
<div class="chat-data">
|
||||
@if (store.chatData.displayName == "") {
|
||||
<span class="main-name">{{'@'+store.chatData.username}}</span>
|
||||
} @else {
|
||||
<span class="main-name">{{store.chatData.displayName}}</span>
|
||||
<span class="alt-name">{{'@'+store.chatData.username}}</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="items-right">
|
||||
<button tuiButton appearance="flat">
|
||||
<tui-icon icon="@tui.phone"/>
|
||||
</button>
|
||||
</div>
|
||||
</navbar>
|
||||
|
||||
<main>
|
||||
|
||||
</main>
|
||||
|
||||
<message-box/>
|
||||
}
|
||||
33
src/app/chat/dm/dm.scss
Normal file
33
src/app/chat/dm/dm.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
:host {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: 70px minmax(0, 1fr) auto;
|
||||
|
||||
navbar {
|
||||
.chat-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.main-name {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.alt-name {
|
||||
margin-top: -5px;
|
||||
color: gray;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.items-right {
|
||||
margin-top: -10px;
|
||||
|
||||
button {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
22
src/app/chat/dm/dm.spec.ts
Normal file
22
src/app/chat/dm/dm.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Dm } from './dm';
|
||||
|
||||
describe('Dm', () => {
|
||||
let component: Dm;
|
||||
let fixture: ComponentFixture<Dm>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Dm],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Dm);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
56
src/app/chat/dm/dm.ts
Normal file
56
src/app/chat/dm/dm.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import {Component, inject, OnInit} from '@angular/core';
|
||||
import {DmStorage, ServiceManager} from '../../service-manager';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {DMService} from '@chatenium/chatenium-sdk/services/dmService';
|
||||
import {IndexedDB} from '../../storage/indexed-db';
|
||||
import {Navbar} from '../elements/navbar/navbar';
|
||||
import {Oimg} from '../elements/oimg/oimg';
|
||||
import {TuiButton, TuiIcon} from '@taiga-ui/core';
|
||||
import {MessageBox} from '../elements/message-box/message-box';
|
||||
|
||||
@Component({
|
||||
selector: 'app-dm',
|
||||
imports: [
|
||||
Navbar,
|
||||
Oimg,
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
MessageBox
|
||||
],
|
||||
templateUrl: './dm.html',
|
||||
styleUrl: './dm.scss',
|
||||
})
|
||||
export class Dm implements OnInit {
|
||||
serviceManager = inject(ServiceManager)
|
||||
route = inject(ActivatedRoute)
|
||||
indexedDb = inject(IndexedDB)
|
||||
|
||||
chatid = ""
|
||||
|
||||
get store(): DmStorage {
|
||||
return this.serviceManager.dmServices()[this.chatid]
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.params.subscribe(params => {
|
||||
const chatid = params['chatid']
|
||||
this.chatid = chatid
|
||||
console.log(this.serviceManager.chats())
|
||||
const session = this.serviceManager.currentSession();
|
||||
const chatData = this.serviceManager.chats().find(chat => chat.chatid == chatid)
|
||||
|
||||
if (!this.serviceManager.dmServices()[chatid] && session != null && chatData != null) {
|
||||
this.serviceManager.dmServices()[chatid] = {
|
||||
service: new DMService(
|
||||
session.userData.userid,
|
||||
session.token,
|
||||
chatid,
|
||||
this.indexedDb.getApi(),
|
||||
() => {}
|
||||
),
|
||||
chatData: chatData
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
7
src/app/chat/elements/message-box/message-box.html
Normal file
7
src/app/chat/elements/message-box/message-box.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<div id="message-box">
|
||||
<div></div>
|
||||
<div class="items-middle">
|
||||
<textarea></textarea>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
29
src/app/chat/elements/message-box/message-box.scss
Normal file
29
src/app/chat/elements/message-box/message-box.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
:host {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
#message-box {
|
||||
width: 60%;
|
||||
background: var(--tui-background-base-alt);
|
||||
height: 75px;
|
||||
border-radius: 200px;
|
||||
border: 2px solid var(--tui-border-normal);
|
||||
display: grid;
|
||||
grid-template-columns: 10% 80% 10%;
|
||||
align-items: center;
|
||||
padding: 0 10px;
|
||||
|
||||
.items-middle {
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
resize: none;
|
||||
color: var(--tui-text-01);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
22
src/app/chat/elements/message-box/message-box.spec.ts
Normal file
22
src/app/chat/elements/message-box/message-box.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MessageBox } from './message-box';
|
||||
|
||||
describe('MessageBox', () => {
|
||||
let component: MessageBox;
|
||||
let fixture: ComponentFixture<MessageBox>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MessageBox],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(MessageBox);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
12
src/app/chat/elements/message-box/message-box.ts
Normal file
12
src/app/chat/elements/message-box/message-box.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {TuiAppearance} from '@taiga-ui/core';
|
||||
|
||||
@Component({
|
||||
selector: 'message-box',
|
||||
imports: [
|
||||
TuiAppearance
|
||||
],
|
||||
templateUrl: './message-box.html',
|
||||
styleUrl: './message-box.scss',
|
||||
})
|
||||
export class MessageBox {}
|
||||
3
src/app/chat/elements/navbar/navbar.html
Normal file
3
src/app/chat/elements/navbar/navbar.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<nav>
|
||||
<ng-content></ng-content>
|
||||
</nav>
|
||||
15
src/app/chat/elements/navbar/navbar.scss
Normal file
15
src/app/chat/elements/navbar/navbar.scss
Normal file
@@ -0,0 +1,15 @@
|
||||
nav {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
::ng-deep .items-right, ::ng-deep .items-left {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
::ng-deep .items-right {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
}
|
||||
}
|
||||
22
src/app/chat/elements/navbar/navbar.spec.ts
Normal file
22
src/app/chat/elements/navbar/navbar.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Navbar } from './navbar';
|
||||
|
||||
describe('Navbar', () => {
|
||||
let component: Navbar;
|
||||
let fixture: ComponentFixture<Navbar>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Navbar],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Navbar);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
9
src/app/chat/elements/navbar/navbar.ts
Normal file
9
src/app/chat/elements/navbar/navbar.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'navbar',
|
||||
imports: [],
|
||||
templateUrl: './navbar.html',
|
||||
styleUrl: './navbar.scss',
|
||||
})
|
||||
export class Navbar {}
|
||||
1
src/app/chat/elements/oimg/oimg.html
Normal file
1
src/app/chat/elements/oimg/oimg.html
Normal file
@@ -0,0 +1 @@
|
||||
<img [src]="src()" [style]="'width:'+width()+';height:'+height()+'; border-radius: '+radius()+'px;'" class="">
|
||||
0
src/app/chat/elements/oimg/oimg.scss
Normal file
0
src/app/chat/elements/oimg/oimg.scss
Normal file
22
src/app/chat/elements/oimg/oimg.spec.ts
Normal file
22
src/app/chat/elements/oimg/oimg.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Oimg } from './oimg';
|
||||
|
||||
describe('Oimg', () => {
|
||||
let component: Oimg;
|
||||
let fixture: ComponentFixture<Oimg>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [Oimg],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(Oimg);
|
||||
component = fixture.componentInstance;
|
||||
await fixture.whenStable();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
18
src/app/chat/elements/oimg/oimg.ts
Normal file
18
src/app/chat/elements/oimg/oimg.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import {Component, input, Input, signal} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'oimg',
|
||||
imports: [],
|
||||
templateUrl: './oimg.html',
|
||||
styleUrl: './oimg.scss',
|
||||
host: {
|
||||
"[style.height]": "height()",
|
||||
"[style.width]": "width()",
|
||||
}
|
||||
})
|
||||
export class Oimg {
|
||||
height = input("")
|
||||
width = input("")
|
||||
src = input("")
|
||||
radius = input(15)
|
||||
}
|
||||
@@ -4,6 +4,9 @@ import {Keyring} from './storage/keyring';
|
||||
import {KeyValue} from './storage/key-value';
|
||||
import {SessionManager} from '@chatenium/chatenium-sdk/services/sessionManager';
|
||||
import {Session} from '@chatenium/chatenium-sdk/domain/sessionManager.schema';
|
||||
import {ChatService} from '@chatenium/chatenium-sdk/services/chatService';
|
||||
import {Chat} from '@chatenium/chatenium-sdk/domain/chatService.schema';
|
||||
import {DMService} from '@chatenium/chatenium-sdk/services/dmService';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@@ -15,4 +18,22 @@ export class ServiceManager {
|
||||
|
||||
sessionManager = new SessionManager(this.database.getApi(), this.keyring.getApi(), this.keyValue.getApi())
|
||||
currentSession = signal<Session | null>(null)
|
||||
|
||||
chatService: ChatService | null = null // Initialized in dm-list.ts
|
||||
chatsStatus = signal<LoadStatus>(LoadStatus.loading)
|
||||
chats = signal<Chat[]>([])
|
||||
|
||||
dmServices = signal<Record<string, DmStorage>>({})
|
||||
}
|
||||
|
||||
export enum LoadStatus {
|
||||
loading = 0,
|
||||
loaded = 1,
|
||||
error = 2,
|
||||
updating = 3,
|
||||
}
|
||||
|
||||
export interface DmStorage {
|
||||
service: DMService
|
||||
chatData: Chat
|
||||
}
|
||||
|
||||
@@ -20,3 +20,9 @@ body {
|
||||
src: url("/Onest-ExtraBold.ttf");
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Onest";
|
||||
src: url("/Onest-SemiBold.ttf");
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user