diff --git a/angular.json b/angular.json
index b8a09b85..f2ff4b21 100644
--- a/angular.json
+++ b/angular.json
@@ -398,6 +398,44 @@
}
}
},
+ "ucap-webmessenger-ui-chat": {
+ "projectType": "library",
+ "schematics": {
+ "@schematics/angular:component": {
+ "style": "scss"
+ }
+ },
+ "root": "projects/ucap-webmessenger-ui-chat",
+ "sourceRoot": "projects/ucap-webmessenger-ui-chat/src",
+ "prefix": "ucap-chat",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-ng-packagr:build",
+ "options": {
+ "tsConfig": "projects/ucap-webmessenger-ui-chat/tsconfig.lib.json",
+ "project": "projects/ucap-webmessenger-ui-chat/ng-package.json"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "projects/ucap-webmessenger-ui-chat/src/test.ts",
+ "tsConfig": "projects/ucap-webmessenger-ui-chat/tsconfig.spec.json",
+ "karmaConfig": "projects/ucap-webmessenger-ui-chat/karma.conf.js"
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "projects/ucap-webmessenger-ui-chat/tsconfig.lib.json",
+ "projects/ucap-webmessenger-ui-chat/tsconfig.spec.json"
+ ],
+ "exclude": ["**/node_modules/**"]
+ }
+ }
+ }
+ },
"ucap-webmessenger-ui-messenger": {
"projectType": "library",
"schematics": {
diff --git a/projects/ucap-webmessenger-app/src/app/app-routing.module.ts b/projects/ucap-webmessenger-app/src/app/app-routing.module.ts
index ce7e1aa9..8498a642 100644
--- a/projects/ucap-webmessenger-app/src/app/app-routing.module.ts
+++ b/projects/ucap-webmessenger-app/src/app/app-routing.module.ts
@@ -1,21 +1,22 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
-import { AuthGuard } from './guards/auth.guard';
-import { MessengerResolver } from './resolvers/messenger.resolver';
+import { AppAuthGuard } from './guards/auth.guard';
+import { AppMessengerResolver } from './resolvers/messenger.resolver';
const routes: Routes = [
{ path: '', redirectTo: '/messenger', pathMatch: 'full' },
{
path: 'messenger',
- loadChildren: './pages/messenger/messenger.page.module#MessengerPageModule',
- canActivate: [AuthGuard],
+ loadChildren:
+ './pages/messenger/messenger.page.module#AppMessengerPageModule',
+ canActivate: [AppAuthGuard],
resolve: {
- protocol: MessengerResolver
+ protocol: AppMessengerResolver
}
},
{
path: 'account',
- loadChildren: './pages/account/account.page.module#AccountPageModule'
+ loadChildren: './pages/account/account.page.module#AppAccountPageModule'
}
];
diff --git a/projects/ucap-webmessenger-app/src/app/guards/auth.guard.ts b/projects/ucap-webmessenger-app/src/app/guards/auth.guard.ts
index 0feb87b1..145d6bde 100644
--- a/projects/ucap-webmessenger-app/src/app/guards/auth.guard.ts
+++ b/projects/ucap-webmessenger-app/src/app/guards/auth.guard.ts
@@ -15,7 +15,7 @@ import { AppAuthenticationService } from '../services/authentication.service';
@Injectable({
providedIn: 'root'
})
-export class AuthGuard implements CanActivate {
+export class AppAuthGuard implements CanActivate {
constructor(
private router: Router,
private appAuthenticationService: AppAuthenticationService
diff --git a/projects/ucap-webmessenger-app/src/app/guards/index.ts b/projects/ucap-webmessenger-app/src/app/guards/index.ts
index d2030c3c..04d11727 100644
--- a/projects/ucap-webmessenger-app/src/app/guards/index.ts
+++ b/projects/ucap-webmessenger-app/src/app/guards/index.ts
@@ -1,3 +1,3 @@
-import { AuthGuard } from './auth.guard';
+import { AppAuthGuard } from './auth.guard';
-export const GUARDS = [AuthGuard];
+export const GUARDS = [AppAuthGuard];
diff --git a/projects/ucap-webmessenger-app/src/app/interceptors/loader.interceptor.ts b/projects/ucap-webmessenger-app/src/app/interceptors/loader.interceptor.ts
index e0fd1e7b..ec560327 100644
--- a/projects/ucap-webmessenger-app/src/app/interceptors/loader.interceptor.ts
+++ b/projects/ucap-webmessenger-app/src/app/interceptors/loader.interceptor.ts
@@ -10,7 +10,7 @@ import { finalize, delay } from 'rxjs/operators';
import { AppLoaderService } from '../services/loader.service';
@Injectable()
-export class LoaderInterceptor implements HttpInterceptor {
+export class AppLoaderInterceptor implements HttpInterceptor {
constructor(private injector: Injector) {}
intercept(
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/chat.layout.module.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/chat.layout.module.ts
new file mode 100644
index 00000000..6250f4e9
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/chat.layout.module.ts
@@ -0,0 +1,26 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { MatIconModule } from '@angular/material/icon';
+import { MatMenuModule } from '@angular/material/menu';
+import { MatTabsModule } from '@angular/material/tabs';
+import { MatToolbarModule } from '@angular/material/toolbar';
+
+import { UCapUiChatModule } from '@ucap-webmessenger/ui-chat';
+
+import { COMPONENTS } from './components';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ MatIconModule,
+ MatMenuModule,
+ MatTabsModule,
+ MatToolbarModule,
+ UCapUiChatModule
+ ],
+ exports: [...COMPONENTS],
+ declarations: [...COMPONENTS],
+ entryComponents: []
+})
+export class AppChatLayoutModule {}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/index.ts
new file mode 100644
index 00000000..259d82f4
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/index.ts
@@ -0,0 +1,15 @@
+import { IntroComponent } from './intro.component';
+import { LeftSidenavComponent } from './left-sidenav.component';
+import { MessagesComponent } from './messages.component';
+import { RightSidenavComponent } from './right-sidenav.component';
+
+import { LEFT_SIDENAV_COMPONENTS } from './left-sidenav';
+
+export const COMPONENTS = [
+ IntroComponent,
+ LeftSidenavComponent,
+ MessagesComponent,
+ RightSidenavComponent,
+
+ ...LEFT_SIDENAV_COMPONENTS
+];
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.html
new file mode 100644
index 00000000..17d12ef1
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.html
@@ -0,0 +1,34 @@
+
+
+ chat
+
+
+
+ Chat App
+
+
+
+ Select a contact to start a chat!
+
+
+
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.spec.ts
new file mode 100644
index 00000000..bc679487
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IntroComponent } from './intro.component';
+
+describe('Chat::IntroComponent', () => {
+ let component: IntroComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [IntroComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IntroComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.ts
new file mode 100644
index 00000000..a87db74a
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/intro.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-intro',
+ templateUrl: './intro.component.html',
+ styleUrls: ['./intro.component.scss'],
+ animations: ucapAnimations
+})
+export class IntroComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.html
new file mode 100644
index 00000000..ff7eb089
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ thumb_up
+
+
+
+
+
+
+
+ thumb_up
+
+
+
+
+
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.spec.ts
new file mode 100644
index 00000000..62d733b1
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LeftSidenavComponent } from './left-sidenav.component';
+
+describe('Chat::LeftSidenavComponent', () => {
+ let component: LeftSidenavComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [LeftSidenavComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(LeftSidenavComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.ts
new file mode 100644
index 00000000..741fe3b8
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-left-sidenav',
+ templateUrl: './left-sidenav.component.html',
+ styleUrls: ['./left-sidenav.component.scss'],
+ animations: ucapAnimations
+})
+export class LeftSidenavComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.html
new file mode 100644
index 00000000..2d973ab8
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.html
@@ -0,0 +1 @@
+Call
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.spec.ts
new file mode 100644
index 00000000..1345ade5
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CallComponent } from './call.component';
+
+describe('Chat::LeftSidenav::CallComponent', () => {
+ let component: CallComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [CallComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CallComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.ts
new file mode 100644
index 00000000..a5f771c0
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/call.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-left-sidenav-call',
+ templateUrl: './call.component.html',
+ styleUrls: ['./call.component.scss'],
+ animations: ucapAnimations
+})
+export class CallComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.html
new file mode 100644
index 00000000..eb05330a
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.html
@@ -0,0 +1 @@
+Chat
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.spec.ts
new file mode 100644
index 00000000..74d4ee87
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ChatComponent } from './chat.component';
+
+describe('Chat::LeftSidenav::ChatComponent', () => {
+ let component: ChatComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ChatComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ChatComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.ts
new file mode 100644
index 00000000..3ed1c460
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/chat.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-left-sidenav-chat',
+ templateUrl: './chat.component.html',
+ styleUrls: ['./chat.component.scss'],
+ animations: ucapAnimations
+})
+export class ChatComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.html
new file mode 100644
index 00000000..e5664964
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.html
@@ -0,0 +1 @@
+Group
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.spec.ts
new file mode 100644
index 00000000..12e99468
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { GroupComponent } from './group.component';
+
+describe('Chat::LeftSidenav::GroupComponent', () => {
+ let component: GroupComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [GroupComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(GroupComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.ts
new file mode 100644
index 00000000..bee719e7
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/group.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-left-sidenav-group',
+ templateUrl: './group.component.html',
+ styleUrls: ['./group.component.scss'],
+ animations: ucapAnimations
+})
+export class GroupComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/index.ts
new file mode 100644
index 00000000..791d7ecb
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/index.ts
@@ -0,0 +1,11 @@
+import { CallComponent } from './call.component';
+import { ChatComponent } from './chat.component';
+import { GroupComponent } from './group.component';
+import { OrganizationComponent } from './organization.component';
+
+export const LEFT_SIDENAV_COMPONENTS = [
+ CallComponent,
+ ChatComponent,
+ GroupComponent,
+ OrganizationComponent
+];
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.html
new file mode 100644
index 00000000..21cac3c7
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.html
@@ -0,0 +1 @@
+Organization
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.spec.ts
new file mode 100644
index 00000000..01b3330d
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { OrganizationComponent } from './organization.component';
+
+describe('Chat::LeftSidenav::OrganizationComponent', () => {
+ let component: OrganizationComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [OrganizationComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(OrganizationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.ts
new file mode 100644
index 00000000..e22cd0d4
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/left-sidenav/organization.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-left-sidenav-organization',
+ templateUrl: './organization.component.html',
+ styleUrls: ['./organization.component.scss'],
+ animations: ucapAnimations
+})
+export class OrganizationComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.html
new file mode 100644
index 00000000..6cadb5a8
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.scss
new file mode 100644
index 00000000..898dc404
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.scss
@@ -0,0 +1,208 @@
+:host {
+ display: flex;
+ flex: 1 0 auto;
+ overflow: hidden;
+ max-width: 100%;
+
+ .chat {
+ .chat-toolbar {
+ min-height: 64px;
+ border-bottom: 1px solid;
+
+ .responsive-chats-button {
+ padding: 0;
+ }
+
+ .chat-contact {
+ cursor: pointer;
+
+ .avatar {
+ margin-right: 16px;
+ }
+ }
+ }
+
+ #chat-content {
+ background: transparent;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+
+ .chat-messages {
+ position: relative;
+ padding: 16px 0 40px 40px;
+
+ .message-row {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-end;
+ padding: 0 16px 4px 16px;
+
+ .avatar {
+ position: absolute;
+ left: -32px;
+ margin: 0;
+ }
+
+ .bubble {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 12px;
+ max-width: 100%;
+
+ .message {
+ white-space: pre-wrap;
+ line-height: 1.2;
+ }
+
+ .time {
+ position: absolute;
+ display: none;
+ width: 100%;
+ font-size: 11px;
+ margin-top: 8px;
+ top: 100%;
+ left: 0;
+ white-space: nowrap;
+ }
+ }
+
+ &.contact {
+ .bubble {
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+
+ border-top-right-radius: 20px;
+ border-bottom-right-radius: 20px;
+
+ .time {
+ margin-left: 12px;
+ }
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-left-radius: 20px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-left-radius: 20px;
+ }
+ }
+ }
+
+ &.me {
+ padding-left: 40px;
+
+ .avatar {
+ order: 2;
+ margin: 0 0 0 16px;
+ }
+
+ .bubble {
+ margin-left: auto;
+
+ border-top-left-radius: 20px;
+ border-bottom-left-radius: 20px;
+
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+
+ .time {
+ justify-content: flex-end;
+ right: 0;
+ margin-right: 12px;
+ }
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-right-radius: 20px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-right-radius: 20px;
+ }
+ }
+ }
+
+ &.contact + .me,
+ &.me + .contact {
+ padding-top: 20px;
+ margin-top: 20px;
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-left-radius: 20px;
+ padding-top: 13px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-left-radius: 20px;
+ padding-bottom: 13px;
+
+ .time {
+ display: flex;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .chat-footer {
+ border-top: 1px solid;
+ padding: 8px 8px 8px 16px;
+
+ .reply-form {
+ position: relative;
+
+ .message-text {
+ padding: 16px 8px;
+
+ .mat-form-field-wrapper {
+ padding: 0;
+
+ .mat-form-field-flex {
+ padding: 0;
+
+ .mat-form-field-infix {
+ padding: 0;
+ border: none;
+ border-radius: 20px;
+ border: 1px solid;
+
+ textarea {
+ overflow: hidden;
+ margin: 16px 48px 16px 16px;
+ width: calc(100% - 64px);
+ padding: 0;
+ }
+ }
+ }
+
+ .mat-form-field-underline {
+ display: none !important;
+ }
+ }
+ }
+
+ .send-message-button {
+ position: absolute;
+ right: 16px;
+ bottom: 21px;
+ }
+ }
+ }
+ }
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.spec.ts
new file mode 100644
index 00000000..0be9fce8
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MessagesComponent } from './messages.component';
+
+describe('Chat::MessagesComponent', () => {
+ let component: MessagesComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [MessagesComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MessagesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.ts
new file mode 100644
index 00000000..90095e04
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/messages.component.ts
@@ -0,0 +1,16 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-messages',
+ templateUrl: './messages.component.html',
+ styleUrls: ['./messages.component.scss'],
+ animations: ucapAnimations
+})
+export class MessagesComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+
+ selectContact() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.html b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.html
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.spec.ts
new file mode 100644
index 00000000..85fcdd20
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { RightSidenavComponent } from './right-sidenav.component';
+
+describe('Chat::RightSidenavComponent', () => {
+ let component: RightSidenavComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [RightSidenavComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(RightSidenavComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.ts
new file mode 100644
index 00000000..64d01951
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/app/layouts/chat/components/right-sidenav.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+import { ucapAnimations } from '@ucap-webmessenger/ui';
+
+@Component({
+ selector: 'app-layout-chat-right-sidenav',
+ templateUrl: './right-sidenav.component.html',
+ styleUrls: ['./right-sidenav.component.scss'],
+ animations: ucapAnimations
+})
+export class RightSidenavComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-app/src/app/pages/account/account-routing.page.module.ts b/projects/ucap-webmessenger-app/src/app/pages/account/account-routing.page.module.ts
index a524597e..e1d9ad79 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/account/account-routing.page.module.ts
+++ b/projects/ucap-webmessenger-app/src/app/pages/account/account-routing.page.module.ts
@@ -15,4 +15,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
-export class AccountRoutingPageModule {}
+export class AppAccountRoutingPageModule {}
diff --git a/projects/ucap-webmessenger-app/src/app/pages/account/account.page.module.ts b/projects/ucap-webmessenger-app/src/app/pages/account/account.page.module.ts
index caf1f47c..71c2fcf4 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/account/account.page.module.ts
+++ b/projects/ucap-webmessenger-app/src/app/pages/account/account.page.module.ts
@@ -3,13 +3,13 @@ import { CommonModule } from '@angular/common';
import { UCapUiAccountModule } from '@ucap-webmessenger/ui-account';
-import { AccountRoutingPageModule } from './account-routing.page.module';
+import { AppAccountRoutingPageModule } from './account-routing.page.module';
import { COMPONENTS } from './components';
@NgModule({
- imports: [CommonModule, UCapUiAccountModule, AccountRoutingPageModule],
+ imports: [CommonModule, UCapUiAccountModule, AppAccountRoutingPageModule],
declarations: [...COMPONENTS],
entryComponents: []
})
-export class AccountPageModule {}
+export class AppAccountPageModule {}
diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.html b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.html
index f1a27735..dfcaaad8 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.html
+++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.html
@@ -16,21 +16,20 @@
mode="side"
matIsLockedOpen="gt-md"
>
-
- dsafsdfsdf
+
-
+
- asdfsdfsdfs
-
-
- safsdf
+
+
diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts
index 9eace471..7de5914b 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts
+++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts
@@ -7,11 +7,14 @@ import { AuthenticationProtocolService } from '@ucap-webmessenger/protocol-authe
styleUrls: ['./main.page.component.scss']
})
export class MainPageComponent implements OnInit {
+ selectedChat: boolean;
+
constructor(
private authenticationProtocolService: AuthenticationProtocolService
) {}
ngOnInit(): void {
// this.authenticationProtocolService.login({});
+ this.selectedChat = true;
}
}
diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger-routing.page.module.ts b/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger-routing.page.module.ts
index 399220eb..9c5d16ac 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger-routing.page.module.ts
+++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger-routing.page.module.ts
@@ -15,4 +15,4 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
-export class MessengerRoutingPageModule {}
+export class AppMessengerRoutingPageModule {}
diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger.page.module.ts b/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger.page.module.ts
index 9519a902..1ecd9244 100644
--- a/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger.page.module.ts
+++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/messenger.page.module.ts
@@ -3,13 +3,20 @@ import { CommonModule } from '@angular/common';
import { MatSidenavModule } from '@angular/material/sidenav';
-import { MessengerRoutingPageModule } from './messenger-routing.page.module';
+import { AppChatLayoutModule } from '@app/layouts/chat/chat.layout.module';
+
+import { AppMessengerRoutingPageModule } from './messenger-routing.page.module';
import { COMPONENTS } from './components';
@NgModule({
- imports: [CommonModule, MatSidenavModule, MessengerRoutingPageModule],
+ imports: [
+ CommonModule,
+ MatSidenavModule,
+ AppChatLayoutModule,
+ AppMessengerRoutingPageModule
+ ],
declarations: [...COMPONENTS],
entryComponents: []
})
-export class MessengerPageModule {}
+export class AppMessengerPageModule {}
diff --git a/projects/ucap-webmessenger-app/src/app/resolvers/index.ts b/projects/ucap-webmessenger-app/src/app/resolvers/index.ts
index 93ac0e7b..b91df641 100644
--- a/projects/ucap-webmessenger-app/src/app/resolvers/index.ts
+++ b/projects/ucap-webmessenger-app/src/app/resolvers/index.ts
@@ -1,3 +1,3 @@
-import { MessengerResolver } from './messenger.resolver';
+import { AppMessengerResolver } from './messenger.resolver';
-export const RESOLVERS = [MessengerResolver];
+export const RESOLVERS = [AppMessengerResolver];
diff --git a/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts b/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts
index 5cd7b167..248bc6b2 100644
--- a/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts
+++ b/projects/ucap-webmessenger-app/src/app/resolvers/messenger.resolver.ts
@@ -24,7 +24,7 @@ import {
import { LocaleCode } from '@ucap-webmessenger/core';
@Injectable()
-export class MessengerResolver implements Resolve {
+export class AppMessengerResolver implements Resolve {
constructor(
private store: Store,
private sessionStorageService: SessionStorageService,
@@ -57,6 +57,7 @@ export class MessengerResolver implements Resolve {
this.innerProtocolService
.conn({})
.pipe(
+ take(1),
map(connRes => {
this.authenticationProtocolService
.login({
@@ -79,6 +80,7 @@ export class MessengerResolver implements Resolve {
productName: 'EZMessenger'
})
.pipe(
+ take(1),
map(loginRes => {
console.log('loginRes', loginRes);
})
diff --git a/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.svg b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.svg
new file mode 100644
index 00000000..946f5481
--- /dev/null
+++ b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.svg
@@ -0,0 +1,2037 @@
+
+
+
\ No newline at end of file
diff --git a/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.ttf b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.ttf
new file mode 100644
index 00000000..b59d861b
Binary files /dev/null and b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.ttf differ
diff --git a/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.woff b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.woff
new file mode 100644
index 00000000..36d55262
Binary files /dev/null and b/projects/ucap-webmessenger-app/src/assets/images/icons/material/material-outline-icons.woff differ
diff --git a/projects/ucap-webmessenger-protocol-authentication/src/lib/services/authentication-protocol.service.ts b/projects/ucap-webmessenger-protocol-authentication/src/lib/services/authentication-protocol.service.ts
index e3f50a32..57810761 100644
--- a/projects/ucap-webmessenger-protocol-authentication/src/lib/services/authentication-protocol.service.ts
+++ b/projects/ucap-webmessenger-protocol-authentication/src/lib/services/authentication-protocol.service.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { map, take } from 'rxjs/operators';
import { ProtocolService } from '@ucap-webmessenger/protocol';
import {
@@ -39,13 +39,19 @@ export class AuthenticationProtocolService {
public login(req: LoginRequest): Observable {
return this.protocolService
.call(SVC_TYPE_LOGIN, SSVC_TYPE_LOGIN_REQ, ...encodeLogin(req))
- .pipe(map(res => decodeLogin(res)));
+ .pipe(
+ take(1),
+ map(res => decodeLogin(res))
+ );
}
public logout(req: LogoutRequest): Observable {
return this.protocolService
.call(SVC_TYPE_LOGOUT, SSVC_TYPE_LOGOUT_REQ, ...encodeLogout(req))
- .pipe(map(res => decodeLogout(res)));
+ .pipe(
+ take(1),
+ map(res => decodeLogout(res))
+ );
}
public logoutRemote(
@@ -57,6 +63,9 @@ export class AuthenticationProtocolService {
SSVC_TYPE_LOGOUT_REMOTE_REQ,
...encodeLogoutRemote(req)
)
- .pipe(map(res => decodeLogoutRemote(res)));
+ .pipe(
+ take(1),
+ map(res => decodeLogoutRemote(res))
+ );
}
}
diff --git a/projects/ucap-webmessenger-protocol-event/src/lib/models/info.ts b/projects/ucap-webmessenger-protocol-event/src/lib/models/info.ts
new file mode 100644
index 00000000..a7f5e172
--- /dev/null
+++ b/projects/ucap-webmessenger-protocol-event/src/lib/models/info.ts
@@ -0,0 +1,96 @@
+import {
+ ProtocolRequest,
+ ProtocolResponse,
+ ProtocolEncoder,
+ PacketBody,
+ ProtocolDecoder,
+ ProtocolMessage,
+ ProtocolStream,
+ PacketBodyValue
+} from '@ucap-webmessenger/protocol';
+import { EventType } from '../types/event.type';
+
+export interface InfoRequest extends ProtocolRequest {
+ // 대화방SEQ(s)
+ roomSeq: string;
+ // 기준이벤트SEQ(n)
+ baseSeq: number;
+ // 요청이벤트개수(n)
+ requestCount: number;
+}
+
+export interface Info {
+ // 이벤트SEQ
+ seq: number;
+ // 이벤트타입
+ type: EventType;
+ // 발신자SEQ
+ senderSeq: number;
+ // 발신일시
+ sendDate: Date;
+ // 발신내용
+ sentMessage: string;
+ // 수신자수
+ receiverCount: number;
+}
+
+export interface InfoData extends ProtocolStream {
+ // 대화방SEQ(s)
+ roomSeq: string;
+ infoList: Info[];
+}
+
+export interface InfoResponse extends ProtocolResponse {
+ // 대화방SEQ(s)
+ roomSeq: string;
+ // 기준이벤트SEQ(n)
+ baseSeq: number;
+ // 유효한파일기준이벤트SEQ(n)
+ validFileBaseSeq: number;
+ // 이벤트정보 개수(n)
+ count: number;
+}
+
+export const encodeInfo: ProtocolEncoder = (req: InfoRequest) => {
+ const bodyList: PacketBody[] = [];
+
+ bodyList.push(
+ { type: PacketBodyValue.String, value: req.roomSeq },
+ { type: PacketBodyValue.Integer, value: req.baseSeq },
+ { type: PacketBodyValue.Integer, value: req.requestCount }
+ );
+
+ return bodyList;
+};
+
+export const decodeInfoData: ProtocolDecoder = (
+ message: ProtocolMessage
+) => {
+ const infoList: Info[] = [];
+ for (let i = 1; i < message.bodyList.length; ) {
+ infoList.push({
+ seq: message.bodyList[i++],
+ type: message.bodyList[i++],
+ senderSeq: message.bodyList[i++],
+ sendDate: message.bodyList[i++],
+ sentMessage: message.bodyList[i++],
+ receiverCount: message.bodyList[i++]
+ });
+ }
+
+ return {
+ roomSeq: message.bodyList[0],
+ infoList
+ } as InfoData;
+};
+
+export const decodeInfo: ProtocolDecoder = (
+ message: ProtocolMessage
+) => {
+ return {
+ roomSeq: message.bodyList[0],
+ baseSeq: message.bodyList[1],
+ validFileBaseSeq: message.bodyList[2],
+ count: message.bodyList[3]
+ } as InfoResponse;
+};
diff --git a/projects/ucap-webmessenger-protocol-event/src/lib/services/event-protocol.service.ts b/projects/ucap-webmessenger-protocol-event/src/lib/services/event-protocol.service.ts
index 38c8034d..73f11c46 100644
--- a/projects/ucap-webmessenger-protocol-event/src/lib/services/event-protocol.service.ts
+++ b/projects/ucap-webmessenger-protocol-event/src/lib/services/event-protocol.service.ts
@@ -1,8 +1,42 @@
import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs';
+import { map, takeWhile, timeout } from 'rxjs/operators';
+
+import { ProtocolService } from '@ucap-webmessenger/protocol';
+
+import {
+ InfoRequest,
+ InfoResponse,
+ encodeInfo,
+ decodeInfo,
+ decodeInfoData,
+ InfoData
+} from '../models/info';
+import {
+ SVC_TYPE_EVENT,
+ SSVC_TYPE_EVENT_INFO_REQ,
+ SSVC_TYPE_EVENT_INFO_RES,
+ SSVC_TYPE_EVENT_INFO_DATA
+} from '../types/service';
+
@Injectable({
providedIn: 'root'
})
export class EventProtocolService {
- constructor() {}
+ constructor(private protocolService: ProtocolService) {}
+
+ public info(req: InfoRequest): Observable {
+ return this.protocolService
+ .call(SVC_TYPE_EVENT, SSVC_TYPE_EVENT_INFO_REQ, ...encodeInfo(req))
+ .pipe(
+ takeWhile(res => SSVC_TYPE_EVENT_INFO_RES !== res.subServiceType),
+ map(res => {
+ if (SSVC_TYPE_EVENT_INFO_DATA === res.subServiceType) {
+ return decodeInfoData(res);
+ }
+ return decodeInfo(res);
+ })
+ );
+ }
}
diff --git a/projects/ucap-webmessenger-protocol-event/src/lib/types/event.type.ts b/projects/ucap-webmessenger-protocol-event/src/lib/types/event.type.ts
new file mode 100644
index 00000000..d1af4254
--- /dev/null
+++ b/projects/ucap-webmessenger-protocol-event/src/lib/types/event.type.ts
@@ -0,0 +1,48 @@
+export enum EventType {
+ // J: 대화참여
+ Join = 'J',
+ // C: 대화전송
+ Character = 'C',
+ // F: 파일전송
+ File = 'F',
+ // S: 스티커
+ Sticker = 'S',
+ // T: Mass Text
+ MassText = 'T',
+ // E: 대화퇴장
+ Exit = 'E',
+ // P: 일정
+ Plan = 'P',
+ // V: 화상회의
+ VideoConference = 'V',
+ // L: 링크(Legacy)
+ Link = 'L',
+ // R: 대화방명변경
+ RenameRoom = '',
+ // Y: 번역
+ Translation = 'Y',
+ // Z: 대용량 번역
+ MassTranslation = 'Z',
+ // U: 회수된 메시지
+ RecalledMessage = 'U',
+ // N: 방Timer 변경 안내
+ GuideForRoomTimerChanged = 'N',
+ // X: iOS캡쳐알림
+ NotificationForiOSCapture = 'X',
+ // B: 타이머대화방알림
+ NotificationForTimerRoom = 'B',
+ // Q: 2개월전 메시지
+ Before2MonthsAgo = 'Q',
+ // G: 강제 퇴장
+ ForcedExit = 'G',
+ // H: 챗봇대화 시작
+ ChatbotStart = 'H',
+ // K: 챗봇대화 종료
+ ChatbotEnd = 'K',
+ // I: 챗봇대화 전송
+ ChatbotSend = 'I',
+ // A: 챗봇 대용량 대화 전송
+ ChatbotSendMass = 'A',
+ // M: 동영상 스트리밍
+ VideoStreamming = 'M'
+}
diff --git a/projects/ucap-webmessenger-protocol-event/src/lib/types/service.ts b/projects/ucap-webmessenger-protocol-event/src/lib/types/service.ts
new file mode 100644
index 00000000..6db7a25e
--- /dev/null
+++ b/projects/ucap-webmessenger-protocol-event/src/lib/types/service.ts
@@ -0,0 +1,39 @@
+export const SVC_TYPE_EVENT = 20;
+
+export const SSVC_TYPE_EVENT_INFO_REQ = 1; // 이벤트 정보 요청
+export const SSVC_TYPE_EVENT_INFO_DATA = 2; // 이벤트 정보
+export const SSVC_TYPE_EVENT_INFO_RES = 3; // 이벤트 정보 완료
+export const SSVC_TYPE_EVENT_SEND_REQ = 11; // 이벤트 전송 요청
+export const SSVC_TYPE_EVENT_SEND_RES = 12; // 이벤트 전송 응답
+export const SSVC_TYPE_EVENT_SEND_NOTI = 13; // 이벤트 전송 알림
+export const SSVC_TYPE_EVENT_PUSH_REQ = 14; // (푸시 요청)
+export const SSVC_TYPE_EVENT_PUSH_CL_REQ = 15; // (AWAY PUSH 요청)
+export const SSVC_TYPE_EVENT_INPUT_STATUS_REQ = 16; // 이벤트 입력 알림 요청
+export const SSVC_TYPE_EVENT_INPUT_STATUS_RES = 17; // 이벤트 입력 알림 응답
+export const SSVC_TYPE_EVENT_READ_REQ = 21; // 이벤트 확인 요청
+export const SSVC_TYPE_EVENT_READ_RES = 22; // 이벤트 확인 응답
+export const SSVC_TYPE_EVENT_READ_NOTI = 23; // 에벤트 확인 알림
+export const SSVC_TYPE_EVENT_UNREAD_CNT_REQ = 25; // 이벤트 UnreadCnt 요청
+export const SSVC_TYPE_EVENT_UNREAD_CNT_RES = 26; // 이벤트 UnreadCnt 응답
+export const SSVC_TYPE_EVENT_USER_UNREAD_CNT_REQ = 27; // 사용자 UnreadCnt 요청
+export const SSVC_TYPE_EVENT_USER_UNREAD_CNT_RES = 28; // 사용자 UnreadCnt 응답
+export const SSVC_TYPE_EVENT_DEL_REQ = 31; // 이벤트 삭제 요청
+export const SSVC_TYPE_EVENT_DEL_RES = 32; // 이벤트 삭제 응답
+export const SSVC_TYPE_EVENT_CANCEL_REQ = 33; // 이벤트 회수 요청
+export const SSVC_TYPE_EVENT_CANCEL_NOTI = 34; // 이벤트 회수 알림
+export const SSVC_TYPE_EVENT_CANCEL_RES = 35; // 이벤트 회수 응답
+export const SSVC_TYPE_EVENT_BOT_NOTI_REQ = 41; // BOT방에 이벤트 전송 요청
+export const SSVC_TYPE_EVENT_BOT_NOTI_RES = 42; // BOT방에 이벤트 전송 응답
+export const SSVC_TYPE_EVENT_CAPTURE_NOTI_REQ = 43; // iOS에서 캡쳐 시,알림 요청
+export const SSVC_TYPE_EVENT_CAPTURE_NOTI_RES = 44; // iOS에서 캡쳐 시,알림 응답
+export const SSVC_TYPE_EVENT_SEND_PLAN_REQ = 51; // 일정 정보 전송 요청
+export const SSVC_TYPE_EVENT_SEND_PLAN_RES = 52; // 일정 정보 전송 응답
+export const SSVC_TYPE_EVENT_SEND_CONF_REQ = 61; // 화상회의 정보 전송 요청
+export const SSVC_TYPE_EVENT_SEND_CONF_RES = 62; // 화상회의 정보 전송 응답
+export const SSVC_TYPE_EVENT_BOT_SMS_REQ = 71; // UCAP SMS이벤트 전송 요청
+export const SSVC_TYPE_EVENT_BOT_SMS_RES = 72; // UCAP SMS이벤트 전송 응답
+export const SSVC_TYPE_EVENT_PUSH_UMG_CL_REQ = 81; // (AWAY 쪽지 PUSH 요청)
+export const SSVC_TYPE_EVENT_PUSH_CHECK_REQ = 91; // 푸시 체크 요청
+export const SSVC_TYPE_EVENT_PUSH_CHECK_RES = 92; // 푸시 체크 응답
+export const SSVC_TYPE_EVENT_SEND_STREAM_REQ = 101; // 동영상 스트리밍 전송 요청
+export const SSVC_TYPE_EVENT_SEND_STREAM_RES = 102; // 동영상 스트리밍 전송 응답
diff --git a/projects/ucap-webmessenger-protocol-inner/src/lib/services/inner-protocol.service.ts b/projects/ucap-webmessenger-protocol-inner/src/lib/services/inner-protocol.service.ts
index 12835ac5..fee603f5 100644
--- a/projects/ucap-webmessenger-protocol-inner/src/lib/services/inner-protocol.service.ts
+++ b/projects/ucap-webmessenger-protocol-inner/src/lib/services/inner-protocol.service.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
-import { map } from 'rxjs/operators';
+import { map, take } from 'rxjs/operators';
import { ProtocolService } from '@ucap-webmessenger/protocol';
@@ -22,6 +22,9 @@ export class InnerProtocolService {
public conn(req: ConnRequest): Observable {
return this.protocolService
.call(SVC_TYPE_INNER, SSVC_TYPE_CONN_REQ, ...encodeConn(req))
- .pipe(map(res => decodeConn(res)));
+ .pipe(
+ take(1),
+ map(res => decodeConn(res))
+ );
}
}
diff --git a/projects/ucap-webmessenger-protocol/src/lib/models/protocol.ts b/projects/ucap-webmessenger-protocol/src/lib/models/protocol.ts
index 6f68868e..43ebde70 100644
--- a/projects/ucap-webmessenger-protocol/src/lib/models/protocol.ts
+++ b/projects/ucap-webmessenger-protocol/src/lib/models/protocol.ts
@@ -8,6 +8,10 @@ export interface ProtocolResponse {
_id?: string;
}
+export interface ProtocolStream {
+ _id?: string;
+}
+
// tslint:disable-next-line: no-empty-interface
export interface ProtocolNotification {}
diff --git a/projects/ucap-webmessenger-protocol/src/lib/services/protocol.service.ts b/projects/ucap-webmessenger-protocol/src/lib/services/protocol.service.ts
index d18f3605..1fa02eb8 100644
--- a/projects/ucap-webmessenger-protocol/src/lib/services/protocol.service.ts
+++ b/projects/ucap-webmessenger-protocol/src/lib/services/protocol.service.ts
@@ -1,7 +1,7 @@
import { Injectable, Inject } from '@angular/core';
import { Subscription, Observable, Subject } from 'rxjs';
-import { share, switchMap, retryWhen, delay } from 'rxjs/operators';
+import { share, switchMap, retryWhen, delay, finalize } from 'rxjs/operators';
import { QueueingSubject } from 'queueing-subject';
@@ -83,7 +83,6 @@ export class ProtocolService {
let requestState: RequestState | null = null;
if (res.requestId) {
requestState = this.pendingRequests.get(res.requestId);
- this.pendingRequests.delete(res.requestId);
}
if (SSVC_TYPE_ERROR_RES === res.message.subServiceType) {
@@ -162,7 +161,18 @@ export class ProtocolService {
{ type: PacketBodyValue.RequestId, value: requestId }
]);
- responseSubject = new Subject();
+ responseSubject = new Subject().pipe(
+ finalize(() => {
+ if (this.pendingRequests.has(requestId)) {
+ this.pendingRequests.delete(requestId);
+ }
+ console.log(
+ 'ProtocolService::pendingRequests.size',
+ this.pendingRequests.size
+ );
+ })
+ ) as Subject;
+
this.pendingRequests.set(requestId, {
subject: responseSubject,
request: { serviceType, subServiceType, bodyList }
diff --git a/projects/ucap-webmessenger-ui-chat/README.md b/projects/ucap-webmessenger-ui-chat/README.md
new file mode 100644
index 00000000..a54ab405
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/README.md
@@ -0,0 +1,24 @@
+# UcapWebmessengerUiChat
+
+This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.2.5.
+
+## Code scaffolding
+
+Run `ng generate component component-name --project ucap-webmessenger-ui-chat` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ucap-webmessenger-ui-chat`.
+> Note: Don't forget to add `--project ucap-webmessenger-ui-chat` or else it will be added to the default project in your `angular.json` file.
+
+## Build
+
+Run `ng build ucap-webmessenger-ui-chat` to build the project. The build artifacts will be stored in the `dist/` directory.
+
+## Publishing
+
+After building your library with `ng build ucap-webmessenger-ui-chat`, go to the dist folder `cd dist/ucap-webmessenger-ui-chat` and run `npm publish`.
+
+## Running unit tests
+
+Run `ng test ucap-webmessenger-ui-chat` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/projects/ucap-webmessenger-ui-chat/karma.conf.js b/projects/ucap-webmessenger-ui-chat/karma.conf.js
new file mode 100644
index 00000000..78c5df43
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/karma.conf.js
@@ -0,0 +1,32 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../../coverage/ucap-webmessenger-ui-chat'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false,
+ restartOnFileChange: true
+ });
+};
diff --git a/projects/ucap-webmessenger-ui-chat/ng-package.json b/projects/ucap-webmessenger-ui-chat/ng-package.json
new file mode 100644
index 00000000..97ed819b
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
+ "dest": "../../dist/ucap-webmessenger-ui-chat",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/projects/ucap-webmessenger-ui-chat/package.json b/projects/ucap-webmessenger-ui-chat/package.json
new file mode 100644
index 00000000..dab499cf
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "@ucap-webmessenger/ui-chat",
+ "version": "0.0.1",
+ "peerDependencies": {
+ "@angular/common": "^8.2.5",
+ "@angular/core": "^8.2.5"
+ }
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.html
new file mode 100644
index 00000000..5666fa63
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.html
@@ -0,0 +1,39 @@
+
+
+
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.scss b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.scss
new file mode 100644
index 00000000..a5ca2a4e
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.scss
@@ -0,0 +1,39 @@
+.chat-form {
+ position: relative;
+
+ .message-text {
+ padding: 16px 8px;
+
+ .mat-form-field-wrapper {
+ padding: 0;
+
+ .mat-form-field-flex {
+ padding: 0;
+
+ .mat-form-field-infix {
+ padding: 0;
+ border: none;
+ border-radius: 20px;
+ border: 1px solid;
+
+ textarea {
+ overflow: hidden;
+ margin: 16px 48px 16px 16px;
+ width: calc(100% - 64px);
+ padding: 0;
+ }
+ }
+ }
+
+ .mat-form-field-underline {
+ display: none !important;
+ }
+ }
+ }
+
+ .send-message-button {
+ position: absolute;
+ right: 16px;
+ bottom: 21px;
+ }
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.spec.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.spec.ts
new file mode 100644
index 00000000..2a56479e
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { FormComponent } from './form.component';
+
+describe('Chat::FormComponent', () => {
+ let component: FormComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [FormComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(FormComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts
new file mode 100644
index 00000000..3a2c959e
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/form.component.ts
@@ -0,0 +1,14 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'ucap-chat-form',
+ templateUrl: './form.component.html',
+ styleUrls: ['./form.component.scss']
+})
+export class FormComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+
+ send() {}
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.html
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.scss b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.scss
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.spec.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.spec.ts
new file mode 100644
index 00000000..bc679487
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IntroComponent } from './intro.component';
+
+describe('Chat::IntroComponent', () => {
+ let component: IntroComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [IntroComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(IntroComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.ts
new file mode 100644
index 00000000..670899c1
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/intro.component.ts
@@ -0,0 +1,12 @@
+import { Component, OnInit } from '@angular/core';
+
+@Component({
+ selector: 'ucap-chat-intro',
+ templateUrl: './intro.component.html',
+ styleUrls: ['./intro.component.scss']
+})
+export class IntroComponent implements OnInit {
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.html b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.html
new file mode 100644
index 00000000..6441b2be
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.html
@@ -0,0 +1,20 @@
+
+
+
+
![]()
+
+
+
{{ message.message }}
+
{{ message.time | date: 'short' }}
+
+
+
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.scss b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.scss
new file mode 100644
index 00000000..7e3d7833
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.scss
@@ -0,0 +1,131 @@
+.chat-messages {
+ position: relative;
+ padding: 16px 0 40px 40px;
+
+ .message-row {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: flex-end;
+ padding: 0 16px 4px 16px;
+
+ .avatar {
+ position: absolute;
+ left: -32px;
+ margin: 0;
+ }
+
+ .bubble {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 12px;
+ max-width: 100%;
+
+ .message {
+ white-space: pre-wrap;
+ line-height: 1.2;
+ }
+
+ .time {
+ position: absolute;
+ display: none;
+ width: 100%;
+ font-size: 11px;
+ margin-top: 8px;
+ top: 100%;
+ left: 0;
+ white-space: nowrap;
+ }
+ }
+
+ &.contact {
+ .bubble {
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+
+ border-top-right-radius: 20px;
+ border-bottom-right-radius: 20px;
+
+ .time {
+ margin-left: 12px;
+ }
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-left-radius: 20px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-left-radius: 20px;
+ }
+ }
+ }
+
+ &.me {
+ padding-left: 40px;
+
+ .avatar {
+ order: 2;
+ margin: 0 0 0 16px;
+ }
+
+ .bubble {
+ margin-left: auto;
+
+ border-top-left-radius: 20px;
+ border-bottom-left-radius: 20px;
+
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+
+ .time {
+ justify-content: flex-end;
+ right: 0;
+ margin-right: 12px;
+ }
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-right-radius: 20px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-right-radius: 20px;
+ }
+ }
+ }
+
+ &.contact + .me,
+ &.me + .contact {
+ padding-top: 20px;
+ margin-top: 20px;
+ }
+
+ &.first-of-group {
+ .bubble {
+ border-top-left-radius: 20px;
+ padding-top: 13px;
+ }
+ }
+
+ &.last-of-group {
+ .bubble {
+ border-bottom-left-radius: 20px;
+ padding-bottom: 13px;
+
+ .time {
+ display: flex;
+ }
+ }
+ }
+ }
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.spec.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.spec.ts
new file mode 100644
index 00000000..0be9fce8
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.spec.ts
@@ -0,0 +1,24 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { MessagesComponent } from './messages.component';
+
+describe('Chat::MessagesComponent', () => {
+ let component: MessagesComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [MessagesComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(MessagesComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.ts b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.ts
new file mode 100644
index 00000000..6a1f843c
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/components/messages.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit, Input } from '@angular/core';
+
+@Component({
+ selector: 'ucap-chat-messages',
+ templateUrl: './messages.component.html',
+ styleUrls: ['./messages.component.scss']
+})
+export class MessagesComponent implements OnInit {
+ @Input()
+ messages: any[];
+
+ constructor() {}
+
+ ngOnInit() {}
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/lib/ucap-ui-chat.module.ts b/projects/ucap-webmessenger-ui-chat/src/lib/ucap-ui-chat.module.ts
new file mode 100644
index 00000000..d28ee6d2
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/lib/ucap-ui-chat.module.ts
@@ -0,0 +1,38 @@
+import { NgModule, ModuleWithProviders } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+
+import { FlexLayoutModule } from '@angular/flex-layout';
+
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatIconModule } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
+
+import { FormComponent } from './components/form.component';
+import { IntroComponent } from './components/intro.component';
+import { MessagesComponent } from './components/messages.component';
+
+const COMPONENTS = [FormComponent, IntroComponent, MessagesComponent];
+const SERVICES = [];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ ReactiveFormsModule,
+ FlexLayoutModule,
+ MatFormFieldModule,
+ MatIconModule,
+ MatInputModule
+ ],
+ exports: [...COMPONENTS],
+ declarations: [...COMPONENTS]
+})
+export class UCapUiChatModule {
+ public static forRoot(): ModuleWithProviders {
+ return {
+ ngModule: UCapUiChatModule,
+ providers: [...SERVICES]
+ };
+ }
+}
diff --git a/projects/ucap-webmessenger-ui-chat/src/public-api.ts b/projects/ucap-webmessenger-ui-chat/src/public-api.ts
new file mode 100644
index 00000000..d747a444
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/public-api.ts
@@ -0,0 +1,9 @@
+/*
+ * Public API Surface of ucap-webmessenger-ui-chat
+ */
+
+export * from './lib/components/form.component';
+export * from './lib/components/intro.component';
+export * from './lib/components/messages.component';
+
+export * from './lib/ucap-ui-chat.module';
diff --git a/projects/ucap-webmessenger-ui-chat/src/test.ts b/projects/ucap-webmessenger-ui-chat/src/test.ts
new file mode 100644
index 00000000..978c64fb
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/src/test.ts
@@ -0,0 +1,21 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone';
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/projects/ucap-webmessenger-ui-chat/tsconfig.lib.json b/projects/ucap-webmessenger-ui-chat/tsconfig.lib.json
new file mode 100644
index 00000000..bd23948e
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/tsconfig.lib.json
@@ -0,0 +1,26 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/lib",
+ "target": "es2015",
+ "declaration": true,
+ "inlineSources": true,
+ "types": [],
+ "lib": [
+ "dom",
+ "es2018"
+ ]
+ },
+ "angularCompilerOptions": {
+ "annotateForClosureCompiler": true,
+ "skipTemplateCodegen": true,
+ "strictMetadataEmit": true,
+ "fullTemplateTypeCheck": true,
+ "strictInjectionParameters": true,
+ "enableResourceInlining": true
+ },
+ "exclude": [
+ "src/test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/projects/ucap-webmessenger-ui-chat/tsconfig.spec.json b/projects/ucap-webmessenger-ui-chat/tsconfig.spec.json
new file mode 100644
index 00000000..16da33db
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/tsconfig.spec.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
diff --git a/projects/ucap-webmessenger-ui-chat/tslint.json b/projects/ucap-webmessenger-ui-chat/tslint.json
new file mode 100644
index 00000000..f01e1f14
--- /dev/null
+++ b/projects/ucap-webmessenger-ui-chat/tslint.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "ucapChat",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "ucap-chat",
+ "kebab-case"
+ ]
+ }
+}
diff --git a/projects/ucap-webmessenger-ui/src/lib/animations/index.ts b/projects/ucap-webmessenger-ui/src/lib/animations/index.ts
new file mode 100644
index 00000000..ac5a437f
--- /dev/null
+++ b/projects/ucap-webmessenger-ui/src/lib/animations/index.ts
@@ -0,0 +1,552 @@
+import {
+ sequence,
+ trigger,
+ animate,
+ style,
+ group,
+ query,
+ transition,
+ animateChild,
+ state,
+ animation,
+ useAnimation,
+ stagger
+} from '@angular/animations';
+
+const customAnimation = animation(
+ [
+ style({
+ opacity: '{{opacity}}',
+ transform: 'scale({{scale}}) translate3d({{x}}, {{y}}, {{z}})'
+ }),
+ animate('{{duration}} {{delay}} cubic-bezier(0.0, 0.0, 0.2, 1)', style('*'))
+ ],
+ {
+ params: {
+ duration: '200ms',
+ delay: '0ms',
+ opacity: '0',
+ scale: '1',
+ x: '0',
+ y: '0',
+ z: '0'
+ }
+ }
+);
+
+export const ucapAnimations = [
+ trigger('animate', [
+ transition('void => *', [useAnimation(customAnimation)])
+ ]),
+
+ trigger('animateStagger', [
+ state('50', style('*')),
+ state('100', style('*')),
+ state('200', style('*')),
+
+ transition(
+ 'void => 50',
+ query('@*', [stagger('50ms', [animateChild()])], { optional: true })
+ ),
+ transition(
+ 'void => 100',
+ query('@*', [stagger('100ms', [animateChild()])], { optional: true })
+ ),
+ transition(
+ 'void => 200',
+ query('@*', [stagger('200ms', [animateChild()])], { optional: true })
+ )
+ ]),
+
+ trigger('fadeInOut', [
+ state(
+ '0, void',
+ style({
+ opacity: 0
+ })
+ ),
+ state(
+ '1, *',
+ style({
+ opacity: 1
+ })
+ ),
+ transition('1 => 0', animate('300ms ease-out')),
+ transition('0 => 1', animate('300ms ease-in')),
+ transition('void <=> *', animate('300ms ease-in'))
+ ]),
+
+ trigger('slideInOut', [
+ state(
+ '0',
+ style({
+ height: '0px'
+ })
+ ),
+ state(
+ '1',
+ style({
+ height: '*'
+ })
+ ),
+ transition('1 => 0', animate('300ms ease-out')),
+ transition('0 => 1', animate('300ms ease-in'))
+ ]),
+
+ trigger('slideIn', [
+ transition('void => left', [
+ style({
+ transform: 'translateX(100%)'
+ }),
+ animate(
+ '300ms ease-in',
+ style({
+ transform: 'translateX(0)'
+ })
+ )
+ ]),
+ transition('left => void', [
+ style({
+ transform: 'translateX(0)'
+ }),
+ animate(
+ '300ms ease-in',
+ style({
+ transform: 'translateX(-100%)'
+ })
+ )
+ ]),
+ transition('void => right', [
+ style({
+ transform: 'translateX(-100%)'
+ }),
+ animate(
+ '300ms ease-in',
+ style({
+ transform: 'translateX(0)'
+ })
+ )
+ ]),
+ transition('right => void', [
+ style({
+ transform: 'translateX(0)'
+ }),
+ animate(
+ '300ms ease-in',
+ style({
+ transform: 'translateX(100%)'
+ })
+ )
+ ])
+ ]),
+
+ trigger('slideInLeft', [
+ state(
+ 'void',
+ style({
+ transform: 'translateX(-100%)'
+ })
+ ),
+ state(
+ '*',
+ style({
+ transform: 'translateX(0)'
+ })
+ ),
+ transition('void => *', animate('300ms')),
+ transition('* => void', animate('300ms'))
+ ]),
+
+ trigger('slideInRight', [
+ state(
+ 'void',
+ style({
+ transform: 'translateX(100%)'
+ })
+ ),
+ state(
+ '*',
+ style({
+ transform: 'translateX(0)'
+ })
+ ),
+ transition('void => *', animate('300ms')),
+ transition('* => void', animate('300ms'))
+ ]),
+
+ trigger('slideInTop', [
+ state(
+ 'void',
+ style({
+ transform: 'translateY(-100%)'
+ })
+ ),
+ state(
+ '*',
+ style({
+ transform: 'translateY(0)'
+ })
+ ),
+ transition('void => *', animate('300ms')),
+ transition('* => void', animate('300ms'))
+ ]),
+
+ trigger('slideInBottom', [
+ state(
+ 'void',
+ style({
+ transform: 'translateY(100%)'
+ })
+ ),
+ state(
+ '*',
+ style({
+ transform: 'translateY(0)'
+ })
+ ),
+ transition('void => *', animate('300ms')),
+ transition('* => void', animate('300ms'))
+ ]),
+
+ trigger('expandCollapse', [
+ state(
+ 'void',
+ style({
+ height: '0px'
+ })
+ ),
+ state(
+ '*',
+ style({
+ height: '*'
+ })
+ ),
+ transition('void => *', animate('300ms ease-out')),
+ transition('* => void', animate('300ms ease-in'))
+ ]),
+
+ // -----------------------------------------------------------------------------------------------------
+ // @ Router animations
+ // -----------------------------------------------------------------------------------------------------
+
+ trigger('routerTransitionLeft', [
+ transition('* => *', [
+ query(
+ 'content > :enter, content > :leave',
+ [
+ style({
+ position: 'absolute',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ })
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({
+ transform: 'translateX(100%)',
+ opacity: 0
+ })
+ ],
+ { optional: true }
+ ),
+ sequence([
+ group([
+ query(
+ 'content > :leave',
+ [
+ style({
+ transform: 'translateX(0)',
+ opacity: 1
+ }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateX(-100%)',
+ opacity: 0
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({ transform: 'translateX(100%)' }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateX(0%)',
+ opacity: 1
+ })
+ )
+ ],
+ { optional: true }
+ )
+ ]),
+ query('content > :leave', animateChild(), { optional: true }),
+ query('content > :enter', animateChild(), { optional: true })
+ ])
+ ])
+ ]),
+
+ trigger('routerTransitionRight', [
+ transition('* => *', [
+ query(
+ 'content > :enter, content > :leave',
+ [
+ style({
+ position: 'absolute',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ })
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({
+ transform: 'translateX(-100%)',
+ opacity: 0
+ })
+ ],
+ { optional: true }
+ ),
+ sequence([
+ group([
+ query(
+ 'content > :leave',
+ [
+ style({
+ transform: 'translateX(0)',
+ opacity: 1
+ }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateX(100%)',
+ opacity: 0
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({ transform: 'translateX(-100%)' }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateX(0%)',
+ opacity: 1
+ })
+ )
+ ],
+ { optional: true }
+ )
+ ]),
+ query('content > :leave', animateChild(), { optional: true }),
+ query('content > :enter', animateChild(), { optional: true })
+ ])
+ ])
+ ]),
+
+ trigger('routerTransitionUp', [
+ transition('* => *', [
+ query(
+ 'content > :enter, content > :leave',
+ [
+ style({
+ position: 'absolute',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ })
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({
+ transform: 'translateY(100%)',
+ opacity: 0
+ })
+ ],
+ { optional: true }
+ ),
+ group([
+ query(
+ 'content > :leave',
+ [
+ style({
+ transform: 'translateY(0)',
+ opacity: 1
+ }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateY(-100%)',
+ opacity: 0
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({ transform: 'translateY(100%)' }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateY(0%)',
+ opacity: 1
+ })
+ )
+ ],
+ { optional: true }
+ )
+ ]),
+ query('content > :leave', animateChild(), { optional: true }),
+ query('content > :enter', animateChild(), { optional: true })
+ ])
+ ]),
+
+ trigger('routerTransitionDown', [
+ transition('* => *', [
+ query(
+ 'content > :enter, content > :leave',
+ [
+ style({
+ position: 'absolute',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ })
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({
+ transform: 'translateY(-100%)',
+ opacity: 0
+ })
+ ],
+ { optional: true }
+ ),
+ sequence([
+ group([
+ query(
+ 'content > :leave',
+ [
+ style({
+ transform: 'translateY(0)',
+ opacity: 1
+ }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateY(100%)',
+ opacity: 0
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({ transform: 'translateY(-100%)' }),
+ animate(
+ '600ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ transform: 'translateY(0%)',
+ opacity: 1
+ })
+ )
+ ],
+ { optional: true }
+ )
+ ]),
+ query('content > :leave', animateChild(), { optional: true }),
+ query('content > :enter', animateChild(), { optional: true })
+ ])
+ ])
+ ]),
+
+ trigger('routerTransitionFade', [
+ transition(
+ '* => *',
+ group([
+ query(
+ 'content > :enter, content > :leave ',
+ [
+ style({
+ position: 'absolute',
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0
+ })
+ ],
+ { optional: true }
+ ),
+
+ query(
+ 'content > :enter',
+ [
+ style({
+ opacity: 0
+ })
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :leave',
+ [
+ style({
+ opacity: 1
+ }),
+ animate(
+ '300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ opacity: 0
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query(
+ 'content > :enter',
+ [
+ style({
+ opacity: 0
+ }),
+ animate(
+ '300ms cubic-bezier(0.0, 0.0, 0.2, 1)',
+ style({
+ opacity: 1
+ })
+ )
+ ],
+ { optional: true }
+ ),
+ query('content > :enter', animateChild(), { optional: true }),
+ query('content > :leave', animateChild(), { optional: true })
+ ])
+ )
+ ])
+];
diff --git a/projects/ucap-webmessenger-ui/src/public-api.ts b/projects/ucap-webmessenger-ui/src/public-api.ts
index a9e50357..cb5b8ca0 100644
--- a/projects/ucap-webmessenger-ui/src/public-api.ts
+++ b/projects/ucap-webmessenger-ui/src/public-api.ts
@@ -2,6 +2,8 @@
* Public API Surface of ucap-webmessenger-ui
*/
+export * from './lib/animations';
+
export * from './lib/dialogs/alert.dialog.component';
export * from './lib/dialogs/confirm.dialog.component';
diff --git a/tsconfig.json b/tsconfig.json
index a6e377fa..89c8c0e9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,6 +15,8 @@
"typeRoots": ["node_modules/@types"],
"lib": ["es2018", "dom"],
"paths": {
+ "@app/*": ["projects/ucap-webmessenger-app/src/app/*"],
+
"@ucap-webmessenger/core": [
"projects/ucap-webmessenger-core/src/public-api"
],
@@ -35,6 +37,9 @@
"@ucap-webmessenger/ui-account": [
"projects/ucap-webmessenger-ui-account/src/public-api"
],
+ "@ucap-webmessenger/ui-chat": [
+ "projects/ucap-webmessenger-ui-chat/src/public-api"
+ ],
"@ucap-webmessenger/ui-messenger": [
"projects/ucap-webmessenger-ui-messenger/src/public-api"
],