Explorar o código

Initialization steps callbacks (partially fixes #38) (#85)

* Initialization steps callbacks (partially fixes #38)

* Use Set instead array
Silly %!s(int64=8) %!d(string=hai) anos
pai
achega
3ec449b5e7
Modificáronse 2 ficheiros con 57 adicións e 8 borrados
  1. 51 8
      src/services/webclient.ts
  2. 6 0
      src/threema.d.ts

+ 51 - 8
src/services/webclient.ts

@@ -137,7 +137,8 @@ export class WebClientService implements threema.WebClientService {
     // State handling
     private startupPromise: ng.IDeferred<{}>; // TODO: deferred type
     private startupDone: boolean = false;
-    private initialized = 0;
+    private pendingInitializationStepRoutines: threema.InitializationStepRoutine[] = [];
+    private initialized: Set<threema.InitializationStep> = new Set();
     private initializedThreshold = 3;
     private state: threema.StateService;
 
@@ -568,9 +569,31 @@ export class WebClientService implements threema.WebClientService {
     }
 
     // Mark a component as initialized
-    public registerInitializationStep(name: string) {
-        this.initialized += 1;
-        if (this.initialized >= this.initializedThreshold) {
+    public registerInitializationStep(name: threema.InitializationStep) {
+        if (this.initialized.has(name) ) {
+            this.$log.warn(this.logTag, 'initialization step', name, 'already registered');
+            return;
+        }
+
+        this.initialized.add(name);
+
+        // check pending routines
+        this.pendingInitializationStepRoutines = this.pendingInitializationStepRoutines.filter((routine) => {
+            let isValid = true;
+            for (let requiredStep of routine.requiredSteps) {
+                if (!this.initialized.has(requiredStep)) {
+                    isValid = false;
+                    break;
+                }
+            }
+            if (isValid) {
+                this.$log.log('run routine after initialisation', name, ' completed');
+                routine.callback();
+            }
+            return !isValid;
+        });
+
+        if (this.initialized.size >= this.initializedThreshold) {
             this.state.updateConnectionBuildupState('done');
             this.startupPromise.resolve();
             this.startupDone = true;
@@ -1174,8 +1197,10 @@ export class WebClientService implements threema.WebClientService {
      * Reset data fields.
      */
     private _resetFields(): void {
-        // Set initialization count back to 0
-        this.initialized = 0;
+        // clear initialized steps
+        this.initialized.clear();
+        // clear step routines
+        this.pendingInitializationStepRoutines = [];
 
         // Create container instances
         this.receivers = this.container.createReceivers();
@@ -1449,7 +1474,8 @@ export class WebClientService implements threema.WebClientService {
                         id: conversation.id,
                         type: conversation.type,
                     } as threema.Receiver);
-                    if (receiver.avatar === undefined) {
+                    if (receiver !== undefined
+                            && receiver.avatar === undefined) {
                         receiver.avatar = {
                             low: this.$filter('bufferToUrl')(conversation.avatar, 'image/png'),
                         };
@@ -2109,7 +2135,9 @@ export class WebClientService implements threema.WebClientService {
                 this._receiveResponseReceivers(message);
                 break;
             case WebClientService.SUB_TYPE_CONVERSATIONS:
-                this._receiveResponseConversations(message);
+                this.runAfterInitializationSteps(['receivers'], () => {
+                    this._receiveResponseConversations(message);
+                });
                 break;
             case WebClientService.SUB_TYPE_CONVERSATION:
                 this._receiveResponseConversation(message);
@@ -2267,6 +2295,21 @@ export class WebClientService implements threema.WebClientService {
         }
     }
 
+    private runAfterInitializationSteps(requiredSteps: threema.InitializationStep[], callback: any): void {
+        for (let requiredStep of requiredSteps) {
+            if (!this.initialized.has(requiredStep)) {
+                this.$log.debug(this.logTag, 'required step', requiredStep, 'not completed, add pending');
+                this.pendingInitializationStepRoutines.push({
+                    requiredSteps: requiredSteps,
+                    callback: callback,
+                } as threema.InitializationStepRoutine);
+                return;
+            }
+        }
+
+        callback();
+    }
+
     private currentController: string;
     public setControllerName(name: string): void {
         this.currentController = name;

+ 6 - 0
src/threema.d.ts

@@ -48,6 +48,12 @@ declare namespace threema {
 
     type MessageType = 'text' | 'image' | 'video' | 'audio' | 'location' | 'status' | 'ballot' | 'file';
     type MessageState = 'delivered' | 'read' | 'send-failed' | 'sent' | 'user-ack' | 'user-dec' | 'pending' | 'sending';
+    type InitializationStep = 'client info' | 'conversations' |  'receivers';
+
+    interface InitializationStepRoutine {
+        requiredSteps: InitializationStep[];
+        callback: any;
+    }
 
     interface Thumbnail {
         img?: string;