Skip to content

Commit 6d20fc7

Browse files
ushahidleetuxpiper
authored andcommitted
Ush 1189 & 1198 - Images in the mobile app (#1085)
1 parent 68ade5f commit 6d20fc7

File tree

10 files changed

+202
-47
lines changed

10 files changed

+202
-47
lines changed

apps/mobile-mzima-client/capacitor.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const config: CapacitorConfig = {
3838
resizeOnFullScreen: true,
3939
},
4040
CapacitorHttp: {
41-
enabled: true,
41+
enabled: false,
4242
},
4343
Intercom: {
4444
iosApiKey: 'ios_sdk-39fba04b7c5ab918fb743cc4a55ea9380221eb3c',

apps/mobile-mzima-client/src/app/post/components/image-uploader/image-uploader.component.html

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
<div class="image-loader">
22
<div class="image-loader__wrap">
33
<div class="post-images" *ngIf="photo?.data">
4-
<img class="post-image" [src]="photo?.data" />
5-
</div>
6-
<div class="post-images" *ngIf="preview && isConnection">
7-
<img class="post-image" [src]="preview" />
4+
<img class="post-image" [src]="this.domSanitizer.bypassSecurityTrustUrl(photo!.data)" />
85
</div>
96
<ng-container *ngIf="!isConnection">
107
<app-offline-notification></app-offline-notification>

apps/mobile-mzima-client/src/app/post/components/image-uploader/image-uploader.component.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Component, forwardRef, Input } from '@angular/core';
22
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
3-
import { SafeUrl } from '@angular/platform-browser';
3+
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
44
import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
55
import { Capacitor } from '@capacitor/core';
66
import { Directory, FileInfo, Filesystem } from '@capacitor/filesystem';
@@ -28,6 +28,9 @@ interface LocalFile {
2828
],
2929
})
3030
export class ImageUploaderComponent implements ControlValueAccessor {
31+
constructor(domSanitizer: DomSanitizer) {
32+
this.domSanitizer = domSanitizer;
33+
}
3134
@Input() public hasCaption: boolean;
3235
@Input() public requiredError?: boolean;
3336
@Input() public isConnection: boolean;
@@ -41,6 +44,7 @@ export class ImageUploaderComponent implements ControlValueAccessor {
4144
upload = false;
4245
onChange: any = () => {};
4346
onTouched: any = () => {};
47+
domSanitizer: DomSanitizer;
4448

4549
writeValue(obj: any): void {
4650
if (obj) {
@@ -97,16 +101,18 @@ export class ImageUploaderComponent implements ControlValueAccessor {
97101
this.fileName = new Date().getTime() + '.jpeg';
98102
const filePath = `${IMAGE_DIR}/${this.fileName}`;
99103
try {
100-
const savedFile = await Filesystem.writeFile({
101-
directory: Directory.Data,
102-
path: filePath,
103-
data: base64Data,
104-
});
105104
// const file = await this.loadFile();
106105

107-
if (Capacitor.getPlatform() === 'hybrid') {
106+
if (['hybrid'].includes(Capacitor.getPlatform())) {
108107
// Display the new image by rewriting the 'file://' path to HTTP
109108
// Details: https://ionicframework.com/docs/building/webview#file-protocol
109+
110+
const savedFile = await Filesystem.writeFile({
111+
directory: Directory.Data,
112+
path: filePath,
113+
data: base64Data,
114+
});
115+
110116
this.photo = {
111117
name: this.fileName,
112118
path: savedFile.uri,
@@ -124,18 +130,20 @@ export class ImageUploaderComponent implements ControlValueAccessor {
124130
}
125131

126132
this.upload = true;
127-
this.preview = null;
133+
// this.preview = photo;
128134
} catch (e) {
129135
console.log(e);
130136
}
131137
}
132138

133139
async deleteSelectedImage() {
134140
try {
135-
await Filesystem.deleteFile({
136-
directory: Directory.Data,
137-
path: this.photo!.path,
138-
});
141+
if (Capacitor.getPlatform() === 'hybrid') {
142+
await Filesystem.deleteFile({
143+
directory: Directory.Data,
144+
path: this.photo!.path,
145+
});
146+
}
139147
this.photo = null;
140148
this.upload = false;
141149
this.preview = null;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export * from './post-edit.form';
22
export * from './convert-image';
33
export * from './upload-file';
4+
export * from './upload-file-progress';
45
export * from './post-helper';
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { HttpEventType, HttpProgressEvent } from '@angular/common/http';
2+
import { Directory, Filesystem } from '@capacitor/filesystem';
3+
import { MediaService } from '@mzima-client/sdk';
4+
import { lastValueFrom, Observable, tap } from 'rxjs';
5+
6+
export class UploadFileProgressHelper {
7+
constructor(private mediaService: MediaService) {}
8+
9+
async uploadFileField(
10+
field: any,
11+
{ data, name, caption, path }: any,
12+
progressCallback: (progress: number) => void,
13+
) {
14+
try {
15+
const fetchPhoto = await fetch(data);
16+
const blob = await fetchPhoto.blob();
17+
const file = new File([blob], name);
18+
const uploadProgress: Observable<any> = this.mediaService
19+
.uploadFileProgress(file, caption)
20+
.pipe(
21+
tap((event) => {
22+
if (event.type === HttpEventType.UploadProgress) {
23+
const progressEvent: HttpProgressEvent = event as HttpProgressEvent;
24+
const percentDone = progressEvent.total
25+
? progressEvent.loaded / progressEvent.total
26+
: 0;
27+
progressCallback(percentDone);
28+
}
29+
}),
30+
);
31+
const event: any = await lastValueFrom(uploadProgress);
32+
33+
if (event?.body?.result?.id) {
34+
field.value = { value: event.body.result.id };
35+
}
36+
37+
Filesystem.deleteFile({
38+
directory: Directory.Data,
39+
path: path,
40+
});
41+
} catch (error: any) {
42+
throw new Error(`Error uploading file: ${error.message}`);
43+
}
44+
45+
return field;
46+
}
47+
}

apps/mobile-mzima-client/src/app/post/post-edit/post-edit.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { TextFieldModule } from '@angular/cdk/text-field';
22
import { CommonModule } from '@angular/common';
33
import { NgModule } from '@angular/core';
44
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
5+
import { MatProgressBarModule } from '@angular/material/progress-bar';
56
import { IonicModule } from '@ionic/angular';
67
import { TranslateModule } from '@ngx-translate/core';
78
import { SortByFieldModule } from '@pipes';
@@ -24,6 +25,7 @@ import { PostEditRoutingModule } from './post-edit.routing.module';
2425
TranslateModule,
2526
PostComponentsModule,
2627
SortByFieldModule,
28+
MatProgressBarModule,
2729
],
2830
declarations: [PostEditPage],
2931
})

apps/mobile-mzima-client/src/app/post/post-edit/post-edit.page.html

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ <h2 class="task-label">{{ task.label }}</h2>
355355
"
356356
>
357357
</app-image-uploader>
358+
<ion-progress-bar [value]="uploadProgress$[field.id] | async"></ion-progress-bar>
358359
</div>
359360
</ng-container>
360361

@@ -521,13 +522,25 @@ <h2 class="task-label">{{ task.label }}</h2>
521522
<app-button
522523
expand="inline"
523524
type="button"
524-
*ngIf="form"
525-
[disabled]="form.disabled || form.invalid || emptyLocation || (!requireApproval || post?.status === 'published' ? taskForm.invalid : false)"
525+
*ngIf="form && isSubmitting !== 'complete'"
526+
[disabled]="isSubmitting==='yes' || form.disabled || form.invalid || emptyLocation || (!requireApproval || post?.status === 'published' ? taskForm.invalid : false)"
526527
(buttonClick)="submitPost()"
528+
[ngSwitch]="isSubmitting"
529+
class="submit-button"
527530
>
528-
Submit
531+
<ng-container *ngSwitchCase="'yes'">
532+
<app-spinner></app-spinner>
533+
Submitting
534+
</ng-container>
535+
<ng-container *ngSwitchCase="'no'"> Submit </ng-container>
529536
</app-button>
530-
<app-button color="medium" fill="outline" expand="inline" (buttonClick)="backNavigation()">
537+
<app-button
538+
*ngIf="isSubmitting==='no'"
539+
color="medium"
540+
fill="outline"
541+
expand="inline"
542+
(buttonClick)="cancelPost()"
543+
>
531544
Cancel
532545
</app-button>
533546
</ion-buttons>

apps/mobile-mzima-client/src/app/post/post-edit/post-edit.page.scss

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,32 @@
6969
}
7070

7171
.form-controls-panel {
72+
display: flex;
73+
flex: 1 1;
74+
flex-direction: row;
7275
gap: 8px;
73-
7476
app-button {
7577
--button-padding-start: 24px;
7678
--button-padding-end: 24px;
79+
width: 100%;
80+
::ng-deep ion-button {
81+
width: 100%;
82+
}
83+
84+
&.submit-button {
85+
::ng-deep ion-button span {
86+
display: flex;
87+
flex-direction: row;
88+
app-spinner {
89+
display: block;
90+
margin-inline: 4px;
91+
--spinner-size: 16px;
92+
::ng-deep ion-spinner {
93+
color: #fff;
94+
}
95+
}
96+
}
97+
}
7798
}
7899
}
79100

0 commit comments

Comments
 (0)