public ServiceHostEventListener(IQueryDispatcher queryDispatcher, IOptions <ServiceHostEventListenerOptions>?options, ILogger <ServiceHostEventListener>?logger) { _queryDispatcher = queryDispatcher ?? throw new ArgumentNullException(nameof(queryDispatcher)); _logger = logger ?? (ILogger)NullLogger.Instance; var optionsValue = options?.Value; _delayOnDropout = optionsValue?.DelayOnDropout ?? ServiceHostEventListenerOptions.DefaultDelayOnDropout; _isActiveSubject = new BehaviorSubject <bool>(true); IsActive = _isActiveSubject .StartWith(true) .DistinctUntilChanged(); var events = Observable .Create <Event>(observer => { var query = new StreamBusEventsQuery { OnEvent = (_, @event) => observer.OnNext(@event) }; return(Observable .FromAsync(async ct => { await _queryDispatcher.DispatchAsync(query, ct).ConfigureAwait(false); throw new InvalidOperationException($"{nameof(StreamBusEventsQuery)} returned unexpectedly."); }) .Subscribe(Noop <Unit> .Action, observer.OnError)); }) .Do(OnEventReceived, OnStreamError) .Retry(wrapSubsequent: source => source.DelaySubscription(_delayOnDropout)) // when subject completes, event stream should complete as well .TakeUntil(_isActiveSubject.Where(_ => false).Materialize()) .Publish(); _events = events.AsObservable(); // no need to explicitly disconnect in Dispose because of TakeUntil events.Connect(); }
protected override void Start() { var rectTransform = ((RectTransform)transform); var topMiddle = new Vector2(0.5f, 1); rectTransform.anchorMin = topMiddle; rectTransform.anchorMax = topMiddle; Tweener tween = null; var dragging = false; m_Record .StartWith(new Record()) .Pairwise() .Where(record => IsValid() && record.Current.piece != null) .Subscribe(pair => { // TODO: Handle a client simulated record somehow special var value = pair.Current; var previous = pair.Previous; var thisStyle = m_Styles.First(style => style.playerId == value.piece.playerId && style.pieceType == value.piece.pieceType); m_Image.sprite = thisStyle.sprite; m_Image.SetNativeSize(); tween?.Kill(); tween = rectTransform.DOAnchorPos(m_BoardView.GetPieceCenterFromTop(value.piece.position), m_TweenDuration); }) .AddTo(this); // Handle dragging and dropping this.OnBeginDragAsObservable() .Subscribe(pointer => { dragging = true; }).AddTo(this); Observable.EveryUpdate() .Where(ignored => dragging) .Subscribe(ignore => { var pointer = ContinuousStandaloneInputModule.instance.pointerEventData; rectTransform.position = pointer.position; }) .AddTo(this); this.OnEndDragAsObservable() .Subscribe(pointer => { dragging = false; var destination = m_BoardView.GetClosestIndexToPointer(pointer); if (destination == -1) { // Not a valid destination, refresh the record to return to the source location. m_Record.OnNext(m_Record.Value); return; } var currentPieceRecord = pieceState; // Eagerly assume the move succeeded m_Record.OnNext(new Record() { id = m_Record.Value.id, piece = new Piece() { pieceType = m_Record.Value.piece.pieceType, playerId = m_Record.Value.piece.playerId, position = destination } }); // Now actually request the move. Ensures that in order, the real result will always come first. m_MoveRequestedSubject.OnNext(new MoveEvent() { sender = this, record = currentPieceRecord, destination = destination }); }).AddTo(this); }
public ReportsViewModel(ITogglDataSource dataSource, ITimeService timeService, INavigationService navigationService, IInteractorFactory interactorFactory, IAnalyticsService analyticsService, ISchedulerProvider schedulerProvider, IRxActionFactory rxActionFactory) : base(navigationService) { Ensure.Argument.IsNotNull(dataSource, nameof(dataSource)); Ensure.Argument.IsNotNull(timeService, nameof(timeService)); Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory)); Ensure.Argument.IsNotNull(analyticsService, nameof(analyticsService)); Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory)); Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider)); Ensure.Argument.IsNotNull(navigationService, nameof(navigationService)); this.dataSource = dataSource; this.timeService = timeService; this.analyticsService = analyticsService; this.interactorFactory = interactorFactory; CalendarViewModel = new ReportsCalendarViewModel(timeService, dataSource, rxActionFactory, navigationService, schedulerProvider); var totalsObservable = reportSubject .SelectMany(_ => interactorFactory.GetReportsTotals(userId, workspaceId, startDate, endDate).Execute()) .Catch <ITimeEntriesTotals, OfflineException>(_ => Observable.Return <ITimeEntriesTotals>(null)) .Where(report => report != null); BarChartViewModel = new ReportsBarChartViewModel(schedulerProvider, dataSource.Preferences, totalsObservable, navigationService); IsLoadingObservable = isLoading.AsObservable().AsDriver(schedulerProvider); StartDate = startDateSubject.AsObservable().AsDriver(schedulerProvider); EndDate = endDateSubject.AsObservable().AsDriver(schedulerProvider); SelectWorkspace = rxActionFactory.FromAsync(selectWorkspace); WorkspaceId = workspaceSubject .Select(workspace => workspace.Id) .DistinctUntilChanged() .AsDriver(schedulerProvider); WorkspaceNameObservable = workspaceSubject .Select(workspace => workspace?.Name ?? string.Empty) .DistinctUntilChanged() .AsDriver(schedulerProvider); WorkspaceHasBillableFeatureEnabled = workspaceSubject .Where(workspace => workspace != null) .SelectMany(workspace => interactorFactory.GetWorkspaceFeaturesById(workspace.Id).Execute()) .Select(workspaceFeatures => workspaceFeatures.IsEnabled(WorkspaceFeatureId.Pro)) .StartWith(false) .DistinctUntilChanged() .AsDriver(schedulerProvider); CurrentDateRange = currentDateRangeStringSubject .StartWith(Resources.ThisWeek) .Where(text => !string.IsNullOrEmpty(text)) .Select(text => $"{text} ▾") .DistinctUntilChanged() .AsDriver(schedulerProvider); WorkspacesObservable = interactorFactory.ObserveAllWorkspaces().Execute() .Select(list => list.Where(w => !w.IsInaccessible)) .Select(readOnlyWorkspaceSelectOptions) .AsDriver(schedulerProvider); DurationFormatObservable = dataSource.Preferences.Current .Select(prefs => prefs.DurationFormat) .AsDriver(schedulerProvider); SegmentsObservable = segmentsSubject.CombineLatest(DurationFormatObservable, applyDurationFormat); GroupedSegmentsObservable = SegmentsObservable.CombineLatest(DurationFormatObservable, groupSegments); ShowEmptyStateObservable = SegmentsObservable.CombineLatest(IsLoadingObservable, shouldShowEmptyState); }