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.contentlinks.errorredirectothersite": "local_moodlemobileapp",
|
||||||
"core.continue": "moodle",
|
"core.continue": "moodle",
|
||||||
"core.copiedtoclipboard": "local_moodlemobileapp",
|
"core.copiedtoclipboard": "local_moodlemobileapp",
|
||||||
|
"core.copytoclipboard": "local_moodlemobileapp",
|
||||||
"core.course": "moodle",
|
"core.course": "moodle",
|
||||||
"core.course.activitydisabled": "local_moodlemobileapp",
|
"core.course.activitydisabled": "local_moodlemobileapp",
|
||||||
"core.course.activitynotyetviewableremoteaddon": "local_moodlemobileapp",
|
"core.course.activitynotyetviewableremoteaddon": "local_moodlemobileapp",
|
||||||
|
@ -1754,6 +1755,7 @@
|
||||||
"core.login.mustconfirm": "moodle",
|
"core.login.mustconfirm": "moodle",
|
||||||
"core.login.newaccount": "moodle",
|
"core.login.newaccount": "moodle",
|
||||||
"core.login.notloggedin": "local_moodlemobileapp",
|
"core.login.notloggedin": "local_moodlemobileapp",
|
||||||
|
"core.login.or": "local_moodlemobileapp",
|
||||||
"core.login.password": "moodle",
|
"core.login.password": "moodle",
|
||||||
"core.login.passwordforgotten": "moodle",
|
"core.login.passwordforgotten": "moodle",
|
||||||
"core.login.passwordforgotteninstructions2": "moodle",
|
"core.login.passwordforgotteninstructions2": "moodle",
|
||||||
|
@ -1860,6 +1862,7 @@
|
||||||
"core.online": "message",
|
"core.online": "message",
|
||||||
"core.openfullimage": "local_moodlemobileapp",
|
"core.openfullimage": "local_moodlemobileapp",
|
||||||
"core.openinbrowser": "local_moodlemobileapp",
|
"core.openinbrowser": "local_moodlemobileapp",
|
||||||
|
"core.openmodinbrowser": "local_moodlemobileapp",
|
||||||
"core.othergroups": "group",
|
"core.othergroups": "group",
|
||||||
"core.pagea": "moodle",
|
"core.pagea": "moodle",
|
||||||
"core.parentlanguage": "langconfig",
|
"core.parentlanguage": "langconfig",
|
||||||
|
|
|
@ -133,8 +133,15 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
ev && ev.stopPropagation();
|
ev && ev.stopPropagation();
|
||||||
|
|
||||||
if (this.assign && (this.description || this.assign.introattachments)) {
|
if (this.assign && (this.description || this.assign.introattachments)) {
|
||||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component,
|
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||||
this.module.id, this.assign.introattachments, true, 'module', this.module.id, this.courseId);
|
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 {
|
showAdvancedGrade(): void {
|
||||||
if (this.feedback && this.feedback.advancedgrade) {
|
if (this.feedback && this.feedback.advancedgrade) {
|
||||||
this.textUtils.expandText(this.translate.instant('core.grades.grade'), this.feedback.gradefordisplay,
|
this.textUtils.viewText(this.translate.instant('core.grades.grade'), this.feedback.gradefordisplay, {
|
||||||
AddonModAssignProvider.COMPONENT, this.moduleId);
|
component: AddonModAssignProvider.COMPONENT,
|
||||||
|
componentId: this.moduleId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,8 +65,14 @@ export class AddonModAssignFeedbackCommentsComponent extends AddonModAssignFeedb
|
||||||
|
|
||||||
if (this.text) {
|
if (this.text) {
|
||||||
// Open a new state with the text.
|
// Open a new state with the text.
|
||||||
this.textUtils.expandText(this.plugin.name, this.text, this.component, this.assign.cmid, undefined, true,
|
this.textUtils.viewText(this.plugin.name, this.text, {
|
||||||
'module', this.assign.cmid, this.assign.course);
|
component: this.component,
|
||||||
|
componentId: this.assign.cmid,
|
||||||
|
filter: true,
|
||||||
|
contextLevel: 'module',
|
||||||
|
instanceId: this.assign.cmid,
|
||||||
|
courseId: this.assign.course,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (this.edit) {
|
} else if (this.edit) {
|
||||||
|
|
|
@ -83,8 +83,14 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
|
||||||
|
|
||||||
if (text) {
|
if (text) {
|
||||||
// Open a new state with the interpolated contents.
|
// Open a new state with the interpolated contents.
|
||||||
this.textUtils.expandText(this.plugin.name, text, this.component, this.assign.cmid, undefined, true,
|
this.textUtils.viewText(this.plugin.name, text, {
|
||||||
'module', this.assign.cmid, this.assign.course);
|
component: this.component,
|
||||||
|
componentId: this.assign.cmid,
|
||||||
|
filter: true,
|
||||||
|
contextLevel: 'module',
|
||||||
|
instanceId: this.assign.cmid,
|
||||||
|
courseId: this.assign.course,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1387,6 +1387,7 @@
|
||||||
"core.contentlinks.errorredirectothersite": "The redirect URL cannot point to a different site.",
|
"core.contentlinks.errorredirectothersite": "The redirect URL cannot point to a different site.",
|
||||||
"core.continue": "Continue",
|
"core.continue": "Continue",
|
||||||
"core.copiedtoclipboard": "Text copied to clipboard",
|
"core.copiedtoclipboard": "Text copied to clipboard",
|
||||||
|
"core.copytoclipboard": "Copy to clipboard",
|
||||||
"core.course": "Course",
|
"core.course": "Course",
|
||||||
"core.course.activitydisabled": "Your organisation has disabled this activity in the mobile app.",
|
"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.",
|
"core.course.activitynotyetviewableremoteaddon": "Your organisation installed a plugin that is not yet supported.",
|
||||||
|
|
|
@ -47,7 +47,13 @@ export class CoreNavigationBarComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
showInfo(): void {
|
showInfo(): void {
|
||||||
this.textUtils.expandText(this.title, this.info, this.component, this.componentId, [], true, this.contextLevel,
|
this.textUtils.viewText(this.title, this.info, {
|
||||||
this.contextInstanceId, this.courseId);
|
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.
|
* Expand the description.
|
||||||
*/
|
*/
|
||||||
expandDescription(): void {
|
expandDescription(): void {
|
||||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id,
|
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||||
[], true, 'module', this.module.id, this.courseId);
|
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.
|
* Expand the description.
|
||||||
*/
|
*/
|
||||||
expandDescription(): void {
|
expandDescription(): void {
|
||||||
this.textUtils.expandText(this.translate.instant('core.description'), this.module.description, undefined, undefined,
|
this.textUtils.viewText(this.translate.instant('core.description'), this.module.description, {
|
||||||
[], true, 'module', this.module.id, this.courseId);
|
filter: true,
|
||||||
|
contextLevel: 'module',
|
||||||
|
instanceId: this.module.id,
|
||||||
|
courseId: this.courseId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,7 +317,7 @@ export class CoreLoginEmailSignupPage {
|
||||||
* Show authentication instructions.
|
* Show authentication instructions.
|
||||||
*/
|
*/
|
||||||
protected showAuthInstructions(): void {
|
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 {
|
} else {
|
||||||
// It's not a URL, open it in a modal so the user can see it and copy it.
|
// 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) {
|
if (span) {
|
||||||
// There's a hidden feedback, show it when the icon is clicked.
|
// There's a hidden feedback, show it when the icon is clicked.
|
||||||
icon.addEventListener('click', (event) => {
|
icon.addEventListener('click', (event) => {
|
||||||
this.textUtils.expandText(title, span.innerHTML, component, componentId, [], true, contextLevel,
|
this.textUtils.viewText(title, span.innerHTML, {
|
||||||
contextInstanceId, courseId);
|
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.
|
* Expand the description.
|
||||||
*/
|
*/
|
||||||
expandDescription(): void {
|
expandDescription(): void {
|
||||||
this.textUtils.expandText(this.translate.instant('core.description'), this.description, this.component, this.module.id,
|
this.textUtils.viewText(this.translate.instant('core.description'), this.description, {
|
||||||
[], true, 'module', this.module.id, this.courseId);
|
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>
|
<core-file *ngFor="let file of files" [file]="file" [component]="component" [componentId]="componentId"></core-file>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
</ion-content>
|
</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 { Component } from '@angular/core';
|
||||||
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
|
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
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.
|
* 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.
|
contextLevel: string; // The context level.
|
||||||
instanceId: number; // The instance ID related to the context.
|
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.
|
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) {
|
constructor(private viewCtrl: ViewController, params: NavParams, textUtils: CoreTextUtilsProvider) {
|
||||||
this.title = params.get('title');
|
this.title = params.get('title');
|
||||||
|
@ -45,6 +47,7 @@ export class CoreViewerTextPage {
|
||||||
this.contextLevel = params.get('contextLevel');
|
this.contextLevel = params.get('contextLevel');
|
||||||
this.instanceId = params.get('instanceId');
|
this.instanceId = params.get('instanceId');
|
||||||
this.courseId = params.get('courseId');
|
this.courseId = params.get('courseId');
|
||||||
|
this.displayCopyButton = !!params.get('displayCopyButton');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,4 +56,11 @@ export class CoreViewerTextPage {
|
||||||
closeModal(): void {
|
closeModal(): void {
|
||||||
this.viewCtrl.dismiss();
|
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.
|
// Open a new state with the contents.
|
||||||
const filter = typeof this.filter != 'undefined' ? this.utils.isTrueOrOne(this.filter) : undefined;
|
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.textUtils.viewText(this.fullTitle || this.translate.instant('core.description'), this.text, {
|
||||||
this.component, this.componentId, undefined, filter, this.contextLevel, this.contextInstanceId, this.courseId);
|
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.",
|
"contenteditingsynced": "The content you are editing has been synced.",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
"copiedtoclipboard": "Text copied to clipboard",
|
"copiedtoclipboard": "Text copied to clipboard",
|
||||||
|
"copytoclipboard": "Copy to clipboard",
|
||||||
"course": "Course",
|
"course": "Course",
|
||||||
"coursedetails": "Course details",
|
"coursedetails": "Course details",
|
||||||
"coursenogroups": "You are not a member of any group of this course.",
|
"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 contextLevel The context level.
|
||||||
* @param instanceId The instance ID related to the context.
|
* @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.
|
* @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[],
|
expandText(title: string, text: string, component?: string, componentId?: string | number, files?: any[],
|
||||||
filter?: boolean, contextLevel?: string, instanceId?: number, courseId?: number): void {
|
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.
|
return this.viewText(title, text, {
|
||||||
params.isModal = true;
|
component,
|
||||||
|
componentId,
|
||||||
const modal = this.modalCtrl.create('CoreViewerTextPage', params);
|
files,
|
||||||
modal.present();
|
filter,
|
||||||
}
|
contextLevel,
|
||||||
|
instanceId,
|
||||||
|
courseId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1133,6 +1125,50 @@ export class CoreTextUtilsProvider {
|
||||||
|
|
||||||
return _unserialize((data + ''), 0)[2];
|
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) {}
|
export class CoreTextUtils extends makeSingleton(CoreTextUtilsProvider) {}
|
||||||
|
|
Loading…
Reference in New Issue