This commit is contained in:
leejinho 2020-01-21 13:32:21 +09:00
commit 4faa89da94
4 changed files with 108 additions and 76 deletions

View File

@ -48,7 +48,7 @@
"title": "DS Talk" "title": "DS Talk"
}, },
"win": { "win": {
"target": ["zip", "nsis"], "target": ["nsis-web"],
"icon": "./config/build/win/icon/daesang/16x16.ico", "icon": "./config/build/win/icon/daesang/16x16.ico",
"legalTrademarks": "(c) 2015 lgucap.com", "legalTrademarks": "(c) 2015 lgucap.com",
"publisherName": "LGCNS", "publisherName": "LGCNS",
@ -72,5 +72,13 @@
"perMachine": false, "perMachine": false,
"differentialPackage": true, "differentialPackage": true,
"include": "./config/build/win/nsis/installer.nsh" "include": "./config/build/win/nsis/installer.nsh"
},
"nsisWeb": {
"appPackageUrl": "https://messenger.daesang.com/AppDist/pc/",
"oneClick": true,
"allowToChangeInstallationDirectory": false,
"perMachine": false,
"differentialPackage": true,
"include": "./config/build/win/nsis/installer.nsh"
} }
} }

View File

@ -10,15 +10,10 @@
(psYReachEnd)="onYReachEnd($event)" (psYReachEnd)="onYReachEnd($event)"
[enableUnequalChildrenSizes]="true" [enableUnequalChildrenSizes]="true"
[modifyOverflowStyleOfParentScroll]="false" [modifyOverflowStyleOfParentScroll]="false"
(vsChange)="onVsChange($event)"
> >
<div <div #chatMessagesContainer class="chat-messages">
#chatMessagesContainer
class="chat-messages hide"
[style.opacity]="fixScreen ? 0 : 1"
>
<div <div
*ngIf="eventRemained && eventList.length > 0" *ngIf="eventRemained && !!eventList && eventList.length > 0"
class="message-row view-previous" class="message-row view-previous"
> >
<button mat-button (click)="onClickMore($event)" class="bg-accent-dark"> <button mat-button (click)="onClickMore($event)" class="bg-accent-dark">
@ -63,7 +58,7 @@
[mine]="message.senderSeq === loginRes.userSeq" [mine]="message.senderSeq === loginRes.userSeq"
[highlight]="isHighlightedEvent(message.seq)" [highlight]="isHighlightedEvent(message.seq)"
[existReadToHere]=" [existReadToHere]="
getReadHere(message) && existReadHere && !clearReadHere readToHereEvent && readToHereEvent.seq === message.seq
" "
[dateChanged]="getDateSplitter(message)" [dateChanged]="getDateSplitter(message)"
[senderName]="getUserName(message.senderSeq)" [senderName]="getUserName(message.senderSeq)"
@ -83,3 +78,9 @@
</div> </div>
</div> </div>
</virtual-scroller> </virtual-scroller>
<div
#chatMessagesBuffer
fxFlexFill
class="chat-messages-buffer disappear"
></div>

View File

@ -189,3 +189,15 @@ $meBox-bg: #ffffff;
.hide { .hide {
opacity: 0 !important; opacity: 0 !important;
} }
.disappear {
display: none !important;
}
.chat-messages-buffer {
position: absolute;
top: 0px;
overflow-y: hidden !important;
padding: 30px 40px;
flex-direction: column;
}

View File

