Skip to content

Commit

Permalink
Communication: Fix clipping issues on mobile devices (#9460)
Browse files Browse the repository at this point in the history
  • Loading branch information
PaRangger authored Oct 24, 2024
1 parent 61c92c6 commit 8bf15b3
Show file tree
Hide file tree
Showing 31 changed files with 703 additions and 151 deletions.
4 changes: 4 additions & 0 deletions src/main/webapp/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { NgbDateDayjsAdapter } from 'app/core/config/datepicker-adapter';
import { JhiLanguageHelper } from 'app/core/language/language.helper';
import { TraceService } from '@sentry/angular';
import { Router } from '@angular/router';
import isMobile from 'ismobilejs-es5';

@NgModule({
imports: [
Expand Down Expand Up @@ -109,5 +110,8 @@ export class ArtemisCoreModule {
const languageKey = sessionStorageService.retrieve('locale') || languageHelper.determinePreferredLanguage();
translateService.use(languageKey);
tooltipConfig.container = 'body';
if (isMobile(window.navigator.userAgent).any ?? false) {
tooltipConfig.disableTooltip = true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(keyup.enter)="onSearch()"
placeholder="{{ 'artemisApp.metis.overview.searchBarDefault' | artemisTranslate }}"
/>
<jhi-button [btnType]="ButtonType.SECONDARY" [icon]="faTimes" (onClick)="courseWideSearchTerm = ''" />
<jhi-button [btnType]="ButtonType.SECONDARY" [icon]="faTimes" (onClick)="hideSearchTerm()" />
<jhi-button id="search-submit" class="ms-1" [icon]="faSearch" (onClick)="onSearch()" />
</div>
<!-- only display after isCodeOfConductAccepted is loaded and set to false -->
Expand All @@ -22,7 +22,7 @@
}
@if (isCodeOfConductAccepted && isServiceSetUp && course) {
<div class="d-flex justify-content-between">
<div [ngClass]="{ 'sidebar-collapsed': isCollapsed }">
<div class="communication-content-sidebar" [ngClass]="{ 'sidebar-collapsed': isCollapsed, 'is-not-in-active-conversation': !activeConversation }">
<jhi-sidebar
(onSelectConversation)="onConversationSelected($event)"
(onUpdateSidebar)="prepareSidebarData()"
Expand All @@ -38,14 +38,18 @@
[sidebarItemAlwaysShow]="DEFAULT_SHOW_ALWAYS"
[collapseState]="DEFAULT_COLLAPSE_STATE"
[inCommunication]="true"
[reEmitNonDistinctSidebarEvents]="isMobile"
/>
</div>
@if (course && !activeConversation && isCodeOfConductPresented) {
<div class="col pe-0 flex-grow-1">
<jhi-course-conversations-code-of-conduct [course]="course!" />
</div>
}
<div class="col flex-grow-1 module-bg rounded-3 scrollable-content" [ngClass]="{ 'content-height-dev': !isProduction || isTestServer }" style="min-width: 200px">
<div
class="communication-message-wrap col flex-grow-1 module-bg rounded-3 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer, 'is-answer-thread-open': !!postInThread }"
>
@if (activeConversation) {
<jhi-conversation-header (collapseSearch)="toggleChannelSearch()" (onUpdateSidebar)="prepareSidebarData()" />
<jhi-conversation-messages
Expand All @@ -59,9 +63,8 @@
}
</div>
<div
class="col d-flex flex-grow-1 justify-end px-0 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer }"
style="max-width: min-content"
class="communication-answer-message-wrap col flex-grow-1 justify-end px-0 scrollable-content"
[ngClass]="{ 'content-height-dev': !isProduction || isTestServer, 'is-answer-thread-open': !!postInThread }"
>
@if (!!postInThread) {
<jhi-conversation-thread-sidebar
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@import 'bootstrap/scss/functions';
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/mixins';

.second-layer-modal-bg {
background-color: var(--secondary);
}
Expand Down Expand Up @@ -28,10 +32,76 @@

@media (max-width: 768px) {
max-height: calc(100vh - var(--header-height) - var(--message-input-height-prod)) !important;
max-height: calc(100dvh - var(--header-height) - var(--message-input-height-prod)) !important;
}
}

.message-input {
border-top: 1px solid;
border-color: var(--bs-card-border-color);
}

.communication-message-wrap {
min-width: 200px;
}

.communication-answer-message-wrap {
max-width: min-content;
display: flex;
}

@include media-breakpoint-down(sm) {
.communication-content-sidebar {
position: absolute;
width: 100%;
z-index: 2;
pointer-events: none;

& .sidebar-wrap,
.communication-content-sidebar .sidebar-width {
max-width: 0;
}

&.sidebar-collapsed {
pointer-events: all;
}

&.sidebar-collapsed .sidebar-wrap,
&.sidebar-collapsed .sidebar-width {
max-width: 100%;
}

&.sidebar-collapsed .sidebar-width {
width: 100%;
}

.sidebar-content {
opacity: 0;
}

&.sidebar-collapsed .sidebar-content {
opacity: 1;
}

.sidebar-wrap {
margin-right: 0;
}
}

.communication-message-wrap.is-answer-thread-open {
display: none;
}

.communication-answer-message-wrap {
max-width: 100%;
display: none;
}

.communication-answer-message-wrap.is-answer-thread-open {
display: flex;
}

.communication-message-wrap {
max-width: 100%;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
import { Component, ElementRef, EventEmitter, HostListener, OnDestroy, OnInit, ViewChild, ViewEncapsulation, inject } from '@angular/core';
import { ConversationDTO } from 'app/entities/metis/conversation/conversation.model';
import { Post } from 'app/entities/metis/post.model';
import { ActivatedRoute, Router } from '@angular/router';
Expand All @@ -22,6 +22,9 @@ import { OneToOneChatCreateDialogComponent } from 'app/overview/course-conversat
import { ChannelAction, ChannelsOverviewDialogComponent } from 'app/overview/course-conversations/dialogs/channels-overview-dialog/channels-overview-dialog.component';
import { ProfileService } from 'app/shared/layouts/profiles/profile.service';
import { ChannelsCreateDialogComponent } from 'app/overview/course-conversations/dialogs/channels-create-dialog/channels-create-dialog.component';
import { CourseSidebarService } from 'app/overview/course-sidebar.service';
import { LayoutService } from 'app/shared/breakpoints/layout.service';
import { CustomBreakpointNames } from 'app/shared/breakpoints/breakpoints.service';

const DEFAULT_CHANNEL_GROUPS: AccordionGroups = {
favoriteChannels: { entityData: [] },
Expand Down Expand Up @@ -85,6 +88,10 @@ const DEFAULT_SHOW_ALWAYS: SidebarItemShowAlways = {
})
export class CourseConversationsComponent implements OnInit, OnDestroy {
private ngUnsubscribe = new Subject<void>();
private closeSidebarEventSubscription: Subscription;
private openSidebarEventSubscription: Subscription;
private toggleSidebarEventSubscription: Subscription;
private breakpointSubscription: Subscription;
course?: Course;
isLoading = false;
isServiceSetUp = false;
Expand All @@ -102,6 +109,7 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
isCollapsed = false;
isProduction = true;
isTestServer = false;
isMobile = false;

readonly CHANNEL_TYPE_SHOW_ADD_OPTION = CHANNEL_TYPE_SHOW_ADD_OPTION;
readonly CHANNEL_TYPE_ICON = CHANNEL_TYPE_ICON;
Expand Down Expand Up @@ -130,6 +138,9 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
createChannelFn?: (channel: ChannelDTO) => Observable<never>;
channelActions$ = new EventEmitter<ChannelAction>();

private courseSidebarService: CourseSidebarService = inject(CourseSidebarService);
private layoutService: LayoutService = inject(LayoutService);

constructor(
private router: Router,
private activatedRoute: ActivatedRoute,
Expand All @@ -156,8 +167,35 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
}

ngOnInit(): void {
this.isMobile = this.layoutService.isBreakpointActive(CustomBreakpointNames.extraSmall);

this.breakpointSubscription = this.layoutService.subscribeToLayoutChanges().subscribe(() => {
this.isMobile = this.layoutService.isBreakpointActive(CustomBreakpointNames.extraSmall);
});

this.openSidebarEventSubscription = this.courseSidebarService.openSidebar$.subscribe(() => {
this.setIsCollapsed(true);
});

this.closeSidebarEventSubscription = this.courseSidebarService.closeSidebar$.subscribe(() => {
this.setIsCollapsed(false);
});

this.toggleSidebarEventSubscription = this.courseSidebarService.toggleSidebar$.subscribe(() => {
this.toggleSidebar();
});

if (!this.isMobile) {
if (this.courseOverviewService.getSidebarCollapseStateFromStorage('conversation')) {
this.courseSidebarService.openSidebar();
} else {
this.courseSidebarService.closeSidebar();
}
} else {
this.courseSidebarService.openSidebar();
}

this.isLoading = true;
this.isCollapsed = this.courseOverviewService.getSidebarCollapseStateFromStorage('conversation');
this.metisConversationService.isServiceSetup$.pipe(takeUntil(this.ngUnsubscribe)).subscribe((isServiceSetUp: boolean) => {
if (isServiceSetUp) {
this.course = this.metisConversationService.course;
Expand Down Expand Up @@ -214,9 +252,13 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
this.activatedRoute.queryParams.pipe(take(1), takeUntil(this.ngUnsubscribe)).subscribe((queryParams) => {
if (queryParams.conversationId) {
this.metisConversationService.setActiveConversation(Number(queryParams.conversationId));

this.closeSidebarOnMobile();
}
if (queryParams.messageId) {
this.postInThread = { id: Number(queryParams.messageId) } as Post;

this.closeSidebarOnMobile();
} else {
this.postInThread = undefined;
}
Expand All @@ -236,12 +278,20 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
ngOnDestroy() {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
this.openSidebarEventSubscription?.unsubscribe();
this.closeSidebarEventSubscription?.unsubscribe();
this.toggleSidebarEventSubscription?.unsubscribe();
this.profileSubscription?.unsubscribe();
this.breakpointSubscription?.unsubscribe();
}

private subscribeToActiveConversation() {
this.metisConversationService.activeConversation$.pipe(takeUntil(this.ngUnsubscribe)).subscribe((conversation: ConversationDTO) => {
const previousConversation = this.activeConversation;
this.activeConversation = conversation;
if (this.isMobile && conversation && previousConversation?.id !== conversation.id) {
this.courseSidebarService.closeSidebar();
}
this.updateQueryParameters();
});
}
Expand Down Expand Up @@ -286,8 +336,20 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
: DEFAULT_CHANNEL_GROUPS;
}

hideSearchTerm() {
this.courseWideSearchTerm = '';
}

onSearch() {
if (this.isMobile) {
if (this.courseWideSearchTerm) {
this.courseSidebarService.closeSidebar();
} else {
this.courseSidebarService.openSidebar();
}
}
this.metisConversationService.setActiveConversation(undefined);
this.activeConversation = undefined;
this.updateQueryParameters();
this.courseWideSearchConfig.searchTerm = this.courseWideSearchTerm;
this.courseWideSearch?.onSearch();
Expand Down Expand Up @@ -316,11 +378,22 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
}

onConversationSelected(conversationId: number) {
this.closeSidebarOnMobile();
this.metisConversationService.setActiveConversation(conversationId);
}

toggleSidebar() {
this.isCollapsed = !this.isCollapsed;
this.setIsCollapsed(!this.isCollapsed);
}

closeSidebarOnMobile() {
if (this.isMobile) {
this.courseSidebarService.closeSidebar();
}
}

setIsCollapsed(value: boolean) {
this.isCollapsed = value;
this.courseOverviewService.setSidebarCollapseState('conversation', this.isCollapsed);
}

Expand Down Expand Up @@ -395,12 +468,14 @@ export class CourseConversationsComponent implements OnInit, OnDestroy {
complete: () => {
if (newActiveConversation) {
this.metisConversationService.setActiveConversation(newActiveConversation);
this.closeSidebarOnMobile();
}
},
});
} else {
if (newActiveConversation) {
this.metisConversationService.setActiveConversation(newActiveConversation);
this.closeSidebarOnMobile();
}
}
this.prepareSidebarData();
Expand Down
Loading

0 comments on commit 8bf15b3

Please sign in to comment.