sync
This commit is contained in:
parent
7dcec1aaad
commit
0c696c3a03
|
@ -6,3 +6,67 @@
|
||||||
파일 컴포넌트
|
파일 컴포넌트
|
||||||
문서 컴포넌트
|
문서 컴포넌트
|
||||||
|
|
||||||
|
대화 복사
|
||||||
|
일반 텍스트
|
||||||
|
장문 텍스트
|
||||||
|
|
||||||
|
combineLatest([
|
||||||
|
this.store.pipe(select(LoginSelector.loginRes)),
|
||||||
|
this.store.pipe(select(DepartmentSelector.departmentInfoList))
|
||||||
|
])
|
||||||
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
||||||
|
.subscribe(([loginRes, deptInfoList]) => {
|
||||||
|
this.loginRes = loginRes;
|
||||||
|
this.treeData = {
|
||||||
|
deptInfoList,
|
||||||
|
displayRoot: environment.productConfig.organization.displayRoot,
|
||||||
|
expanded: !!this._initialExpanded
|
||||||
|
? [this._initialExpanded]
|
||||||
|
: undefined
|
||||||
|
};
|
||||||
|
this.changeDetectorRef.markForCheck();
|
||||||
|
if (!!loginRes && !!deptInfoList) {
|
||||||
|
this._initialExpanded = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
http://lftalk2.lfcorp.com:8011/Common/FileTalkDownload.aspx
|
||||||
|
?
|
||||||
|
p_user_seq=102&
|
||||||
|
p_device_type=P&
|
||||||
|
p_token=MTg1MDM5NTc5Nzk1MTQ1MTk0ODU0MTY2MTI0NDE2ODY3NjY5ODY5Ng&
|
||||||
|
p_att_seq=68450
|
||||||
|
|
||||||
|
|
||||||
|
attachmentsSeq: "15186849"
|
||||||
|
deviceType: "W"
|
||||||
|
token: "NDcyNDEwMjg2NjcyMjg3MTkxNzAyNDk2ODEwMzg2MDI4NjY5NzcyNA"
|
||||||
|
userSeq: 770074
|
||||||
|
|
||||||
|
http://13.124.88.127:8011/Common/FileTalkDownload.aspx?p_user_seq=770074&p_device_type=W&p_token=NDcyNDEwMjg2NjcyMjg3MTkxNzAyNDk2ODEwMzg2MDI4NjY5NzcyNA&p_att_seq=15186849
|
||||||
|
|
||||||
|
public urlForFileTalkDownload(
|
||||||
|
req: FileTalkDownloadRequest,
|
||||||
|
fileTalkDownloadUrl?: string
|
||||||
|
): string {
|
||||||
|
const fileTalkDownloadEncodeMap = {
|
||||||
|
userSeq: 'p_user_seq',
|
||||||
|
deviceType: 'p_device_type',
|
||||||
|
token: 'p_token',
|
||||||
|
attachmentsSeq: 'p_att_seq'
|
||||||
|
};
|
||||||
|
const extraParams: any = {};
|
||||||
|
|
||||||
|
const url = ParameterUtil.encode(
|
||||||
|
fileTalkDownloadEncodeMap,
|
||||||
|
req,
|
||||||
|
extraParams
|
||||||
|
);
|
||||||
|
const params = encodeFileTalkDownload(req);
|
||||||
|
|
||||||
|
const tttt = `${fileTalkDownloadUrl}?${url.toString()}`;
|
||||||
|
const temp = `${fileTalkDownloadUrl}${
|
||||||
|
!!params ? `?${params.toString()}` : ''
|
||||||
|
}`;
|
||||||
|
return tttt;
|
||||||
|
}
|
||||||
|
|
50
documents/업무/6월/2째주/0610.txt
Normal file
50
documents/업무/6월/2째주/0610.txt
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
클립보드 다이얼로그
|
||||||
|
|
||||||
|
"Failed to execute 'query' on 'Permissions': The provided value 'clipboard' is not a valid enum value of type PermissionName."
|
||||||
|
"TypeError: Failed to execute 'query' on 'Permissions': The provided value 'clipboard' is not a valid enum value of type PermissionName.
|
||||||
|
at FormSectionComponent.onPasteReply (http://localhost:4200/pages-chat-chat-page-module.27fafdb1d452d17534ca.hot-update.js:251:14)
|
||||||
|
at FormSectionComponent_Template_textarea_paste_8_listener (http://localhost:4200/pages-chat-chat-page-module.27fafdb1d452d17534ca.hot-update.js:351:282)
|
||||||
|
at executeListenerWithErrorHandling (http://localhost:4200/vendor.js:54608:16)
|
||||||
|
at wrapListenerIn_markDirtyAndPreventDefault (http://localhost:4200/vendor.js:54650:22)
|
||||||
|
at HTMLTextAreaElement.<anonymous> (http://localhost:4200/vendor.js:125315:38)
|
||||||
|
at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:443:35)
|
||||||
|
at Object.onInvokeTask (http://localhost:4200/vendor.js:71697:33)
|
||||||
|
at ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:442:40)
|
||||||
|
at Zone.runTask (http://localhost:4200/polyfills.js:211:51)
|
||||||
|
at ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:524:38)"
|
||||||
|
|
||||||
|
|
||||||
|
navigator.permissions
|
||||||
|
.query({
|
||||||
|
name: 'clipboard-read' as PermissionName
|
||||||
|
})
|
||||||
|
.then((permissionStatus) => {
|
||||||
|
// Will be 'granted', 'denied' or 'prompt':
|
||||||
|
console.log(permissionStatus.state);
|
||||||
|
|
||||||
|
// Listen for changes to the permission state
|
||||||
|
permissionStatus.onchange = () => {
|
||||||
|
console.log(permissionStatus.state);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
navigator.permissions
|
||||||
|
.query({ name: 'clipboard-read' as PermissionName })
|
||||||
|
.then((result: PermissionStatus) => {
|
||||||
|
console.log('1: ', result);
|
||||||
|
if ('granted' === result.state || 'prompt' === result.state) {
|
||||||
|
console.log(event.clipboardData.items);
|
||||||
|
navigator.clipboard
|
||||||
|
.readText()
|
||||||
|
.then((value) => {
|
||||||
|
console.log(value);
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
console.log(reason);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((reason) => {
|
||||||
|
console.log(reason);
|
||||||
|
});
|
|
@ -1,117 +0,0 @@
|
||||||
<div class="ucap-binary-viewer-container">
|
|
||||||
<mat-toolbar class="ucap-binary-viewer-header">
|
|
||||||
<!--<mat-icon class="ucap-binary-viewer-icon">attachment</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="ucap-binary-viewer-icon"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
<span class="ucap-binary-viewer-title">{{
|
|
||||||
fileInfo.sentMessageJson.fileName
|
|
||||||
}}</span>
|
|
||||||
<span class="ucap-binary-viewer-spacer"></span>
|
|
||||||
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-binary-viewer-action"
|
|
||||||
matTooltip="{{ 'common.file.download' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickDownload()"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span class="stroke-bar"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
color="warn"
|
|
||||||
class="ucap-binary-viewer-action"
|
|
||||||
(click)="onClickClose()"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</mat-toolbar>
|
|
||||||
<div style="position: relative;">
|
|
||||||
<div
|
|
||||||
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
|
|
||||||
style="position: absolute; width: 100%;"
|
|
||||||
>
|
|
||||||
<mat-progress-bar
|
|
||||||
mode="determinate"
|
|
||||||
[value]="fileDownloadItem.downloadingProgress$ | async"
|
|
||||||
></mat-progress-bar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ucap-binary-viewer-body">
|
|
||||||
<div
|
|
||||||
class="ucap-binary-viewer-content-wrapper"
|
|
||||||
fxLayout="column"
|
|
||||||
fxLayout.xs="row"
|
|
||||||
fxFlexFill
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<div class="circle-box">
|
|
||||||
<div
|
|
||||||
[ngClass]="[
|
|
||||||
'mime-icon',
|
|
||||||
'light',
|
|
||||||
'ico-' + fileInfo.sentMessageJson.fileExt
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<div class="ico"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="guide-msg">
|
|
||||||
{{ 'common.file.errors.noPreview' | translate }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
colori
|
|
||||||
mat-raised-button
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickDownload()"
|
|
||||||
>
|
|
||||||
{{ 'common.file.download' | translate }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,67 +0,0 @@
|
||||||
.ucap-binary-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ucap-binary-viewer-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 60px;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
background-color: #333333;
|
|
||||||
color: #ffffff;
|
|
||||||
|
|
||||||
.ucap-binary-viewer-icon {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-binary-viewer-title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-binary-viewer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-bar {
|
|
||||||
width: 1px;
|
|
||||||
height: 30px;
|
|
||||||
background-color: rgba(256, 256, 256, 0.3);
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
.ucap-binary-viewer-action {
|
|
||||||
margin-left: auto;
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 10px;
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-binary-viewer-body {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
|
|
||||||
.ucap-image-viewer-image-wrapper {
|
|
||||||
height: 100%;
|
|
||||||
padding: 20px;
|
|
||||||
background-color: rgba(0, 0, 0, 0.9);
|
|
||||||
}
|
|
||||||
.circle-box {
|
|
||||||
display: flex;
|
|
||||||
width: 140px;
|
|
||||||
height: 140px;
|
|
||||||
border-radius: 50%;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border: 2px solid #ffffff;
|
|
||||||
background-color: rgba(256, 256, 256, 0.7);
|
|
||||||
}
|
|
||||||
.guide-msg {
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 30px;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { BinaryViewerComponent } from './binary-viewer.component';
|
|
||||||
|
|
||||||
describe('BinaryViewerComponent', () => {
|
|
||||||
let component: BinaryViewerComponent;
|
|
||||||
let fixture: ComponentFixture<BinaryViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [BinaryViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(BinaryViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,41 +0,0 @@
|
||||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
|
||||||
import { ucapAnimations } from '../../animations';
|
|
||||||
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
import { FileInfo } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-binary-viewer',
|
|
||||||
templateUrl: './binary-viewer.component.html',
|
|
||||||
styleUrls: ['./binary-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations
|
|
||||||
})
|
|
||||||
export class BinaryViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
fileInfo: FileInfo;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
onClickDownload(): void {
|
|
||||||
this.fileDownloadItem = new FileDownloadItem();
|
|
||||||
this.download.emit(this.fileDownloadItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickClose(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<div class="ucap-image-viewer-container">
|
|
||||||
<mat-toolbar class="bg-primary-dark">
|
|
||||||
<span>Third Line</span>
|
|
||||||
<span class="ucap-image-viewer-spacer"></span>
|
|
||||||
<mat-icon
|
|
||||||
class="example-icon"
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-label="Example heart icon"
|
|
||||||
>favorite</mat-icon
|
|
||||||
>
|
|
||||||
<mat-icon
|
|
||||||
class="example-icon"
|
|
||||||
aria-hidden="false"
|
|
||||||
aria-label="Example delete icon"
|
|
||||||
>delete</mat-icon
|
|
||||||
>
|
|
||||||
</mat-toolbar>
|
|
||||||
<div style="position: relative;">
|
|
||||||
<div
|
|
||||||
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
|
|
||||||
style="position: absolute; width: 100%;"
|
|
||||||
>
|
|
||||||
<mat-progress-bar
|
|
||||||
mode="determinate"
|
|
||||||
[value]="fileDownloadItem.downloadingProgress$ | async"
|
|
||||||
></mat-progress-bar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,13 +0,0 @@
|
||||||
.ucap-document-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ucap-document-viewer-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
|
|
||||||
.ucap-document-viewer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { DocumentViewerComponent } from './document-viewer.component';
|
|
||||||
|
|
||||||
describe('DocumentViewerComponent', () => {
|
|
||||||
let component: DocumentViewerComponent;
|
|
||||||
let fixture: ComponentFixture<DocumentViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [DocumentViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(DocumentViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,39 +0,0 @@
|
||||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
|
||||||
import { ucapAnimations } from '../../animations';
|
|
||||||
import { FileInfo } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-document-viewer',
|
|
||||||
templateUrl: './document-viewer.component.html',
|
|
||||||
styleUrls: ['./document-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations
|
|
||||||
})
|
|
||||||
export class DocumentViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
fileInfo: FileInfo;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
onClickDownload(): void {
|
|
||||||
this.fileDownloadItem = new FileDownloadItem();
|
|
||||||
this.download.emit(this.fileDownloadItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickClose(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<div
|
|
||||||
class="ucap-file-viewer-container"
|
|
||||||
[ngSwitch]="detectFileViewerType(currentFileInfo)"
|
|
||||||
>
|
|
||||||
<ucap-document-viewer
|
|
||||||
*ngSwitchCase="FileViewerType.Document"
|
|
||||||
[fileInfo]="currentFileInfo"
|
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
|
||||||
(download)="onDownload($event)"
|
|
||||||
(closed)="onClosedViewer()"
|
|
||||||
>
|
|
||||||
</ucap-document-viewer>
|
|
||||||
<ucap-binary-viewer
|
|
||||||
*ngSwitchDefault
|
|
||||||
[fileInfo]="currentFileInfo"
|
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
|
||||||
(download)="onDownload($event)"
|
|
||||||
(closed)="onClosedViewer()"
|
|
||||||
></ucap-binary-viewer>
|
|
||||||
</div>
|
|
|
@ -1,4 +0,0 @@
|
||||||
.ucap-file-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { FileViewerComponent } from './file-viewer.component';
|
|
||||||
|
|
||||||
describe('FileViewerComponent', () => {
|
|
||||||
let component: FileViewerComponent;
|
|
||||||
let fixture: ComponentFixture<FileViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [FileViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(FileViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,77 +0,0 @@
|
||||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
|
||||||
import { ucapAnimations } from '../animations';
|
|
||||||
|
|
||||||
import { FileViewerType } from '../types/file-viewer.type';
|
|
||||||
import { FileType, FileInfo, isSound } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
import { SelectFileInfo } from '../models/select-file-info';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-file-viewer',
|
|
||||||
templateUrl: './file-viewer.component.html',
|
|
||||||
styleUrls: ['./file-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations
|
|
||||||
})
|
|
||||||
export class FileViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
set fileInfo(v: { fileInfos: FileInfo[]; selectFileInfo: SelectFileInfo }) {
|
|
||||||
this._fileInfo = v;
|
|
||||||
|
|
||||||
this.currentFileInfo = v.fileInfos.find(
|
|
||||||
f => f.sentMessageJson.attachmentSeq === v.selectFileInfo.attachmentSeq
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// tslint:disable-next-line: variable-name
|
|
||||||
_fileInfo: {
|
|
||||||
fileInfos: FileInfo[];
|
|
||||||
selectFileInfo: SelectFileInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: (attachmentSeq: number) => string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<{
|
|
||||||
attachmentSeq?: number;
|
|
||||||
downloadUrl?: string;
|
|
||||||
fileName: string;
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
currentFileInfo: FileInfo;
|
|
||||||
FileViewerType = FileViewerType;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
detectFileViewerType(fileInfo: FileInfo): FileViewerType {
|
|
||||||
switch (fileInfo.type) {
|
|
||||||
case FileType.Image:
|
|
||||||
return FileViewerType.Image;
|
|
||||||
case FileType.Sound:
|
|
||||||
return FileViewerType.Sound;
|
|
||||||
case FileType.Video:
|
|
||||||
return FileViewerType.Video;
|
|
||||||
default:
|
|
||||||
if (isSound(fileInfo)) {
|
|
||||||
return FileViewerType.Sound;
|
|
||||||
}
|
|
||||||
return FileViewerType.Binary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onDownload(fileDownloadItem: FileDownloadItem): void {
|
|
||||||
this.download.emit({
|
|
||||||
attachmentSeq: this.currentFileInfo.sentMessageJson.attachmentSeq,
|
|
||||||
fileName: this.currentFileInfo.sentMessageJson.fileName,
|
|
||||||
fileDownloadItem
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosedViewer(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
<ng-container *ngIf="!!currentFileInfo">
|
|
||||||
<ucap-file-viewer
|
|
||||||
*ngIf="!isMediaType"
|
|
||||||
[fileInfo]="fileInfo"
|
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
|
||||||
(download)="onDownload($event)"
|
|
||||||
(closed)="onClosedViewer()"
|
|
||||||
></ucap-file-viewer>
|
|
||||||
|
|
||||||
<ucap-media-viewer
|
|
||||||
*ngIf="isMediaType"
|
|
||||||
[fileInfo]="fileInfo"
|
|
||||||
[fileDownloadUrl]="fileDownloadUrl"
|
|
||||||
(download)="onDownload($event)"
|
|
||||||
(closed)="onClosedViewer()"
|
|
||||||
></ucap-media-viewer>
|
|
||||||
</ng-container>
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { FileViewerDialogComponent } from './file-viewer.dialog.component';
|
|
||||||
|
|
||||||
describe('FileViewerDialogComponent', () => {
|
|
||||||
let component: FileViewerDialogComponent;
|
|
||||||
let fixture: ComponentFixture<FileViewerDialogComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [FileViewerDialogComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(FileViewerDialogComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,178 +0,0 @@
|
||||||
import { Component, OnInit, OnDestroy, Inject } from '@angular/core';
|
|
||||||
|
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
|
||||||
|
|
||||||
import { DeviceType } from '@ucap-webmessenger/core';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
import { CommonApiService } from '@ucap-webmessenger/api-common';
|
|
||||||
import { AppFileService } from '@app/services/file.service';
|
|
||||||
import { FileInfo, isMedia } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { SelectFileInfo, SnackBarService } from '@ucap-webmessenger/ui';
|
|
||||||
import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
export interface FileViewerDialogData {
|
|
||||||
fileInfos: FileInfo[];
|
|
||||||
selectFileInfo: SelectFileInfo;
|
|
||||||
downloadUrl: string;
|
|
||||||
userSeq: number;
|
|
||||||
deviceType: DeviceType;
|
|
||||||
token: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileViewerDialogResult {}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-layout-common-file-viewer',
|
|
||||||
templateUrl: './file-viewer.dialog.component.html',
|
|
||||||
styleUrls: ['./file-viewer.dialog.component.scss']
|
|
||||||
})
|
|
||||||
export class FileViewerDialogComponent implements OnInit, OnDestroy {
|
|
||||||
isMediaType: boolean;
|
|
||||||
fileInfo: {
|
|
||||||
fileInfos: FileInfo[];
|
|
||||||
selectFileInfo: SelectFileInfo;
|
|
||||||
};
|
|
||||||
currentFileInfo: FileInfo;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
public dialogRef: MatDialogRef<
|
|
||||||
FileViewerDialogData,
|
|
||||||
FileViewerDialogResult
|
|
||||||
>,
|
|
||||||
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
|
|
||||||
@Inject(MAT_DIALOG_DATA) public data: FileViewerDialogData,
|
|
||||||
private snackBarService: SnackBarService,
|
|
||||||
private commonApiService: CommonApiService,
|
|
||||||
private appFileService: AppFileService,
|
|
||||||
private translateService: TranslateService,
|
|
||||||
private logger: NGXLogger
|
|
||||||
) {
|
|
||||||
this.currentFileInfo = this.data.fileInfos.find(
|
|
||||||
(f) => f.seq === this.data.selectFileInfo.attachmentSeq
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!this.currentFileInfo) {
|
|
||||||
this.logger.warn(
|
|
||||||
'file info is exist',
|
|
||||||
this.data.fileInfos,
|
|
||||||
this.data.selectFileInfo
|
|
||||||
);
|
|
||||||
this.dialogRef.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isMediaType = isMedia(this.currentFileInfo);
|
|
||||||
|
|
||||||
this.fileInfo = {
|
|
||||||
fileInfos: this.data.fileInfos.filter((f) => {
|
|
||||||
const i = isMedia(f);
|
|
||||||
return this.isMediaType ? i : !i;
|
|
||||||
}),
|
|
||||||
selectFileInfo: this.data.selectFileInfo
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {}
|
|
||||||
|
|
||||||
onDownload(info: {
|
|
||||||
attachmentSeq?: number;
|
|
||||||
fileName: string;
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
roomSeq?: number;
|
|
||||||
eventSeq?: number;
|
|
||||||
}): void {
|
|
||||||
let fileName;
|
|
||||||
|
|
||||||
const startIdx = info.fileName.indexOf('.thumb');
|
|
||||||
|
|
||||||
if (startIdx < 0) {
|
|
||||||
fileName = info.fileName;
|
|
||||||
} else {
|
|
||||||
const endIdx = info.fileName.lastIndexOf('.');
|
|
||||||
const startFileName = info.fileName.substring(0, startIdx - 4);
|
|
||||||
const endFileName = info.fileName.substring(endIdx, info.fileName.length);
|
|
||||||
|
|
||||||
fileName = startFileName.concat(endFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.nativeService
|
|
||||||
.selectSaveFilePath(fileName)
|
|
||||||
.then((result) => {
|
|
||||||
if (!result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.canceled) {
|
|
||||||
} else {
|
|
||||||
this.saveFile(info, result.filePath);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((reason) => {
|
|
||||||
this.snackBarService.open(
|
|
||||||
this.translateService.instant('common.file.errors.failToSpecifyPath'),
|
|
||||||
this.translateService.instant('common.file.errors.label')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
saveFile(
|
|
||||||
info: {
|
|
||||||
attachmentSeq?: number;
|
|
||||||
downloadUrl?: string;
|
|
||||||
fileName: string;
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
roomSeq?: number;
|
|
||||||
eventSeq?: number;
|
|
||||||
},
|
|
||||||
savePath: string
|
|
||||||
) {
|
|
||||||
if (!!info.roomSeq && !!info.eventSeq) {
|
|
||||||
this.appFileService.fileTalkDownloadMulti({
|
|
||||||
req: {
|
|
||||||
userSeq: this.data.userSeq,
|
|
||||||
deviceType: this.data.deviceType,
|
|
||||||
token: this.data.token,
|
|
||||||
roomSeq: info.roomSeq,
|
|
||||||
eventSeq: info.eventSeq,
|
|
||||||
thumbUrl: info.fileName,
|
|
||||||
fileDownloadItem: info.fileDownloadItem
|
|
||||||
},
|
|
||||||
fileName: info.fileName,
|
|
||||||
savePath
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.appFileService.fileTalkDownlod({
|
|
||||||
req: {
|
|
||||||
userSeq: this.data.userSeq,
|
|
||||||
deviceType: this.data.deviceType,
|
|
||||||
token: this.data.token,
|
|
||||||
attachmentsSeq: info.attachmentSeq,
|
|
||||||
fileDownloadItem: info.fileDownloadItem
|
|
||||||
},
|
|
||||||
fileName: info.fileName,
|
|
||||||
fileDownloadUrl: this.data.downloadUrl,
|
|
||||||
savePath
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosedViewer(): void {
|
|
||||||
this.dialogRef.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
fileDownloadUrl = (attachmentSeq: number) => {
|
|
||||||
return this.commonApiService.urlForFileTalkDownload(
|
|
||||||
{
|
|
||||||
userSeq: this.data.userSeq,
|
|
||||||
deviceType: this.data.deviceType,
|
|
||||||
token: this.data.token,
|
|
||||||
attachmentsSeq: attachmentSeq
|
|
||||||
},
|
|
||||||
this.data.downloadUrl
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,179 +0,0 @@
|
||||||
<div class="ucap-image-viewer-container">
|
|
||||||
<mat-toolbar class="ucap-image-viewer-header bg-primary-dark">
|
|
||||||
<!--<mat-icon class="ucap-image-viewer-icon">image</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="ucap-image-viewer-icon"
|
|
||||||
>
|
|
||||||
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
||||||
<circle cx="8.5" cy="8.5" r="1.5" />
|
|
||||||
<path d="M20.4 14.5L16 10 4 20" />
|
|
||||||
</svg>
|
|
||||||
<span class="ucap-image-viewer-title">{{ fileName }}</span>
|
|
||||||
<span class="ucap-image-viewer-spacer"></span>
|
|
||||||
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-image-viewer-action"
|
|
||||||
matTooltip="{{ 'common.messages.zoomReset' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickZoomReset()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>settings_overscan</mat-icon>-->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3.8 3.8l16.4 16.4M20.2 3.8L3.8 20.2M15 3h6v6M9 3H3v6M15 21h6v-6M9 21H3v-6"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-image-viewer-action"
|
|
||||||
matTooltip="{{ 'common.messages.zoomOut' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickZoomOut()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>zoom_out</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<circle cx="11" cy="11" r="8"></circle>
|
|
||||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
||||||
<line x1="8" y1="11" x2="14" y2="11"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-image-viewer-action"
|
|
||||||
matTooltip="{{ 'common.messages.zoomIn' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickZoomIn()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>zoom_in</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<circle cx="11" cy="11" r="8"></circle>
|
|
||||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
|
||||||
<line x1="11" y1="8" x2="11" y2="14"></line>
|
|
||||||
<line x1="8" y1="11" x2="14" y2="11"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-image-viewer-action"
|
|
||||||
matTooltip="{{ 'common.file.download' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickDownload()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>get_app</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span class="stroke-bar"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
color="warn"
|
|
||||||
class="ucap-image-viewer-action btn-close"
|
|
||||||
matTooltip="{{ 'common.messages.close' | translate }}"
|
|
||||||
(click)="onClickClose()"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</mat-toolbar>
|
|
||||||
<div style="position: relative;">
|
|
||||||
<div
|
|
||||||
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
|
|
||||||
style="position: absolute; width: 100%;"
|
|
||||||
>
|
|
||||||
<mat-progress-bar
|
|
||||||
mode="determinate"
|
|
||||||
[value]="fileDownloadItem.downloadingProgress$ | async"
|
|
||||||
></mat-progress-bar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ucap-image-viewer-body">
|
|
||||||
<div
|
|
||||||
#imageContainer
|
|
||||||
class="ucap-image-viewer-image-wrapper"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
fxFlexFill
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
#downloadImage
|
|
||||||
*ngIf="fileDownloadUrl"
|
|
||||||
[src]="fileDownloadUrl"
|
|
||||||
[style.width]="'auto'"
|
|
||||||
[style.height]="imageHeight + 'px'"
|
|
||||||
(load)="onLoadFileDownloadUrl(downloadImage)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,73 +0,0 @@
|
||||||
.ucap-image-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ucap-image-viewer-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 60px;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
background-color: #333333;
|
|
||||||
|
|
||||||
.ucap-image-viewer-icon {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-image-viewer-title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-image-viewer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-bar {
|
|
||||||
width: 1px;
|
|
||||||
height: 30px;
|
|
||||||
background-color: rgba(256, 256, 256, 0.3);
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
.ucap-image-viewer-action {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 10px;
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-image-viewer-body {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
|
|
||||||
.ucap-image-viewer-image-wrapper {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
max-width: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-corner {
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar:hover {
|
|
||||||
background-color: rgba(255, 255, 255, 0.12);
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
box-shadow: inset 0 0 0 12px rgba(255, 255, 255, 0.37);
|
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-thumb:active {
|
|
||||||
box-shadow: inset 0 0 0 12px rgba(255, 255, 255, 0.54);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { ImageViewerComponent } from './image-viewer.component';
|
|
||||||
|
|
||||||
describe('ImageViewerComponent', () => {
|
|
||||||
let component: ImageViewerComponent;
|
|
||||||
let fixture: ComponentFixture<ImageViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ImageViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ImageViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,149 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
OnInit,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
EventEmitter,
|
|
||||||
ChangeDetectorRef,
|
|
||||||
ChangeDetectionStrategy,
|
|
||||||
ViewChild,
|
|
||||||
ElementRef,
|
|
||||||
HostListener
|
|
||||||
} from '@angular/core';
|
|
||||||
import { ucapAnimations } from '../../animations';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
import { FileInfo } from '@ucap-webmessenger/protocol-file';
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-image-viewer',
|
|
||||||
templateUrl: './image-viewer.component.html',
|
|
||||||
styleUrls: ['./image-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations,
|
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush
|
|
||||||
})
|
|
||||||
export class ImageViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
fileInfo: FileInfo;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileName: string;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
|
||||||
|
|
||||||
@ViewChild('imageContainer', { static: false })
|
|
||||||
imageContainer: ElementRef<HTMLElement>;
|
|
||||||
|
|
||||||
@ViewChild('downloadImage', { static: false })
|
|
||||||
downloadImage: ElementRef<HTMLElement>;
|
|
||||||
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
|
|
||||||
naturalWidth = 0;
|
|
||||||
naturalHeight = 0;
|
|
||||||
imageHeight = 0;
|
|
||||||
|
|
||||||
zoomRatio = 100;
|
|
||||||
|
|
||||||
constructor(private changeDetectorRef: ChangeDetectorRef) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.naturalWidth = this.fileInfo.sentMessageJson.imageWidth;
|
|
||||||
this.naturalHeight = this.fileInfo.sentMessageJson.imageHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
|
||||||
onResize(event: Event) {
|
|
||||||
this.setImageHeight();
|
|
||||||
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickDownload(): void {
|
|
||||||
this.fileDownloadItem = new FileDownloadItem();
|
|
||||||
this.download.emit(this.fileDownloadItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickClose(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadFileDownloadUrl(img: HTMLImageElement) {
|
|
||||||
this.naturalWidth = img.naturalWidth;
|
|
||||||
this.naturalHeight = img.naturalHeight;
|
|
||||||
|
|
||||||
this.setImageHeight();
|
|
||||||
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickZoomOut() {
|
|
||||||
if (60 >= this.zoomRatio) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.zoomRatio -= 10;
|
|
||||||
|
|
||||||
this.setImageHeight();
|
|
||||||
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
onClickZoomIn() {
|
|
||||||
if (180 <= this.zoomRatio) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.zoomRatio += 10;
|
|
||||||
|
|
||||||
this.setImageHeight();
|
|
||||||
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
onClickZoomReset() {
|
|
||||||
this.zoomRatio = 100;
|
|
||||||
|
|
||||||
this.setImageHeight();
|
|
||||||
|
|
||||||
this.changeDetectorRef.detectChanges();
|
|
||||||
}
|
|
||||||
|
|
||||||
setImageHeight() {
|
|
||||||
const realContainerHeight =
|
|
||||||
this.imageContainer.nativeElement.clientHeight - 20;
|
|
||||||
const oriHeight =
|
|
||||||
this.naturalHeight > realContainerHeight
|
|
||||||
? realContainerHeight
|
|
||||||
: this.naturalHeight;
|
|
||||||
|
|
||||||
const oriWidth = (oriHeight * this.naturalWidth) / this.naturalHeight;
|
|
||||||
|
|
||||||
const imageHeight = oriHeight * (this.zoomRatio / 100);
|
|
||||||
const imageWidth = oriWidth * (this.zoomRatio / 100);
|
|
||||||
let imageTop =
|
|
||||||
(this.imageContainer.nativeElement.clientHeight - imageHeight) / 2;
|
|
||||||
let imageLeft =
|
|
||||||
(this.imageContainer.nativeElement.clientWidth - imageWidth) / 2;
|
|
||||||
|
|
||||||
let scrollTop = 0;
|
|
||||||
if (0 > imageTop) {
|
|
||||||
scrollTop = Math.abs(imageTop);
|
|
||||||
imageTop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let scrollLeft = 0;
|
|
||||||
if (0 > imageLeft) {
|
|
||||||
scrollLeft = Math.abs(imageLeft);
|
|
||||||
imageLeft = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.downloadImage.nativeElement.style.top = `${imageTop}px`;
|
|
||||||
this.downloadImage.nativeElement.style.left = `${imageLeft}px`;
|
|
||||||
this.imageContainer.nativeElement.scrollTop = scrollTop;
|
|
||||||
this.imageContainer.nativeElement.scrollLeft = scrollLeft;
|
|
||||||
|
|
||||||
this.imageHeight = imageHeight;
|
|
||||||
}
|
|
||||||
}
|
|
BIN
documents/업무/6월/2째주/backup/next-ucap-messenger-lf-2020-0610.zip
Normal file
BIN
documents/업무/6월/2째주/backup/next-ucap-messenger-lf-2020-0610.zip
Normal file
Binary file not shown.
|
@ -1,144 +0,0 @@
|
||||||
<div class="ucap-sound-viewer-container">
|
|
||||||
<mat-toolbar color="accent" class="ucap-sound-viewer-header">
|
|
||||||
<mat-icon class="ucap-sound-viewer-icon">music_note</mat-icon>
|
|
||||||
<span class="ucap-sound-viewer-title">{{ fileName }}</span>
|
|
||||||
<span class="ucap-sound-viewer-spacer"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-image-viewer-action"
|
|
||||||
matTooltip="{{ 'common.file.download' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickDownload()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>get_app</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span class="stroke-bar"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
color="warn"
|
|
||||||
class="ucap-image-viewer-action btn-close"
|
|
||||||
matTooltip="{{ 'common.messages.close' | translate }}"
|
|
||||||
(click)="onClickClose()"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</mat-toolbar>
|
|
||||||
<div style="position: relative;">
|
|
||||||
<div
|
|
||||||
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
|
|
||||||
style="position: absolute; width: 100%;"
|
|
||||||
>
|
|
||||||
<mat-progress-bar
|
|
||||||
mode="determinate"
|
|
||||||
[value]="fileDownloadItem.downloadingProgress$ | async"
|
|
||||||
></mat-progress-bar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ucap-sound-viewer-body">
|
|
||||||
<div
|
|
||||||
class="ucap-sound-viewer-sound-icon"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<audio
|
|
||||||
[src]="fileDownloadUrl"
|
|
||||||
#audioPlayer
|
|
||||||
(playing)="onPlayingAudio()"
|
|
||||||
(pause)="onPauseAudio()"
|
|
||||||
(timeupdate)="onTimeUpdateAudio()"
|
|
||||||
(volumechange)="onVolumeChangeAudio()"
|
|
||||||
(loadstart)="onLoadStartAudio()"
|
|
||||||
(loadeddata)="onLoadedDataAudio()"
|
|
||||||
></audio>
|
|
||||||
<div class="circle-box">
|
|
||||||
<mat-icon class="ucap-sound-viewer-icon" *ngIf="!playing">
|
|
||||||
music_note
|
|
||||||
</mat-icon>
|
|
||||||
<div class="sound-wave" *ngIf="playing">
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
<div class="sound-bar bg-accent-dark"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="viewer-bottom">
|
|
||||||
<div
|
|
||||||
class="ucap-sound-viewer-sound-time"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<mat-slider
|
|
||||||
#timeSlider
|
|
||||||
min="0"
|
|
||||||
[max]="duration"
|
|
||||||
[value]="currentTime"
|
|
||||||
(change)="onChangeTimeSlider($event)"
|
|
||||||
>
|
|
||||||
</mat-slider>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="ucap-sound-viewer-sound-controls"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
>
|
|
||||||
<div class="ucap-sound-viewer-sound-time-current">
|
|
||||||
{{ currentTime | ucapSecondsToMinutes }}
|
|
||||||
</div>
|
|
||||||
<span class="ucap-sound-viewer-spacer"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-sound-viewer-action"
|
|
||||||
matTooltip="{{
|
|
||||||
(playing ? 'common.player.stop' : 'common.player.play') | translate
|
|
||||||
}}"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickPlayOrPause()"
|
|
||||||
>
|
|
||||||
<mat-icon>{{ playing ? 'pause' : 'play_arrow' }}</mat-icon>
|
|
||||||
</button>
|
|
||||||
<span class="ucap-sound-viewer-spacer"></span>
|
|
||||||
<div class="ucap-sound-viewer-sound-time-total">
|
|
||||||
{{ duration | ucapSecondsToMinutes }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,163 +0,0 @@
|
||||||
.ucap-sound-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ucap-sound-viewer-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 60px;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
background-color: #333333;
|
|
||||||
|
|
||||||
.ucap-sound-viewer-icon {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-sound-viewer-title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.stroke-bar {
|
|
||||||
width: 1px;
|
|
||||||
height: 30px;
|
|
||||||
background-color: rgba(256, 256, 256, 0.3);
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
.ucap-sound-viewer-action {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 10px;
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-sound-viewer-body {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
|
|
||||||
.circle-box {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
width: 140px;
|
|
||||||
height: 140px;
|
|
||||||
border-radius: 50%;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border: 2px solid #ffffff;
|
|
||||||
background-color: rgba(256, 256, 256, 0.7);
|
|
||||||
.mat-icon {
|
|
||||||
font-size: 100px;
|
|
||||||
height: 100px;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
.sound-wave {
|
|
||||||
height: 80px;
|
|
||||||
left: 50%;
|
|
||||||
margin: -35px 0 0 -35px;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 30px;
|
|
||||||
width: 70px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-sound-viewer-sound-icon {
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 80px);
|
|
||||||
}
|
|
||||||
.viewer-bottom {
|
|
||||||
background-color: #212121;
|
|
||||||
color: #ffffff;
|
|
||||||
.ucap-sound-viewer-sound-time {
|
|
||||||
width: 100%;
|
|
||||||
height: 30px;
|
|
||||||
}
|
|
||||||
.ucap-sound-viewer-sound-controls {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
|
|
||||||
.ucap-sound-viewer-sound-time-current {
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-sound-viewer-sound-time-total {
|
|
||||||
padding-right: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ucap-sound-viewer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
.ucap-sound-viewer-action {
|
|
||||||
.mat-icon {
|
|
||||||
font-size: 40px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sound-bar {
|
|
||||||
bottom: 1px;
|
|
||||||
height: 10px;
|
|
||||||
position: absolute;
|
|
||||||
width: 5px;
|
|
||||||
animation: sound-play 0ms -800ms linear infinite alternate;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(1) {
|
|
||||||
left: 0px;
|
|
||||||
animation-duration: 474ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(2) {
|
|
||||||
left: 7px;
|
|
||||||
animation-duration: 433ms;
|
|
||||||
}
|
|
||||||
.sound-bar {
|
|
||||||
left: 14px;
|
|
||||||
animation-duration: 407ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(4) {
|
|
||||||
left: 21px;
|
|
||||||
animation-duration: 458ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(5) {
|
|
||||||
left: 28px;
|
|
||||||
animation-duration: 400ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(6) {
|
|
||||||
left: 35px;
|
|
||||||
animation-duration: 427ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(7) {
|
|
||||||
left: 42px;
|
|
||||||
animation-duration: 441ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(8) {
|
|
||||||
left: 49px;
|
|
||||||
animation-duration: 419ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(9) {
|
|
||||||
left: 56px;
|
|
||||||
animation-duration: 487ms;
|
|
||||||
}
|
|
||||||
.sound-bar:nth-child(10) {
|
|
||||||
left: 63px;
|
|
||||||
animation-duration: 442ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes sound-play {
|
|
||||||
0% {
|
|
||||||
opacity: 0.35;
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 1;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mat-slider {
|
|
||||||
width: 94%;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { SoundViewerComponent } from './sound-viewer.component';
|
|
||||||
|
|
||||||
describe('SoundViewerComponent', () => {
|
|
||||||
let component: SoundViewerComponent;
|
|
||||||
let fixture: ComponentFixture<SoundViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [SoundViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(SoundViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,104 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
OnInit,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
EventEmitter,
|
|
||||||
ViewChild,
|
|
||||||
ElementRef
|
|
||||||
} from '@angular/core';
|
|
||||||
import { ucapAnimations } from '../../animations';
|
|
||||||
import { FileInfo } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { MatSlider, MatSliderChange } from '@angular/material/slider';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-sound-viewer',
|
|
||||||
templateUrl: './sound-viewer.component.html',
|
|
||||||
styleUrls: ['./sound-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations
|
|
||||||
})
|
|
||||||
export class SoundViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
fileInfo: FileInfo;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileName: string;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
@ViewChild('audioPlayer', { static: true })
|
|
||||||
audioPlayer: ElementRef<HTMLAudioElement>;
|
|
||||||
|
|
||||||
@ViewChild('timeSlider', { static: true })
|
|
||||||
timeSlider: MatSlider;
|
|
||||||
|
|
||||||
playing = false;
|
|
||||||
duration = 0.01;
|
|
||||||
currentTime = 0;
|
|
||||||
volume = 0.1;
|
|
||||||
loading = false;
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
onClickPlayOrPause(): void {
|
|
||||||
if (this.loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.audioPlayer.nativeElement.paused) {
|
|
||||||
this.audioPlayer.nativeElement.play();
|
|
||||||
} else {
|
|
||||||
this.currentTime = this.audioPlayer.nativeElement.currentTime;
|
|
||||||
this.audioPlayer.nativeElement.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeTimeSlider(e: MatSliderChange): void {
|
|
||||||
this.audioPlayer.nativeElement.currentTime = e.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onPlayingAudio(): void {
|
|
||||||
this.playing = true;
|
|
||||||
// this.duration = Math.floor(this.audioPlayer.nativeElement.duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
onPauseAudio(): void {
|
|
||||||
this.playing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onTimeUpdateAudio(): void {
|
|
||||||
this.currentTime = Math.floor(this.audioPlayer.nativeElement.currentTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
onVolumeChangeAudio(): void {
|
|
||||||
this.volume = Math.floor(this.audioPlayer.nativeElement.volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadStartAudio(): void {
|
|
||||||
this.loading = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadedDataAudio(): void {
|
|
||||||
this.loading = false;
|
|
||||||
this.duration = Math.floor(this.audioPlayer.nativeElement.duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickDownload(): void {
|
|
||||||
this.fileDownloadItem = new FileDownloadItem();
|
|
||||||
this.download.emit(this.fileDownloadItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickClose(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,169 +0,0 @@
|
||||||
<div class="ucap-video-viewer-container">
|
|
||||||
<mat-toolbar color="accent" class="ucap-video-viewer-header">
|
|
||||||
<!--<mat-icon class="ucap-video-viewer-icon">video_label</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
class="ucap-video-viewer-icon"
|
|
||||||
>
|
|
||||||
<rect x="2" y="2" width="20" height="20" rx="2.18" ry="2.18"></rect>
|
|
||||||
<line x1="7" y1="2" x2="7" y2="22"></line>
|
|
||||||
<line x1="17" y1="2" x2="17" y2="22"></line>
|
|
||||||
<line x1="2" y1="12" x2="22" y2="12"></line>
|
|
||||||
<line x1="2" y1="7" x2="7" y2="7"></line>
|
|
||||||
<line x1="2" y1="17" x2="7" y2="17"></line>
|
|
||||||
<line x1="17" y1="17" x2="22" y2="17"></line>
|
|
||||||
<line x1="17" y1="7" x2="22" y2="7"></line>
|
|
||||||
</svg>
|
|
||||||
<span class="ucap-video-viewer-title">{{ fileName }}</span>
|
|
||||||
<span class="ucap-video-viewer-spacer"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-video-viewer-action"
|
|
||||||
matTooltip="{{ 'common.file.download' | translate }}"
|
|
||||||
matTooltipPosition="below"
|
|
||||||
aria-label=""
|
|
||||||
(click)="onClickDownload()"
|
|
||||||
>
|
|
||||||
<!--<mat-icon>get_app</mat-icon>-->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M3 15v4c0 1.1.9 2 2 2h14a2 2 0 0 0 2-2v-4M17 9l-5 5-5-5M12 12.8V2.5"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<span class="stroke-bar"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
color="warn"
|
|
||||||
class="ucap-image-viewer-action btn-close"
|
|
||||||
matTooltip="{{ 'common.messages.close' | translate }}"
|
|
||||||
(click)="onClickClose()"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="21"
|
|
||||||
height="21"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="butt"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
||||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</mat-toolbar>
|
|
||||||
<div style="position: relative;">
|
|
||||||
<div
|
|
||||||
*ngIf="fileDownloadItem && fileDownloadItem.downloadingProgress$"
|
|
||||||
style="position: absolute; width: 100%;"
|
|
||||||
>
|
|
||||||
<mat-progress-bar
|
|
||||||
mode="determinate"
|
|
||||||
[value]="fileDownloadItem.downloadingProgress$ | async"
|
|
||||||
></mat-progress-bar>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ucap-video-viewer-body">
|
|
||||||
<div
|
|
||||||
#videoContainer
|
|
||||||
class="ucap-video-viewer-video-icon"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<video
|
|
||||||
*ngIf="playable"
|
|
||||||
#audioPlayer
|
|
||||||
[src]="fileDownloadUrl"
|
|
||||||
[style.width]="'auto'"
|
|
||||||
[style.height]="
|
|
||||||
videoHeight > videoContainer.clientHeight
|
|
||||||
? ((videoContainer.clientHeight - 20) / videoHeight) * videoHeight +
|
|
||||||
'px'
|
|
||||||
: videoHeight + 'px'
|
|
||||||
"
|
|
||||||
(playing)="onPlayingVideo()"
|
|
||||||
(pause)="onPauseVideo()"
|
|
||||||
(timeupdate)="onTimeUpdateVideo()"
|
|
||||||
(volumechange)="onVolumeChangeVideo()"
|
|
||||||
(loadstart)="onLoadStartVideo()"
|
|
||||||
(loadeddata)="onLoadedDataVideo()"
|
|
||||||
></video>
|
|
||||||
<div *ngIf="!playable" class="guide-msg">
|
|
||||||
{{ 'common.file.errors.cantPlay' | translate }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="viewer-bottom">
|
|
||||||
<div
|
|
||||||
class="ucap-video-viewer-video-time"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
fxLayoutAlign="center center"
|
|
||||||
>
|
|
||||||
<mat-slider
|
|
||||||
#timeSlider
|
|
||||||
min="0"
|
|
||||||
[max]="duration"
|
|
||||||
[value]="currentTime"
|
|
||||||
(change)="onChangeTimeSlider($event)"
|
|
||||||
>
|
|
||||||
</mat-slider>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="ucap-video-viewer-video-controls"
|
|
||||||
fxLayout="row"
|
|
||||||
fxLayout.xs="column"
|
|
||||||
>
|
|
||||||
<div class="ucap-video-viewer-video-time-current">
|
|
||||||
{{ Math.floor(currentTime) | ucapSecondsToMinutes }}
|
|
||||||
</div>
|
|
||||||
<span class="ucap-video-viewer-spacer"></span>
|
|
||||||
<button
|
|
||||||
mat-icon-button
|
|
||||||
class="ucap-video-viewer-action"
|
|
||||||
matTooltip="{{
|
|
||||||
(playing ? 'common.player.stop' : 'common.player.play') | translate
|
|
||||||
}}"
|
|
||||||
aria-label=""
|
|
||||||
[disabled]="!playable"
|
|
||||||
(click)="onClickPlayOrPause()"
|
|
||||||
>
|
|
||||||
<mat-icon>{{ playing ? 'pause' : 'play_arrow' }}</mat-icon>
|
|
||||||
<!--{{ playing ? '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
|
||||||
<rect x="6" y="4" width="4" height="16"></rect>
|
|
||||||
<rect x="14" y="4" width="4" height="16"></rect>
|
|
||||||
</svg>' : '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
||||||
stroke-width="2" stroke-linecap="butt" stroke-linejoin="round">
|
|
||||||
<polygon points="5 3 19 12 5 21 5 3"></polygon>
|
|
||||||
</svg>'}}-->
|
|
||||||
</button>
|
|
||||||
<span class="ucap-video-viewer-spacer"></span>
|
|
||||||
<div class="ucap-video-viewer-video-time-total">
|
|
||||||
{{ Math.floor(duration) | ucapSecondsToMinutes }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,100 +0,0 @@
|
||||||
.ucap-video-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.ucap-video-viewer-header {
|
|
||||||
width: 100%;
|
|
||||||
height: 60px;
|
|
||||||
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
background-color: #333333;
|
|
||||||
color: #ffffff;
|
|
||||||
.ucap-video-viewer-icon {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-video-viewer-title {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.stroke-bar {
|
|
||||||
width: 1px;
|
|
||||||
height: 30px;
|
|
||||||
background-color: rgba(256, 256, 256, 0.3);
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
.ucap-image-viewer-action {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
margin-left: 10px;
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-video-viewer-body {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 60px);
|
|
||||||
|
|
||||||
.ucap-video-viewer-video-icon {
|
|
||||||
width: 100%;
|
|
||||||
height: calc(100% - 80px);
|
|
||||||
|
|
||||||
.guide-msg {
|
|
||||||
font-size: 16px;
|
|
||||||
margin: 30px;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.viewer-bottom {
|
|
||||||
background-color: #212121;
|
|
||||||
color: #ffffff;
|
|
||||||
.ucap-video-viewer-video-time {
|
|
||||||
width: 100%;
|
|
||||||
height: 30px;
|
|
||||||
.mat-slider {
|
|
||||||
width: 94%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ucap-video-viewer-video-controls {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
|
|
||||||
.ucap-video-viewer-video-time-current {
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ucap-video-viewer-video-time-total {
|
|
||||||
padding-right: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ucap-video-viewer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
.ucap-video-viewer-action {
|
|
||||||
.mat-icon {
|
|
||||||
font-size: 40px;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//viewr 플레이어 공통
|
|
||||||
::ng-deep .viewer-bottom {
|
|
||||||
.mat-slider-horizontal {
|
|
||||||
.mat-slider-track-background {
|
|
||||||
background-color: #999999 !important;
|
|
||||||
}
|
|
||||||
&.mat-slider-min-value {
|
|
||||||
&:not(.mat-slider-thumb-label-showing) {
|
|
||||||
.mat-slider-thumb {
|
|
||||||
border-color: #999999 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
import { DebugElement } from '@angular/core';
|
|
||||||
|
|
||||||
import { ImageViewerComponent } from './image-viewer.component';
|
|
||||||
|
|
||||||
describe('ImageViewerComponent', () => {
|
|
||||||
let component: ImageViewerComponent;
|
|
||||||
let fixture: ComponentFixture<ImageViewerComponent>;
|
|
||||||
|
|
||||||
beforeEach(async(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
declarations: [ImageViewerComponent]
|
|
||||||
}).compileComponents();
|
|
||||||
}));
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fixture = TestBed.createComponent(ImageViewerComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,125 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
OnInit,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
EventEmitter,
|
|
||||||
ViewChild,
|
|
||||||
ElementRef,
|
|
||||||
ChangeDetectorRef
|
|
||||||
} from '@angular/core';
|
|
||||||
import { MatSlider, MatSliderChange } from '@angular/material/slider';
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
|
||||||
import { FileInfo } from '@ucap-webmessenger/protocol-file';
|
|
||||||
import { FileDownloadItem } from '@ucap-webmessenger/api';
|
|
||||||
|
|
||||||
import { ucapAnimations } from '../../animations';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'ucap-video-viewer',
|
|
||||||
templateUrl: './video-viewer.component.html',
|
|
||||||
styleUrls: ['./video-viewer.component.scss'],
|
|
||||||
animations: ucapAnimations
|
|
||||||
})
|
|
||||||
export class VideoViewerComponent implements OnInit {
|
|
||||||
@Input()
|
|
||||||
fileInfo: FileInfo;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileName: string;
|
|
||||||
|
|
||||||
@Input()
|
|
||||||
fileDownloadUrl: string;
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
download = new EventEmitter<FileDownloadItem>();
|
|
||||||
|
|
||||||
@Output()
|
|
||||||
closed = new EventEmitter<void>();
|
|
||||||
|
|
||||||
@ViewChild('audioPlayer', { static: false })
|
|
||||||
audioPlayer: ElementRef<HTMLVideoElement>;
|
|
||||||
|
|
||||||
@ViewChild('timeSlider', { static: true })
|
|
||||||
timeSlider: MatSlider;
|
|
||||||
|
|
||||||
playing = false;
|
|
||||||
duration = 0.0;
|
|
||||||
currentTime = 0.0;
|
|
||||||
volume = 0.1;
|
|
||||||
loading = false;
|
|
||||||
fileDownloadItem: FileDownloadItem;
|
|
||||||
|
|
||||||
videoWidth = 0;
|
|
||||||
videoHeight = 0;
|
|
||||||
|
|
||||||
playable = true;
|
|
||||||
|
|
||||||
Math = Math;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
|
||||||
private logger: NGXLogger
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {}
|
|
||||||
|
|
||||||
onClickPlayOrPause(): void {
|
|
||||||
if (this.loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.audioPlayer.nativeElement.paused) {
|
|
||||||
this.audioPlayer.nativeElement.play();
|
|
||||||
} else {
|
|
||||||
this.currentTime = this.audioPlayer.nativeElement.currentTime;
|
|
||||||
this.audioPlayer.nativeElement.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeTimeSlider(e: MatSliderChange): void {
|
|
||||||
this.audioPlayer.nativeElement.currentTime = e.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
onPlayingVideo(): void {
|
|
||||||
this.playing = true;
|
|
||||||
// this.duration = Math.floor(this.audioPlayer.nativeElement.duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
onPauseVideo(): void {
|
|
||||||
this.playing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onTimeUpdateVideo(): void {
|
|
||||||
this.currentTime = this.audioPlayer.nativeElement.currentTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
onVolumeChangeVideo(): void {
|
|
||||||
this.volume = this.audioPlayer.nativeElement.volume;
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadStartVideo(): void {
|
|
||||||
this.loading = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoadedDataVideo(): void {
|
|
||||||
this.loading = false;
|
|
||||||
this.duration = this.audioPlayer.nativeElement.duration;
|
|
||||||
|
|
||||||
this.videoWidth = this.audioPlayer.nativeElement.videoWidth;
|
|
||||||
this.videoHeight = this.audioPlayer.nativeElement.videoHeight;
|
|
||||||
|
|
||||||
if (0 === this.videoHeight || 0 === this.videoWidth) {
|
|
||||||
this.playable = false;
|
|
||||||
this.duration = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickDownload(): void {
|
|
||||||
this.fileDownloadItem = new FileDownloadItem();
|
|
||||||
this.download.emit(this.fileDownloadItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickClose(): void {
|
|
||||||
this.closed.emit();
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user