فهرست منبع

Add generic typing to the activity monitor

Steven Silvester 8 سال پیش
والد
کامیت
b01956d21a
2فایلهای تغییر یافته به همراه60 افزوده شده و 32 حذف شده
  1. 34 8
      src/common/activitymonitor.ts
  2. 26 24
      test/src/common/activitymonitor.spec.ts

+ 34 - 8
src/common/activitymonitor.ts

@@ -14,11 +14,11 @@ import {
  * A class that monitors activity on a signal.
  */
 export
-class ActivityMonitor implements IDisposable {
+class ActivityMonitor<Sender, Args> implements IDisposable {
   /**
    * Construct a new activity monitor.
    */
-  constructor(options: ActivityMonitor.IOptions) {
+  constructor(options: ActivityMonitor.IOptions<Sender, Args>) {
     options.signal.connect(this._onSignalFired, this);
     this._timeout = options.timeout || 1000;
   }
@@ -26,7 +26,7 @@ class ActivityMonitor implements IDisposable {
   /**
    * A signal emitted when activity has ceased.
    */
-  get activityStopped(): ISignal<ActivityMonitor, void> {
+  get activityStopped(): ISignal<ActivityMonitor<Sender, Args>, ActivityMonitor.IArguments<Sender, Args>> {
     return Private.activityStoppedSignal.bind(this);
   }
 
@@ -64,15 +64,24 @@ class ActivityMonitor implements IDisposable {
   /**
    * A signal handler for the monitored signal.
    */
-  private _onSignalFired(): void {
+  private _onSignalFired(sender: Sender, args: Args): void {
     clearTimeout(this._timer);
+    this._sender = sender;
+    this._args = args;
     this._timer = setTimeout(() => {
-      this.activityStopped.emit(void 0);
+      this.activityStopped.emit({
+        sender: this._sender,
+        args: this._args
+      });
+      this._sender = null;
+      this._args = null;
     }, this._timeout);
   }
 
   private _timer = -1;
   private _timeout = -1;
+  private _sender: Sender = null;
+  private _args: Args = null;
   private _isDisposed = false;
 }
 
@@ -86,11 +95,11 @@ namespace ActivityMonitor {
    * The options used to construct a new `ActivityMonitor`.
    */
   export
-  interface IOptions {
+  interface IOptions<Sender, Args> {
     /**
      * The signal to monitor.
      */
-    signal: ISignal<any, any>;
+    signal: ISignal<Sender, Args>;
 
     /**
      * The activity timeout in milliseconds.
@@ -99,6 +108,23 @@ namespace ActivityMonitor {
      */
     timeout?: number;
   }
+
+  /**
+   * The argument object for an activity timeout.
+   *
+   */
+  export
+  interface IArguments<Sender, Args> {
+    /**
+     * The most recent sender object.
+     */
+    sender: Sender;
+
+    /**
+     * The most recent argument object.
+     */
+    args: Args;
+  }
 }
 
 
@@ -110,5 +136,5 @@ namespace Private {
    * A signal emitted when activity has ceased.
    */
   export
-  const activityStoppedSignal = new Signal<ActivityMonitor, void>();
+  const activityStoppedSignal = new Signal<ActivityMonitor<any, any>, ActivityMonitor.IArguments<any, any>>();
 }

+ 26 - 24
test/src/common/activitymonitor.spec.ts

@@ -19,14 +19,14 @@ describe('common/activitymonitor', () => {
     describe('#constructor()', () => {
 
       it('should accept a signal', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         expect(monitor).to.be.an(ActivityMonitor);
       });
 
       it('should accept a timeout', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal, timeout: 100 });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal, timeout: 100 });
         expect(monitor).to.be.an(ActivityMonitor);
       });
 
@@ -35,15 +35,16 @@ describe('common/activitymonitor', () => {
     describe('#activityStopped', () => {
 
       it('should be emitted after the signal has fired and a timeout', (done) => {
-        let signal = new Signal<any, void>().bind(window);
+        let signal = new Signal<Window, number>().bind(window);
         let called = false;
         let monitor = new ActivityMonitor({ signal, timeout: 100 });
         monitor.activityStopped.connect((sender, args) => {
           expect(sender).to.be(monitor);
-          expect(args).to.be(void 0);
+          expect(args.sender).to.be(window);
+          expect(args.args).to.be(10);
           called = true;
         });
-        signal.emit(void 0);
+        signal.emit(10);
         expect(called).to.be(false);
         setTimeout(() => {
           expect(called).to.be(true);
@@ -52,18 +53,19 @@ describe('common/activitymonitor', () => {
       });
 
       it('should collapse during activity', (done) => {
-        let signal = new Signal<any, void>().bind(window);
+        let signal = new Signal<Window, number>().bind(window);
         let called = false;
-        let monitor = new ActivityMonitor({ signal, timeout: 100 });
+        let monitor = new ActivityMonitor<Window, number>({ signal, timeout: 100 });
         monitor.activityStopped.connect((sender, args) => {
           expect(sender).to.be(monitor);
-          expect(args).to.be(void 0);
+          expect(args.sender).to.be(window);
+          expect(args.args).to.be(10);
           called = true;
         });
-        signal.emit(void 0);
+        signal.emit(5);
         expect(called).to.be(false);
         setTimeout(() => {
-          signal.emit(void 0);
+          signal.emit(10);
         }, 90);
         setTimeout(() => {
           expect(called).to.be(false);
@@ -79,14 +81,14 @@ describe('common/activitymonitor', () => {
     describe('#timeout', () => {
 
       it('should default to `1000`', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         expect(monitor.timeout).to.be(1000);
       });
 
       it('should be set-able', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         monitor.timeout = 200;
         expect(monitor.timeout).to.be(200);
       });
@@ -96,16 +98,16 @@ describe('common/activitymonitor', () => {
     describe('#isDisposed', () => {
 
       it('should test whether the monitor is disposed', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         expect(monitor.isDisposed).to.be(false);
         monitor.dispose();
         expect(monitor.isDisposed).to.be(true);
       });
 
       it('should be read-only', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         expect(() => { monitor.isDisposed = false; }).to.throwError();
       });
 
@@ -114,15 +116,15 @@ describe('common/activitymonitor', () => {
     describe('#dispose()', () => {
 
       it('should disposed of the resources used by the monitor', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         monitor.dispose();
         expect(monitor.isDisposed).to.be(true);
       });
 
       it('should be a no-op if called more than once', () => {
-        let signal = new Signal<any, any>().bind(window);
-        let monitor = new ActivityMonitor({ signal });
+        let signal = new Signal<Window, number>().bind(window);
+        let monitor = new ActivityMonitor<Window, number>({ signal });
         monitor.dispose();
         monitor.dispose();
         expect(monitor.isDisposed).to.be(true);