Skip to content

Commit 6924b8d

Browse files
committed
feat: Respect aspect ratio for single images and videos
1 parent c16cde3 commit 6924b8d

File tree

3 files changed

+98
-48
lines changed

3 files changed

+98
-48
lines changed

projects/stream-chat-angular/src/lib/attachment-configuration.service.spec.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ describe('AttachmentConfigurationService', () => {
6969
service.getImageAttachmentConfiguration(attachment, 'gallery')
7070
).toEqual({
7171
url: 'http://url/to/img?h=300&w=300',
72-
height: '150px',
72+
height: '',
7373
width: '',
7474
});
7575
});
@@ -96,7 +96,7 @@ describe('AttachmentConfigurationService', () => {
9696

9797
expect(service.getVideoAttachmentConfiguration(attachment)).toEqual({
9898
url: 'http://url/to/video',
99-
height: '100%',
99+
height: '300px',
100100
width: '100%',
101101
thumbUrl: 'http://url/to/poster?h=600&w=600',
102102
});
@@ -108,9 +108,9 @@ describe('AttachmentConfigurationService', () => {
108108

109109
expect(service.getVideoAttachmentConfiguration(attachment)).toEqual({
110110
url: 'http://url/to/video',
111-
height: '100%',
111+
height: '169px',
112112
width: '100%',
113-
thumbUrl: 'http://url/to/poster?oh=1080&ow=1920&h=600&w=1067',
113+
thumbUrl: 'http://url/to/poster?oh=1080&ow=1920&h=338&w=600',
114114
});
115115

116116
attachment = {
@@ -119,7 +119,7 @@ describe('AttachmentConfigurationService', () => {
119119

120120
expect(service.getVideoAttachmentConfiguration(attachment)).toEqual({
121121
url: 'http://url/to/video',
122-
height: '100%',
122+
height: '300px',
123123
width: '100%',
124124
thumbUrl: undefined,
125125
});
@@ -231,10 +231,10 @@ describe('AttachmentConfigurationService', () => {
231231

232232
const result = service.getImageAttachmentConfiguration(
233233
attachment,
234-
'single'
234+
'gallery'
235235
);
236236

237-
expect(result.url).toContain('h=750&w=600');
237+
expect(result.url).toContain('h=374&w=300');
238238
});
239239

240240
it('should turn off thumbnail generation for video files', () => {

projects/stream-chat-angular/src/lib/attachment-configuration.service.ts

Lines changed: 90 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -61,24 +61,49 @@ export class AttachmentConfigurationService<
6161
);
6262
}
6363

64-
// x2 values for retina displays
65-
const sizeResctriction = {
66-
gallery: { height: 300, width: 300 },
67-
single: { height: 600, width: 600 },
68-
carousel: { height: undefined, width: undefined },
69-
}[location];
70-
71-
const height = sizeResctriction.height
72-
? `${sizeResctriction.height / 2}px`
73-
: '';
74-
7564
const url = new URL(
7665
(attachment.img_url ||
7766
attachment.thumb_url ||
7867
attachment.image_url ||
7968
'') as string
8069
);
81-
this.addResiziParamsToUrl(sizeResctriction, url);
70+
const urlParams = url.searchParams;
71+
const originalHeight = Number(urlParams.get('oh')) || 1;
72+
const originalWidth = Number(urlParams.get('ow')) || 1;
73+
let sizeRestriction: { width: number; height: number } | undefined;
74+
let height: string;
75+
switch (location) {
76+
case 'carousel': {
77+
sizeRestriction = undefined;
78+
height = ''; // Set from CSS
79+
break;
80+
}
81+
case 'gallery': {
82+
sizeRestriction = this.getSizeRestrictionForFixedAspectRatio(
83+
originalHeight,
84+
originalWidth,
85+
150
86+
);
87+
height = ''; // Set from CSS:
88+
break;
89+
}
90+
case 'single': {
91+
sizeRestriction = this.getSizeRestrictionForFixedWidth(
92+
originalHeight,
93+
originalWidth,
94+
300,
95+
300
96+
);
97+
height = `${sizeRestriction.height}px`;
98+
}
99+
}
100+
101+
if (sizeRestriction) {
102+
// Apply 2x for retina displays
103+
sizeRestriction.height *= 2;
104+
sizeRestriction.width *= 2;
105+
this.addResiziParamsToUrl(sizeRestriction, url);
106+
}
82107

83108
return {
84109
url: url.href,
@@ -98,16 +123,29 @@ export class AttachmentConfigurationService<
98123
return this.customVideoAttachmentConfigurationHandler(attachment);
99124
}
100125

126+
let height = '300px';
101127
let thumbUrl = undefined;
102128
if (attachment.thumb_url && this.shouldGenerateVideoThumbnail) {
103129
const url = new URL(attachment.thumb_url);
104-
this.addResiziParamsToUrl({ width: 600, height: 600 }, url);
130+
const urlParams = url.searchParams;
131+
const originalHeight = Number(urlParams.get('oh')) || 1;
132+
const originalWidth = Number(urlParams.get('ow')) || 1;
133+
const sizeRestriction = this.getSizeRestrictionForFixedWidth(
134+
originalHeight,
135+
originalWidth,
136+
300,
137+
300
138+
);
139+
height = `${sizeRestriction.height}px`;
140+
sizeRestriction.height *= 2;
141+
sizeRestriction.width *= 2;
142+
this.addResiziParamsToUrl(sizeRestriction, url);
105143
thumbUrl = url.href;
106144
}
107145
return {
108146
url: attachment.asset_url || '',
109147
width: '100%', // Set from CSS
110-
height: '100%',
148+
height,
111149
thumbUrl: thumbUrl,
112150
};
113151
}
@@ -151,35 +189,47 @@ export class AttachmentConfigurationService<
151189
}
152190

153191
private addResiziParamsToUrl(
154-
sizeResctriction: { width: number | undefined; height: number | undefined },
192+
sizeRestriction: { width: number; height: number },
155193
url: URL
156194
) {
157-
const urlParams = url.searchParams;
158-
const originalHeight = Number(urlParams.get('oh')) || 1;
159-
const originalWidth = Number(urlParams.get('ow')) || 1;
160-
161-
const h = sizeResctriction.height
162-
? Math.round(
163-
Math.max(
164-
sizeResctriction.height,
165-
((sizeResctriction.width || 1) / originalWidth) * originalHeight
166-
)
167-
).toString()
168-
: undefined;
169-
const w = sizeResctriction.width
170-
? Math.round(
171-
Math.max(
172-
sizeResctriction.width,
173-
((sizeResctriction.height || 1) / originalHeight) * originalWidth
174-
)
175-
).toString()
176-
: undefined;
195+
url.searchParams.append('h', sizeRestriction.height.toString());
196+
url.searchParams.append('w', sizeRestriction.width.toString());
197+
}
177198

178-
if (h) {
179-
url.searchParams.append('h', h);
180-
}
181-
if (w) {
182-
url.searchParams.append('w', w);
199+
private getSizeRestrictionForFixedWidth(
200+
originalHeight: number,
201+
originalWidth: number,
202+
maxHeight: number,
203+
width: number
204+
) {
205+
if (originalHeight && originalWidth) {
206+
return {
207+
width,
208+
height: Math.round(
209+
Math.min(maxHeight, (width / originalWidth) * originalHeight)
210+
),
211+
};
212+
} else {
213+
return this.getSizeRestrictionForFixedAspectRatio(
214+
1,
215+
1,
216+
Math.max(maxHeight, width)
217+
);
183218
}
184219
}
220+
221+
private getSizeRestrictionForFixedAspectRatio(
222+
originalHeight: number,
223+
originalWidth: number,
224+
maxSize: number
225+
) {
226+
return {
227+
height: Math.round(
228+
Math.max(maxSize, (maxSize / originalWidth) * originalHeight)
229+
),
230+
width: Math.round(
231+
Math.max(maxSize, (maxSize / originalHeight) * originalWidth)
232+
),
233+
};
234+
}
185235
}

projects/stream-chat-angular/src/lib/attachment-list/attachment-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
data-testclass="attachment-container"
77
class="str-chat__message-attachment str-chat__message-attachment--{{
88
attachment.type
9-
}}"
9+
}} str-chat__message-attachment-dynamic-size"
1010
[class.str-chat__message-attachment--card]="isCard(attachment)"
1111
[class.str-chat-angular__message-attachment-file-single]="
1212
isFile(attachment)

0 commit comments

Comments
 (0)