this.get('assets/talks.json').subscribe((talks: Array<TalkModel>) => {
     this.talks = talks;
     talks.forEach((talk: TalkModel) => subject.next(talk));
     subject.complete();
 });
 .then(user => {
   logger.debug('has authenticated user', user);
   authState.next({ state: 'signedIn', user: user });
 })
 .then(data => {
   logger.debug('signOut success');
   authState.next({ state: 'signedOut', user: null });
   return data;
 })
Example #4
0
 observe(): Observable<any> {
   return this._subject.asObservable();
 }
 this.image.onerror = (err) => {
   this.imageLoadSubject.complete();
 };
Example #6
0
 constructor(event: esriMouseEvent) {
     super(event);
     this._featureSubject = new Subject();
     this.features = this._featureSubject.asObservable();
 }
                .then((directoryUser:DirectoryUser) => {
                    this._sessionUser.isAdmin = directoryUser.isAdmin;
                    this.isSignedInSubject.next(true);

                    return this._sessionUser.hostedDomain === GoogleApplicationAccount.domain;
                })
  private onEnd(event: TransitionEvent | AnimationEvent): void {

    if (!this.animationEnd.closed) {
      this.animationEnd.next(event);
    }
  }
 ngOnDestroy(): void {
   if (this.animationEnd && !this.animationEnd.closed) {
     this.animationEnd.complete();
   }
 }
Example #10
0
 res => this.dispatcher$.next(res),
Example #11
0
  constructor() {
    this.dispatcher$ = new Subject();

    this.dispatcher$.subscribe(x => console.log('dispatcher', x))
  }
Example #12
0
 filterBy(unit, cls) {
   this.unitSubject.next(unit);
   this.cls = cls;
   this.unit = unit;
   console.log(unit);
 }
this.talks.forEach((talk: TalkModel) => subject.next(talk));
 setTimeout(() => {
     this.talks.forEach((talk: TalkModel) => subject.next(talk));
     subject.complete();
 });
describe('TaskManagerService', () => {
  let taskManagerService: TaskManagerService;

  const summaryDataSource = new Subject();
  const fakeService = {
    summaryData$: summaryDataSource.asObservable()
  };

  const summary = {
    executing_tasks: [],
    health_status: 'HEALTH_OK',
    mgr_id: 'x',
    rbd_mirroring: { errors: 0, warnings: 0 },
    rbd_pools: [],
    have_mon_connection: true,
    finished_tasks: [{ name: 'foo', metadata: {} }],
    filesystems: [{ id: 1, name: 'cephfs_a' }]
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [TaskManagerService, { provide: SummaryService, useValue: fakeService }]
    });

    taskManagerService = TestBed.get(TaskManagerService);
  });

  it('should be created', () => {
    expect(taskManagerService).toBeTruthy();
  });

  it(
    'should subscribe and be notified when task is finished',
    fakeAsync(() => {
      let called = false;
      taskManagerService.subscribe('foo', {}, () => (called = true));
      expect(taskManagerService.subscriptions.length).toBe(1);

      summaryDataSource.next(summary);
      tick();

      expect(called).toEqual(true);
      expect(taskManagerService.subscriptions).toEqual([]);
    })
  );

  it(
    'should subscribe and process executing taks',
    fakeAsync(() => {
      let called = false;
      taskManagerService.subscribe('foo', {}, () => (called = true));
      const original_subscriptions = _.cloneDeep(taskManagerService.subscriptions);
      const new_summary = _.assign(summary, {
        executing_tasks: [{ name: 'foo', metadata: {} }],
        finished_tasks: []
      });
      summaryDataSource.next(summary);
      tick();
      expect(taskManagerService.subscriptions).toEqual(original_subscriptions);
    })
  );
});
Example #16
0
 .subscribe(response => {
     this.cameraSetting.next(response.json());
 });
Example #17
0
/**
 * TODO: For now this is a copy of StoreService customized for D2. Over time we should either
 * consolidate them, or at least organize them better.
 */
