Skip to content

Commit 1fc3dc5

Browse files
committed
potential memory leaks fix
1 parent 19f3454 commit 1fc3dc5

File tree

1 file changed

+88
-83
lines changed

1 file changed

+88
-83
lines changed

src/speeddial/index.ts

Lines changed: 88 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,9 @@
33
* @module @nativescript-community/ui-material-speedial
44
*/
55

6-
import {
7-
Animation,
8-
AnimationDefinition,
9-
CSSType,
10-
Color,
11-
EventData,
12-
FlexboxLayout,
13-
GestureTypes,
14-
GridLayout,
15-
HorizontalAlignment,
16-
ImageSource,
17-
View,
18-
backgroundColorProperty,
19-
colorProperty,
20-
isUserInteractionEnabledProperty
21-
} from '@nativescript/core';
6+
import { Animation, AnimationDefinition, CSSType, Color, CoreTypes, EventData, FlexboxLayout, GridLayout, ImageSource, isUserInteractionEnabledProperty } from '@nativescript/core';
227
import { Button } from '@nativescript-community/ui-material-button';
238
import { LinearGradient } from '@nativescript/core/ui/styling/gradient';
24-
import { AnimationCurve } from '@nativescript/core/ui/enums';
259
import { NotifyData } from '@nativescript/core/data/observable';
2610

