Skip to content

Commit c34bc3f

Browse files
committed
fix badge/bell elements
1 parent f501b6e commit c34bc3f

File tree

6 files changed

+138
-100
lines changed

6 files changed

+138
-100
lines changed

src/page/bell/Badge.ts

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,25 @@ export default class Badge extends AnimatedElement {
99
);
1010
}
1111

12-
increment(): void {
13-
// If it IS a number (is not not a number)
14-
if (!isNaN(this.content as any)) {
15-
let badgeNumber = +this.content; // Coerce to int
16-
badgeNumber += 1;
17-
this.content = badgeNumber.toString();
12+
_updateCount(delta: number): void {
13+
const num = Number(this.content);
14+
if (!Number.isNaN(num)) {
15+
const newNum = num + delta;
16+
this.content = newNum > 0 ? newNum.toString() : '';
1817
}
1918
}
2019

20+
increment(): void {
21+
this._updateCount(1);
22+
}
23+
24+
decrement(): void {
25+
this._updateCount(-1);
26+
}
27+
2128
show(): Promise<AnimatedElement> {
2229
const promise = super.show();
2330
OneSignal._notifyButton?.setCustomColorsIfSpecified();
2431
return promise;
2532
}
26-
27-
decrement() {
28-
// If it IS a number (is not not a number)
29-
if (!isNaN(this.content as any)) {
30-
let badgeNumber = +this.content; // Coerce to int
31-
badgeNumber -= 1;
32-
if (badgeNumber > 0) this.content = badgeNumber.toString();
33-
else this.content = '';
34-
}
35-
}
3633
}

src/page/bell/Bell.ts

Lines changed: 94 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ export default class Bell {
3737
public hovering = false;
3838
public initialized = false;
3939
public _launcher: Launcher | undefined;
40-
public _button: any;
41-
public _badge: any;
42-
public _message: any;
43-
public _dialog: any;
40+
public _button: Button | undefined;
41+
public _badge: Badge | undefined;
42+
public _message: Message | undefined;
43+
public _dialog: Dialog | undefined;
4444

4545
private DEFAULT_SIZE: BellSize = 'medium';
4646
private DEFAULT_POSITION: BellPosition = 'bottom-right';
@@ -114,7 +114,9 @@ export default class Bell {
114114
document,
115115
'click',
116116
(e: Event, destroyEventListener: () => void) => {
117-
const wasDialogClicked = this.dialog.element.contains(e.target);
117+
const wasDialogClicked = this.dialog.element?.contains(
118+
e.target as Node,
119+
);
118120
if (wasDialogClicked) {
119121
return;
120122
}
@@ -199,11 +201,16 @@ export default class Bell {
199201
private installEventHooks() {
200202
// Install event hooks
201203
OneSignal._emitter.on(Bell.EVENTS.SUBSCRIBE_CLICK, () => {
202-
this.dialog.subscribeButton.disabled = true;
204+
const subscribeButton = this.dialog.subscribeButton;
205+
if (subscribeButton) {
206+
subscribeButton.disabled = true;
207+
}
203208
this._ignoreSubscriptionState = true;
204209
OneSignal.User.PushSubscription.optIn()
205210
.then(() => {
206-
this.dialog.subscribeButton.disabled = false;
211+
if (subscribeButton) {
212+
subscribeButton.disabled = false;
213+
}
207214
return this.dialog.hide();
208215
})
209216
.then(() => {
@@ -227,10 +234,15 @@ export default class Bell {
227234
});
228235

229236
OneSignal._emitter.on(Bell.EVENTS.UNSUBSCRIBE_CLICK, () => {
230-
this.dialog.unsubscribeButton.disabled = true;
237+
const unsubscribeButton = this.dialog.unsubscribeButton;
238+
if (unsubscribeButton) {
239+
unsubscribeButton.disabled = true;
240+
}
231241
OneSignal.User.PushSubscription.optOut()
232242
.then(() => {
233-
this.dialog.unsubscribeButton.disabled = false;
243+
if (unsubscribeButton) {
244+
unsubscribeButton.disabled = false;
245+
}
234246
return this.dialog.hide();
235247
})
236248
.then(() => {
@@ -299,7 +311,7 @@ export default class Bell {
299311
return;
300312
}
301313

302-
if (!this.dialog.hidden) {
314+
if (this.dialog.shown) {
303315
// If the dialog is being brought up when clicking button, don't shrink
304316
return;
305317
}
@@ -311,11 +323,11 @@ export default class Bell {
311323
// immediately after because of the way mobile click events work. Basically only happens if HOVERING and HOVERED
312324
// fire within a few milliseconds of each other
313325
this.message
314-
.waitUntilShown()
326+
.show()
315327
.then(() => delay(Message.TIMEOUT))
316328
.then(() => this.message.hide())
317329
.then(() => {
318-
if (this.launcher.wasInactive && this.dialog.hidden) {
330+
if (this.launcher.wasInactive && !this.dialog.shown) {
319331
this.launcher.inactivate();
320332
this.launcher.wasInactive = false;
321333
}
@@ -324,7 +336,7 @@ export default class Bell {
324336

325337
if (this.message.shown) {
326338
this.message.hide().then(() => {
327-
if (this.launcher.wasInactive && this.dialog.hidden) {
339+
if (this.launcher.wasInactive && !this.dialog.shown) {
328340
this.launcher.inactivate();
329341
this.launcher.wasInactive = false;
330342
}
@@ -543,15 +555,15 @@ export default class Bell {
543555
const bellShadow = `drop-shadow(0 2px 4px rgba(34,36,38,0.35));`;
544556
const badgeShadow = `drop-shadow(0 2px 4px rgba(34,36,38,0));`;
545557
const dialogShadow = `drop-shadow(0px 2px 2px rgba(34,36,38,.15));`;
546-
this.graphic.setAttribute(
558+
this.graphic?.setAttribute(
547559
'style',
548560
`filter: ${bellShadow}; -webkit-filter: ${bellShadow};`,
549561
);
550-
this.badge.element.setAttribute(
562+
this.badge?.element?.setAttribute(
551563
'style',
552564
`filter: ${badgeShadow}; -webkit-filter: ${badgeShadow};`,
553565
);
554-
this.dialog.element.setAttribute(
566+
this.dialog?.element?.setAttribute(
555567
'style',
556568
`filter: ${dialogShadow}; -webkit-filter: ${dialogShadow};`,
557569
);
@@ -587,20 +599,40 @@ export default class Bell {
587599

588600
setCustomColorsIfSpecified() {
589601
// Some common vars first
590-
const dialogButton = this.dialog.element.querySelector('button.action');
591-
const pulseRing = this.button.element.querySelector('.pulse-ring');
602+
const dialogElement = this.dialog.element;
603+
const dialogButton =
604+
dialogElement?.querySelector<HTMLButtonElement>('button.action');
605+
const buttonElement = this.button.element;
606+
const pulseRing = buttonElement?.querySelector<HTMLElement>('.pulse-ring');
607+
const graphic = this.graphic;
608+
592609
// Reset added styles first
593-
this.graphic.querySelector('.background').style.cssText = '';
594-
const foregroundElements = this.graphic.querySelectorAll('.foreground');
595-
for (let i = 0; i < foregroundElements.length; i++) {
596-
const element = foregroundElements[i];
597-
element.style.cssText = '';
610+
if (graphic) {
611+
const background = graphic.querySelector<HTMLElement>('.background');
612+
if (background) {
613+
background.style.cssText = '';
614+
}
615+
const foregroundElements =
616+
graphic.querySelectorAll<HTMLElement>('.foreground');
617+
for (let i = 0; i < foregroundElements.length; i++) {
618+
const element = foregroundElements[i];
619+
if (element) {
620+
element.style.cssText = '';
621+
}
622+
}
623+
const stroke = graphic.querySelector<HTMLElement>('.stroke');
624+
if (stroke) {
625+
stroke.style.cssText = '';
626+
}
598627
}
599-
this.graphic.querySelector('.stroke').style.cssText = '';
600-
this.badge.element.style.cssText = '';
628+
629+
const badgeElement = this.badge.element;
630+
if (badgeElement) {
631+
badgeElement.style.cssText = '';
632+
}
633+
601634
if (dialogButton) {
602635
dialogButton.style.cssText = '';
603-
dialogButton.style.cssText = '';
604636
}
605637
if (pulseRing) {
606638
pulseRing.style.cssText = '';
@@ -610,35 +642,48 @@ export default class Bell {
610642
if (this.options.colors) {
611643
const colors = this.options.colors;
612644
if (colors['circle.background']) {
613-
this.graphic.querySelector('.background').style.cssText +=
614-
`fill: ${colors['circle.background']}`;
645+
const background = graphic?.querySelector<HTMLElement>('.background');
646+
if (background) {
647+
background.style.cssText += `fill: ${colors['circle.background']}`;
648+
}
615649
}
616650
if (colors['circle.foreground']) {
617-
const foregroundElements = this.graphic.querySelectorAll('.foreground');
651+
const foregroundElements =
652+
graphic?.querySelectorAll<HTMLElement>('.foreground') ?? [];
618653
for (let i = 0; i < foregroundElements.length; i++) {
619654
const element = foregroundElements[i];
620-
element.style.cssText += `fill: ${colors['circle.foreground']}`;
655+
if (element) {
656+
element.style.cssText += `fill: ${colors['circle.foreground']}`;
657+
}
658+
}
659+
const stroke = graphic?.querySelector<HTMLElement>('.stroke');
660+
if (stroke) {
661+
stroke.style.cssText += `stroke: ${colors['circle.foreground']}`;
621662
}
622-
this.graphic.querySelector('.stroke').style.cssText +=
623-
`stroke: ${colors['circle.foreground']}`;
624663
}
625-
if (colors['badge.background']) {
626-
this.badge.element.style.cssText += `background: ${colors['badge.background']}`;
664+
if (colors['badge.background'] && badgeElement) {
665+
badgeElement.style.cssText += `background: ${colors['badge.background']}`;
627666
}
628-
if (colors['badge.bordercolor']) {
629-
this.badge.element.style.cssText += `border-color: ${colors['badge.bordercolor']}`;
667+
if (colors['badge.bordercolor'] && badgeElement) {
668+
badgeElement.style.cssText += `border-color: ${colors['badge.bordercolor']}`;
630669
}
631-
if (colors['badge.foreground']) {
632-
this.badge.element.style.cssText += `color: ${colors['badge.foreground']}`;
670+
if (colors['badge.foreground'] && badgeElement) {
671+
badgeElement.style.cssText += `color: ${colors['badge.foreground']}`;
633672
}
634-
if (dialogButton) {
673+
if (dialogButton && dialogElement) {
635674
if (colors['dialog.button.background']) {
636-
this.dialog.element.querySelector('button.action').style.cssText +=
637-
`background: ${colors['dialog.button.background']}`;
675+
const actionButton =
676+
dialogElement.querySelector<HTMLButtonElement>('button.action');
677+
if (actionButton) {
678+
actionButton.style.cssText += `background: ${colors['dialog.button.background']}`;
679+
}
638680
}
639681
if (colors['dialog.button.foreground']) {
640-
this.dialog.element.querySelector('button.action').style.cssText +=
641-
`color: ${colors['dialog.button.foreground']}`;
682+
const actionButton =
683+
dialogElement.querySelector<HTMLButtonElement>('button.action');
684+
if (actionButton) {
685+
actionButton.style.cssText += `color: ${colors['dialog.button.foreground']}`;
686+
}
642687
}
643688
if (colors['dialog.button.background.hovering']) {
644689
this.addCssToHead(
@@ -653,10 +698,11 @@ export default class Bell {
653698
);
654699
}
655700
}
656-
if (pulseRing) {
657-
if (colors['pulse.color']) {
658-
this.button.element.querySelector('.pulse-ring').style.cssText =
659-
`border-color: ${colors['pulse.color']}`;
701+
if (colors['pulse.color']) {
702+
const pulseRingElement =
703+
buttonElement?.querySelector<HTMLElement>('.pulse-ring');
704+
if (pulseRingElement) {
705+
pulseRingElement.style.cssText = `border-color: ${colors['pulse.color']}`;
660706
}
661707
}
662708
}
@@ -716,7 +762,7 @@ export default class Bell {
716762
}
717763

718764
get graphic() {
719-
return this.button.element.querySelector('svg');
765+
return this.button.element?.querySelector('svg');
720766
}
721767

722768
get launcher() {

src/page/bell/Button.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Message from './Message';
88

99
export default class Button extends AnimatedElement {
1010
public _isHandlingClick: boolean = false;
11-
public events: any;
11+
public events: Record<string, string>;
1212
public bell: Bell;
1313

1414
constructor(bell: Bell) {

src/page/bell/Dialog.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,17 @@ export default class Dialog extends AnimatedElement {
5050

5151
get subscribeButton() {
5252
return this.element
53-
? this.element.querySelector('#' + this.subscribeButtonSelectorId)
53+
? this.element.querySelector<HTMLButtonElement>(
54+
'#' + this.subscribeButtonSelectorId,
55+
)
5456
: null;
5557
}
5658

5759
get unsubscribeButton() {
5860
return this.element
59-
? this.element.querySelector('#' + this.unsubscribeButtonSelectorId)
61+
? this.element.querySelector<HTMLButtonElement>(
62+
'#' + this.unsubscribeButtonSelectorId,
63+
)
6064
: null;
6165
}
6266

src/page/bell/Launcher.ts

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -79,31 +79,23 @@ export default class Launcher extends AnimatedElement {
7979
this.wasInactive = false;
8080
}
8181

82-
inactivate() {
83-
return this.bell.message.hide().then(() => {
84-
if (this.bell.badge.content.length > 0) {
85-
return this.bell.badge
86-
.hide()
87-
.then(() => Promise.all([super.inactivate(), this.resize('small')]))
88-
.then(() => this.bell.badge.show());
89-
} else {
90-
return Promise.all([super.inactivate(), this.resize('small')]);
91-
}
92-
});
82+
async inactivate() {
83+
await this.bell.message.hide();
84+
if (this.bell.badge.content.length > 0) {
85+
await this.bell.badge.hide();
86+
await Promise.all([super.inactivate(), this.resize('small')]);
87+
return this.bell.badge.show();
88+
} else {
89+
await Promise.all([super.inactivate(), this.resize('small')]);
90+
return this;
91+
}
9392
}
9493

95-
activate() {
94+
async activate() {
9695
if (this.bell.badge.content.length > 0) {
97-
return this.bell.badge
98-
.hide()
99-
.then(() =>
100-
Promise.all([super.activate(), this.resize(this.bell.options.size!)]),
101-
);
102-
} else {
103-
return Promise.all([
104-
super.activate(),
105-
this.resize(this.bell.options.size!),
106-
]);
96+
await this.bell.badge.hide();
10797
}
98+
await Promise.all([super.activate(), this.resize(this.bell.options.size!)]);
99+
return this;
108100
}
109101
}

0 commit comments

Comments
 (0)