Merge pull request #213 in YR/star-web-components from notification to master

* commit 'fe7dfc974fe28dc2b12115be7b96e5e65c0cd46b':
  修复第一条通知不显示,通知组展开状态下新增通知没有背景色,左滑样式错误的bug
  BUG: #150442 - 添加消息通知组展开动效
This commit is contained in:
汪昌棋 2022-12-30 16:59:02 +08:00
commit 5f0841e633
3 changed files with 178 additions and 40 deletions

View File

@ -5,24 +5,106 @@ import {
eventOptions,
queryAssignedElements,
} from 'lit/decorators.js'
import {StarNotification} from '../notification/notification.js'
import {StarNotification} from '@star-web-components/notification'
@customElement('star-notification-group')
export class StarNotificationGroup extends LitElement {
_opacity: number = 0
_show: boolean = false
@property({type: Number}) count = 0
@property({type: String}) id = ''
@queryAssignedElements({flatten: true}) slotElements!:
| HTMLSlotElement[]
| StarNotification[]
get show() {
return this._show
}
n = 0
set show(value) {
if (this._show !== value) {
/* 暂时未填加手指按住滑动的控制, 变更show, 即在合并和展开之间二极切换 */
if (value) {
this.addGroupHeight(this._singleHeight * this.children.length)
} else {
this.addGroupHeight(0)
}
this.setAttribute('show', String(value))
this._show = value
}
}
/* 控制单条消息具体内容的透明度 */
set contentOpacity(value: number) {
this._opacity = value
this.style.setProperty('--single-noti-opacity', String(value))
if (value !== 1) {
this.style.setProperty('--single-noti-events', 'none')
} else {
this.style.removeProperty('--single-noti-events')
}
}
get contentOpacity() {
return this._opacity
}
/**
*
*/
set containerHeight(value: number) {
// 通知组DOM的最大高度, 为通知数量个数的高度之和
const maxHeight = this._singleHeight * this.children.length
if (value < (this._singleHeight ?? 0)) {
// 小于单条通知高度时, 移除展开高度的控制, 显示为合并高度
this.style.removeProperty('--expand-height')
return
} else if (value > maxHeight) {
value = maxHeight
}
this.style.setProperty('--expand-height', value + 'px')
}
/* 增加控制通知组容器高度 */
addGroupHeight(value: number) {
// 所有被隐藏的通知的展开动画的将会在滑动一个高度前完成
let ratio = value / this._singleHeight
ratio = ratio > 1 ? 1 : ratio
ratio = ratio < 0 ? 0 : ratio
this.contentOpacity = ratio
this.containerHeight = value
}
_singleHeight!: number
connectedCallback() {
super.connectedCallback()
window.addEventListener('notification-delete', this)
window.addEventListener('notification-touchmove', this)
window.addEventListener('notification-touchmove-right', this)
window.addEventListener('resize', this.resize)
// 用于监控自身高度变化, 用于第一时间设置自身高度
const resizeObserver = new ResizeObserver(() => {
if ((this.children[0] as HTMLElement)?.offsetHeight) {
this.resize()
resizeObserver.unobserve(this)
}
})
resizeObserver.observe(this)
}
resize = () => {
if (this.children.length) {
// 获取单条通知高度, 并作为合并状态时的高度
this._singleHeight = (this.children[0] as StarNotification).offsetHeight
this.style.setProperty('--shrink-height', this._singleHeight + 'px')
} else {
this.addEventListener('slotchange', this.resize, {once: true})
}
}
firstUpdated() {
this.setAttribute('show', 'false')
this.show = false
}
@eventOptions({passive: false})
@ -36,7 +118,7 @@ export class StarNotificationGroup extends LitElement {
;(this.slotElements as StarNotification[]).forEach(
(el: StarNotification) => {
if (!el.noclear) {
if (this.getAttribute('show') == 'false') {
if (!this.show) {
if (el.id == id) {
// 删除某个notification-group
this.dispatchEvent(
@ -62,6 +144,8 @@ export class StarNotificationGroup extends LitElement {
break
// 左滑通知时,对未闭合操作按钮的其它通知进行闭合
case 'notification-touchmove':
this.setAttribute('removeBackground', 'true')
this.style.setProperty('--single-noti-bgc', 'var(--notification-bgc)')
let targetId = (event as any).detail.id
if (this.slotElements.length > 1) {
;(this.slotElements as StarNotification[]).forEach(
@ -73,6 +157,10 @@ export class StarNotificationGroup extends LitElement {
)
}
break
case 'notification-touchmove-right':
this.setAttribute('removeBackground', 'false')
this.style.setProperty('--single-noti-bgc', 'transparent')
break
}
}
@ -94,23 +182,26 @@ export class StarNotificationGroup extends LitElement {
if (slotLen == 1) {
// group中只有一条消息应该转为'one-notification'类型,并折叠
this.setAttribute('show', 'false')
firstChild.setAttribute(
'notificationType',
'group-with-one-notification'
)
this.show = false
this.contentOpacity = 1
firstChild.withArrowUp = false
firstChild.removeEventListener('notification-tap', allNotificationshown)
} else if (slotLen > 1) {
let lastChild = slotElements[slotLen - 1] as StarNotification
if (this.getAttribute('show') == 'true') {
if (this.show) {
// 展开
this.addGroupHeight(this._singleHeight * this.slotElements.length)
firstChild.setAttribute('radiusType', 'top-border-radius')
firstChild.setAttribute('notificationType', 'more-notifiactions')
firstChild.withArrowUp = true
} else {
// 折叠
this.addGroupHeight(0)
firstChild.setAttribute('radiusType', 'border-radius')
firstChild.setAttribute(
'notificationType',
@ -167,10 +258,11 @@ export class StarNotificationGroup extends LitElement {
event.stopImmediatePropagation()
}
let isShow = this.getAttribute('show') == 'true'
let isShow = this.show
if (isShow) {
// 当前是展开状态,点击需折叠
let self = this
this.show = false
firstChild.setAttribute('radiusType', 'border-radius')
firstChild.withArrowUp = false
firstChild.setAttribute('notificationType', 'more-notifiactions-first')
@ -179,7 +271,7 @@ export class StarNotificationGroup extends LitElement {
;(element as StarNotification).classList.add('animation-out')
element.addEventListener('animationend', function tEnd() {
if (index == self.slotElements.length - 1) {
self.setAttribute('show', 'false')
self.show = false
self.dispatchEventFurther()
}
;(element as StarNotification).classList.remove('animation-out')
@ -188,7 +280,7 @@ export class StarNotificationGroup extends LitElement {
}
})
} else {
this.setAttribute('show', 'true')
this.show = true
this.dispatchEventFurther()
this.slotElements.forEach((element) => {
if (element !== firstChild) {
@ -228,7 +320,7 @@ export class StarNotificationGroup extends LitElement {
collapseNotifications() {
let firstChild = this.slotElements[0] as StarNotification
let isShow = this.getAttribute('show') == 'true'
let isShow = this.show
;(this.slotElements as StarNotification[]).forEach((element) => {
element.closeNotificationTools()
})
@ -243,7 +335,7 @@ export class StarNotificationGroup extends LitElement {
;(element as StarNotification).classList.add('animation-out')
element.addEventListener('animationend', function tEnd() {
if (index == self.slotElements.length - 1) {
self.setAttribute('show', 'false')
self.show = false
self.preventDefaultBehavior(true)
}
;(element as StarNotification).classList.remove('animation-out')
@ -264,15 +356,24 @@ export class StarNotificationGroup extends LitElement {
:host {
display: block;
margin-top: var(--auto-16px);
background: var(--notification-bgc);
border-radius: var(--auto-20px);
height: var(--expand-height, var(--shrink-height));
transition: height 0.25s;
--notification-bgc: var(--opacity-white-55);
--single-noti-opacity: 0;
--single-noti-bgc: transparent;
}
:host([show='false']) ::slotted(*) {
display: none;
:host([removeBackground='true']) {
background: unset !important;
}
:host([show='false']) ::slotted(:first-child) {
display: block;
@media (prefers-color-scheme: dark) {
:host {
--notification-bgc: var(--opacity-black-25);
}
}
:host([show='true']) ::slotted(*) {
@ -295,6 +396,10 @@ export class StarNotificationGroup extends LitElement {
animation: disappearing 0.25s cubic-bezier(0.25, 0.1, 0.25, 1);
}
::slotted(*) {
background: transparent;
}
@keyframes disappearing {
0% {
opacity: 1;

View File

@ -296,10 +296,10 @@ export class StarNotification extends StarBaseElement {
const deleteShow =
this.noclear == true
? html`
<div class="btn-tool-wrapper btn-tool-only-settings
<div data-icon="settings" @click=${this}></div>
</div>
`
<div class="btn-tool-wrapper btn-tool-only-settings">
<div data-icon="settings" @click=${this}></div>
</div>
`
: html`
<div class="btn-tool-wrapper btn-tool">
<div data-icon="delete" @click=${this}></div>
@ -389,6 +389,7 @@ export class StarNotification extends StarBaseElement {
event.preventDefault()
break
case 'swipeleft':
event.stopPropagation()
this.touchAction.last.clientX = event.detail.endTouch.clientX
let touchPosX =
this.touchAction.last.clientX - this.touchAction.start.clientX
@ -454,6 +455,7 @@ export class StarNotification extends StarBaseElement {
break
case 'swiperight':
event.preventDefault()
event.stopPropagation()
this.notification.style.transform = 'translateX(' + 0 + 'px)'
let tranEnd = () => {
this.notification.removeEventListener('transitionend', tranEnd)
@ -465,6 +467,16 @@ export class StarNotification extends StarBaseElement {
}
this.notification.addEventListener('transitionend', tranEnd)
this.moveDirection = 'right'
this.dispatchEvent(
new CustomEvent('notification-touchmove-right', {
detail: {
id: this.id,
direction: this.moveDirection,
},
bubbles: true,
composed: true,
})
)
break
case 'click':
event.stopPropagation()

View File

@ -30,6 +30,7 @@ export const sharedStyles: CSSResult = css`
position: relative;
left: 0;
top: 0;
box-sizing: border-box;
}
:host([notificationType='bluetooth-transfer']) {
@ -43,7 +44,6 @@ export const sharedStyles: CSSResult = css`
}
.notification {
// transition: transform 0.6s;
transition: transform 0.2s cubic-bezier(0.25, 0.1, 0.25, 1);
height: inherit;
width: inherit;
@ -109,10 +109,11 @@ export const sharedStyles: CSSResult = css`
width: 90.2%;
height: 18.4%;
left: 9.8%;
top: 23.7%;
top: 24%;
}
.notification > div.title-container .title {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex: none;
@ -127,6 +128,7 @@ export const sharedStyles: CSSResult = css`
line-height: 1;
// font-size: 2.3vw;
font-size: var(--auto-28px);
max-width: var(--auto-640px);
}
.notification > div.title-container .timestamp {
@ -153,9 +155,9 @@ export const sharedStyles: CSSResult = css`
// font-size: 2vw;
line-height: 1;
// right: 3.7%;
top: -2.6%;
font-size: var(--auto-24px);
right: var(--auto-32px);
line-height: var(--auto-24px);
}
.notification > div.detail {
@ -163,7 +165,7 @@ export const sharedStyles: CSSResult = css`
position: absolute;
width: 90.2%;
left: 9.8%;
top: 55%;
top: 58.65%;
}
.notification > div.detail .detail-content {
@ -181,7 +183,7 @@ export const sharedStyles: CSSResult = css`
// font-size: 2.2vw;
font-size: var(--auto-26px);
max-width: var(--auro-640px);
max-width: var(--auto-640px);
// width: 246px;
// height: 11px;
// font-size: 8px;
@ -241,7 +243,7 @@ export const sharedStyles: CSSResult = css`
display: flex;
justify-content: space-between;
width: 100%;
height: 100%;
height: inherit;
overflow: hidden;
}
@ -323,7 +325,9 @@ export const sharedStyles: CSSResult = css`
// left: 28px;
width: 90.2%;
height: var(--auto-48px);
left: 9.8%;
line-height: inherit;
}
.container .title {
@ -335,11 +339,30 @@ export const sharedStyles: CSSResult = css`
// line-height: 28px;
// font-size: 28px;
height: 18.4%;
line-height: 1;
// height: 18.4%;
// line-height: 1;
// font-size: 1.45vh;
// font-size: 2.3vw;
font-size: var(--auto-28px);
line-height: var(--auto-38px);
height: var(--auto-38px);
max-width: 40%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
/* 打开通知组动画过程中时 */
.more,
.one {
transition: opacity 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
}
.one {
opacity: var(--single-noti-opacity, 1);
pointer-events: var(--single-noti-events, all);
}
.more {
opacity: calc(1 - var(--single-noti-opacity, 1));
}
.container .detail-content {
@ -362,22 +385,18 @@ export const sharedStyles: CSSResult = css`
left: 0.93%;
// top: -3px;
top: -2%;
// top: -2%;
// top: -0.16vh;
// font-size: 1.35vh;
font-size: var(--auto-26px);
}
.one-container {
// top: 36px;
// top: 12px;
top: 23.7%;
top: 20.7%;
}
.another-container {
// top: 89px;
// top: 29px;
top: 58.5%;
top: 58.65%;
}
.one-container .timestamp {
@ -400,9 +419,8 @@ export const sharedStyles: CSSResult = css`
// height: 1.8vh;
height: var(--auto-34px);
right: 4%;
top: -0.2vh;
line-height: 1.7vh;
right: var(--auto-32px);
line-height: var(--auto-34px);
// font-size: 2vw;
font-size: var(--auto-24px);
}
@ -519,10 +537,13 @@ export const sharedStyles: CSSResult = css`
mix-blend-mode: normal;
opacity: 0.65;
}
.notification {
background: var(--single-noti-bgc, var(--notification-bgc));
}
@media (prefers-color-scheme: light) {
.notification {
background: var(--notification-background-lm);
:host {
--notification-bgc: var(--notification-background-lm);
}
.notification > div.title-container .title {
@ -571,8 +592,8 @@ export const sharedStyles: CSSResult = css`
}
@media (prefers-color-scheme: dark) {
.notification {
background: var(--notification-background-dm);
:host {
--notification-bgc: var(--notification-background-dm);
}
.notification > div.detail .arrow-up {