Skip to content

Commit 3d51b17

Browse files
committed
MOBILE-4482 forum: Avoid reuploading files when editing post
1 parent ec5c8d6 commit 3d51b17

File tree

1 file changed

+122
-64
lines changed
  • src/addons/mod/forum/components/post

1 file changed

+122
-64
lines changed

src/addons/mod/forum/components/post/post.ts

Lines changed: 122 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import {
3939
} from '../../services/forum';
4040
import { CoreTag } from '@features/tag/services/tag';
4141
import { Translate } from '@singletons';
42-
import { CoreFileUploader } from '@features/fileuploader/services/fileuploader';
42+
import { CoreFileUploader, CoreFileUploaderStoreFilesResult } from '@features/fileuploader/services/fileuploader';
4343
import { AddonModForumSync } from '../../services/forum-sync';
4444
import { CoreSync } from '@services/sync';
4545
import { CoreText } from '@singletons/text';
@@ -57,6 +57,7 @@ import { CoreToasts } from '@services/toasts';
5757
import { toBoolean } from '@/core/transforms/boolean';
5858
import { CorePopovers } from '@services/popovers';
5959
import { CoreLoadings } from '@services/loadings';
60+
import { CoreWSFile } from '@services/ws';
6061

6162
/**
6263
* Components that shows a discussion post, its attachments and the action buttons allowed (reply, etc.).
@@ -214,7 +215,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
214215
this.formData.isEditing = !!isEditing;
215216
this.formData.subject = subject || this.defaultReplySubject || '';
216217
this.formData.message = message || null;
217-
this.formData.files = files || [];
218+
this.formData.files = (files ?? []).slice(); // Make a copy to avoid modifying the original array.
218219
this.formData.isprivatereply = !!isPrivate;
219220
this.formData.id = postId;
220221

@@ -392,10 +393,9 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
392393
return;
393394
}
394395

395-
let saveOffline = false;
396396
let message = this.formData.message;
397397
const subject = this.formData.subject;
398-
const replyingTo = this.formData.replyingTo!;
398+
const replyingTo = this.formData.replyingTo ?? 0;
399399
const files = this.formData.files || [];
400400
const isEditOnline = this.formData.id && this.formData.id > 0;
401401
const modal = await CoreLoadings.show('core.sending', true);
@@ -413,73 +413,56 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
413413
// Add some HTML to the message if needed.
414414
message = CoreText.formatHtmlLines(message);
415415

416-
// Upload attachments first if any.
417-
let attachments;
418-
419416
try {
420-
if (files.length) {
421-
try {
422-
attachments = await AddonModForumHelper.uploadOrStoreReplyFiles(
423-
this.forum.id,
424-
isEditOnline ? this.formData.id! : replyingTo,
425-
files,
426-
false,
427-
);
428-
} catch (error) {
429-
// Cannot upload them in online, save them in offline.
430-
if (!this.forum.id || isEditOnline || CoreUtils.isWebServiceError(error)) {
431-
// Cannot store them in offline. Reject.
432-
throw error;
433-
}
434-
435-
saveOffline = true;
436-
attachments = await AddonModForumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true);
437-
}
438-
}
439-
440417
let sent = false;
441418

442-
if (isEditOnline) {
443-
sent = await AddonModForum.updatePost(this.formData.id!, subject, message, {
419+
if (this.formData.id && this.formData.id > 0) {
420+
const attachments = await this.uploadAttachmentsForEditOnline(this.formData.id);
421+
422+
sent = await AddonModForum.updatePost(this.formData.id, subject, message, {
444423
attachmentsid: attachments,
445424
inlineattachmentsid: this.preparePostData?.draftitemid,
446425
});
447-
} else if (saveOffline) {
448-
// Save post in offline.
449-
await AddonModForumOffline.replyPost(
450-
replyingTo,
451-
this.discussionId,
452-
this.forum.id,
453-
this.forum.name,
454-
this.courseId,
455-
subject,
456-
message,
457-
{
458-
attachmentsid: attachments,
459-
private: !!this.formData.isprivatereply,
460-
},
461-
);
462-
463-
// Set sent to false since it wasn't sent to server.
464-
sent = false;
465426
} else {
466-
// Try to send it to server.
467-
// Don't allow offline if there are attachments since they were uploaded fine.
468-
sent = await AddonModForum.replyPost(
469-
replyingTo,
470-
this.discussionId,
471-
this.forum.id,
472-
this.forum.name,
473-
this.courseId,
474-
subject,
475-
message,
476-
{
477-
attachmentsid: attachments,
478-
private: !!this.formData.isprivatereply,
479-
},
480-
undefined,
481-
!files.length,
482-
);
427+
const { attachments, saveOffline } = await this.uploadAttachmentsForReply(replyingTo);
428+
429+
if (saveOffline) {
430+
// Save post in offline.
431+
await AddonModForumOffline.replyPost(
432+
replyingTo,
433+
this.discussionId,
434+
this.forum.id,
435+
this.forum.name,
436+
this.courseId,
437+
subject,
438+
message,
439+
{
440+
attachmentsid: attachments,
441+
private: !!this.formData.isprivatereply,
442+
},
443+
);
444+
445+
// Set sent to false since it wasn't sent to server.
446+
sent = false;
447+
} else {
448+
// Try to send it to server.
449+
// Don't allow offline if there are attachments since they were uploaded fine.
450+
sent = await AddonModForum.replyPost(
451+
replyingTo,
452+
this.discussionId,
453+
this.forum.id,
454+
this.forum.name,
455+
this.courseId,
456+
subject,
457+
message,
458+
{
459+
attachmentsid: attachments,
460+
private: !!this.formData.isprivatereply,
461+
},
462+
undefined,
463+
!files.length,
464+
);
465+
}
483466
}
484467

485468
if (sent && this.forum.id) {
@@ -506,6 +489,81 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
506489
}
507490
}
508491

492+
/**
493+
* Upload attachments when editing an online post.
494+
*
495+
* @param postId Post ID being edited.
496+
* @returns Draft area id (if any attachment has changed).
497+
*/
498+
protected async uploadAttachmentsForEditOnline(postId: number): Promise<number | undefined> {
499+
const files = this.formData.files || [];
500+
const previousAttachments = (this.post.attachments ?? []) as CoreWSFile[];
501+
502+
if (!CoreFileUploader.areFileListDifferent(files, previousAttachments)) {
503+
return;
504+
}
505+
506+
// Use prepare post for edition to avoid re-uploading all files.
507+
let filesToKeep = files.filter((file): file is CoreWSFile => !CoreUtils.isFileEntry(file));
508+
let removedFiles: { filepath: string; filename: string }[] | undefined;
509+
510+
if (previousAttachments.length && !filesToKeep.length) {
511+
// Post had attachments but they were all removed. We cannot use the filesToKeep option because it doesn't allow
512+
// removing all files. In this case we'll just keep 1 file and remove it later.
513+
filesToKeep = [previousAttachments[0]];
514+
removedFiles = [{
515+
filename: previousAttachments[0].filename ?? '',
516+
filepath: previousAttachments[0].filepath ?? '',
517+
}];
518+
}
519+
520+
const preparePostData = await AddonModForum.preparePostForEdition(postId, 'attachment', { filesToKeep });
521+
522+
if (removedFiles?.length) {
523+
await CoreFileUploader.deleteDraftFiles(preparePostData.draftitemid, removedFiles);
524+
}
525+
526+
await CoreFileUploader.uploadFiles(preparePostData.draftitemid, files);
527+
528+
return preparePostData.draftitemid;
529+
}
530+
531+
/**
532+
* Upload attachments for a reply that isn't an online post being edited.
533+
*
534+
* @param replyingTo Replying to post ID.
535+
* @returns Draft area id (if any attachment was uploaded) and whether data should be saved offline.
536+
*/
537+
async uploadAttachmentsForReply(
538+
replyingTo: number,
539+
): Promise<{ attachments: CoreFileUploaderStoreFilesResult | number | undefined; saveOffline: boolean }> {
540+
const files = this.formData.files || [];
541+
if (!files.length) {
542+
return { attachments: undefined, saveOffline: false };
543+
}
544+
545+
try {
546+
const attachments = await AddonModForumHelper.uploadOrStoreReplyFiles(
547+
this.forum.id,
548+
replyingTo,
549+
files,
550+
false,
551+
);
552+
553+
return { attachments, saveOffline: false };
554+
} catch (error) {
555+
// Cannot upload them in online, save them in offline.
556+
if (!this.forum.id || CoreUtils.isWebServiceError(error)) {
557+
// Cannot store them in offline. Reject.
558+
throw error;
559+
}
560+
561+
const attachments = await AddonModForumHelper.uploadOrStoreReplyFiles(this.forum.id, replyingTo, files, true);
562+
563+
return { attachments, saveOffline: true };
564+
}
565+
}
566+
509567
/**
510568
* Cancel reply.
511569
*/

0 commit comments

Comments
 (0)