diff --git a/frontend/src/assets/main.css b/frontend/src/assets/main.css index d94ee08..d61c226 100644 --- a/frontend/src/assets/main.css +++ b/frontend/src/assets/main.css @@ -6409,6 +6409,62 @@ button { backdrop-filter: blur(32px) saturate(180%); -webkit-backdrop-filter: blur(32px) saturate(180%); } +.messages-media-picker-sheet { + z-index: 90; + --sky-overlay-backdrop: rgb(0 0 0 / 34%); + --sky-sheet-background: rgb(247 247 251 / 96%); +} +.messages-media-picker-sheet .sky-sheet__panel { + height: min(62%, 480px); + max-height: 78%; + overflow: hidden; + display: flex; + flex-direction: column; + border: 1px solid rgb(255 255 255 / 76%); + border-bottom: 0; + border-radius: 30px 30px 0 0; + background: var(--sky-sheet-background); + box-shadow: 0 -14px 38px rgb(20 26 43 / 18%); + backdrop-filter: blur(34px) saturate(180%); + -webkit-backdrop-filter: blur(34px) saturate(180%); +} +.messages-media-picker-sheet .sky-sheet__grabber { + flex: none; + height: 27px; +} +.messages-media-picker-sheet .messages-media-picker { + position: relative; + z-index: auto; + inset: auto; + width: 100%; + height: auto; + min-height: 0; + flex: 1; + border: 0; + background: transparent; + box-shadow: none; + animation: none; + backdrop-filter: none; + -webkit-backdrop-filter: none; +} +.messages-media-picker-sheet .messages-media-picker > header { + height: 44px; + padding: 0 18px 0 20px; + border-color: rgb(60 60 67 / 14%); +} +.messages-media-picker-sheet .messages-media-picker > header strong { + font-size: 16px; + line-height: 20px; +} +.messages-media-picker-sheet .messages-media-picker__contacts, +.messages-media-picker-sheet .messages-media-picker__gifs { + height: calc(100% - 44px); + padding-bottom: calc(var(--sky-safe-area-bottom) + 10px); + overscroll-behavior: contain; +} +.messages-media-picker-sheet .messages-media-picker__contacts { + padding-top: 6px; +} .messages-media-picker__photos, .messages-media-picker__gifs, .messages-media-picker__videos { @@ -6768,6 +6824,14 @@ button { box-shadow: 0 -10px 34px rgb(0 0 0 / 38%); color: #f5f5f7; } +.phone-app.dark .messages-media-picker-sheet { + --sky-overlay-backdrop: rgb(0 0 0 / 52%); + --sky-sheet-background: rgb(28 28 30 / 96%); +} +.phone-app.dark .messages-media-picker-sheet .sky-sheet__panel { + border-color: rgb(255 255 255 / 11%); + box-shadow: 0 -16px 42px rgb(0 0 0 / 46%); +} .phone-app.dark .messages-gif-search, .phone-app.dark .messages-full-emoji-picker__search, .phone-app.dark .messages-full-emoji-picker > header button, diff --git a/frontend/src/views/apps/MessagesApp.contract.test.ts b/frontend/src/views/apps/MessagesApp.contract.test.ts index c490cb0..d3334da 100644 --- a/frontend/src/views/apps/MessagesApp.contract.test.ts +++ b/frontend/src/views/apps/MessagesApp.contract.test.ts @@ -6,6 +6,10 @@ const source = readFileSync( new URL('./MessagesApp.vue', import.meta.url), 'utf8', ) +const styles = readFileSync( + new URL('../../assets/main.css', import.meta.url), + 'utf8', +) describe('MessagesApp Sky UI contract', () => { it('uses first-party Sky UI without direct Konsta markup', () => { @@ -22,6 +26,7 @@ describe('MessagesApp Sky UI contract', () => { expect(source).toContain(' { ) }) + it('opens contact sharing in a draggable Sky UI bottom sheet', () => { + const sheetStart = source.indexOf('class="messages-media-picker-sheet"') + const sheetEnd = source.indexOf('', sheetStart) + const sheet = source.slice(sheetStart, sheetEnd) + + expect(sheetStart).toBeGreaterThan(-1) + expect(sheetEnd).toBeGreaterThan(sheetStart) + expect(sheet).toContain( + ':opened="activeCanMessage && attachmentPicker !== null"', + ) + expect(sheet).toContain('swipe-to-close') + expect(sheet).toContain('grabber-clickable') + expect(sheet).toContain('@backdropclick="closeAttachmentPicker"') + expect(sheet).toContain('@escape="closeAttachmentPicker"') + expect(sheet).toContain('@grabberclick="closeAttachmentPicker"') + expect(sheet).toContain('@swipeclose="closeAttachmentPicker"') + expect(sheet).toContain('v-if="attachmentPicker === \'contacts\'"') + expect(sheet).toContain('@click="sendContact(contact)"') + expect(source).toContain('function closeAttachmentPicker(): void') + expect(styles).toMatch( + /\.messages-media-picker-sheet \.sky-sheet__panel\s*\{[^}]*border-radius:\s*30px 30px 0 0/s, + ) + }) + it('uses a surface back target in the thread and a compact recipient row', () => { const threadStart = source.indexOf( 'class="messages-sky-page messages-sky-thread"', @@ -278,10 +307,7 @@ describe('MessagesApp Sky UI contract', () => { ) const contactProfile = source.slice(contactProfileStart, threadScrollStart) const blockDialogOpened = source.indexOf(':opened="blockDialogOpened"') - const blockDialogStart = source.lastIndexOf( - ' { -
-
- - {{ - phone.t( - attachmentPicker === 'contacts' - ? 'Apps.messages.contacts' - : 'Apps.messages.gifs', - ) - }} - - - {{ phone.t('Common.done') }} - -
- - + + {{ + phone.t( + attachmentPicker === 'contacts' + ? 'Apps.messages.contacts' + : 'Apps.messages.gifs', + ) + }} + + + {{ phone.t('Common.done') }} + + + - - -

- {{ phone.t('Apps.messages.noContactsToShare') }} -

-
-
- - - -
- - {{ errorText(gifError) }} - + +
+ + {{ errorText(gifError) }} + +
+
- -
-
+ +