diff --git a/src/components/notification-group/notification-group.ts b/src/components/notification-group/notification-group.ts index febe22a..30d4019 100644 --- a/src/components/notification-group/notification-group.ts +++ b/src/components/notification-group/notification-group.ts @@ -95,7 +95,10 @@ export class StarNotificationGroup extends LitElement { if (slotLen == 1) { // group中只有一条消息,应该转为'one-notification'类型,并折叠 this.setAttribute('show', 'false') - firstChild.setAttribute('notificationType', 'one-notification') + firstChild.setAttribute( + 'notificationType', + 'group-with-one-notification' + ) firstChild.withArrowUp = false firstChild.removeEventListener('notification-tap', allNotificationshown) } else if (slotLen > 1) { @@ -165,7 +168,6 @@ export class StarNotificationGroup extends LitElement { } let isShow = this.getAttribute('show') == 'true' - console.log('hellowq allNotificationshown isShow: ', isShow) if (isShow) { // 当前是展开状态,点击需折叠 let self = this @@ -178,6 +180,7 @@ export class StarNotificationGroup extends LitElement { element.addEventListener('animationend', function tEnd() { if (index == self.slotElements.length - 1) { self.setAttribute('show', 'false') + self.dispatchEventFurther() } ;(element as StarNotification).classList.remove('animation-out') element.removeEventListener('animationend', tEnd) @@ -186,6 +189,7 @@ export class StarNotificationGroup extends LitElement { }) } else { this.setAttribute('show', 'true') + this.dispatchEventFurther() this.slotElements.forEach((element) => { if (element !== firstChild) { ;(element as StarNotification).classList.add('animation-in') @@ -201,6 +205,15 @@ export class StarNotificationGroup extends LitElement { } } + dispatchEventFurther() { + this.dispatchEvent( + new CustomEvent('notification-group-tap', { + bubbles: true, + composed: true, + }) + ) + } + disappearing(callback?: Function) { this.classList.add('disappearing') let self = this @@ -231,6 +244,7 @@ export class StarNotificationGroup extends LitElement { element.addEventListener('animationend', function tEnd() { if (index == self.slotElements.length - 1) { self.setAttribute('show', 'false') + self.preventDefaultBehavior(true) } ;(element as StarNotification).classList.remove('animation-out') element.removeEventListener('animationend', tEnd) @@ -240,11 +254,17 @@ export class StarNotificationGroup extends LitElement { } } + preventDefaultBehavior(isPrevent: boolean) { + ;(this.slotElements as StarNotification[]).forEach((element) => { + element.isPrevent = isPrevent + }) + } + static styles = css` :host { display: block; - margin-top: 0.83vh; - border-radius: 1.7vw; + margin-top: var(--auto-16px); + border-radius: var(--auto-20px); } :host([show='false']) ::slotted(*) { diff --git a/src/components/notification/notification.ts b/src/components/notification/notification.ts index 9b57c09..36e2d3c 100644 --- a/src/components/notification/notification.ts +++ b/src/components/notification/notification.ts @@ -8,13 +8,17 @@ import { } from 'lit/decorators.js' import {sharedStyles} from './notificationstyle.js' import {StarBaseElement} from '@star-web-components/base' -// ONE : 单条通知,notification-group展开时第一条notification类型 +// ONE : 单条通知 // MORE : notification-group中除第一条以外的notification类型 // MORE_FIRST: notification-group折叠时第一条notification类型 +// GROUP_ONE: notification-group展开时第一条notification类型 +// BLUETOOTH_TRANSFER: 蓝牙文件传输(进度条) export enum NotificationType { ONE = 'one-notification', MORE = 'more-notifiactions', MORE_FIRST = 'more-notifiactions-first', + GROUP_ONE = 'group-with-one-notification', + BLUETOOTH_TRANSFER = 'bluetooth-transfer', } // TOP_BORDER_RADIUS 对应notification-group展开时第一条notification,仅上边有圆角 @@ -54,13 +58,18 @@ export class StarNotification extends StarBaseElement { // 消息通知toast @property({type: Boolean}) isToast = false @property({type: Boolean}) btnShown = false + @property({type: Boolean}) isPrevent = true @property({type: String}) moveDirection = '' @property({type: Number}) notificationPosition = 0 @property({type: Number}) width = 0 @property({type: Number}) widthleft = 0 @property({type: Number}) velocityThreshold = 0.8 + @property({type: String}) transferMode = '' + @property({type: Number}) value = 0 + @property({type: String}) data_id = '' + @property({type: String}) transferDescription = '' @query('.notification') notification!: HTMLDivElement - @query('.btn-tool') btnTool!: HTMLDivElement + @query('.btn-tool-wrapper') btnTool!: HTMLDivElement @query('.arrow-up') arrowUp!: HTMLElement @state() touchAction = { // 触摸开始落点 @@ -114,9 +123,12 @@ export class StarNotification extends StarBaseElement { switch (this.notificationType) { case NotificationType.ONE: case NotificationType.MORE: + case NotificationType.GROUP_ONE: return this.getone() case NotificationType.MORE_FIRST: return this.getmorefirst() + case NotificationType.BLUETOOTH_TRANSFER: + return this.getbluetoothtransfer() default: console.error('unhandled 【star-notification】 type') return nothing @@ -151,16 +163,19 @@ export class StarNotification extends StarBaseElement { ` : nothing - const deleteShow = this.noclear - ? html` - - ` - : nothing + const deleteShow = + this.noclear == true + ? html` +
+
+
+ ` + : html` +
+
+
+
+ ` // "more-notifiactions"用于notification-group中的第二条及以后的notification, // 中间位置notification没有圆角(radiusType为""),最底部的radiusType为bottom-border-radius. @@ -198,11 +213,7 @@ export class StarNotification extends StarBaseElement { ${arrowShow} -
-
-
- ${deleteShow} -
+ ${deleteShow} ` } else { @@ -282,16 +293,19 @@ export class StarNotification extends StarBaseElement { // } this.timestamp ? new Date(this.timestamp) : new Date() - const deleteShow = this.noclear - ? html` - - ` - : nothing + const deleteShow = + this.noclear == true + ? html` +
+ + ` + : html` +
+
+
+
+ ` return html`
${this.count}
-
-
-
- ${deleteShow} + ${deleteShow} +
+ ` + } + + getbluetoothtransfer(): HTMLTemplateResult | typeof nothing { + return html` +
+
+ +
${this.title}
+ +
+ ${this.transferDescription} + + ${Math.round(this.value * 100)}% + +
` } @eventOptions({passive: false}) - handleEvent(event: TouchEvent) { + handleEvent(event: any) { let self = this + let deleteBtn: HTMLElement + let settingsBtn: HTMLElement if (!this.isToast) { + if (this.noclear == false) { + deleteBtn = this.btnTool.children[0] as HTMLElement + settingsBtn = this.btnTool.children[1] as HTMLElement + } else { + settingsBtn = this.btnTool.children[0] as HTMLElement + } + switch (event.type) { case 'touchstart': this.touchAction.start.clientX = event.touches[0].clientX @@ -342,78 +383,64 @@ export class StarNotification extends StarBaseElement { this.btnTool.style.visibility = 'visiable' break case 'touchmove': + if (!this.isPrevent) { + return + } event.preventDefault() - let deleteBtn = this.btnTool.children[0] as HTMLElement - let settingsBtn = this.btnTool.children[1] as HTMLElement - this.touchAction.last.clientX = event.touches[0].clientX - this.touchAction.last.timeStamp = event.timeStamp + break + case 'swipeleft': + this.touchAction.last.clientX = event.detail.endTouch.clientX let touchPosX = this.touchAction.last.clientX - this.touchAction.start.clientX - let time = - this.touchAction.last.timeStamp - this.touchAction.start.timeStamp - let velocityThreshold = Math.abs(touchPosX) / time - if (touchPosX < 0) { - let translateX = this.notificationPosition * 0.309 - let quickRemove = - !this.btnShown && - Math.abs(touchPosX) > 1.5 * translateX && - velocityThreshold > this.velocityThreshold - if (quickRemove || this.btnShown) { - if (quickRemove) { - // 直接删除消息 - this.notification.style.transform = - 'translateX(-' + this.notificationPosition + 'px)' - } - - if (this.btnShown) { - this.btnShown = false - } - - if (!this.noclear) { - this.dispatchEvent( - new CustomEvent('notification-delete', { - detail: { - id: this.id, - notification: this, - }, - bubbles: true, - composed: true, - }) - ) - } - return + let velocityThreshold = event.detail.velocity + // if (touchPosX < 0) { + let translateX = this.notificationPosition * 0.309 + let quickRemove = + !this.btnShown && + Math.abs(touchPosX) > 1.5 * translateX && + velocityThreshold > this.velocityThreshold + if (quickRemove || this.btnShown) { + if (quickRemove) { + // 直接删除消息 + this.notification.style.transform = + 'translateX(-' + this.notificationPosition + 'px)' } - this.notification.style.transform = 'translateX(-30.9%)' - let self = this - this.notification.addEventListener( - 'transitionend', - function tranEnd() { - self.notification.removeEventListener('transitionend', tranEnd) - if (!self.noclear) { - deleteBtn.style.visibility = 'visible' - deleteBtn.style.opacity = '1' - } - settingsBtn.style.visibility = 'visible' - settingsBtn.style.opacity = '1' - self.btnShown = true - } - ) - this.widthleft = this.width - translateX - this.moveDirection = 'left' - } else if (touchPosX > 0) { - this.notification.style.transform = 'translateX(' + 0 + 'px)' - let tranEnd = () => { - this.notification.removeEventListener('transitionend', tranEnd) - if (!this.noclear) { - deleteBtn.style.visibility = 'hidden' - } - settingsBtn.style.visibility = 'hidden' + if (this.btnShown) { this.btnShown = false } - this.notification.addEventListener('transitionend', tranEnd) - this.moveDirection = 'right' + + if (this.noclear == false) { + this.dispatchEvent( + new CustomEvent('notification-delete', { + detail: { + id: this.id, + notification: this, + }, + bubbles: true, + composed: true, + }) + ) + } + return } + + this.notification.style.transform = 'translateX(-30.9%)' + this.notification.addEventListener( + 'transitionend', + function tranEnd() { + self.notification.removeEventListener('transitionend', tranEnd) + if (self.noclear == false) { + deleteBtn.style.visibility = 'visible' + deleteBtn.style.opacity = '1' + } + settingsBtn.style.visibility = 'visible' + settingsBtn.style.opacity = '1' + self.btnShown = true + } + ) + this.widthleft = this.width - translateX + this.moveDirection = 'left' this.dispatchEvent( new CustomEvent('notification-touchmove', { detail: { @@ -425,7 +452,19 @@ export class StarNotification extends StarBaseElement { }) ) break - case 'touchend': + case 'swiperight': + event.preventDefault() + this.notification.style.transform = 'translateX(' + 0 + 'px)' + let tranEnd = () => { + this.notification.removeEventListener('transitionend', tranEnd) + if (this.noclear == false) { + deleteBtn.style.visibility = 'hidden' + } + settingsBtn.style.visibility = 'hidden' + this.btnShown = false + } + this.notification.addEventListener('transitionend', tranEnd) + this.moveDirection = 'right' break case 'click': event.stopPropagation() @@ -443,7 +482,7 @@ export class StarNotification extends StarBaseElement { target.addEventListener('transitionend', function tranEnd() { target.removeEventListener('transitionend', tranEnd) target.removeAttribute('clicked') - if (!self.noclear) { + if (self.noclear == false) { self.dispatchEvent( new CustomEvent('notification-delete', { detail: { @@ -566,12 +605,16 @@ export class StarNotification extends StarBaseElement { } this.notification.style.transform = 'translateX(0px)' - let deleteBtn = this.btnTool.children[0] as HTMLElement - let settingsBtn = this.btnTool.children[1] as HTMLElement + let deleteBtn + let settingsBtn // let tranEnd = () => { // this.notification.removeEventListener('transitionend', tranEnd) - if (!this.noclear) { + if (this.noclear == false) { + deleteBtn = this.btnTool.children[0] as HTMLElement + settingsBtn = this.btnTool.children[1] as HTMLElement deleteBtn.style.visibility = 'hidden' + } else { + settingsBtn = this.btnTool.children[0] as HTMLElement } settingsBtn.style.visibility = 'hidden' this.btnShown = false @@ -580,7 +623,7 @@ export class StarNotification extends StarBaseElement { // this.notification.addEventListener('transitionend', tranEnd) } - public static override get styles(): CSSResultArray { + static override get styles(): CSSResultArray { return [sharedStyles] } } diff --git a/src/components/notification/notificationstyle.ts b/src/components/notification/notificationstyle.ts index 33e06ac..f4d4470 100644 --- a/src/components/notification/notificationstyle.ts +++ b/src/components/notification/notificationstyle.ts @@ -22,19 +22,24 @@ export const sharedStyles: CSSResult = css` --more-text-color-lm: rgba(64, 64, 64, 0.65); --more-text-color-dm: rgba(224, 224, 224, 1); - width: 71.7vw; - height: 7.9vh; + // width: 71.7vw; + // height: 7.9vh; + width: calc(860px / var(--hostDevicePixelRatio)); + height: var(--auto-152px); display: block; position: relative; left: 0; top: 0; } - :host([notificationType='one-notification']) { - // margin: 5px 0 0 0; + :host([notificationType='bluetooth-transfer']) { + height: calc(194px / var(--hostDevicePixelRatio)); + margin: var(--auto-16px); + } - // margin: 16px 0 0 0; + :host([notificationType='one-notification']) { margin: 0.8vh 0 0 0; + margin-top: var(--auto-16px); } .notification { @@ -61,25 +66,23 @@ export const sharedStyles: CSSResult = css` } .top-border-radius { - // border-top-left-radius: 20px; - // border-top-right-radius: 20px; + // border-top-left-radius: 1.7vw; + // border-top-right-radius: 1.7vw; - border-top-left-radius: 1.7vw; - border-top-right-radius: 1.7vw; + border-top-left-radius: var(--auto-20px); + border-top-right-radius: var(--auto-20px); } .bottom-border-radius { - // border-bottom-left-radius: 20px; - // border-bottom-right-radius: 20px; - - border-bottom-left-radius: 1.7vw; - border-bottom-right-radius: 1.7vw; + // border-bottom-left-radius: 1.7vw; + // border-bottom-right-radius: 1.7vw; + border-bottom-left-radius: var(--auto-20px); + border-bottom-right-radius: var(--auto-20px); } .border-radius { - // border-radius: 20px; - - border-radius: 1.7vw; + // border-radius: 1.7vw; + border-radius: var(--auto-20px); } .notification > img { @@ -88,8 +91,10 @@ export const sharedStyles: CSSResult = css` // pointer-events: none; // margin: 26px 10px 78px 26px; - width: 4vw; - height: 4vw; + // width: 4vw; + // height: 4vw; + width: var(--auto-48px); + height: var(--auto-48px); position: absolute; top: 17.1%; left: 3%; @@ -99,11 +104,6 @@ export const sharedStyles: CSSResult = css` .notification > div.title-container { display: flex; position: absolute; - - // width: calc(100% - 28px); - // left: 28px; - // top: 23.7%; - font-family: 'OPPOSans'; font-style: normal; width: 90.2%; @@ -125,7 +125,8 @@ export const sharedStyles: CSSResult = css` // font-size: 28px; line-height: 1; - font-size: 2.3vw; + // font-size: 2.3vw; + font-size: var(--auto-28px); } .notification > div.title-container .timestamp { @@ -147,24 +148,19 @@ export const sharedStyles: CSSResult = css` // font-size: 24px; // line-height: 32px; - right: 10.67px; - top: -1.33px; - font-size: 2vw; + // right: 10.67px; + // top: -1.33px; + // font-size: 2vw; line-height: 1; - right: 3.7%; + // right: 3.7%; top: -2.6%; - top: -0.2vh; - right: 2.6vw; + font-size: var(--auto-24px); + right: var(--auto-32px); } .notification > div.detail { display: flex; position: absolute; - - // width: calc(100% - 84px); - // left: 84px; - // top: 84px; - width: 90.2%; left: 9.8%; top: 55%; @@ -182,8 +178,10 @@ export const sharedStyles: CSSResult = css` font-weight: 400; mix-blend-mode: normal; opacity: 0.65; - font-size: 2.2vw; + // font-size: 2.2vw; + font-size: var(--auto-26px); + max-width: var(--auro-640px); // width: 246px; // height: 11px; // font-size: 8px; @@ -204,15 +202,19 @@ export const sharedStyles: CSSResult = css` // line-height: 34px; // border-radius: 189px; - height: 1.8vh; - width: 4.7vw; + // height: 1.8vh; + // width: 4.7vw; right: 3%; bottom: 19.7%; - border-radius: 15.75vw; + // border-radius: 15.75vw; text-align: center; vertical-align: middle; line-height: 1; + + height: var(--auto-34px); + width: var(--auto-56px); + border-radius: calc(189px / var(--hostDevicePixelRatio)); } .notification > div.detail .arrow-up::after { @@ -228,6 +230,10 @@ export const sharedStyles: CSSResult = css` width: 1.33vw; height: 1.33vw; + + width: var(--auto-16px); + height: var(--auto-16px); + font-size: var(--auto-16px); } .one, @@ -239,7 +245,8 @@ export const sharedStyles: CSSResult = css` overflow: hidden; } - .btn-tool { + .btn-tool, + .btn-tool-only-settings { display: flex; align-items: center; position: absolute; @@ -247,48 +254,46 @@ export const sharedStyles: CSSResult = css` visibility: hidden; // right: 18px; - - // right: 6px; - right: 2.1%; } - .btn-tool > div { + .btn-tool-only-settings { + right: var(--auto-140px); + } + + .btn-tool > div, + .btn-tool-only-settings > div { display: flex; align-items: center; justify-content: center; border-radius: 50%; opacity: 0.6; transition: transform 0.1s; - - // width: 80px; - // height: 80px; - width: 6.7vw; height: 6.7vw; + + width: var(--auto-80px); + height: var(--auto-80px); } .btn-tool > div:first-child { - // margin-right: 15px; - // visibility: hidden; - - // margin-right: 44px; - // visibility: hidden; - - margin-right: 5.1%; - margin-right: 3.7vw; + // margin-right: 3.7vw; + margin-right: calc(44px / var(--hostDevicePixelRatio)); visibility: hidden; } - .btn-tool > div:last-child { + .btn-tool > div:last-child, + .btn-tool-only-settings > div { visibility: hidden; } - .btn-tool > div[clicked] { + .btn-tool > div[clicked], + .btn-tool-only-settings > div[clicked] { transform: scale(0.9); } - .btn-tool > div::after { + .btn-tool > div::after, + .btn-tool-only-settings > div::after { text-align: center; vertical-align: middle; content: attr(data-icon); @@ -304,7 +309,8 @@ export const sharedStyles: CSSResult = css` width: 40%; height: 40%; - font-size: 2.7vw; + // font-size: 2.7vw; + font-size: var(--auto-32px); } .container { @@ -331,8 +337,9 @@ export const sharedStyles: CSSResult = css` height: 18.4%; line-height: 1; - font-size: 1.45vh; - font-size: 2.3vw; + // font-size: 1.45vh; + // font-size: 2.3vw; + font-size: var(--auto-28px); } .container .detail-content { @@ -354,10 +361,11 @@ export const sharedStyles: CSSResult = css` // font-size: 26px; left: 0.93%; - top: -3px; + // top: -3px; top: -2%; - top: -0.16vh; - font-size: 1.35vh; + // top: -0.16vh; + // font-size: 1.35vh; + font-size: var(--auto-26px); } .one-container { @@ -390,11 +398,13 @@ export const sharedStyles: CSSResult = css` // font-size: 8px; // line-height: 11px; - height: 1.8vh; + // height: 1.8vh; + height: var(--auto-34px); right: 4%; top: -0.2vh; line-height: 1.7vh; - font-size: 2vw; + // font-size: 2vw; + font-size: var(--auto-24px); } .another-container .notification-counts { @@ -412,26 +422,104 @@ export const sharedStyles: CSSResult = css` // font-size: 20px; // border-radius: 189px; - // width: 18px; - // height: 11px; - // right: 8px; - // bottom: 10px; - // top: -1px; - // line-height: 11px; - // font-size: 7px; - // border-radius: 63px; + // width: 4.7vw; + // height: 1.8vh; + // right: 3%; + // bottom: 19.7%; + // border-radius: 15.75vw; + // top: -0.08vw; + // font-size: 1.7vw; + // line-height: 1.8vh; - width: 4.7vw; - height: 1.8vh; + width: var(--auto-56px); + height: var(--auto-34px); right: 3%; bottom: 19.7%; - border-radius: 15.75vw; + border-radius: calc(189px / var(--hostDevicePixelRatio)); top: -0.08vw; - font-size: 1.7vw; - line-height: 1.8vh; + font-size: var(--auto-20px); + line-height: var(--auto-34px); vertical-align: middle; } + .bluetooth-title { + height: var(--auto-28px); + position: absolute; + left: calc(84px / var(--hostDevicePixelRatio)); + top: var(--auto-36px); + + font-family: 'OPPOSans'; + font-style: normal; + font-weight: 400; + font-size: var(--auto-28px); + line-height: var(--auto-28px); + color: var(--title-color-lm); + } + + [data-icon='bluetooth-transfer-circle'] { + width: var(--auto-48px); + height: var(--auto-48px); + position: absolute; + left: var(--auto-26px); + top: var(--auto-26px); + } + + [data-icon='bluetooth-transfer-circle']::after { + text-align: center; + vertical-align: middle; + content: attr(data-icon); + font-family: 'gaia-icons'; + font-style: normal; + font-size: var(--auto-48px); + text-rendering: optimizelegibility; + font-weight: 500; + } + + progress { + width: calc(700px / var(--hostDevicePixelRatio)); + height: var(--auto-12px); + position: absolute; + left: calc(84px / var(--hostDevicePixelRatio)); + top: var(--auto-100px); + background: rgba(38, 38, 38, 0.04); + border-radius: var(--auto-10px); + } + + progress::-moz-progress-bar, + progress::-webkit-progress-bar { + background-color: #0e92f0; + border-radius: var(--auto-10px); + } + + .transfer-detail > #description { + height: var(--auto-34px); + position: absolute; + left: calc(84px / var(--hostDevicePixelRatio)); + top: calc(127px / var(--hostDevicePixelRatio)); + + font-family: 'OPPOSans'; + font-style: normal; + font-weight: 400; + font-size: var(--auto-26px); + line-height: var(--auto-34px); + mix-blend-mode: normal; + } + + #transfer-precentage { + height: var(--auto-32px); + right: var(--auto-76px); + position: absolute; + top: var(--auto-129px); + font-family: 'OPPOSans'; + font-style: normal; + font-weight: 400; + font-size: var(--auto-24px); + line-height: var(--auto-32px); + text-align: right; + mix-blend-mode: normal; + opacity: 0.65; + } + @media (prefers-color-scheme: light) { .notification { background: var(--notification-background-lm); @@ -453,19 +541,22 @@ export const sharedStyles: CSSResult = css` background: var(--arrow-background-lm); } - .btn-tool > div { + .btn-tool-wrapper > div { background: var(--button-background-color-lm); } - .btn-tool > div::after { + .btn-tool-wrapper > div::after { color: var(--button-color-lm); } - .container .title { + .container .title, + .bluetooth-title, + #transfer-precentage { color: var(--title-color-lm); } - .container .detail-content { + .container .detail-content, + .transfer-detail > #description { color: var(--more-text-color-lm); } @@ -488,11 +579,11 @@ export const sharedStyles: CSSResult = css` background: var(--arrow-background-dm); } - .btn-tool > div { + .btn-tool-wrapper > div { background: var(--button-background-color-dm); } - .btn-tool > div::after { + .btn-tool-wrapper > div::after { color: var(--button-color-dm); } @@ -502,7 +593,9 @@ export const sharedStyles: CSSResult = css` } .container .title, - .notification > div.title-container .title { + .notification > div.title-container .title, + .bluetooth-title, + #transfer-precentage { color: var(--title-color-dm); } @@ -514,7 +607,8 @@ export const sharedStyles: CSSResult = css` color: var(--single-text-color-dm); } - .container .detail-content { + .container .detail-content, + .transfer-detail > #description { color: var(--more-text-color-dm); } diff --git a/src/test/panels/notification/notification.ts b/src/test/panels/notification/notification.ts index 4bb5d7a..20b4a51 100644 --- a/src/test/panels/notification/notification.ts +++ b/src/test/panels/notification/notification.ts @@ -52,6 +52,9 @@ export class PanelNotifiaciton extends LitElement { render() { return html`
+