MOBILE-3631 core: Send message form component
This commit is contained in:
		
							parent
							
								
									572ee7bead
								
							
						
					
					
						commit
						deaad4de5b
					
				@ -16,6 +16,7 @@ import { NgModule } from '@angular/core';
 | 
				
			|||||||
import { CommonModule } from '@angular/common';
 | 
					import { CommonModule } from '@angular/common';
 | 
				
			||||||
import { IonicModule } from '@ionic/angular';
 | 
					import { IonicModule } from '@ionic/angular';
 | 
				
			||||||
import { TranslateModule } from '@ngx-translate/core';
 | 
					import { TranslateModule } from '@ngx-translate/core';
 | 
				
			||||||
 | 
					import { FormsModule } from '@angular/forms';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { CoreChronoComponent } from './chrono/chrono';
 | 
					import { CoreChronoComponent } from './chrono/chrono';
 | 
				
			||||||
import { CoreDownloadRefreshComponent } from './download-refresh/download-refresh';
 | 
					import { CoreDownloadRefreshComponent } from './download-refresh/download-refresh';
 | 
				
			||||||
@ -38,10 +39,11 @@ import { CoreContextMenuItemComponent } from './context-menu/context-menu-item';
 | 
				
			|||||||
import { CoreContextMenuPopoverComponent } from './context-menu/context-menu-popover';
 | 
					import { CoreContextMenuPopoverComponent } from './context-menu/context-menu-popover';
 | 
				
			||||||
import { CoreUserAvatarComponent } from './user-avatar/user-avatar';
 | 
					import { CoreUserAvatarComponent } from './user-avatar/user-avatar';
 | 
				
			||||||
import { CoreDynamicComponent } from './dynamic-component/dynamic-component';
 | 
					import { CoreDynamicComponent } from './dynamic-component/dynamic-component';
 | 
				
			||||||
 | 
					import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons';
 | 
				
			||||||
 | 
					import { CoreSendMessageFormComponent } from './send-message-form/send-message-form';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { CoreDirectivesModule } from '@directives/directives.module';
 | 
					import { CoreDirectivesModule } from '@directives/directives.module';
 | 
				
			||||||
import { CorePipesModule } from '@pipes/pipes.module';
 | 
					import { CorePipesModule } from '@pipes/pipes.module';
 | 
				
			||||||
