UI Components of chat are added & Protocol service is modified
This commit is contained in:
parent
e847133650
commit
692a585c1e
38
angular.json
38
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": {
|
"ucap-webmessenger-ui-messenger": {
|
||||||
"projectType": "library",
|
"projectType": "library",
|
||||||
"schematics": {
|
"schematics": {
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
import { AuthGuard } from './guards/auth.guard';
|
import { AppAuthGuard } from './guards/auth.guard';
|
||||||
import { MessengerResolver } from './resolvers/messenger.resolver';
|
import { AppMessengerResolver } from './resolvers/messenger.resolver';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: '/messenger', pathMatch: 'full' },
|
{ path: '', redirectTo: '/messenger', pathMatch: 'full' },
|
||||||
{
|
{
|
||||||
path: 'messenger',
|
path: 'messenger',
|
||||||
loadChildren: './pages/messenger/messenger.page.module#MessengerPageModule',
|
loadChildren:
|
||||||
canActivate: [AuthGuard],
|
'./pages/messenger/messenger.page.module#AppMessengerPageModule',
|
||||||
|
canActivate: [AppAuthGuard],
|
||||||
resolve: {
|
resolve: {
|
||||||
protocol: MessengerResolver
|
protocol: AppMessengerResolver
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'account',
|
path: 'account',
|
||||||
loadChildren: './pages/account/account.page.module#AccountPageModule'
|
loadChildren: './pages/account/account.page.module#AppAccountPageModule'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { AppAuthenticationService } from '../services/authentication.service';
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class AuthGuard implements CanActivate {
|
export class AppAuthGuard implements CanActivate {
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private appAuthenticationService: AppAuthenticationService
|
private appAuthenticationService: AppAuthenticationService
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import { AuthGuard } from './auth.guard';
|
import { AppAuthGuard } from './auth.guard';
|
||||||
|
|
||||||
export const GUARDS = [AuthGuard];
|
export const GUARDS = [AppAuthGuard];
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { finalize, delay } from 'rxjs/operators';
|
||||||
import { AppLoaderService } from '../services/loader.service';
|
import { AppLoaderService } from '../services/loader.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LoaderInterceptor implements HttpInterceptor {
|
export class AppLoaderInterceptor implements HttpInterceptor {
|
||||||
constructor(private injector: Injector) {}
|
constructor(private injector: Injector) {}
|
||||||
|
|
||||||
intercept(
|
intercept(
|
||||||
|
|
|
@ -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 {}
|
|
@ -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
|
||||||
|
];
|
|
@ -0,0 +1,34 @@
|
||||||
|
<div fxFlex fxLayout="column" fxLayoutAlign="center center">
|
||||||
|
<div
|
||||||
|
class="big-circle app-logo"
|
||||||
|
fxLayout="column"
|
||||||
|
fxLayoutAlign="center center"
|
||||||
|
[@animate]="{ value: '*', params: { delay: '50ms', scale: '0.2' } }"
|
||||||
|
>
|
||||||
|
<mat-icon class="s-64 s-md-128 mat-accent">chat</mat-icon>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="app-title mt-48 mb-8"
|
||||||
|
[@animate]="{ value: '*', params: { delay: '100ms', y: '25px' } }"
|
||||||
|
>
|
||||||
|
Chat App
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
fxHide
|
||||||
|
fxShow.gt-md
|
||||||
|
class="app-message"
|
||||||
|
[@animate]="{ value: '*', params: { delay: '200ms', y: '50px' } }"
|
||||||
|
>
|
||||||
|
Select a contact to start a chat!
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
mat-raised-button
|
||||||
|
fxHide.gt-md
|
||||||
|
fuseMatSidenavToggler="chat-left-sidenav"
|
||||||
|
>
|
||||||
|
Select a contact to start a chat!
|
||||||
|
</button>
|
||||||
|
</div>
|
|
@ -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<IntroComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [IntroComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(IntroComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
<mat-tab-group>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon></mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<app-layout-chat-left-sidenav-group></app-layout-chat-left-sidenav-group>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon></mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<app-layout-chat-left-sidenav-chat></app-layout-chat-left-sidenav-chat>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon>thumb_up</mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<app-layout-chat-left-sidenav-organization></app-layout-chat-left-sidenav-organization>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<mat-icon>thumb_up</mat-icon>
|
||||||
|
</ng-template>
|
||||||
|
<ng-template matTabContent>
|
||||||
|
<app-layout-chat-left-sidenav-call></app-layout-chat-left-sidenav-call>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
|
@ -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<LeftSidenavComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [LeftSidenavComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LeftSidenavComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Call
|
|
@ -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<CallComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [CallComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(CallComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Chat
|
|
@ -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<ChatComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ChatComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ChatComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
Group
|
|
@ -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<GroupComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [GroupComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(GroupComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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
|
||||||
|
];
|
|
@ -0,0 +1 @@
|
||||||
|
Organization
|
|
@ -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<OrganizationComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [OrganizationComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(OrganizationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!-- CHAT -->
|
||||||
|
<div class="chat" fxFlex fxLayout="column">
|
||||||
|
<!-- CHAT TOOLBAR -->
|
||||||
|
<mat-toolbar class="chat-toolbar">
|
||||||
|
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
|
||||||
|
<div fxLayout="row" fxLayoutAlign="start center">
|
||||||
|
<!-- RESPONSIVE CHATS BUTTON-->
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
fxHide.gt-md
|
||||||
|
class="responsive-chats-button mr-16"
|
||||||
|
fuseMatSidenavToggler="chat-left-sidenav"
|
||||||
|
aria-label="chats button"
|
||||||
|
>
|
||||||
|
<mat-icon>chat</mat-icon>
|
||||||
|
</button>
|
||||||
|
<!-- / RESPONSIVE CHATS BUTTON-->
|
||||||
|
|
||||||
|
<!-- CHAT CONTACT-->
|
||||||
|
|
||||||
|
<!-- / CHAT CONTACT-->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
[matMenuTriggerFor]="contactMenu"
|
||||||
|
aria-label="more"
|
||||||
|
>
|
||||||
|
<mat-icon>more_vert</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<mat-menu #contactMenu="matMenu">
|
||||||
|
<button
|
||||||
|
mat-menu-item
|
||||||
|
fuseMatSidenavToggler="chat-right-sidenav"
|
||||||
|
(click)="selectContact()"
|
||||||
|
>
|
||||||
|
Contact Info
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-toolbar>
|
||||||
|
<!-- / CHAT TOOLBAR -->
|
||||||
|
|
||||||
|
<!-- CHAT CONTENT -->
|
||||||
|
<div id="chat-content" fxFlex="1 1 auto" fusePerfectScrollbar>
|
||||||
|
<!-- CHAT MESSAGES -->
|
||||||
|
<ucap-chat-messages></ucap-chat-messages>
|
||||||
|
<!-- CHAT MESSAGES -->
|
||||||
|
</div>
|
||||||
|
<!-- / CHAT CONTENT -->
|
||||||
|
|
||||||
|
<!-- CHAT FOOTER -->
|
||||||
|
<div class="chat-footer" fxFlex="0 0 auto" fxLayout="column">
|
||||||
|
<!-- REPLY FORM -->
|
||||||
|
<ucap-chat-form></ucap-chat-form>
|
||||||
|
<!-- / REPLY FORM -->
|
||||||
|
</div>
|
||||||
|
<!-- / CHAT FOOTER-->
|
||||||
|
</div>
|
||||||
|
<!-- / CHAT -->
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<MessagesComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [MessagesComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MessagesComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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<RightSidenavComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [RightSidenavComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RightSidenavComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -15,4 +15,4 @@ const routes: Routes = [
|
||||||
imports: [RouterModule.forChild(routes)],
|
imports: [RouterModule.forChild(routes)],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
export class AccountRoutingPageModule {}
|
export class AppAccountRoutingPageModule {}
|
||||||
|
|
|
@ -3,13 +3,13 @@ import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
import { UCapUiAccountModule } from '@ucap-webmessenger/ui-account';
|
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';
|
import { COMPONENTS } from './components';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, UCapUiAccountModule, AccountRoutingPageModule],
|
imports: [CommonModule, UCapUiAccountModule, AppAccountRoutingPageModule],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
entryComponents: []
|
entryComponents: []
|
||||||
})
|
})
|
||||||
export class AccountPageModule {}
|
export class AppAccountPageModule {}
|
||||||
|
|
|
@ -16,21 +16,20 @@
|
||||||
mode="side"
|
mode="side"
|
||||||
matIsLockedOpen="gt-md"
|
matIsLockedOpen="gt-md"
|
||||||
>
|
>
|
||||||
<!-- <chat-left-sidenav></chat-left-sidenav> -->
|
<app-layout-chat-left-sidenav></app-layout-chat-left-sidenav>
|
||||||
dsafsdfsdf
|
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<!-- / LEFT SIDENAV -->
|
<!-- / LEFT SIDENAV -->
|
||||||
|
|
||||||
<!-- CONTENT -->
|
<!-- CONTENT -->
|
||||||
<!-- <chat-start *ngIf="!selectedChat"></chat-start>
|
<app-layout-chat-intro *ngIf="!selectedChat"></app-layout-chat-intro>
|
||||||
|
|
||||||
<chat-view *ngIf="selectedChat"></chat-view> -->
|
<app-layout-chat-messages
|
||||||
|
*ngIf="selectedChat"
|
||||||
|
></app-layout-chat-messages>
|
||||||
<!-- / CONTENT -->
|
<!-- / CONTENT -->
|
||||||
asdfsdfsdfs
|
|
||||||
<!-- RIGHT SIDENAV -->
|
<!-- RIGHT SIDENAV -->
|
||||||
<mat-sidenav class="sidenav" position="end" opened="false" mode="over">
|
<mat-sidenav class="sidenav" position="end" opened="true" mode="side">
|
||||||
<!-- <chat-right-sidenav></chat-right-sidenav> -->
|
<app-layout-chat-right-sidenav></app-layout-chat-right-sidenav>
|
||||||
safsdf
|
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<!-- / RIGHT SIDENAV -->
|
<!-- / RIGHT SIDENAV -->
|
||||||
</mat-sidenav-container>
|
</mat-sidenav-container>
|
||||||
|
|
|
@ -7,11 +7,14 @@ import { AuthenticationProtocolService } from '@ucap-webmessenger/protocol-authe
|
||||||
styleUrls: ['./main.page.component.scss']
|
styleUrls: ['./main.page.component.scss']
|
||||||
})
|
})
|
||||||
export class MainPageComponent implements OnInit {
|
export class MainPageComponent implements OnInit {
|
||||||
|
selectedChat: boolean;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authenticationProtocolService: AuthenticationProtocolService
|
private authenticationProtocolService: AuthenticationProtocolService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// this.authenticationProtocolService.login({});
|
// this.authenticationProtocolService.login({});
|
||||||
|
this.selectedChat = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,4 @@ const routes: Routes = [
|
||||||
imports: [RouterModule.forChild(routes)],
|
imports: [RouterModule.forChild(routes)],
|
||||||
exports: [RouterModule]
|
exports: [RouterModule]
|
||||||
})
|
})
|
||||||
export class MessengerRoutingPageModule {}
|
export class AppMessengerRoutingPageModule {}
|
||||||
|
|
|
@ -3,13 +3,20 @@ import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
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';
|
import { COMPONENTS } from './components';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, MatSidenavModule, MessengerRoutingPageModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MatSidenavModule,
|
||||||
|
AppChatLayoutModule,
|
||||||
|
AppMessengerRoutingPageModule
|
||||||
|
],
|
||||||
declarations: [...COMPONENTS],
|
declarations: [...COMPONENTS],
|
||||||
entryComponents: []
|
entryComponents: []
|
||||||
})
|
})
|
||||||
export class MessengerPageModule {}
|
export class AppMessengerPageModule {}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import { MessengerResolver } from './messenger.resolver';
|
import { AppMessengerResolver } from './messenger.resolver';
|
||||||
|
|
||||||
export const RESOLVERS = [MessengerResolver];
|
export const RESOLVERS = [AppMessengerResolver];
|
||||||
|
|
|
@ -24,7 +24,7 @@ import {
|
||||||
import { LocaleCode } from '@ucap-webmessenger/core';
|
import { LocaleCode } from '@ucap-webmessenger/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MessengerResolver implements Resolve<void> {
|
export class AppMessengerResolver implements Resolve<void> {
|
||||||
constructor(
|
constructor(
|
||||||
private store: Store<any>,
|
private store: Store<any>,
|
||||||
private sessionStorageService: SessionStorageService,
|
private sessionStorageService: SessionStorageService,
|
||||||
|
@ -57,6 +57,7 @@ export class MessengerResolver implements Resolve<void> {
|
||||||
this.innerProtocolService
|
this.innerProtocolService
|
||||||
.conn({})
|
.conn({})
|
||||||
.pipe(
|
.pipe(
|
||||||
|
take(1),
|
||||||
map(connRes => {
|
map(connRes => {
|
||||||
this.authenticationProtocolService
|
this.authenticationProtocolService
|
||||||
.login({
|
.login({
|
||||||
|
@ -79,6 +80,7 @@ export class MessengerResolver implements Resolve<void> {
|
||||||
productName: 'EZMessenger'
|
productName: 'EZMessenger'
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
|
take(1),
|
||||||
map(loginRes => {
|
map(loginRes => {
|
||||||
console.log('loginRes', loginRes);
|
console.log('loginRes', loginRes);
|
||||||
})
|
})
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
Binary file not shown.
|
@ -1,7 +1,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map, take } from 'rxjs/operators';
|
||||||
|
|
||||||
import { ProtocolService } from '@ucap-webmessenger/protocol';
|
import { ProtocolService } from '@ucap-webmessenger/protocol';
|
||||||
import {
|
import {
|
||||||
|
@ -39,13 +39,19 @@ export class AuthenticationProtocolService {
|
||||||
public login(req: LoginRequest): Observable<LoginResponse> {
|
public login(req: LoginRequest): Observable<LoginResponse> {
|
||||||
return this.protocolService
|
return this.protocolService
|
||||||
.call(SVC_TYPE_LOGIN, SSVC_TYPE_LOGIN_REQ, ...encodeLogin(req))
|
.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<LogoutResponse> {
|
public logout(req: LogoutRequest): Observable<LogoutResponse> {
|
||||||
return this.protocolService
|
return this.protocolService
|
||||||
.call(SVC_TYPE_LOGOUT, SSVC_TYPE_LOGOUT_REQ, ...encodeLogout(req))
|
.call(SVC_TYPE_LOGOUT, SSVC_TYPE_LOGOUT_REQ, ...encodeLogout(req))
|
||||||
.pipe(map(res => decodeLogout(res)));
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => decodeLogout(res))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public logoutRemote(
|
public logoutRemote(
|
||||||
|
@ -57,6 +63,9 @@ export class AuthenticationProtocolService {
|
||||||
SSVC_TYPE_LOGOUT_REMOTE_REQ,
|
SSVC_TYPE_LOGOUT_REMOTE_REQ,
|
||||||
...encodeLogoutRemote(req)
|
...encodeLogoutRemote(req)
|
||||||
)
|
)
|
||||||
.pipe(map(res => decodeLogoutRemote(res)));
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => decodeLogoutRemote(res))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<InfoRequest> = (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<InfoData> = (
|
||||||
|
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<InfoResponse> = (
|
||||||
|
message: ProtocolMessage
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
roomSeq: message.bodyList[0],
|
||||||
|
baseSeq: message.bodyList[1],
|
||||||
|
validFileBaseSeq: message.bodyList[2],
|
||||||
|
count: message.bodyList[3]
|
||||||
|
} as InfoResponse;
|
||||||
|
};
|
|
@ -1,8 +1,42 @@
|
||||||
import { Injectable } from '@angular/core';
|
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({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class EventProtocolService {
|
export class EventProtocolService {
|
||||||
constructor() {}
|
constructor(private protocolService: ProtocolService) {}
|
||||||
|
|
||||||
|
public info(req: InfoRequest): Observable<InfoResponse | InfoData> {
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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'
|
||||||
|
}
|
|
@ -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; // 동영상 스트리밍 전송 응답
|
|
@ -1,7 +1,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map, take } from 'rxjs/operators';
|
||||||
|
|
||||||
import { ProtocolService } from '@ucap-webmessenger/protocol';
|
import { ProtocolService } from '@ucap-webmessenger/protocol';
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ export class InnerProtocolService {
|
||||||
public conn(req: ConnRequest): Observable<ConnResponse> {
|
public conn(req: ConnRequest): Observable<ConnResponse> {
|
||||||
return this.protocolService
|
return this.protocolService
|
||||||
.call(SVC_TYPE_INNER, SSVC_TYPE_CONN_REQ, ...encodeConn(req))
|
.call(SVC_TYPE_INNER, SSVC_TYPE_CONN_REQ, ...encodeConn(req))
|
||||||
.pipe(map(res => decodeConn(res)));
|
.pipe(
|
||||||
|
take(1),
|
||||||
|
map(res => decodeConn(res))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,10 @@ export interface ProtocolResponse {
|
||||||
_id?: string;
|
_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProtocolStream {
|
||||||
|
_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
// tslint:disable-next-line: no-empty-interface
|
// tslint:disable-next-line: no-empty-interface
|
||||||
export interface ProtocolNotification {}
|
export interface ProtocolNotification {}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Injectable, Inject } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { Subscription, Observable, Subject } from 'rxjs';
|
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';
|
import { QueueingSubject } from 'queueing-subject';
|
||||||
|
|
||||||
|
@ -83,7 +83,6 @@ export class ProtocolService {
|
||||||
let requestState: RequestState | null = null;
|
let requestState: RequestState | null = null;
|
||||||
if (res.requestId) {
|
if (res.requestId) {
|
||||||
requestState = this.pendingRequests.get(res.requestId);
|
requestState = this.pendingRequests.get(res.requestId);
|
||||||
this.pendingRequests.delete(res.requestId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SSVC_TYPE_ERROR_RES === res.message.subServiceType) {
|
if (SSVC_TYPE_ERROR_RES === res.message.subServiceType) {
|
||||||
|
@ -162,7 +161,18 @@ export class ProtocolService {
|
||||||
{ type: PacketBodyValue.RequestId, value: requestId }
|
{ type: PacketBodyValue.RequestId, value: requestId }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
responseSubject = new Subject<ProtocolMessage>();
|
responseSubject = new Subject<ProtocolMessage>().pipe(
|
||||||
|
finalize(() => {
|
||||||
|
if (this.pendingRequests.has(requestId)) {
|
||||||
|
this.pendingRequests.delete(requestId);
|
||||||
|
}
|
||||||
|
console.log(
|
||||||
|
'ProtocolService::pendingRequests.size',
|
||||||
|
this.pendingRequests.size
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) as Subject<ProtocolMessage>;
|
||||||
|
|
||||||
this.pendingRequests.set(requestId, {
|
this.pendingRequests.set(requestId, {
|
||||||
subject: responseSubject,
|
subject: responseSubject,
|
||||||
request: { serviceType, subServiceType, bodyList }
|
request: { serviceType, subServiceType, bodyList }
|
||||||
|
|
24
projects/ucap-webmessenger-ui-chat/README.md
Normal file
24
projects/ucap-webmessenger-ui-chat/README.md
Normal file
|
@ -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).
|
32
projects/ucap-webmessenger-ui-chat/karma.conf.js
Normal file
32
projects/ucap-webmessenger-ui-chat/karma.conf.js
Normal file
|
@ -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
|
||||||
|
});
|
||||||
|
};
|
7
projects/ucap-webmessenger-ui-chat/ng-package.json
Normal file
7
projects/ucap-webmessenger-ui-chat/ng-package.json
Normal file
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
8
projects/ucap-webmessenger-ui-chat/package.json
Normal file
8
projects/ucap-webmessenger-ui-chat/package.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"name": "@ucap-webmessenger/ui-chat",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^8.2.5",
|
||||||
|
"@angular/core": "^8.2.5"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div
|
||||||
|
class="chat-form"
|
||||||
|
fxFlex="0 0 auto"
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="center center"
|
||||||
|
>
|
||||||
|
<form
|
||||||
|
#replyForm="ngForm"
|
||||||
|
(ngSubmit)="send($event)"
|
||||||
|
(keydown.enter)="send($event)"
|
||||||
|
fxFlex
|
||||||
|
fxLayout="row"
|
||||||
|
fxLayoutAlign="start center"
|
||||||
|
>
|
||||||
|
<mat-form-field
|
||||||
|
class="message-text"
|
||||||
|
fxFlex
|
||||||
|
floatLabel="never"
|
||||||
|
appearance="standard"
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
matInput
|
||||||
|
#replyInput
|
||||||
|
placeholder="Type your message"
|
||||||
|
ngModel
|
||||||
|
name="message"
|
||||||
|
[rows]="1"
|
||||||
|
[matTextareaAutosize]="true"
|
||||||
|
></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="send-message-button"
|
||||||
|
mat-icon-button
|
||||||
|
type="submit"
|
||||||
|
aria-label="Send message"
|
||||||
|
></button>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<FormComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [FormComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(FormComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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<IntroComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [IntroComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(IntroComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
<div class="chat-messages">
|
||||||
|
<!-- MESSAGE -->
|
||||||
|
<div
|
||||||
|
*ngFor="let message of messages; let i = index"
|
||||||
|
class="message-row"
|
||||||
|
[ngClass]="{
|
||||||
|
me: message.who === user.id,
|
||||||
|
contact: message.who !== user.id,
|
||||||
|
'first-of-group': isFirstMessageOfGroup(message, i),
|
||||||
|
'last-of-group': isLastMessageOfGroup(message, i)
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<img *ngIf="" src="" class="avatar" />
|
||||||
|
|
||||||
|
<div class="bubble">
|
||||||
|
<div class="message">{{ message.message }}</div>
|
||||||
|
<div class="time secondary-text">{{ message.time | date: 'short' }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<MessagesComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [MessagesComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MessagesComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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<UCapUiChatModule> {
|
||||||
|
return {
|
||||||
|
ngModule: UCapUiChatModule,
|
||||||
|
providers: [...SERVICES]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
9
projects/ucap-webmessenger-ui-chat/src/public-api.ts
Normal file
9
projects/ucap-webmessenger-ui-chat/src/public-api.ts
Normal file
|
@ -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';
|
21
projects/ucap-webmessenger-ui-chat/src/test.ts
Normal file
21
projects/ucap-webmessenger-ui-chat/src/test.ts
Normal file
|
@ -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);
|
26
projects/ucap-webmessenger-ui-chat/tsconfig.lib.json
Normal file
26
projects/ucap-webmessenger-ui-chat/tsconfig.lib.json
Normal file
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
17
projects/ucap-webmessenger-ui-chat/tsconfig.spec.json
Normal file
17
projects/ucap-webmessenger-ui-chat/tsconfig.spec.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
17
projects/ucap-webmessenger-ui-chat/tslint.json
Normal file
17
projects/ucap-webmessenger-ui-chat/tslint.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tslint.json",
|
||||||
|
"rules": {
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
"ucapChat",
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
"ucap-chat",
|
||||||
|
"kebab-case"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
552
projects/ucap-webmessenger-ui/src/lib/animations/index.ts
Normal file
552
projects/ucap-webmessenger-ui/src/lib/animations/index.ts
Normal file
|
@ -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 })
|
||||||
|
])
|
||||||
|
)
|
||||||
|
])
|
||||||
|
];
|
|
@ -2,6 +2,8 @@
|
||||||
* Public API Surface of ucap-webmessenger-ui
|
* Public API Surface of ucap-webmessenger-ui
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export * from './lib/animations';
|
||||||
|
|
||||||
export * from './lib/dialogs/alert.dialog.component';
|
export * from './lib/dialogs/alert.dialog.component';
|
||||||
export * from './lib/dialogs/confirm.dialog.component';
|
export * from './lib/dialogs/confirm.dialog.component';
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
"typeRoots": ["node_modules/@types"],
|
"typeRoots": ["node_modules/@types"],
|
||||||
"lib": ["es2018", "dom"],
|
"lib": ["es2018", "dom"],
|
||||||
"paths": {
|
"paths": {
|
||||||
|
"@app/*": ["projects/ucap-webmessenger-app/src/app/*"],
|
||||||
|
|
||||||
"@ucap-webmessenger/core": [
|
"@ucap-webmessenger/core": [
|
||||||
"projects/ucap-webmessenger-core/src/public-api"
|
"projects/ucap-webmessenger-core/src/public-api"
|
||||||
],
|
],
|
||||||
|
@ -35,6 +37,9 @@
|
||||||
"@ucap-webmessenger/ui-account": [
|
"@ucap-webmessenger/ui-account": [
|
||||||
"projects/ucap-webmessenger-ui-account/src/public-api"
|
"projects/ucap-webmessenger-ui-account/src/public-api"
|
||||||
],
|
],
|
||||||
|
"@ucap-webmessenger/ui-chat": [
|
||||||
|
"projects/ucap-webmessenger-ui-chat/src/public-api"
|
||||||
|
],
|
||||||
"@ucap-webmessenger/ui-messenger": [
|
"@ucap-webmessenger/ui-messenger": [
|
||||||
"projects/ucap-webmessenger-ui-messenger/src/public-api"
|
"projects/ucap-webmessenger-ui-messenger/src/public-api"
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue
Block a user