@ -27,7 +27,6 @@ import { DatePipe } from '@angular/common';
import moment from 'moment'; import moment from 'moment';
import { FileDownloadItem } from '@ucap-webmessenger/api'; import { FileDownloadItem } from '@ucap-webmessenger/api';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { VirtualScrollerComponent, IPageInfo } from 'ngx-virtual-scroller'; import { VirtualScrollerComponent, IPageInfo } from 'ngx-virtual-scroller';
@ -108,8 +107,8 @@ export class MessagesComponent implements OnInit, OnDestroy {
@ViewChild('chatMessagesContainer', { static: false }) @ViewChild('chatMessagesContainer', { static: false })
chatMessagesContainer: ElementRef<HTMLElement>; chatMessagesContainer: ElementRef<HTMLElement>;
@ViewChild(PerfectScrollbarDirective, { static: false }) @ViewChild('chatMessagesBuffer', { static: false })
psChatContent: PerfectScrollbarDirective; chatMessagesBuffer: ElementRef<HTMLElement>;
@ViewChild(VirtualScrollerComponent, { static: false }) @ViewChild(VirtualScrollerComponent, { static: false })
private virtualScroller: VirtualScrollerComponent; private virtualScroller: VirtualScrollerComponent;
@ -141,8 +140,8 @@ export class MessagesComponent implements OnInit, OnDestroy {
profileImageRoot: string; profileImageRoot: string;
moment = moment; moment = moment;
existReadHere = false; readToHereEvent: Info<EventJson>;
fixScreen = false; swapped = false;
constructor( constructor(
private logger: NGXLogger, private logger: NGXLogger,
@ -181,6 +180,8 @@ export class MessagesComponent implements OnInit, OnDestroy {
this.firstCheckReadHere = false; this.firstCheckReadHere = false;
} }
this.readToHereEvent = eventList.find(e => this.getReadHere(e));
this.eventList = eventList; this.eventList = eventList;
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
@ -358,7 +359,6 @@ export class MessagesComponent implements OnInit, OnDestroy {
this.eventList[messageIndex].seq === this.eventList[messageIndex].seq ===
this.roomInfo.lastReadEventSeq + 1 this.roomInfo.lastReadEventSeq + 1
) { ) {
this.existReadHere = true;
return true; return true;
} }
} }
@ -381,42 +381,71 @@ export class MessagesComponent implements OnInit, OnDestroy {
]; ];
} }
scrollToStoredItem() { swapScroll(
if (!this.scrollUpInitalized) { to: Info<EventJson>,
this.chatMessagesContainer.nativeElement.classList.remove('hide'); preCallback: () => void,
postCallback: () => void,
useSwap: boolean = true
) {
this.preSwapScroll(useSwap);
if (!!preCallback) {
preCallback();
} }
this.virtualScroller.scrollInto(to, true, 0, 0, () => {
this.virtualScroller.scrollInto(this.storedScrollItem, true, 0, 0, () => { setTimeout(() => {
this.storedScrollItem = undefined; if (!!postCallback) {
postCallback();
}
this.postSwapScroll(useSwap);
}, 100);
}); });
} }
ready(): void { preSwapScroll(useSwap: boolean = true) {
if (!this.scrollUpInitalized) { if (useSwap && !this.swapped) {
this.chatMessagesContainer.nativeElement.classList.add('hide'); this.chatMessagesBuffer.nativeElement.innerHTML = this.chatMessagesContainer.nativeElement.innerHTML;
this.chatMessagesBuffer.nativeElement.scrollTop = this.chatMessagesContainer.nativeElement.scrollTop;
this.chatMessagesBuffer.nativeElement.classList.remove('disappear');
this.swapped = true;
} }
setTimeout(() => { this.chatMessagesContainer.nativeElement.classList.add('hide');
this.scrollToBottom(); }
});
postSwapScroll(useSwap: boolean = true) {
if (useSwap && this.swapped) {
this.chatMessagesBuffer.nativeElement.innerHTML = '';
this.chatMessagesBuffer.nativeElement.scrollTop = 0;
this.chatMessagesBuffer.nativeElement.classList.add('disappear');
this.swapped = false;
}
this.chatMessagesContainer.nativeElement.classList.remove('hide');
}
ready(): void {
this.scrollToBottom();
} }
scrollToBottom(speed?: number): void { scrollToBottom(speed?: number): void {
if (!!this.storedScrollItem) { if (!!this.storedScrollItem) {
// if (this.psChatContent) { if (!!this.readToHereEvent && this.firstCheckReadHere) {
// this.psChatContent.update(); this.swapScroll(
this.readToHereEvent,
const element = document.getElementById('message-box-readhere'); () => {},
if (!!element && this.firstCheckReadHere) { () => {
setTimeout(() => { this.firstCheckReadHere = false;
this.psChatContent.scrollToTop(element.offsetTop - 200, speed); }
}); );
this.firstCheckReadHere = false;
} else { } else {
this.scrollToStoredItem(); this.swapScroll(
this.storedScrollItem,
() => {},
() => {
this.storedScrollItem = undefined;
}
);
} }
// }
} else if (this.scrollUpInitalized) { } else if (this.scrollUpInitalized) {
if (!!this.newEventList && this.newEventList.length > 0) { if (!!this.newEventList && this.newEventList.length > 0) {
this.existNewMessage.emit( this.existNewMessage.emit(
@ -425,27 +454,22 @@ export class MessagesComponent implements OnInit, OnDestroy {
} }
} else { } else {
speed = speed || 0; speed = speed || 0;
if (this.psChatContent) {
this.psChatContent.update();
const element = document.getElementById('message-box-readhere'); if (!!this.readToHereEvent && this.firstCheckReadHere) {
if (!!element && this.firstCheckReadHere) { this.swapScroll(
setTimeout(() => { this.readToHereEvent,
this.psChatContent.scrollToTop(element.offsetTop - 200, speed); () => {},
}); () => {
this.firstCheckReadHere = false;
this.firstCheckReadHere = false; }
} else { );
this.virtualScroller.scrollToIndex( } else {
this.eventList.length - 1, this.swapScroll(
true, this.eventList[this.eventList.length - 1],
0, () => {},
0, () => {},
() => { false
this.chatMessagesContainer.nativeElement.classList.remove('hide'); );
}
);
}
} }
} }
} }
@ -459,23 +483,9 @@ export class MessagesComponent implements OnInit, OnDestroy {
clear() {} clear() {}
gotoPosition(eventSeq: number) { gotoPosition(eventSeq: number) {
// if (this.psChatContent) {
// this.psChatContent.update();
// const element = document.getElementById(eventSeq.toString());
// if (!!element) {
// setTimeout(() => {
// this.psChatContent.scrollToTop(element.offsetTop - 200);
// });
// }
// }
if (!!this.virtualScroller) { if (!!this.virtualScroller) {
const e = this.eventList.find(v => v.seq === eventSeq); const e = this.eventList.find(v => v.seq === eventSeq);
this.fixScreen = true; this.virtualScroller.scrollInto(e, false, undefined, 0, () => {});
this.virtualScroller.scrollInto(e, false, undefined, 0, () => {
this.fixScreen = false;
});
} }
} }
@ -488,9 +498,10 @@ export class MessagesComponent implements OnInit, OnDestroy {
event.stopPropagation(); event.stopPropagation();
if (this.scrollUpInitalized && this.eventRemained) { if (this.scrollUpInitalized && this.eventRemained) {
// this.storedScrollItem = this.psChatContent.elementRef.nativeElement.scrollHeight;
this.storeScrollPosition(); this.storeScrollPosition();
this.preSwapScroll();
this.moreEvent.emit(this.eventList[0].seq); this.moreEvent.emit(this.eventList[0].seq);
this.virtualScroller.invalidateCachedMeasurementAtIndex(0); this.virtualScroller.invalidateCachedMeasurementAtIndex(0);
@ -554,7 +565,7 @@ export class MessagesComponent implements OnInit, OnDestroy {
) { ) {
return; return;
} }
this.logger.debug('onVsChange', event); // this.logger.debug('onVsChange', event);
} }
trackByEvent(index: number, info: Info<EventJson>): number { trackByEvent(index: number, info: Info<EventJson>): number {