import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
    declarations: [
 | 
					    declarations: [
 | 
				
			||||||
@ -67,10 +69,12 @@ import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons';
 | 
				
			|||||||
        CoreNavBarButtonsComponent,
 | 
					        CoreNavBarButtonsComponent,
 | 
				
			||||||
        CoreUserAvatarComponent,
 | 
					        CoreUserAvatarComponent,
 | 
				
			||||||
        CoreDynamicComponent,
 | 
					        CoreDynamicComponent,
 | 
				
			||||||
 | 
					        CoreSendMessageFormComponent,
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    imports: [
 | 
					    imports: [
 | 
				
			||||||
        CommonModule,
 | 
					        CommonModule,
 | 
				
			||||||
        IonicModule.forRoot(),
 | 
					        IonicModule.forRoot(),
 | 
				
			||||||
 | 
					        FormsModule,
 | 
				
			||||||
        TranslateModule.forChild(),
 | 
					        TranslateModule.forChild(),
 | 
				
			||||||
        CoreDirectivesModule,
 | 
					        CoreDirectivesModule,
 | 
				
			||||||
        CorePipesModule,
 | 
					        CorePipesModule,
 | 
				
			||||||
@ -98,6 +102,7 @@ import { CoreNavBarButtonsComponent } from './navbar-buttons/navbar-buttons';
 | 
				
			|||||||
        CoreNavBarButtonsComponent,
 | 
					        CoreNavBarButtonsComponent,
 | 
				
			||||||
        CoreUserAvatarComponent,
 | 
					        CoreUserAvatarComponent,
 | 
				
			||||||
        CoreDynamicComponent,
 | 
					        CoreDynamicComponent,
 | 
				
			||||||
 | 
					        CoreSendMessageFormComponent,
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class CoreComponentsModule {}
 | 
					export class CoreComponentsModule {}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					<form #messageForm>
 | 
				
			||||||
 | 
					    <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows
 | 
				
			||||||
 | 
					        [(ngModel)]="message" name="message" (onResize)="textareaResized()" (keydown.enter)="enterClicked($event)"
 | 
				
			||||||
 | 
					        (keydown.control.enter)="enterClicked($event, 'control')" (keydown.meta.enter)="enterClicked($event, 'meta')"
 | 
				
			||||||
 | 
					        aria-multiline="true"></textarea>
 | 
				
			||||||
 | 
					    <ion-buttons>
 | 
				
			||||||
 | 
					        <ion-button fill="clear" type="submit" [disabled]="!message || sendDisabled"
 | 
				
			||||||
 | 
					            [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)">
 | 
				
			||||||
 | 
					            <ion-icon name="send" color="dark" slot="icon-only"></ion-icon>
 | 
				
			||||||
 | 
					        </ion-button>
 | 
				
			||||||
 | 
					    </ion-buttons>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										33
									
								
								src/core/components/send-message-form/send-message-form.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/components/send-message-form/send-message-form.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					:host {
 | 
				
			||||||
 | 
					  background: var(--white);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  form {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    margin-top: 5px;
 | 
				
			||||||
 | 
					    margin-bottom: 5px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .core-send-message-input {
 | 
				
			||||||
 | 
					    appearance: none;
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    min-height: 28px;
 | 
				
			||||||
 | 
					    border: 0;
 | 
				
			||||||
 | 
					    font-family: inherit;
 | 
				
			||||||
 | 
					    background: var(--core-send-message-input-background);
 | 
				
			||||||
 | 
					    color: var(--core-send-message-input-color);
 | 
				
			||||||
 | 
					    border-radius: 5px;
 | 
				
			||||||
 | 
					    margin: 0 5px;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .core-send-message-button {
 | 
				
			||||||
 | 
					    margin: 0;
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					    display: none;
 | 
				
			||||||
 | 
					    min-height: 0;
 | 
				
			||||||
 | 
					    align-self: self-end;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										126
									
								
								src/core/components/send-message-form/send-message-form.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/core/components/send-message-form/send-message-form.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,126 @@
 | 
				
			|||||||
 | 
					// (C) Copyright 2015 Moodle Pty Ltd.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { Component, Input, Output, EventEmitter, OnInit, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
 | 
					import { CoreApp } from '@services/app';
 | 
				
			||||||
 | 
					import { CoreConfig } from '@services/config';
 | 
				
			||||||
 | 
					import { CoreEvents } from '@singletons/events';
 | 
				
			||||||
 | 
					import { CoreSites } from '@services/sites';
 | 
				
			||||||
 | 
					import { CoreUtils } from '@services/utils/utils';
 | 
				
			||||||
 | 
					import { CoreTextUtils } from '@services/utils/text';
 | 
				
			||||||
 | 
					import { CoreDomUtils } from '@services/utils/dom';
 | 
				
			||||||
 | 
					import { CoreConstants } from '@/core/constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component to display a "send message form".
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @description
 | 
				
			||||||
 | 
					 * This component will display a standalone send message form in order to have a better UX.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Example usage:
 | 
				
			||||||
 | 
					 * <core-send-message-form (onSubmit)="sendMessage($event)" [placeholder]="'core.messages.newmessage' | translate"
 | 
				
			||||||
 | 
					 * [show-keyboard]="showKeyboard"></core-send-message-form>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					    selector: 'core-send-message-form',
 | 
				
			||||||
 | 
					    templateUrl: 'core-send-message-form.html',
 | 
				
			||||||
 | 
					    styleUrls: ['send-message-form.scss'],
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class CoreSendMessageFormComponent implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Input() message = ''; // Input text.
 | 
				
			||||||
 | 
					    @Input() placeholder = ''; // Placeholder for the input area.
 | 
				
			||||||
 | 
					    @Input() showKeyboard = false; // If keyboard is shown or not.
 | 
				
			||||||
 | 
					    @Input() sendDisabled = false; // If send is disabled.
 | 
				
			||||||
 | 
					    @Output() onSubmit: EventEmitter<string>; // Send data when submitting the message form.
 | 
				
			||||||
 | 
					    @Output() onResize: EventEmitter<void>; // Emit when resizing the textarea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ViewChild('messageForm') formElement!: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected sendOnEnter = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.onSubmit = new EventEmitter();
 | 
				
			||||||
 | 
					        this.onResize = new EventEmitter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CoreConfig.instance.get(CoreConstants.SETTINGS_SEND_ON_ENTER, !CoreApp.instance.isMobile()).then((sendOnEnter) => {
 | 
				
			||||||
 | 
					            this.sendOnEnter = !!sendOnEnter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }).catch(() => {
 | 
				
			||||||
 | 
					            // Nothing to do.
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CoreEvents.on<boolean>(CoreEvents.SEND_ON_ENTER_CHANGED, (newValue) => {
 | 
				
			||||||
 | 
					            this.sendOnEnter = newValue;
 | 
				
			||||||
 | 
					        }, CoreSites.instance.getCurrentSiteId());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ngOnInit(): void {
 | 
				
			||||||
 | 
					        this.showKeyboard = CoreUtils.instance.isTrueOrOne(this.showKeyboard);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Form submitted.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param $event Mouse event.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    submitForm($event: Event): void {
 | 
				
			||||||
 | 
					        $event.preventDefault();
 | 
				
			||||||
 | 
					        $event.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let value = this.message.trim();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!value) {
 | 
				
			||||||
 | 
					            // Silent error.
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.message = ''; // Reset the form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, false, CoreSites.instance.getCurrentSiteId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        value = CoreTextUtils.instance.replaceNewLines(value, '<br>');
 | 
				
			||||||
 | 
					        this.onSubmit.emit(value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Textarea resized.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    textareaResized(): void {
 | 
				
			||||||
 | 
					        this.onResize.emit();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Enter key clicked.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param e Event.
 | 
				
			||||||
 | 
					     * @param other The name of the other key that was clicked, undefined if no other key.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    enterClicked(e: Event, other?: string): void {
 | 
				
			||||||
 | 
					        if (this.sendDisabled) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.sendOnEnter && !other) {
 | 
				
			||||||
 | 
					            // Enter clicked, send the message.
 | 
				
			||||||
 | 
					            this.submitForm(e);
 | 
				
			||||||
 | 
					        } else if (!this.sendOnEnter && !CoreApp.instance.isMobile() && other == 'control') {
 | 
				
			||||||
 | 
					            // Cmd+Enter or Ctrl+Enter, send message.
 | 
				
			||||||
 | 
					            this.submitForm(e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user