function makeD2StoresService(): D2StoreServiceType {
  'ngInject';

  let _stores: D2Store[] = [];

  // A subject that keeps track of the current account. Because it's a
  // behavior subject, any new subscriber will always see its last
  // value.
  const accountStream = new BehaviorSubject<DestinyAccount | null>(null);

  // The triggering observable for force-reloading stores.
  const forceReloadTrigger = new Subject();

  // A stream of stores that switches on account changes and supports reloading.
  // This is a ConnectableObservable that must be connected to start.
  const storesStream = accountStream
    // Only emit when the account changes
    .distinctUntilChanged(compareAccounts)
    // But also re-emit the current value of the account stream
    // whenever the force reload triggers
    .merge(forceReloadTrigger.switchMap(() => accountStream.take(1)))
    // Whenever either trigger happens, load stores
    .switchMap(loadStores)
    // Keep track of the last value for new subscribers
    .publishReplay(1);

  // TODO: If we can make the store structures immutable, we could use
  //       distinctUntilChanged to avoid emitting store updates when
  //       nothing changed!

  const service = {
    getActiveStore: () => _stores.find((s) => s.current),
    getStores: () => _stores,
    getStore: (id: string) => _stores.find((s) => s.id === id),
    getVault: () => _stores.find((s) => s.isVault) as D2Vault | undefined,
    getAllItems: () => flatMap(_stores, (s) => s.items),
    getStoresStream,
    getItemAcrossStores,
    updateCharacters,
    reloadStores,
    refreshRatingsData,
    touch() {
      store.dispatch(update(_stores));
    }
  };

  return service;

  /**
   * Find an item among all stores that matches the params provided.
   */
  function getItemAcrossStores(params: {
    id?: string;
    hash?: number;
    notransfer?: boolean;
    amount?: number;
  }) {
    const predicate = _.iteratee(_.pick(params, 'id', 'hash', 'notransfer', 'amount')) as (
      i: DimItem
    ) => boolean;
    for (const store of _stores) {
      const result = store.items.find(predicate);
      if (result) {
        return result;
      }
    }
    return undefined;
  }

  /**
   * Update the high level character information for all the stores
   * (level, light, int/dis/str, etc.). This does not update the
   * items in the stores - to do that, call reloadStores.
   */
  function updateCharacters(account: DestinyAccount): IPromise<D2Store[]> {
    // TODO: the router.globals.params defaults are just for now, to bridge callsites that don't know platform
    if (!account) {
      if (router.globals.params.membershipId && router.globals.params.platformType) {
        account = {
          membershipId: router.globals.params.membershipId,
          platformType: router.globals.params.platformType,
          displayName: 'Unknown',
          platformLabel: 'Unknown',
          destinyVersion: 2
        };
      } else {
        throw new Error("Don't know membership ID and platform type");
      }
    }

    return $q
      .all([getDefinitions(), getCharacters(account)])
      .then(([defs, profileInfo]: [D2ManifestDefinitions, DestinyProfileResponse]) => {
        // TODO: create a new store
        _stores.forEach((dStore) => {
          if (!dStore.isVault) {
            const bStore = profileInfo.characters.data[dStore.id];
            if (bStore) {
              dStore.updateCharacterInfo(defs, bStore);
            }
          }
        });
        service.touch();
        return _stores;
      });
  }

  /**
   * Set the current account, and get a stream of stores updates.
   * This will keep returning stores even if something else changes
   * the account by also calling "storesStream". This won't force the
   * stores to reload unless they haven't been loaded at all.
   *
   * @return a stream of store updates
   */
  function getStoresStream(account: DestinyAccount) {
    accountStream.next(account);
    // Start the stream the first time it's asked for. Repeated calls
    // won't do anything.
    storesStream.connect();
    return storesStream;
  }

  /**
   * Force the inventory and characters to reload.
   * @return the new stores
   */
  function reloadStores() {
    // adhere to the old contract by returning the next value as a
    // promise We take 2 from the stream because the publishReplay
    // will always return the latest value instantly, and we want the
    // next value (the refreshed value). toPromise returns the last
    // value in the sequence.
    const promise = storesStream.take(2).toPromise();
    forceReloadTrigger.next(); // signal the force reload
    return promise;
  }

  /**
   * Returns a promise for a fresh view of the stores and their items.
   */
  function loadStores(account: DestinyAccount): IPromise<D2Store[] | undefined> {
    // Save a snapshot of all the items before we update
    const previousItems = NewItemsService.buildItemSet(_stores);

    resetIdTracker();

    const reloadPromise = $q
      .all([
        getDefinitions(),
        getBuckets(),
        NewItemsService.loadNewItems(account),
        getItemInfoSource(account),
        getStores(account)
      ])
      .then(([defs, buckets, newItems, itemInfoService, profileInfo]) => {
        NewItemsService.applyRemovedNewItems(newItems);

        // TODO: components may be hidden (privacy)

        if (!profileInfo.profileInventory.data || !profileInfo.characterInventories.data) {
          console.error(
            'Vault or character inventory was missing - bailing in order to avoid corruption'
          );
          throw new Error(t('BungieService.Difficulties'));
        }

        const lastPlayedDate = findLastPlayedDate(profileInfo);

        const processVaultPromise = processVault(
          profileInfo.profileInventory.data ? profileInfo.profileInventory.data.items : [],
          profileInfo.profileCurrencies.data ? profileInfo.profileCurrencies.data.items : [],
          profileInfo.itemComponents,
          buckets,
          previousItems,
          newItems,
          itemInfoService
        );

        const processStorePromises = $q.all(
          Object.keys(profileInfo.characters.data).map((characterId) =>
            processCharacter(
              defs,
              profileInfo.characters.data[characterId],
              profileInfo.characterInventories.data &&
              profileInfo.characterInventories.data[characterId]
                ? profileInfo.characterInventories.data[characterId].items
                : [],
              profileInfo.profileInventory.data ? profileInfo.profileInventory.data.items : [],
              profileInfo.characterEquipment.data &&
              profileInfo.characterEquipment.data[characterId]
                ? profileInfo.characterEquipment.data[characterId].items
                : [],
              profileInfo.itemComponents,
              profileInfo.characterProgressions.data &&
              profileInfo.characterProgressions.data[characterId]
                ? profileInfo.characterProgressions.data[characterId].progressions
                : [],
              buckets,
              previousItems,
              newItems,
              itemInfoService,
              lastPlayedDate
            )
          )
        );

        store.dispatch(setBuckets(buckets));

        return $q.all([
          defs,
          buckets,
          newItems,
          itemInfoService,
          processVaultPromise,
          processStorePromises
        ]);
      })
      .then(([defs, buckets, newItems, itemInfoService, vault, characters]) => {
        // Save the list of new item IDs
        NewItemsService.applyRemovedNewItems(newItems);
        NewItemsService.saveNewItems(newItems, account);

        const stores = [...characters, vault];
        _stores = stores;

        // TODO: update vault counts for character account-wide
        updateVaultCounts(buckets, characters.find((c) => c.current)!, vault);

        dimDestinyTrackerService.fetchReviews(stores);

        itemInfoService.cleanInfos(stores);

        stores.forEach((s) => updateBasePower(account, stores, s, defs));

        // Let our styling know how many characters there are
        document
          .querySelector('html')!
          .style.setProperty('--num-characters', String(_stores.length - 1));

        dimDestinyTrackerService.reattachScoresFromCache(stores);

        store.dispatch(update(stores));

        return stores;
      })
      .catch((e: DimError) => {
        toaster.pop(bungieErrorToaster(e));
        console.error('Error loading stores', e);
        reportException('d2stores', e);
        // It's important that we swallow all errors here - otherwise
        // our observable will fail on the first error. We could work
        // around that with some rxjs operators, but it's easier to
        // just make this never fail.
        return undefined;
      })
      .finally(() => {
        $rootScope.$broadcast('dim-filter-invalidate');
        D2ManifestService.loaded = true;
      });

    loadingTracker.addPromise(reloadPromise);
    return reloadPromise;
  }

  /**
   * Process a single character from its raw form to a DIM store, with all the items.
   */
  function processCharacter(
    defs: D2ManifestDefinitions,
    character: DestinyCharacterComponent,
    characterInventory: DestinyItemComponent[],
    profileInventory: DestinyItemComponent[],
    characterEquipment: DestinyItemComponent[],
    itemComponents: DestinyItemComponentSetOfint64,
    progressions: { [key: number]: DestinyProgression },
    buckets: InventoryBuckets,
    previousItems: Set<string>,
    newItems: Set<string>,
    itemInfoService: ItemInfoSource,
    lastPlayedDate: Date
  ): IPromise<D2Store> {
    const store = makeCharacter(defs, character, lastPlayedDate);

    // This is pretty much just needed for the xp bar under the character header
    store.progression = progressions ? { progressions: Object.values(progressions) } : null;

    // We work around the weird account-wide buckets by assigning them to the current character
    let items = characterInventory.concat(Object.values(characterEquipment));
    if (store.current) {
      items = items.concat(
        Object.values(profileInventory).filter((i) => {
          // items that can be stored in a vault
          return buckets.byHash[i.bucketHash].vaultBucket;
        })
      );
    }

    return processItems(
      store,
      items,
      itemComponents,
      previousItems,
      newItems,
      itemInfoService
    ).then((items) => {
      store.items = items;

      // by type-bucket
      store.buckets = _.groupBy(items, (i) => i.location.id);

      // Fill in any missing buckets
      Object.values(buckets.byType).forEach((bucket) => {
        if (!store.buckets[bucket.id]) {
          store.buckets[bucket.id] = [];
        }
      });

      return store;
    });
  }

  function processVault(
    profileInventory: DestinyItemComponent[],
    profileCurrencies: DestinyItemComponent[],
    itemComponents: DestinyItemComponentSetOfint64,
    buckets: InventoryBuckets,
    previousItems: Set<string>,
    newItems: Set<string>,
    itemInfoService: ItemInfoSource
  ): IPromise<D2Vault> {
    const store = makeVault(profileCurrencies);

    const items = Object.values(profileInventory).filter((i) => {
      // items that cannot be stored in the vault, and are therefore *in* a vault
      return !buckets.byHash[i.bucketHash].vaultBucket;
    });
    return processItems(
      store,
      items,
      itemComponents,
      previousItems,
      newItems,
      itemInfoService
    ).then((items) => {
      store.items = items;

      // by type-bucket
      store.buckets = _.groupBy(items, (i) => i.location.id);

      store.vaultCounts = {};

      // Fill in any missing buckets
      Object.values(buckets.byType).forEach((bucket) => {
        if (!store.buckets[bucket.id]) {
          store.buckets[bucket.id] = [];
        }

        if (bucket.vaultBucket) {
          const vaultBucketId = bucket.vaultBucket.id;
          store.vaultCounts[vaultBucketId] = store.vaultCounts[vaultBucketId] || {
            count: 0,
            bucket: bucket.accountWide ? bucket : bucket.vaultBucket
          };
          store.vaultCounts[vaultBucketId].count += store.buckets[bucket.id].length;
        }
      });

      return store;
    });
  }

  /**
   * Find the date of the most recently played character.
   */
  function findLastPlayedDate(profileInfo: DestinyProfileResponse) {
    return Object.values(profileInfo.characters.data).reduce(
      (memo, character: DestinyCharacterComponent) => {
        const d1 = new Date(character.dateLastPlayed);
        return memo ? (d1 >= memo ? d1 : memo) : d1;
      },
      new Date(0)
    );
  }

  // Add a fake stat for "max base power"
  function updateBasePower(
    account: DestinyAccount,
    stores: D2Store[],
    store: D2Store,
    defs: D2ManifestDefinitions
  ) {
    if (!store.isVault) {
      const def = defs.Stat.get(1935470627);
      const maxBasePower = getLight(store, maxBasePowerLoadout(stores, store));

      const hasClassified = flatMap(_stores, (s) => s.items).some((i) => {
        return (
          i.classified &&
          (i.location.sort === 'Weapons' || i.location.sort === 'Armor' || i.type === 'Ghost')
        );
      });

      store.stats.maxBasePower = {
        id: -1,
        name: t('Stats.MaxBasePower'),
        hasClassified,
        description: def.displayProperties.description,
        value: hasClassified ? `${maxBasePower}*` : maxBasePower,
        icon: bungieNetPath(def.displayProperties.icon),
        tiers: [maxBasePower],
        tierMax: getCurrentMaxBasePower(account)
      };
    }
  }

  function getCurrentMaxBasePower(account: DestinyAccount) {
    if (!account.versionsOwned) {
      return 600;
    }
    if (DestinyGameVersions.Forsaken & account.versionsOwned) {
      return 600;
    }
    if (DestinyGameVersions.DLC2 & account.versionsOwned) {
      return 380;
    }
    if (DestinyGameVersions.DLC1 & account.versionsOwned) {
      return 330;
    }
    if (DestinyGameVersions.Destiny2 & account.versionsOwned) {
      return 300;
    }
    return 600;
  }

  function maxBasePowerLoadout(stores: D2Store[], store: D2Store) {
    const statHashes = new Set([
      1480404414, // Attack
      3897883278 // Defense
    ]);

    const applicableItems = flatMap(stores, (s) => s.items).filter((i) => {
      return (
        i.canBeEquippedBy(store) &&
        i.primStat && // has a primary stat (sanity check)
        statHashes.has(i.primStat.statHash)
      ); // one of our selected stats
    });

    const bestItemFn = (item: D2Item) => {
      let value = item.basePower;

      // Break ties when items have the same stats. Note that this should only
      // add less than 0.25 total, since in the exotics special case there can be
      // three items in consideration and you don't want to go over 1 total.
      if (item.owner === store.id) {
        // Prefer items owned by this character
        value += 0.1;
        if (item.equipped) {
          // Prefer them even more if they're already equipped
          value += 0.1;
        }
      } else if (item.owner === 'vault') {
        // Prefer items in the vault over items owned by a different character
        // (but not as much as items owned by this character)
        value += 0.05;
      }
      return value;
    };

    return optimalLoadout(applicableItems, bestItemFn, '');
  }

  // TODO: vault counts are silly and convoluted. We really need an
  // object to represent a Profile.
  function updateVaultCounts(buckets: InventoryBuckets, activeStore: D2Store, vault: D2Vault) {
    // Fill in any missing buckets
    Object.values(buckets.byType).forEach((bucket) => {
      if (bucket.accountWide && bucket.vaultBucket) {
        const vaultBucketId = bucket.id;
        vault.vaultCounts[vaultBucketId] = vault.vaultCounts[vaultBucketId] || {
          count: 0,
          bucket
        };
        vault.vaultCounts[vaultBucketId].count += activeStore.buckets[bucket.id].length;
      }
    });
    activeStore.vault = vault; // god help me
  }

  function refreshRatingsData() {
    dimDestinyTrackerService.clearCache();
    dimDestinyTrackerService.fetchReviews(_stores);
  }
}
Example #18
0
 return this.http.post(this.config.get('camera.settings'), json).map(response => {
     const cameraSettings = response.json();
     this.cameraSetting.next(cameraSettings);
     return cameraSettings;
 });
 return new Observable(fn => subject.subscribe(fn));
