MOBILE-2995 qr: Add copy to clipboard button in QR text modal
parent
d79f48e3fb
commit
ec19082f7b
|
@ -1387,6 +1387,7 @@
|
|||
"core.contentlinks.errorredirectothersite": "local_moodlemobileapp",
|
||||
"core.continue": "moodle",
|
||||
"core.copiedtoclipboard": "local_moodlemobileapp",
|
||||
"core.copytoclipboard": "local_moodlemobileapp",
|
||||
"core.course": "moodle",
|
||||
"core.course.activitydisabled": "local_moodlemobileapp",
|
||||
"core.course.activitynotyetviewableremoteaddon": "local_moodlemobileapp",
|
||||
|
@ -1754,6 +1755,7 @@
|
|||
"core.login.mustconfirm": "moodle",
|
||||
"core.login.newaccount": "moodle",
|
||||
"core.login.notloggedin": "local_moodlemobileapp",
|
||||
"core.login.or": "local_moodlemobileapp",
|
||||
"core.login.password": "moodle",
|
||||
"core.login.passwordforgotten": "moodle",
|
||||
"core.login.passwordforgotteninstructions2": "moodle",
|
||||
|
@ -1860,6 +1862,7 @@
|
|||
"core.online": "message",
|
||||
"core.openfullimage": "local_moodlemobileapp",
|
||||
"core.openinbrowser": "local_moodlemobileapp",
|
||||
"core.openmodinbrowser": "local_moodlemobileapp",
|
||||
"core.othergroups": "group",
|
||||
"core.pagea": "moodle",
|
||||
"core.parentlanguage": "langconfig",
|
||||
|
|
|
@ -133,8 +133,15 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
|
|||
ev && ev.stopPropagation();
|
||||
|
||||
if (this.assign && (this.description || this.assign.introattachments)) {
|
||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component,
|
||||
this.module.id, this.assign.introattachments, true, 'module', this.module.id, this.courseId);
|
||||
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||
component: this.component,
|
||||
componentId: this.module.id,
|
||||
files: this.assign.introattachments,
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.module.id,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -678,8 +678,10 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
showAdvancedGrade(): void {
|
||||
if (this.feedback && this.feedback.advancedgrade) {
|
||||
this.textUtils.expandText(this.translate.instant('core.grades.grade'), this.feedback.gradefordisplay,
|
||||
AddonModAssignProvider.COMPONENT, this.moduleId);
|
||||
this.textUtils.viewText(this.translate.instant('core.grades.grade'), this.feedback.gradefordisplay, {
|
||||
component: AddonModAssignProvider.COMPONENT,
|
||||
componentId: this.moduleId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,8 +65,14 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb
|
|||
|
||||
if (this.text) {
|
||||
// Open a new state with the text.
|
||||
this.textUtils.expandText(this.plugin.name, this.text, this.component, this.assign.cmid, undefined, true,
|
||||
'module', this.assign.cmid, this.assign.course);
|
||||
this.textUtils.viewText(this.plugin.name, this.text, {
|
||||
component: this.component,
|
||||
componentId: this.assign.cmid,
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.assign.cmid,
|
||||
courseId: this.assign.course,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (this.edit) {
|
||||
|
|
|
@ -83,8 +83,14 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
|
|||
|
||||
if (text) {
|
||||
// Open a new state with the interpolated contents.
|
||||
this.textUtils.expandText(this.plugin.name, text, this.component, this.assign.cmid, undefined, true,
|
||||
'module', this.assign.cmid, this.assign.course);
|
||||
this.textUtils.viewText(this.plugin.name, text, {
|
||||
component: this.component,
|
||||
componentId: this.assign.cmid,
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.assign.cmid,
|
||||
courseId: this.assign.course,
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
|
|
@ -1387,6 +1387,7 @@
|
|||
"core.contentlinks.errorredirectothersite": "The redirect URL cannot point to a different site.",
|
||||
"core.continue": "Continue",
|
||||
"core.copiedtoclipboard": "Text copied to clipboard",
|
||||
"core.copytoclipboard": "Copy to clipboard",
|
||||
"core.course": "Course",
|
||||
"core.course.activitydisabled": "Your organisation has disabled this activity in the mobile app.",
|
||||
"core.course.activitynotyetviewableremoteaddon": "Your organisation installed a plugin that is not yet supported.",
|
||||
|
|
|
@ -47,7 +47,13 @@ export class CoreNavigationBarComponent {
|
|||
}
|
||||
|
||||
showInfo(): void {
|
||||
this.textUtils.expandText(this.title, this.info, this.component, this.componentId, [], true, this.contextLevel,
|
||||
this.contextInstanceId, this.courseId);
|
||||
this.textUtils.viewText(this.title, this.info, {
|
||||
component: this.component,
|
||||
componentId: this.componentId,
|
||||
filter: true,
|
||||
contextLevel: this.contextLevel,
|
||||
instanceId: this.contextInstanceId,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -265,8 +265,14 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
* Expand the description.
|
||||
*/
|
||||
expandDescription(): void {
|
||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id,
|
||||
[], true, 'module', this.module.id, this.courseId);
|
||||
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||
component: this.component,
|
||||
componentId: this.module.id,
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.module.id,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,11 @@ export class CoreCourseUnsupportedModulePage {
|
|||
* Expand the description.
|
||||
*/
|
||||
expandDescription(): void {
|
||||
this.textUtils.expandText(this.translate.instant('core.description'), this.module.description, undefined, undefined,
|
||||
[], true, 'module', this.module.id, this.courseId);
|
||||
this.textUtils.viewText(this.translate.instant('core.description'), this.module.description, {
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.module.id,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@ export class CoreLoginEmailSignupPage {
|
|||
* Show authentication instructions.
|
||||
*/
|
||||
protected showAuthInstructions(): void {
|
||||
this.textUtils.expandText(this.translate.instant('core.login.instructions'), this.authInstructions);
|
||||
this.textUtils.viewText(this.translate.instant('core.login.instructions'), this.authInstructions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -192,7 +192,9 @@ export class CoreMainMenuMorePage implements OnDestroy {
|
|||
});
|
||||
} else {
|
||||
// It's not a URL, open it in a modal so the user can see it and copy it.
|
||||
this.textUtils.expandText(this.translate.instant('core.qrscanner'), text);
|
||||
this.textUtils.viewText(this.translate.instant('core.qrscanner'), text, {
|
||||
displayCopyButton: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -709,8 +709,14 @@ export class CoreQuestionHelperProvider {
|
|||
if (span) {
|
||||
// There's a hidden feedback, show it when the icon is clicked.
|
||||
icon.addEventListener('click', (event) => {
|
||||
this.textUtils.expandText(title, span.innerHTML, component, componentId, [], true, contextLevel,
|
||||
contextInstanceId, courseId);
|
||||
this.textUtils.viewText(title, span.innerHTML, {
|
||||
component: component,
|
||||
componentId: componentId,
|
||||
filter: true,
|
||||
contextLevel: contextLevel,
|
||||
instanceId: contextInstanceId,
|
||||
courseId: courseId,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -146,8 +146,14 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
|||
* Expand the description.
|
||||
*/
|
||||
expandDescription(): void {
|
||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id,
|
||||
[], true, 'module', this.module.id, this.courseId);
|
||||
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||
component: this.component,
|
||||
componentId: this.module.id,
|
||||
filter: true,
|
||||
contextLevel: 'module',
|
||||
instanceId: this.module.id,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,3 +16,9 @@
|
|||
<core-file *ngFor="let file of files" [file]="file" [component]="component" [componentId]="componentId"></core-file>
|
||||
</ion-card>
|
||||
</ion-content>
|
||||
<ion-footer color="light" *ngIf="displayCopyButton">
|
||||
<button ion-button block color="light" icon-start (click)="copyText()">
|
||||
<ion-icon name="copy" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.copytoclipboard' | translate }}
|
||||
</button>
|
||||
</ion-footer>
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
ion-app.app-root page-core-viewer-text {
|
||||
ion-footer {
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUtils } from '@providers/utils/utils';
|
||||
|
||||
/**
|
||||
* Page to render a certain text. If opened as a modal, it will have a button to close the modal.
|
||||
|
@ -34,6 +35,7 @@ export class CoreViewerTextPage {
|
|||
contextLevel: string; // The context level.
|
||||
instanceId: number; // The instance ID related to the context.
|
||||
courseId: number; // Course ID the text belongs to. It can be used to improve performance with filters.
|
||||
displayCopyButton: boolean; // Whether to display a button to copy the contents.
|
||||
|
||||
constructor(private viewCtrl: ViewController, params: NavParams, textUtils: CoreTextUtilsProvider) {
|
||||
this.title = params.get('title');
|
||||
|
@ -45,6 +47,7 @@ export class CoreViewerTextPage {
|
|||
this.contextLevel = params.get('contextLevel');
|
||||
this.instanceId = params.get('instanceId');
|
||||
this.courseId = params.get('courseId');
|
||||
this.displayCopyButton = !!params.get('displayCopyButton');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,4 +56,11 @@ export class CoreViewerTextPage {
|
|||
closeModal(): void {
|
||||
this.viewCtrl.dismiss();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the text to clipboard.
|
||||
*/
|
||||
copyText(): void {
|
||||
CoreUtils.instance.copyToClipboard(this.content);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -307,8 +307,14 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
// Open a new state with the contents.
|
||||
const filter = typeof this.filter != 'undefined' ? this.utils.isTrueOrOne(this.filter) : undefined;
|
||||
|
||||
this.textUtils.expandText(this.fullTitle || this.translate.instant('core.description'), this.text,
|
||||
this.component, this.componentId, undefined, filter, this.contextLevel, this.contextInstanceId, this.courseId);
|
||||
this.textUtils.viewText(this.fullTitle || this.translate.instant('core.description'), this.text, {
|
||||
component: this.component,
|
||||
componentId: this.componentId,
|
||||
filter: filter,
|
||||
contextLevel: this.contextLevel,
|
||||
instanceId: this.contextInstanceId,
|
||||
courseId: this.courseId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"contenteditingsynced": "The content you are editing has been synced.",
|
||||
"continue": "Continue",
|
||||
"copiedtoclipboard": "Text copied to clipboard",
|
||||
"copytoclipboard": "Copy to clipboard",
|
||||
"course": "Course",
|
||||
"coursedetails": "Course details",
|
||||
"coursenogroups": "You are not a member of any group of this course.",
|
||||
|
|
|
@ -441,28 +441,20 @@ export class CoreTextUtilsProvider {
|
|||
* @param contextLevel The context level.
|
||||
* @param instanceId The instance ID related to the context.
|
||||
* @param courseId Course ID the text belongs to. It can be used to improve performance with filters.
|
||||
* @deprecated since 3.8.3. Please use viewText instead.
|
||||
*/
|
||||
expandText(title: string, text: string, component?: string, componentId?: string | number, files?: any[],
|
||||
filter?: boolean, contextLevel?: string, instanceId?: number, courseId?: number): void {
|
||||
if (text.length > 0) {
|
||||
const params: any = {
|
||||
title: title,
|
||||
content: text,
|
||||
component: component,
|
||||
componentId: componentId,
|
||||
files: files,
|
||||
filter: filter,
|
||||
contextLevel: contextLevel,
|
||||
instanceId: instanceId,
|
||||
courseId: courseId
|
||||
};
|
||||
|
||||
// Open a modal with the contents.
|
||||
params.isModal = true;
|
||||
|
||||
const modal = this.modalCtrl.create('CoreViewerTextPage', params);
|
||||
modal.present();
|
||||
}
|
||||
return this.viewText(title, text, {
|
||||
component,
|
||||
componentId,
|
||||
files,
|
||||
filter,
|
||||
contextLevel,
|
||||
instanceId,
|
||||
courseId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1133,6 +1125,50 @@ export class CoreTextUtilsProvider {
|
|||
|
||||
return _unserialize((data + ''), 0)[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a text on a new page.
|
||||
*
|
||||
* @param title Title of the new state.
|
||||
* @param text Content of the text to be expanded.
|
||||
* @param component Component to link the embedded files to.
|
||||
* @param componentId An ID to use in conjunction with the component.
|
||||
* @param files List of files to display along with the text.
|
||||
* @param filter Whether the text should be filtered.
|
||||
* @param contextLevel The context level.
|
||||
* @param instanceId The instance ID related to the context.
|
||||
* @param courseId Course ID the text belongs to. It can be used to improve performance with filters.
|
||||
*/
|
||||
viewText(title: string, text: string, options?: CoreTextUtilsViewTextOptions): void {
|
||||
if (text.length > 0) {
|
||||
options = options || {};
|
||||
|
||||
const params: any = {
|
||||
title: title,
|
||||
content: text,
|
||||
isModal: true,
|
||||
};
|
||||
|
||||
Object.assign(params, options);
|
||||
|
||||
const modal = this.modalCtrl.create('CoreViewerTextPage', params);
|
||||
modal.present();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for viewText.
|
||||
*/
|
||||
export type CoreTextUtilsViewTextOptions = {
|
||||
component?: string; // Component to link the embedded files to.
|
||||
componentId?: string | number; // An ID to use in conjunction with the component.
|
||||
files?: any[]; // List of files to display along with the text.
|
||||
filter?: boolean; // Whether the text should be filtered.
|
||||
contextLevel?: string; // The context level.
|
||||
instanceId?: number; // The instance ID related to the context.
|
||||
courseId?: number; // Course ID the text belongs to. It can be used to improve performance with filters.
|
||||
displayCopyButton?: boolean; // Whether to display a button to copy the text.
|
||||
};
|
||||
|
||||
export class CoreTextUtils extends makeSingleton(CoreTextUtilsProvider) {}
|
||||
|
|
Loading…
Reference in New Issue