2711
export class SpeedDialItemBase extends GridLayout {}
@@ -97,36 +81,45 @@ export class SpeedDialButton extends SpeedDialItemButton {}
9781
@CSSType('MDSpeedDialItem')
9882
export class SpeedDialItem extends SpeedDialItemBase {
9983
public actualActive = false;
100-
titleView: SpeedDialItemTitle;
101-
button: SpeedDialItemButton;
84+
mTitleView: WeakRef<SpeedDialItemTitle>;
85+
mButton: WeakRef<SpeedDialItemButton>;
10286
fabmenu: WeakRef<SpeedDial>;
87+
88+
get titleView() {
89+
return this.mTitleView?.get();
90+
}
91+
get button() {
92+
return this.mButton?.get();
93+
}
10394
constructor(size = 'mini', private isMain = false) {
10495
super();
10596
// this._fabsHolder.isPassThroughParentEnabled = true;
10697
this.isPassThroughParentEnabled = true;
107-
this.titleView = new SpeedDialItemTitle();
108-
this.titleView.notify = this.notifyChildEvent(this.titleView, this.titleView.notify);
109-
this.titleView.col = 1;
110-
this.titleView.text = this.title;
111-
this.button = isMain ? new SpeedDialButton() : new SpeedDialItemButton();
112-
this.button.notify = this.notifyChildEvent(this.button, this.button.notify);
113-
this.button.horizontalAlignment = 'center';
98+
const titleView = new SpeedDialItemTitle();
99+
titleView.notify = this.notifyChildEvent(titleView, titleView.notify);
100+
titleView.col = 1;
101+
titleView.text = this.title;
102+
const button = isMain ? new SpeedDialButton() : new SpeedDialItemButton();
103+
button.notify = this.notifyChildEvent(button, button.notify);
104+
button.horizontalAlignment = 'center';
114105
// this.fabButtonTitle.style['css:elevation'] = 4;this.fabButtonTitle.style['css:elevation'] = 2;
115-
this.button.col = this.fabButtonCol;
106+
button.col = this.fabButtonCol;
116107
if (size === 'mini') {
117-
// this.button.style['css:border-radius'] = 20;
118-
this.button.style['css:width'] = 40;
119-
this.button.style['css:height'] = 40;
120-
this.button.style['css:margin'] = 16;
108+
// button.style['css:border-radius'] = 20;
109+
button.style['css:width'] = 40;
110+
button.style['css:height'] = 40;
111+
button.style['css:margin'] = 16;
121112
} else {
122-
// this.button.style['css:border-radius'] = 28;
123-
this.button.style['css:width'] = 56;
124-
this.button.style['css:height'] = 56;
125-
this.button.style['css:margin'] = 16;
113+
// button.style['css:border-radius'] = 28;
114+
button.style['css:width'] = 56;
115+
button.style['css:height'] = 56;
116+
button.style['css:margin'] = 16;
126117
}
127118
(this as any).columns = this.fabColumns;
128-
this.addChild(this.titleView);
129-
this.addChild(this.button);
119+
this.addChild(titleView);
120+
this.addChild(button);
121+
this.mTitleView = new WeakRef(titleView);
122+
this.mButton = new WeakRef(button);
130123
}
131124
updateAlignment() {
132125
(this as any).columns = this.fabColumns;
@@ -265,14 +258,24 @@ export class SpeedDialItem extends SpeedDialItemBase {
265258

266259
@CSSType('MDSpeedDial')
267260
export class SpeedDial extends SpeedDialItemBase {
268-
fabs: SpeedDialItem[] = [];
269-
private _fabsHolder: FlexboxLayout;
261+
mFabs: WeakRef<SpeedDialItem>[] = [];
262+
private mFabsHolder: WeakRef<FlexboxLayout>;
270263
rows: string;
271264
columns: string;
272265
orientation = 'vertical';
273266
isActive = false;
274267
actualActive = false;
275-
private _fabMainButton: SpeedDialItem;
268+
private mFabMainButton: WeakRef<SpeedDialItem>;
269+
270+
get fabsHolder() {
271+
return this.mFabsHolder?.get();
272+
}
273+
get fabMainButton() {
274+
return this.mFabMainButton?.get();
275+
}
276+
get fabs() {
277+
return this.mFabs.map((f) => f?.get()).filter((f) => !!f);
278+
}
276279
constructor() {
277280
super();
278281
this.actualActive = this.isActive;
@@ -281,23 +284,25 @@ export class SpeedDial extends SpeedDialItemBase {
281284
this.rows = 'auto,*,auto,auto';
282285
this.style['css:padding-left'] = 8;
283286
this.style['css:padding-right'] = 8;
284-
this._fabsHolder = new FlexboxLayout();
285-
this._fabsHolder.row = 2;
286-
this._fabsHolder.horizontalAlignment = this.horizontalAlignment;
287+
const fabHolder = new FlexboxLayout();
288+
fabHolder.row = 2;
289+
fabHolder.horizontalAlignment = this.horizontalAlignment;
287290
this.isPassThroughParentEnabled = true;
288291
if (global.isIOS) {
289-
this._fabsHolder.isPassThroughParentEnabled = true;
292+
fabHolder.isPassThroughParentEnabled = true;
290293
}
291-
this._fabsHolder.flexDirection = this.orientation === 'vertical' ? 'column-reverse' : 'row-reverse';
292-
this._fabsHolder.visibility = 'hidden';
294+
fabHolder.flexDirection = this.orientation === 'vertical' ? 'column-reverse' : 'row-reverse';
295+
fabHolder.visibility = 'hidden';
293296
this.backgroundColor = new Color('#00000000');
294297

295-
this._fabMainButton = new SpeedDialItem(null, true);
296-
this.prepareItem(this._fabMainButton, true);
297-
this._fabMainButton.row = 3;
298+
const fabMainButton = new SpeedDialItem(null, true);
299+
this.prepareItem(fabMainButton, true);
300+
fabMainButton.row = 3;
298301

299-
this.addChild(this._fabMainButton);
300-
this.addChild(this._fabsHolder);
302+
this.addChild(fabMainButton);
303+
this.addChild(fabHolder);
304+
this.mFabsHolder = new WeakRef(fabHolder);
305+
this.mFabMainButton = new WeakRef(fabMainButton);
301306
}
302307

303308
get backDrop() {
@@ -326,11 +331,11 @@ export class SpeedDial extends SpeedDialItemBase {
326331
});
327332
}
328333
insertChild(child, index) {
329-
if (child !== this._fabMainButton && child instanceof SpeedDialItem) {
334+
if (child !== this.fabMainButton && child instanceof SpeedDialItem) {
330335
this.prepareItem(child);
331336

332-
this.fabs.splice(index, 0, child);
333-
this._fabsHolder.insertChild(child, index);
337+
this.mFabs.splice(index, 0, new WeakRef(child));
338+
this.fabsHolder.insertChild(child, index);
334339
} else {
335340
super.insertChild(child, index);
336341
}
@@ -341,11 +346,11 @@ export class SpeedDial extends SpeedDialItemBase {
341346
// this is to make sure the view does not get "visible" too quickly
342347
// before we apply the translation
343348
// super.addChild(child);
344-
if (child !== this._fabMainButton && child instanceof SpeedDialItem) {
349+
if (child !== this.fabMainButton && child instanceof SpeedDialItem) {
345350
this.prepareItem(child);
346351

347-
this.fabs.push(child);
348-
this._fabsHolder.addChild(child);
352+
this.mFabs.push(new WeakRef(child));
353+
this.fabsHolder.addChild(child);
349354
} else {
350355
super.addChild(child);
351356
}
@@ -370,7 +375,7 @@ export class SpeedDial extends SpeedDialItemBase {
370375
}
371376
computeAnimationData(way: 'open' | 'hide', fab: SpeedDialItem, index, count, duration, isMain = false): AnimationDefinition[] {
372377
const delay = (duration / count) * index;
373-
const curve = AnimationCurve.easeOut;
378+
const curve = CoreTypes.AnimationCurve.easeOut;
374379
if (way === 'open') {
375380
const result: AnimationDefinition[] = [
376381
{
@@ -439,18 +444,18 @@ export class SpeedDial extends SpeedDialItemBase {
439444
return acc;
440445
}, [] as AnimationDefinition[])
441446
.filter((a) => !!a)
442-
.concat(this.computeAnimationData('open', this._fabMainButton, 0, length, duration, true))
447+
.concat(this.computeAnimationData('open', this.fabMainButton, 0, length, duration, true))
443448
.concat([
444449
{
445450
target: this.backDrop,
446451
backgroundColor: new Color('#00000099'),
447-
curve: AnimationCurve.easeInOut,
452+
curve: CoreTypes.AnimationCurve.easeInOut,
448453
duration
449454
}
450455
]);
451456

452457
try {
453-
this._fabsHolder.visibility = 'visible';
458+
this.fabsHolder.visibility = 'visible';
454459
this.isPassThroughParentEnabled = false;
455460
await new Animation(params).play();
456461
fabs.forEach((f) => (f.isUserInteractionEnabled = true));
@@ -471,12 +476,12 @@ export class SpeedDial extends SpeedDialItemBase {
471476
return acc;
472477
}, [] as AnimationDefinition[])
473478
.filter((a) => !!a)
474-
.concat(this.computeAnimationData('hide', this._fabMainButton, 0, length, duration, true))
479+
.concat(this.computeAnimationData('hide', this.fabMainButton, 0, length, duration, true))
475480
.concat([
476481
{
477482
target: this.backDrop,
478483
backgroundColor: new Color('#00000000'),
479-
curve: AnimationCurve.easeInOut,
484+
curve: CoreTypes.AnimationCurve.easeInOut,
480485
duration
481486
}
482487
]);
@@ -485,7 +490,7 @@ export class SpeedDial extends SpeedDialItemBase {
485490
fabs.forEach((f) => (f.isUserInteractionEnabled = false));
486491
await new Animation(params).play();
487492
this.isPassThroughParentEnabled = true;
488-
this._fabsHolder.visibility = 'hidden';
493+
this.fabsHolder.visibility = 'hidden';
489494
} catch (err) {
490495
// console.error(err);
491496
} finally {
@@ -515,52 +520,52 @@ export class SpeedDial extends SpeedDialItemBase {
515520

516521
//@ts-ignore
517522
get icon() {
518-
return this._fabMainButton.icon;
523+
return this.fabMainButton.icon;
519524
}
520525
set icon(value: string | ImageSource) {
521-
this._fabMainButton.icon = value;
522-
this._fabMainButton.padding = 0;
526+
this.fabMainButton.icon = value;
527+
this.fabMainButton.padding = 0;
523528
}
524529
get buttonClass() {
525-
return this._fabMainButton.buttonClass;
530+
return this.fabMainButton.buttonClass;
526531
}
527532
set buttonClass(value: string) {
528-
this._fabMainButton.buttonClass = value;
533+
this.fabMainButton.buttonClass = value;
529534
}
530535
get buttonFontSize() {
531-
return this._fabMainButton.buttonFontSize;
536+
return this.fabMainButton.buttonFontSize;
532537
}
533538
set buttonFontSize(value) {
534-
this._fabMainButton.buttonFontSize = value;
539+
this.fabMainButton.buttonFontSize = value;
535540
}
536541

537542
//@ts-ignore
538543
get color() {
539-
return this._fabMainButton.color;
544+
return this.fabMainButton.color;
540545
}
541546
set color(value) {
542-
this._fabMainButton.color = value;
547+
this.fabMainButton.color = value;
543548
}
544549
get text() {
545-
return this._fabMainButton.text;
550+
return this.fabMainButton.text;
546551
}
547552
set text(value: string) {
548-
this._fabMainButton.text = value;
553+
this.fabMainButton.text = value;
549554
}
550555
get title() {
551-
return this._fabMainButton.title;
556+
return this.fabMainButton.title;
552557
}
553558
set title(value: string) {
554-
this._fabMainButton.title = value;
559+
this.fabMainButton.title = value;
555560
}
556561
//@ts-ignore
557562
get horizontalAlignment() {
558-
return this._fabsHolder.horizontalAlignment;
563+
return this.fabsHolder.horizontalAlignment;
559564
}
560565
set horizontalAlignment(value) {
561-
this._fabsHolder.horizontalAlignment = value;
562-
this._fabMainButton.updateAlignment();
563-
this._fabsHolder.eachChild((c) => {
566+
this.fabsHolder.horizontalAlignment = value;
567+
this.fabMainButton.updateAlignment();
568+
this.fabsHolder.eachChild((c) => {
564569
if (c instanceof SpeedDialItem) {
565570
c.updateAlignment();
566571
}
@@ -595,10 +600,10 @@ export class SpeedDial extends SpeedDialItemBase {
595600
// }
596601

597602
get titleClass() {
598-
return this._fabMainButton.titleClass;
603+
return this.fabMainButton.titleClass;
599604
}
600605
set titleClass(value: string) {
601-
this._fabMainButton.titleClass = value;
606+
this.fabMainButton.titleClass = value;
602607
}
603608

604609
onBackdropTap(args) {

0 commit comments

Comments
 (0)