Example #20
0
 filterBy(size: string) {
   this.sizeSubject.next(size);
 }
Example #21
0
 setAttribute(key: string, value: any): void {
   set(this, key, value);
   this._subject.next(this);
 }
Example #22
0
 it('should apply transforms on scroll events', () => {
   fixture.detectChanges();
   const scrollSpy = spyOn(instance, 'applyTransforms');
   ionScrollSubject.next(scrollEventMock as any);
   expect(scrollSpy).toHaveBeenCalledWith(scrollEventMock.scrollTop);
 });
Example #23
0
 mockFirebaseAuth.subscribe.and.callFake(callback => {
   authSubject.subscribe(callback);
 });
Example #24
0
 public claimMouse(name: string, zindex: number): void {
     this._claimMouse$.next({name: name, zindex: zindex});
 }
 this.image.onload = () => {
   this.imageLoadSubject.next(null);
   this.imageLoadSubject.complete();
 };
Example #26
0
 public unclaimMouse(name: string): void {
     this._claimMouse$.next({name: name, zindex: null});
 }
 .catch(err => {
   logger.debug('no authenticated user', err);
   authState.next({ state: 'signedOut', user: null });
 });
Example #28
0
    constructor(element: HTMLElement) {
        this._element = element;

        this._preventMouseDownOperation$ = new Subject<IPreventMouseDownOperation>();
        this._preventMouseDown$ = new Subject<boolean>();
        this._mouseMoveOperation$ = new Subject<IMouseMoveOperation>();
        this._claimMouse$ = new Subject<IMouseClaim>();

        this._mouseDown$ = Observable.fromEvent<MouseEvent>(element, "mousedown");
        this._mouseLeave$ = Observable.fromEvent<MouseEvent>(element, "mouseleave");
        this._mouseUp$ = Observable.fromEvent<MouseEvent>(element, "mouseup");
        this._mouseOver$ = Observable.fromEvent<MouseEvent>(element, "mouseover");

        this._click$ = Observable.fromEvent<MouseEvent>(element, "click");

        this._mouseWheel$ = Observable.fromEvent<WheelEvent>(element, "wheel");

        this._mouseWheel$
            .subscribe(
                (event: WheelEvent): void => {
                    event.preventDefault();
                });

        this._preventMouseDownOperation$
            .scan<boolean>(
                (prevent: boolean, operation: IPreventMouseDownOperation): boolean => {
                    return operation(prevent);
                },
                true)
            .subscribe();

        this._preventMouseDown$
            .map<IPreventMouseDownOperation>(
                (prevent: boolean): IPreventMouseDownOperation => {
                    return (previous: boolean): boolean => {
                        return prevent;
                    };
                })
            .subscribe(this._preventMouseDownOperation$);

        this._mouseDown$
            .map<IPreventMouseDownOperation>(
                (e: MouseEvent): IPreventMouseDownOperation => {
                    return (prevent: boolean): boolean => {
                        if (prevent) {
                            e.preventDefault();
                        }

                        return prevent;
                    };
                })
            .subscribe(this._preventMouseDownOperation$);

        this._mouseMove$ = this._mouseMoveOperation$
            .scan<MouseEvent>(
                (e: MouseEvent, operation: IMouseMoveOperation): MouseEvent => {
                    return operation(e);
                },
                null);

        Observable
            .fromEvent<MouseEvent>(element, "mousemove")
            .map<IMouseMoveOperation>(
                (e: MouseEvent) => {
                    return (previous: MouseEvent): MouseEvent => {
                        if (previous == null) {
                            previous = e;
                        }

                        if (e.movementX == null) {
                            e.movementX = e.clientX - previous.clientX;
                        }

                        if (e.movementY == null) {
                            e.movementY = e.clientY - previous.clientY;
                        }

                        return e;
                    };
                })
            .subscribe(this._mouseMoveOperation$);

        let dragStop$: Observable<MouseEvent> = Observable
            .merge<MouseEvent>(this._mouseLeave$, this._mouseUp$);

        this._mouseDragStart$ = this._mouseDown$
            .mergeMap<MouseEvent>((e: MouseEvent): Observable<MouseEvent> => {
                return this._mouseMove$
                    .takeUntil(dragStop$)
                    .take(1);
            });

        this._mouseDrag$ = this._mouseDown$
            .mergeMap<MouseEvent>((e: MouseEvent): Observable<MouseEvent> => {
                return this._mouseMove$
                    .skip(1)
                    .takeUntil(dragStop$);
            });

        this._mouseDragEnd$ = this._mouseDragStart$
            .mergeMap<MouseEvent>((e: MouseEvent): Observable<MouseEvent> => {
                return dragStop$.first();
            });

        this._staticClick$ = this._mouseDown$
            .switchMap<MouseEvent>(
                (e: MouseEvent): Observable<MouseEvent> => {
                    return this._click$
                        .takeUntil(this._mouseMove$)
                        .take(1);
                });

        this._mouseOwner$ = this._claimMouse$
            .scan<{[key: string]: number}>(
                (claims: {[key: string]: number}, mouseClaim: IMouseClaim): {[key: string]: number} => {
                    if (mouseClaim.zindex == null) {
                        delete claims[mouseClaim.name];
                    } else {
                        claims[mouseClaim.name] = mouseClaim.zindex;
                    }
                    return claims;
                },
                {})
            .map<string>((claims: {[key: string]: number}): string => {
                let owner: string = null;
                let curZ: number = -1;

                for (let name in claims) {
                    if (claims.hasOwnProperty(name)) {
                        if (claims[name] > curZ) {
                            curZ = claims[name];
                            owner = name;
                        }
                    }
                }
                return owner;
            })
            .publishReplay(1)
            .refCount();
    }
 .then(data => {
   logger.debug('signUp success');
   authState.next({ state: 'confirmSignUp', user: { username: username }});
   return data;
 })
 set selectedFunction(value: FunctionInfo) {
     this.functionSelectStream
         .next(value);
 }