This commit is contained in:
khk 2019-12-31 16:03:54 +09:00
commit e110849fbe
63 changed files with 741 additions and 94 deletions

View File

@ -82,7 +82,7 @@ const mainConfig: webpack.Configuration = {
), ),
new CopyWebpackPlugin([ new CopyWebpackPlugin([
{ {
from: 'ucap-webmessenger-electron/resources/**/*', from: 'ucap-webmessenger-electron/assets/**/*',
to: path.resolve(__dirname, '..', 'dist'), to: path.resolve(__dirname, '..', 'dist'),
context: 'electron-projects' context: 'electron-projects'
} }

View File

@ -23,9 +23,25 @@
"!**/.awcache", "!**/.awcache",
"!**/.vscode", "!**/.vscode",
"!config/", "!config/",
"!dist/",
"!docker/", "!docker/",
"!tsconfig.json", "!tsconfig.json",
"!tslint.json" "!tslint.json",
{
"filter": ["**/*"],
"from": "./dist/ucap-webmessenger-app/",
"to": "./renderer/"
},
{
"filter": ["**/*"],
"from": "./dist/ucap-webmessenger-electron/",
"to": "./electron/"
},
{
"filter": ["**/*"],
"from": "./config/build/${os}/icon/daesang/",
"to": "./assets/icon/"
}
], ],
"protocols": { "protocols": {
"name": "DS Talk", "name": "DS Talk",

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -165,11 +165,7 @@ export class AppWindow {
} else { } else {
this.window.loadURL( this.window.loadURL(
url.format({ url.format({
pathname: path.join( pathname: path.join(__dirname, '..', 'renderer/index.html'),
__dirname,
'..',
'ucap-webmessenger-app/index.html'
),
protocol: 'file:', protocol: 'file:',
slashes: true slashes: true
}) })

View File

@ -52,13 +52,18 @@ const appIconPath = __LINUX__
? path.join( ? path.join(
__dirname, __dirname,
'../../', '../../',
'config/build/linux/icon/woori/', 'config/build/linux/icon/daesang/',
'256x256.png' '256x256.png'
) )
: path.join(__dirname, 'resources/linuxicon', '256x256.png') : path.join(__dirname, '..', '/assets/icon/', '256x256.png')
: __DEV__ : __DEV__
? path.join(__dirname, 'resources/image', '64_64.png') ? path.join(
: path.join(__dirname, 'resources/image', '64_64.png'); __dirname,
'../../',
'config/build/win/icon/daesang/',
'16x16.ico'
)
: path.join(__dirname, '..', '/assets/icon/', '16x16.ico');
let appWindow: AppWindow | null = null; let appWindow: AppWindow | null = null;
let appTray: Tray | null = null; let appTray: Tray | null = null;
@ -266,12 +271,12 @@ app.on(ElectronAppChannel.Ready, () => {
notificationService.options.defaultWindow.webPreferences.preload = path.join( notificationService.options.defaultWindow.webPreferences.preload = path.join(
__dirname, __dirname,
'resources/notification/preload.js' 'assets/notification/preload.js'
); );
notificationService.templatePath = path.join( notificationService.templatePath = path.join(
__dirname, __dirname,
'resources/notification/template.html' 'assets/notification/template.html'
); );
updateWindowService = new ElectronUpdateWindowService({ updateWindowService = new ElectronUpdateWindowService({
@ -299,7 +304,7 @@ app.on(ElectronAppChannel.Ready, () => {
updateWindowService.templatePath = path.join( updateWindowService.templatePath = path.join(
__dirname, __dirname,
'resources/update-window/template.html' 'assets/update-window/template.html'
); );
// updateWindowService.show(); // updateWindowService.show();
@ -589,15 +594,12 @@ ipcMain.on(
text: noti.contents, text: noti.contents,
image: image:
noti.image || noti.image ||
path.join( path.join(__dirname, 'assets/notification/images/img_nophoto_50.png'),
__dirname,
'resources/notification/images/img_nophoto_50.png'
),
sound: noti.useSound sound: noti.useSound
? path.join( ? path.join(
'file://', 'file://',
__dirname, __dirname,
'resources/notification/sounds/messageAlarm.mp3' 'assets/notification/sounds/messageAlarm.mp3'
) )
: '', : '',
displayTime: !!noti.displayTime ? noti.displayTime : undefined, displayTime: !!noti.displayTime ? noti.displayTime : undefined,

View File

@ -3,7 +3,7 @@ import * as path from 'path';
// tslint:disable-next-line: variable-name // tslint:disable-next-line: variable-name
const _root = __DEV__ const _root = __DEV__
? path.resolve(__dirname, '..', '..') ? path.resolve(__dirname, '..', '..')
: path.resolve(__dirname, '..', '..'); : path.resolve(__dirname, '..');
export function root(...paths: string[]) { export function root(...paths: string[]) {
const args = Array.prototype.slice.call(paths, 0); const args = Array.prototype.slice.call(paths, 0);

View File

@ -145,5 +145,5 @@
"webpack-node-externals": "^1.7.2", "webpack-node-externals": "^1.7.2",
"zone.js": "~0.9.1" "zone.js": "~0.9.1"
}, },
"main": "./dist/ucap-webmessenger-electron/main.js" "main": "./electron/main.js"
} }

View File

@ -4,7 +4,9 @@ import {
APIResponse, APIResponse,
APIEncoder, APIEncoder,
APIDecoder, APIDecoder,
ParameterUtil ParameterUtil,
StatusCode,
JsonAnalization
} from '@ucap-webmessenger/api'; } from '@ucap-webmessenger/api';
export interface TransMassTalkDownloadRequest extends APIRequest { export interface TransMassTalkDownloadRequest extends APIRequest {
@ -15,23 +17,41 @@ export interface TransMassTalkDownloadRequest extends APIRequest {
} }
export interface TransMassTalkDownloadResponse extends APIResponse { export interface TransMassTalkDownloadResponse extends APIResponse {
Original?: string; content?: string;
Translation?: string; userName?: string;
Locale?: string; regDate?: string;
UserName?: string; returnJson?: any;
RegDate?: string;
} }
const transMassTalkDownloadEncodeMap = {}; const transMassTalkDownloadEncodeMap = {
userSeq: 'p_user_seq',
deviceType: 'p_device_type',
token: 'p_token',
eventTransSeq: 'p_event_mass_seq'
};
export const encodeTransMassTalkDownload: APIEncoder< export const encodeTransMassTalkDownload: APIEncoder<TransMassTalkDownloadRequest> = (
TransMassTalkDownloadRequest req: TransMassTalkDownloadRequest
> = (req: TransMassTalkDownloadRequest) => { ) => {
return ParameterUtil.encode(transMassTalkDownloadEncodeMap, req); return ParameterUtil.encode(transMassTalkDownloadEncodeMap, req);
}; };
export const decodeTransMassTalkDownload: APIDecoder< export const decodeTransMassTalkDownload: APIDecoder<TransMassTalkDownloadResponse> = (
TransMassTalkDownloadResponse res: any
> = (res: any) => { ) => {
return {} as TransMassTalkDownloadResponse; try {
const json = JsonAnalization.receiveAnalization(res);
return {
statusCode: json.StatusCode,
content: json.Content,
userName: json.UserName,
regDate: json.RegDate,
returnJson: res
} as TransMassTalkDownloadResponse;
} catch (e) {
return {
statusCode: StatusCode.Fail,
errorMessage: e
} as TransMassTalkDownloadResponse;
}
}; };

View File

@ -49,16 +49,15 @@ export const decodeTransMassTalkSave: APIDecoder<TransMassTalkSaveResponse> = (
res: any res: any
) => { ) => {
try { try {
const json = JsonAnalization.receiveAnalization(res);
return { return {
statusCode: json.StatusCode, statusCode: res.StatusCode,
translationSeq: json.EventTransSEQ, translationSeq: res.EventTransSEQ,
roomSeq: json.RoomID, roomSeq: res.RoomID,
registrationDate: json.RegDate, registrationDate: res.RegDate,
locale: json.Locale, locale: res.Locale,
original: json.Original, original: res.Original,
translation: json.Translation, translation: res.Translation,
returnJson: res returnJson: JSON.stringify(res)
} as TransMassTalkSaveResponse; } as TransMassTalkSaveResponse;
} catch (e) { } catch (e) {
return { return {

View File

@ -4,7 +4,9 @@ import {
APIResponse, APIResponse,
APIEncoder, APIEncoder,
APIDecoder, APIDecoder,
ParameterUtil ParameterUtil,
StatusCode,
JsonAnalization
} from '@ucap-webmessenger/api'; } from '@ucap-webmessenger/api';
export interface TranslationReqRequest extends APIRequest { export interface TranslationReqRequest extends APIRequest {
@ -17,13 +19,21 @@ export interface TranslationReqRequest extends APIRequest {
} }
export interface TranslationReqResponse extends APIResponse { export interface TranslationReqResponse extends APIResponse {
SrcLocale?: string; srcLocale?: string;
DestLocale?: string; destLocale?: string;
Original?: string; original?: string;
Translation?: string; translation?: string;
returnJson?: any;
} }
const translationReqEncodeMap = {}; const translationReqEncodeMap = {
userSeq: 'p_user_seq',
deviceType: 'p_device_type',
token: 'p_token',
original: 'p_original',
srcLocale: 'p_src_locale',
destLocale: 'p_dest_locale'
};
export const encodeTranslationReq: APIEncoder<TranslationReqRequest> = ( export const encodeTranslationReq: APIEncoder<TranslationReqRequest> = (
req: TranslationReqRequest req: TranslationReqRequest
@ -34,5 +44,20 @@ export const encodeTranslationReq: APIEncoder<TranslationReqRequest> = (
export const decodeTranslationReq: APIDecoder<TranslationReqResponse> = ( export const decodeTranslationReq: APIDecoder<TranslationReqResponse> = (
res: any res: any
) => { ) => {
try {
return {
statusCode: res.StatusCode,
srcLocale: res.SrcLocale,
destLocale: res.DestLocale,
original: res.Original,
translation: res.Translation,
returnJson: JSON.stringify(res)
} as TranslationReqResponse;
} catch (e) {
return {
statusCode: StatusCode.Fail,
errorMessage: e
} as TranslationReqResponse;
}
return {} as TranslationReqResponse; return {} as TranslationReqResponse;
}; };

View File

@ -20,7 +20,7 @@ export interface TranslationSaveRequest extends APIRequest {
} }
export interface TranslationSaveResponse extends APIResponse { export interface TranslationSaveResponse extends APIResponse {
translationSeq?: string; translationSeq?: number;
roomSeq?: string; roomSeq?: string;
registrationDate?: string; registrationDate?: string;
srcLocale?: string; srcLocale?: string;
@ -50,17 +50,16 @@ export const decodeTranslationSave: APIDecoder<TranslationSaveResponse> = (
res: any res: any
) => { ) => {
try { try {
const json = JsonAnalization.receiveAnalization(res);
return { return {
statusCode: json.StatusCode, statusCode: res.StatusCode,
translationSeq: json.EventTransSEQ, translationSeq: !!res.EventTransSeq ? Number(res.EventTransSeq) : 0,
roomSeq: json.RoomID, roomSeq: res.RoomID,
registrationDate: json.RegDate, registrationDate: res.RegDate,
srcLocale: json.SrcLocale, srcLocale: res.SrcLocale,
destLocale: json.DestLocale, destLocale: res.DestLocale,
original: json.Original, original: res.Original,
translation: json.Translation, translation: res.Translation,
returnJson: res returnJson: JSON.stringify(res)
} as TranslationSaveResponse; } as TranslationSaveResponse;
} catch (e) { } catch (e) {
return { return {

View File

@ -19,7 +19,7 @@ export function createTranslateLoader(nativeService: NativeService) {
break; break;
case NativeType.Electron: case NativeType.Electron:
prefix = environment.production prefix = environment.production
? '/dist/ucap-webmessenger-app/assets/i18n/' ? '/renderer/assets/i18n/'
: '/projects/ucap-webmessenger-app/src/assets/i18n/'; : '/projects/ucap-webmessenger-app/src/assets/i18n/';
break; break;

View File

@ -233,6 +233,7 @@
[minShowReadHere]=" [minShowReadHere]="
environment.productConfig.CommonSetting.readHereShowMinimumEventCount environment.productConfig.CommonSetting.readHereShowMinimumEventCount
" "
[translationSimpleview]="translationSimpleview"
(moreEvent)="onMoreEvent($event)" (moreEvent)="onMoreEvent($event)"
(massDetail)="onMassDetail($event)" (massDetail)="onMassDetail($event)"
(save)="onSave($event)" (save)="onSave($event)"
@ -266,6 +267,25 @@
<div></div> <div></div>
</div> </div>
<!-- / sticker-selector --> <!-- / sticker-selector -->
<!-- Translation -->
<div class="translation-container">
<ucap-translation-section
*ngIf="isShowTranslation"
[destLocale]="destLocale"
[simpleView]="translationSimpleview"
[preView]="translationPreview"
[translationPreviewInfo]="translationPreviewInfo"
(changeTranslationSimpleview)="onChangeTranslationSimpleView($event)"
(changeTranslationPreview)="onChangeTranslationPreView($event)"
(changeDestLocale)="onChangeDestLocale($event)"
(cancelTranslation)="onCancelTranslation($event)"
(sendTranslationMessage)="onSendTranslationMessage($event)"
>
</ucap-translation-section>
</div>
<!-- / Translation -->
<!-- CHAT FOOTER --> <!-- CHAT FOOTER -->
<div fxFlex="0 0 auto" fxLayout="column" *ngIf="getEnableSend()"> <div fxFlex="0 0 auto" fxLayout="column" *ngIf="getEnableSend()">
<!-- REPLY FORM --> <!-- REPLY FORM -->
@ -276,6 +296,7 @@
(sendFiles)="onFileSelected($event)" (sendFiles)="onFileSelected($event)"
(clearView)="clearView()" (clearView)="clearView()"
(toggleStickerSelector)="onShowToggleStickerSelector($event)" (toggleStickerSelector)="onShowToggleStickerSelector($event)"
(toggleTranslation)="onShowToggleTranslation($event)"
></ucap-chat-form> ></ucap-chat-form>
<!-- / REPLY FORM --> <!-- / REPLY FORM -->
</div> </div>

View File

@ -127,6 +127,22 @@
width: 100%; width: 100%;
} }
} }
.translation-container {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: transparent;
.translation-zone {
position: absolute;
padding: 10px 10px 0 10px;
background-color: rgba(250, 255, 255, 0.8);
bottom: 0;
width: 100%;
}
}
} }
::ng-deep .chat-snackbar-class { ::ng-deep .chat-snackbar-class {

View File

@ -23,7 +23,7 @@ import {
} from '@ucap-webmessenger/ui'; } from '@ucap-webmessenger/ui';
import { Store, select } from '@ngrx/store'; import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
import { Observable, Subscription, forkJoin, of, combineLatest } from 'rxjs'; import { Observable, Subscription, forkJoin, combineLatest, of } from 'rxjs';
import { import {
Info, Info,
EventType, EventType,
@ -35,7 +35,8 @@ import {
EventJson, EventJson,
FileEventJson, FileEventJson,
StickerEventJson, StickerEventJson,
MassTextEventJson MassTextEventJson,
TranslationEventJson
} from '@ucap-webmessenger/protocol-event'; } from '@ucap-webmessenger/protocol-event';
import * as AppStore from '@app/store'; import * as AppStore from '@app/store';
@ -72,7 +73,9 @@ import { FileUploadItem } from '@ucap-webmessenger/api';
import { import {
CommonApiService, CommonApiService,
FileTalkSaveRequest, FileTalkSaveRequest,
FileTalkSaveResponse FileTalkSaveResponse,
TranslationReqRequest,
TranslationSaveRequest
} from '@ucap-webmessenger/api-common'; } from '@ucap-webmessenger/api-common';
import { import {
CreateChatDialogComponent, CreateChatDialogComponent,
@ -166,6 +169,13 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
isShowStickerSelector = false; isShowStickerSelector = false;
selectedSticker: StickerFilesInfo; selectedSticker: StickerFilesInfo;
/** About Translation */
isShowTranslation = false;
translationSimpleview = false;
translationPreview = false;
destLocale = 'en'; // default English :: en
translationPreviewInfo: TranslationEventJson | null;
/** About ReadHere */ /** About ReadHere */
firstcheckReadHere = true; firstcheckReadHere = true;
clearReadHere = false; clearReadHere = false;
@ -360,8 +370,17 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
// Chat Search Clear.. // Chat Search Clear..
this.onCloseSearchArea(); this.onCloseSearchArea();
// Translate Clear..
this.isShowTranslation = false;
this.translationSimpleview = false;
this.translationPreview = false;
// this.destLocale = 'en'; // default English :: en
this.translationPreviewInfo = null;
// Read here Clear..
this.firstcheckReadHere = true; this.firstcheckReadHere = true;
// Chat Formfield Clear..
if (!!this.chatForm) { if (!!this.chatForm) {
this.chatForm.replyForm.reset(); this.chatForm.replyForm.reset();
} }
@ -578,6 +597,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
/** Send Event */
async onSendMessage(message: string) { async onSendMessage(message: string) {
this.setEventMoreInit(); this.setEventMoreInit();
@ -598,8 +618,77 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
if (!!this.isShowTranslation && this.destLocale.trim().length > 0) {
/** CASE : Translation */
console.log('번역들어간다.');
const destLocale = this.destLocale;
const original = message;
const roomSeq = this.roomInfo.roomSeq;
this.commonApiService
.translationSave({
userSeq: this.loginRes.userSeq,
deviceType: this.environmentsInfo.deviceType,
token: this.loginRes.tokenString,
roomSeq,
original,
srcLocale: '',
destLocale
} as TranslationSaveRequest)
.pipe(
take(1),
map(res => {
console.log(res);
if (res.statusCode === StatusCode.Success) {
if (res.translationSeq > 0) {
// Mass Text Translation
} else {
// Normal Text Translation
const json: TranslationEventJson = {
locale: destLocale,
original,
translation: res.translation,
stickername: '',
stickerfile: !!this.selectedSticker
? this.selectedSticker.index
: ''
};
if (!!this.translationPreview) {
// preview
this.translationPreviewInfo = json;
} else {
// direct send
this.store.dispatch(
EventStore.send({
senderSeq: this.loginRes.userSeq,
req: {
roomSeq,
eventType: EventType.Translation,
sentMessage: JSON.stringify(json)
}
})
);
if (!!this.translationPreviewInfo) {
this.translationPreviewInfo = null;
}
}
if (!!this.selectedSticker) { if (!!this.selectedSticker) {
// Send Sticker this.isShowStickerSelector = false;
this.setStickerHistory(this.selectedSticker);
}
}
} else {
this.logger.error(res);
}
}),
catchError(error => of(this.logger.error(error)))
)
.subscribe();
} else if (!!this.selectedSticker) {
/** CASE : Sticker */
if ( if (
!!message && !!message &&
message.trim().length > message.trim().length >
@ -640,7 +729,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
message.trim().length > message.trim().length >
environment.productConfig.CommonSetting.masstextLength environment.productConfig.CommonSetting.masstextLength
) { ) {
// MASS TEXT /** CASE : MASS TEXT */
this.store.dispatch( this.store.dispatch(
EventStore.sendMass({ EventStore.sendMass({
senderSeq: this.loginRes.userSeq, senderSeq: this.loginRes.userSeq,
@ -653,6 +742,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
}) })
); );
} else { } else {
/** CASE : Normal Text */
this.store.dispatch( this.store.dispatch(
EventStore.send({ EventStore.send({
senderSeq: this.loginRes.userSeq, senderSeq: this.loginRes.userSeq,
@ -1361,4 +1451,37 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
} }
/** About Translation */
onShowToggleTranslation() {
this.isShowTranslation = !this.isShowTranslation;
if (!this.isShowTranslation) {
}
}
onChangeTranslationSimpleView(value: boolean) {
this.translationSimpleview = value;
}
onChangeTranslationPreView(value: boolean) {
this.translationPreview = value;
}
onChangeDestLocale(destLocale: string) {
this.destLocale = destLocale;
}
onCancelTranslation() {
this.translationPreviewInfo = null;
}
onSendTranslationMessage(translationInfo: TranslationEventJson) {
this.store.dispatch(
EventStore.send({
senderSeq: this.loginRes.userSeq,
req: {
roomSeq: this.roomInfo.roomSeq,
eventType: EventType.Translation,
sentMessage: JSON.stringify(translationInfo)
}
})
);
this.translationPreviewInfo = null;
}
} }

View File

@ -5,21 +5,21 @@ export interface TranslationEventJson {
locale?: string; locale?: string;
original?: string; original?: string;
translation?: string; translation?: string;
stickerName?: string; stickername?: string;
stickerFile?: string; stickerfile?: string;
} }
export const decodeTranslationEventJson: EventJsonDecoder< export const decodeTranslationEventJson: EventJsonDecoder<TranslationEventJson> = (
TranslationEventJson message: string
> = (message: string) => { ) => {
try { try {
const json = JsonAnalization.receiveAnalization(message); const json = JsonAnalization.receiveAnalization(message);
return { return {
locale: json.locale, locale: json.locale,
original: json.original, original: json.original,
translation: json.translation, translation: json.translation,
stickerName: json.stickername, stickername: json.stickername,
stickerFile: json.stickerfile stickerfile: json.stickerfile
} as TranslationEventJson; } as TranslationEventJson;
} catch (e) { } catch (e) {
return {} as TranslationEventJson; return {} as TranslationEventJson;

View File

@ -24,9 +24,13 @@
<mat-icon>sentiment_satisfied_alt</mat-icon> <mat-icon>sentiment_satisfied_alt</mat-icon>
</button> </button>
<!-- <button mat-icon-button class="material-icons"> <button
mat-icon-button
class="material-icons"
(click)="onClickTranslation()"
>
<mat-icon>g_translate</mat-icon> <mat-icon>g_translate</mat-icon>
</button> --> </button>
</div> </div>
<form <form

View File

@ -28,6 +28,8 @@ export class FormComponent implements OnInit {
@Output() @Output()
toggleStickerSelector = new EventEmitter<void>(); toggleStickerSelector = new EventEmitter<void>();
@Output()
toggleTranslation = new EventEmitter<void>();
@Output() @Output()
clearView = new EventEmitter(); clearView = new EventEmitter();
@ -78,4 +80,8 @@ export class FormComponent implements OnInit {
onClickStickerSelector() { onClickStickerSelector() {
this.toggleStickerSelector.emit(); this.toggleStickerSelector.emit();
} }
onClickTranslation() {
this.toggleTranslation.emit();
}
} }

View File

@ -0,0 +1,24 @@
<div class="translation-main">
<div class="original">
{{ message.sentMessageJson.translation }}
</div>
<div class="translation">
<span class="language">Kor</span>
녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트
</div>
<div class="btn-box">
<ul>
<li>
<button mat-button>Save</button>
</li>
<li>
<button mat-button><span class="language">Kor</span>번역보기</button>
</li>
</ul>
</div>
</div>

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Input } from '@angular/core';
import { TranslationEventJson, Info } from '@ucap-webmessenger/protocol-event';
@Component({ @Component({
selector: 'ucap-chat-message-box-mass-translation', selector: 'ucap-chat-message-box-mass-translation',
@ -6,6 +7,9 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./mass-translation.component.scss'] styleUrls: ['./mass-translation.component.scss']
}) })
export class MassTranslationComponent implements OnInit { export class MassTranslationComponent implements OnInit {
@Input()
message: Info<TranslationEventJson>;
constructor() {} constructor() {}
ngOnInit() {} ngOnInit() {}

View File

@ -1,17 +1,30 @@
<div class="translation-main"> <div class="translation-main">
<div class="original"> <div
{{ message.sentMessageJson.translation }} *ngIf="
!!this.message.sentMessageJson &&
!!this.message.sentMessageJson.stickerfile &&
this.message.sentMessageJson.stickerfile.trim().length > 0
"
class="sticker"
>
<img
[src]="stickerUrl"
onerror="this.src='assets/sticker/sticker_default.png'"
/>
</div> </div>
<div class="translation"> <div
<span class="language">Kor</span> *ngIf="!translationSimpleview || (!!translationSimpleview && !!isMe)"
녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 class="original"
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 [innerHTML]="message.sentMessageJson.original | linky"
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 ></div>
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 <div
장문장문 롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 *ngIf="!translationSimpleview || (!!translationSimpleview && !isMe)"
롱텍스트안녕하세요 장문장문 롱텍스트안녕하세요 장문장문 롱텍스트 class="translation"
>
<span class="language">{{ message.sentMessageJson.locale }}</span>
<span [innerHTML]="message.sentMessageJson.translation | linky"> </span>
</div> </div>
<div class="btn-box"> <!-- <div class="btn-box">
<ul> <ul>
<li> <li>
<button mat-button>Save</button> <button mat-button>Save</button>
@ -20,5 +33,5 @@
<button mat-button><span class="language">Kor</span>번역보기</button> <button mat-button><span class="language">Kor</span>번역보기</button>
</li> </li>
</ul> </ul>
</div> </div> -->
</div> </div>

View File

@ -10,7 +10,23 @@ export class TranslationComponent implements OnInit {
@Input() @Input()
message: Info<TranslationEventJson>; message: Info<TranslationEventJson>;
@Input()
translationSimpleview: boolean;
@Input()
isMe: boolean;
stickerUrl?: string;
constructor() {} constructor() {}
ngOnInit() {} ngOnInit() {
if (
!!this.message.sentMessageJson &&
!!this.message.sentMessageJson.stickerfile &&
this.message.sentMessageJson.stickerfile.trim().length > 0
) {
this.stickerUrl = `assets/sticker/sticker_s_${this.message.sentMessageJson.stickerfile}.png`;
}
}
} }

View File

@ -196,6 +196,13 @@
(contextmenu)="onContextMenuMessage($event, message)" (contextmenu)="onContextMenuMessage($event, message)"
> >
</ucap-chat-message-box-schedule> </ucap-chat-message-box-schedule>
<ucap-chat-message-box-translation
*ngSwitchCase="EventType.Translation"
[message]="message"
[translationSimpleview]="translationSimpleview"
[isMe]="message.senderSeq === loginRes.userSeq"
class="information-msg"
></ucap-chat-message-box-translation>
<ucap-chat-message-box-allim <ucap-chat-message-box-allim
*ngSwitchCase="EventType.AllimTms" *ngSwitchCase="EventType.AllimTms"
@ -209,13 +216,12 @@
class="information-msg" class="information-msg"
> >
</ucap-chat-message-box-allim> </ucap-chat-message-box-allim>
<div *ngSwitchDefault> <div *ngSwitchDefault>
<!-- mass-translation <!-- mass-translation
<ucap-chat-message-box-mass-translation></ucap-chat-message-box-mass-translation> <ucap-chat-message-box-mass-translation></ucap-chat-message-box-mass-translation>
notice notice
<ucap-chat-message-box-notice></ucap-chat-message-box-notice> <ucap-chat-message-box-notice></ucap-chat-message-box-notice>
translation
<ucap-chat-message-box-translation></ucap-chat-message-box-translation>
video-conference video-conference
<ucap-chat-message-box-video-conference></ucap-chat-message-box-video-conference> <ucap-chat-message-box-video-conference></ucap-chat-message-box-video-conference>

View File

@ -50,6 +50,8 @@ export class MessagesComponent implements OnInit {
clearReadHere: boolean; clearReadHere: boolean;
@Input() @Input()
minShowReadHere = 10; minShowReadHere = 10;
@Input()
translationSimpleview = false;
@Output() @Output()
openProfile = new EventEmitter<UserInfo>(); openProfile = new EventEmitter<UserInfo>();

View File

@ -0,0 +1,108 @@
<div
*ngIf="
isShowTranslationPreview &&
!!translationPreviewInfo &&
!!translationPreviewInfo.translation
"
class="translation-preview"
>
<span class="translation-section">
{{ translationPreviewInfo.translation }}
</span>
<button
mat-stroked-button
(click)="onClickSendTranslationMessage(translationPreviewInfo)"
>
Send
</button>
<span class="btn-close">
<button
mat-button
matSuffix
mat-icon-button
aria-label="Close"
(click)="onClickTranslationCancel()"
>
<mat-icon>close</mat-icon>
</button>
</span>
</div>
<div>
<form name="translationForm" [formGroup]="translationForm">
<mat-form-field>
<mat-label>Dest Type</mat-label>
<mat-select
formControlName="destType"
(selectionChange)="onChangeSelection($event)"
>
<mat-option value="">번역없음</mat-option>
<mat-option *ngFor="let dest of translationDestList" [value]="dest.key"
>{{ dest.text }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-slide-toggle
labelPosition="before"
[checked]="simpleView"
(change)="onChangToggleSimpleview($event)"
>Simple View</mat-slide-toggle
>
<mat-slide-toggle
labelPosition="before"
[checked]="preView"
(change)="onChangTogglePreview($event)"
>Preview</mat-slide-toggle
>
</form>
</div>
<!-- <div *ngIf="currentSticker" class="selected-sticker">
<img [src]="getStickerContentsImage(currentSticker)" />
<span class="btn-close">
<button
mat-button
matSuffix
mat-icon-button
aria-label="Close"
(click)="onClickClose()"
>
<mat-icon>close</mat-icon>
</button>
</span>
</div>
<div class="sticker-selector">
<mat-tab-group
mat-stretch-tabs
animationDuration="0ms"
(selectedIndexChange)="onSelectedIndexChange($event)"
>
<mat-tab
*ngFor="let stickerInfo of stickerInfoList; let idx = index"
[aria-label]="stickerInfo.title"
>
<ng-template mat-tab-label>
<img
#stickerTitle
[matTooltip]="stickerInfo.title"
matTooltipPosition="after"
[src]="getStickerTitleImage(stickerInfo, false, idx)"
(mouseover)="
stickerTitle.src = getStickerTitleImage(stickerInfo, true, idx)
"
(mouseout)="
stickerTitle.src = getStickerTitleImage(stickerInfo, false, idx)
"
/>
</ng-template>
<div fxFlex fxLayout="row" fxLayoutGap="20px" class="sticker-item-box">
<div
*ngFor="let sticker of getStickerInfos(stickerInfo)"
(click)="onClickSelectSticker(sticker)"
class="sticker-item"
>
<img [src]="getStickerContentsImage(sticker)" />
</div>
</div>
</mat-tab>
</mat-tab-group>
</div> -->

View File

@ -0,0 +1,34 @@
.sticker-selector {
border-top: 1px solid #cccccc;
// .sticker-item-box {
// flex-wrap: wrap;
// padding: 20px 20px 0;
// overflow: auto;
// }
}
// .sticker-item {
// width: 60px;
// margin-bottom: 20px;
// display: inline-flex;
// cursor: pointer;
// }
.selected-sticker {
position: relative;
height: 100px;
padding: 20px;
text-align: right;
background-color: rgba(0, 0, 0, 0.4);
// img {
// margin-right: 40px;
// }
// .btn-close {
// position: absolute;
// top: 2px;
// right: 20px;
// width: 40px;
// height: 40px;
// color: #ffffff;
// }
}

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslationSectionComponent } from './translation-section.component';
describe('TranslationSectionComponent', () => {
let component: TranslationSectionComponent;
let fixture: ComponentFixture<TranslationSectionComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TranslationSectionComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TranslationSectionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,181 @@
import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
import {
StickerInfo,
StickerFilesInfo,
StickerUtil,
StickerMap
} from '@ucap-webmessenger/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { MatSlideToggleChange, MatSelectChange } from '@angular/material';
import { TranslationEventJson } from '@ucap-webmessenger/protocol-event';
@Component({
selector: 'ucap-translation-section',
templateUrl: './translation-section.component.html',
styleUrls: ['./translation-section.component.scss']
})
export class TranslationSectionComponent implements OnInit {
@Input()
destLocale: string;
@Input()
simpleView: boolean;
@Input()
preView: boolean;
@Input()
translationPreviewInfo: TranslationEventJson | null;
@Output()
changeTranslationSimpleview = new EventEmitter<boolean>();
@Output()
changeTranslationPreview = new EventEmitter<boolean>();
@Output()
changeDestLocale = new EventEmitter<string>();
@Output()
cancelTranslation = new EventEmitter<void>();
@Output()
sendTranslationMessage = new EventEmitter<TranslationEventJson>();
isShowTranslationSimpleview = false;
isShowTranslationPreview = false;
translationDestList: {
key: string;
text: string;
}[] = [
{ key: 'af', text: 'Afrikaans' },
{ key: 'sq', text: 'Albanian' },
{ key: 'am', text: 'Amharic' },
{ key: 'ar', text: 'Arabic' },
{ key: 'hy', text: 'Armenian' },
{ key: 'az', text: 'Azeerbaijani' },
{ key: 'eu', text: 'Basque' },
{ key: 'be', text: 'Belarusian' },
{ key: 'bn', text: 'Bengali' },
{ key: 'bs', text: 'Bosnian' },
{ key: 'bg', text: 'Bulgarian' },
{ key: 'ca', text: 'Catalan' },
{ key: 'ceb', text: 'Cebuano' },
{ key: 'zh-CN', text: 'Chinese(Simplified)' },
{ key: 'zh-TW', text: 'Chinese(Traditional)' },
{ key: 'co', text: 'Corsican' },
{ key: 'hr', text: 'Croatian' },
{ key: 'cs', text: 'Czech' },
{ key: 'da', text: 'Danish' },
{ key: 'nl', text: 'Dutch' },
{ key: 'en', text: 'English' },
{ key: 'eo', text: 'Esperanto' },
{ key: 'fi', text: 'Finnish' },
{ key: 'fr', text: 'French' },
{ key: 'fy', text: 'Frisian' },
{ key: 'gl', text: 'Galician' },
{ key: 'ka', text: 'Georgian' },
{ key: 'de', text: 'German' },
{ key: 'el', text: 'Greek' },
{ key: 'gu', text: 'Gujarati' },
{ key: 'ht', text: 'Haitian Creole' },
{ key: 'ha', text: 'Hausa' },
{ key: 'haw', text: 'Hawaiian' },
{ key: 'iw', text: 'Hebrew' },
{ key: 'hi', text: 'Hindi' },
{ key: 'hmn', text: 'Hmong' },
{ key: 'hu', text: 'Hungarian' },
{ key: 'is', text: 'Icelandic' },
{ key: 'ig', text: 'Igbo' },
{ key: 'id', text: 'Indonesian' },
{ key: 'ga', text: 'Irish' },
{ key: 'it', text: 'Italian' },
{ key: 'ja', text: 'Japanese' },
{ key: 'jw', text: 'Javanese' },
{ key: 'kn', text: 'Kannada' },
{ key: 'kk', text: 'Kazakh' },
{ key: 'km', text: 'Khmer' },
{ key: 'ko', text: 'Korean' },
{ key: 'ku', text: 'Kurdish' },
{ key: 'ky', text: 'Kyrgyz' },
{ key: 'lo', text: 'Lao' },
{ key: 'la', text: 'Latin' },
{ key: 'lv', text: 'Latvian' },
{ key: 'lt', text: 'Lithuanian' },
{ key: 'lb', text: 'Luxembourgish' },
{ key: 'mk', text: 'Macedonian' },
{ key: 'mg', text: 'Malagasy' },
{ key: 'ms', text: 'Malay' },
{ key: 'ml', text: 'Malayalam' },
{ key: 'mi', text: 'Maori' },
{ key: 'mr', text: 'Marathi' },
{ key: 'mn', text: 'Mongolian' },
{ key: 'my', text: 'Myanmar(Burmese)' },
{ key: 'ne', text: 'Nepali' },
{ key: 'no', text: 'Norwegian' },
{ key: 'ny', text: 'Nyanja(Chichewa)' },
{ key: 'ps', text: 'Pashto' },
{ key: 'fa', text: 'Persian' },
{ key: 'pl', text: 'Polish' },
{ key: 'pt', text: 'Portuguese' },
{ key: 'pa', text: 'Punjabi' },
{ key: 'ro', text: 'Romanian' },
{ key: 'ru', text: 'Russian' },
{ key: 'sm', text: 'Samoan' },
{ key: 'gd', text: 'Scots Gaelic' },
{ key: 'sr', text: 'Serbian' },
{ key: 'st', text: 'Sesotho' },
{ key: 'sn', text: 'Shona' },
{ key: 'sd', text: 'Sindhi' },
{ key: 'si', text: 'Sinhala(Sinhalese)' },
{ key: 'sk', text: 'Slovak' },
{ key: 'sl', text: 'Slovenian' },
{ key: 'so', text: 'Somali' },
{ key: 'es', text: 'Spanish' },
{ key: 'su', text: 'Sundanese' },
{ key: 'sw', text: 'Swahili' },
{ key: 'sv', text: 'Swedish' },
{ key: 'tl', text: 'Tagalog(Filipino)' },
{ key: 'tg', text: 'Tajik' },
{ key: 'ta', text: 'Tamil' },
{ key: 'te', text: 'Telugu' },
{ key: 'th', text: 'Thai' },
{ key: 'tr', text: 'Turkish' },
{ key: 'uk', text: 'Ukrainian' },
{ key: 'ur', text: 'Urdu' },
{ key: 'uz', text: 'Uzbek' },
{ key: 'vi', text: 'Vietnamese' },
{ key: 'cy', text: 'Welsh' },
{ key: 'xh', text: 'Xhosa' },
{ key: 'yi', text: 'Yiddish' },
{ key: 'yo', text: 'Yoruba' },
{ key: 'zu', text: 'Zulu' }
];
translationForm: FormGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.translationForm = this.formBuilder.group({
destType: [this.destLocale]
});
}
onChangeSelection(event: MatSelectChange) {
this.destLocale = event.value;
this.changeDestLocale.emit(this.destLocale);
}
onChangToggleSimpleview(event: MatSlideToggleChange) {
this.isShowTranslationSimpleview = event.checked;
this.changeTranslationSimpleview.emit(event.checked);
}
onChangTogglePreview(event: MatSlideToggleChange) {
this.isShowTranslationPreview = event.checked;
this.changeTranslationPreview.emit(event.checked);
}
onClickSendTranslationMessage(translationInfo: TranslationEventJson) {
this.sendTranslationMessage.emit(translationInfo);
}
onClickTranslationCancel() {
this.cancelTranslation.emit();
}
}

View File

@ -19,6 +19,11 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonToggleModule } from '@angular/material/button-toggle'; import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatMenuModule } from '@angular/material/menu'; import { MatMenuModule } from '@angular/material/menu';
import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatDatepickerModule } from '@angular/material/datepicker';
import {
MatTabsModule,
MatSelectModule,
MatSlideToggleModule,
} from '@angular/material';
import { DragDropModule } from '@angular/cdk/drag-drop'; import { DragDropModule } from '@angular/cdk/drag-drop';
@ -66,12 +71,12 @@ import { LinkyPipe } from './pipes/linky.pipe';
import { TranslatePipe } from './pipes/translate.pipe'; import { TranslatePipe } from './pipes/translate.pipe';
import { DatePipe } from './pipes/date.pipe'; import { DatePipe } from './pipes/date.pipe';
import { MatTabsModule } from '@angular/material';
import { import {
StringEmptyCheckPipe, StringEmptyCheckPipe,
StringFormatterPhonePipe StringFormatterPhonePipe
} from './pipes/string.pipe'; } from './pipes/string.pipe';
import { ClickDebounceDirective } from './directives/click-debounce.directive'; import { ClickDebounceDirective } from './directives/click-debounce.directive';
import { TranslationSectionComponent } from './components/translation-section.component';
const COMPONENTS = [ const COMPONENTS = [
FileUploadQueueComponent, FileUploadQueueComponent,
@ -83,6 +88,7 @@ const COMPONENTS = [
PickDateComponent, PickDateComponent,
PickTimeComponent, PickTimeComponent,
StepInputComponent, StepInputComponent,
TranslationSectionComponent,
BinaryViewerComponent, BinaryViewerComponent,
DocumentViewerComponent, DocumentViewerComponent,
@ -142,6 +148,8 @@ const SERVICES = [
MatButtonToggleModule, MatButtonToggleModule,
MatMenuModule, MatMenuModule,
MatDatepickerModule, MatDatepickerModule,
MatSelectModule,
MatSlideToggleModule,
DragDropModule DragDropModule
], ],
exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES], exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES],