FIX - correct messages GIF picker layout

This commit is contained in:
smx.pusha
2026-08-20 12:52:14 +02:00
parent a24cda989a
commit c2fe8b5e23
4 changed files with 99 additions and 23 deletions
+45 -1
View File
@@ -6615,9 +6615,47 @@ button {
display: block;
object-fit: contain;
}
.messages-media-picker__gifs--masonry {
display: flex;
flex-direction: column;
align-items: stretch;
gap: 10px;
}
.messages-gif-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
align-items: start;
gap: 8px;
}
.messages-gif-column {
min-width: 0;
display: grid;
align-content: start;
gap: 8px;
}
.messages-media-picker__gifs--masonry .messages-gif-result {
width: 100%;
min-height: 0;
display: block;
overflow: hidden;
border: 1px solid rgb(60 60 67 / 10%);
border-radius: 12px;
background: var(--sky-surface-muted);
box-shadow: none;
}
.messages-media-picker__gifs--masonry .messages-gif-result img {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
}
.messages-media-picker__gifs .messages-gif-more {
width: 100%;
min-height: 36px;
grid-column: 1 / -1;
flex: 0 0 auto;
border: 0;
background: transparent;
box-shadow: none;
color: var(--ios-blue);
font-size: 12px;
font-weight: 650;
@@ -6939,6 +6977,12 @@ button {
.phone-app.dark .messages-media-picker__gifs button {
background: #2c2c2e;
}
.phone-app.dark
.messages-media-picker__gifs--masonry
.messages-gif-result {
border-color: rgb(255 255 255 / 10%);
background: var(--sky-surface-muted);
}
.phone-app.dark .messages-media-picker__gifs .messages-gif-more,
.phone-app.dark .messages-media-picker__gifs .messages-gif-error button {
background: rgb(10 132 255 / 20%);
@@ -186,6 +186,13 @@ describe('MessagesApp Sky UI contract', () => {
expect(source).toContain(
'aspectRatio: `${Math.max(1, gif.width)} / ${Math.max(1, gif.height)}`',
)
expect(source).toContain('const gifColumns = computed')
expect(source).toContain('class="messages-gif-grid"')
expect(source).toContain('class="messages-gif-column"')
expect(source).toContain('class="messages-gif-result"')
expect(styles).toMatch(
/\.messages-media-picker__gifs--masonry \.messages-gif-result img\s*\{[^}]*object-fit:\s*cover/s,
)
})
it('opens contact sharing in a draggable Sky UI bottom sheet', () => {
+38 -13
View File
@@ -126,6 +126,19 @@ const gifLoading = ref(false)
const gifError = ref<string | null>(null)
const gifHasMore = ref(true)
const gifNextOffset = ref(0)
const gifColumns = computed<[GifSearchResult[], GifSearchResult[]]>(() => {
const columns: [GifSearchResult[], GifSearchResult[]] = [[], []]
const columnHeights = [0, 0]
for (const gif of gifResults.value) {
const columnIndex = columnHeights[0] <= columnHeights[1] ? 0 : 1
columns[columnIndex].push(gif)
columnHeights[columnIndex] +=
Math.max(1, gif.height) / Math.max(1, gif.width)
}
return columns
})
const recording = ref(false)
const recordingStarting = ref(false)
const recordingElapsedMs = ref(0)
@@ -1714,7 +1727,10 @@ onBeforeUnmount(() => {
{{ phone.t('Apps.messages.noContactsToShare') }}
</p>
</SkyList>
<div v-else class="messages-media-picker__gifs">
<div
v-else
class="messages-media-picker__gifs messages-media-picker__gifs--masonry"
>
<SkySearchbar
v-model="gifQuery"
class="messages-gif-search"
@@ -1724,18 +1740,27 @@ onBeforeUnmount(() => {
@input="queueGifSearch"
@clear="queueGifSearch"
/>
<button
v-for="gif in gifResults"
:key="gif.id"
type="button"
:aria-label="gif.title"
:style="{
aspectRatio: `${Math.max(1, gif.width)} / ${Math.max(1, gif.height)}`,
}"
@click="sendAttachment('gif', gif.url)"
>
<img :src="gif.previewUrl" :alt="gif.title" loading="lazy" />
</button>
<div v-if="gifResults.length" class="messages-gif-grid">
<div
v-for="(column, columnIndex) in gifColumns"
:key="columnIndex"
class="messages-gif-column"
>
<button
v-for="gif in column"
:key="gif.id"
type="button"
class="messages-gif-result"
:aria-label="gif.title"
:style="{
aspectRatio: `${Math.max(1, gif.width)} / ${Math.max(1, gif.height)}`,
}"
@click="sendAttachment('gif', gif.url)"
>
<img :src="gif.previewUrl" :alt="gif.title" loading="lazy" />
</button>
</div>
</div>
<button
v-if="gifResults.length && gifHasMore && !gifLoading"
type="button"
+9 -9
View File
@@ -2205,12 +2205,12 @@ const attachmentAssets = {
video: new Set(['city-loop', 'ocean-loop', 'sunset-loop']),
}
const gifMocks = [
['ICOgUNjpvO0PC', 'Cat reaction'],
['MDJ9IbxxvDUQM', 'Happy dog'],
['l0HlPystfePnAI3G8', 'Celebrate'],
['26ufdipQqU2lhNA4g', 'Wow'],
['3o7abKhOpu0NwenH3O', 'Perfect'],
['xT0xeJpnrWC4XWblEk', 'Party'],
['JIX9t2j0ZTN9S', 'Cat reaction', 200, 200],
['MDJ9IbxxvDUQM', 'Happy dog', 200, 112],
['l0HlPystfePnAI3G8', 'Celebrate', 200, 200],
['26ufdipQqU2lhNA4g', 'Wow', 200, 200],
['3o7abKhOpu0NwenH3O', 'Perfect', 200, 112],
['xT0xeJpnrWC4XWblEk', 'Party', 200, 132],
['111ebonMs90YLu', 'Thumbs up'],
['5GoVLqeAOo6PK', 'Excited'],
['TdfyKrN7HGTIY', 'Happy dance'],
@@ -9647,13 +9647,13 @@ app.post('/api/:endpoint', (request, response) => {
const pageSize = 6
const results = gifMocks
.slice(offset, offset + pageSize)
.map(([id, title]) => ({
height: 200,
.map(([id, title, width, height]) => ({
height: height ?? 200,
id,
previewUrl: `https://media.giphy.com/media/${id}/200w.gif`,
title,
url: `https://media.giphy.com/media/${id}/giphy.gif`,
width: 200,
width: width ?? 200,
}))
response.json({
success: true,