public TimelineViewModel()
        {
            this.WhenAnyValue(x => x.RecordActivity).ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(value => Toggl.SetTimelineRecordingEnabled(value));
            OpenTogglHelpUri = ReactiveCommand.Create(() =>
                                                      Toggl.OpenInBrowser("https://support.toggl.com/en/articles/3836325-toggl-desktop-for-windows"));

            Toggl.TimelineSelectedDate.Subscribe(date => SelectedDate = date);

            this.WhenAnyValue(x => x.SelectedDate)
            .Where(date => date != Toggl.TimelineSelectedDate.Value)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(date => Toggl.SetViewTimelineDay(Toggl.UnixFromDateTime(date)));

            this.WhenAnyValue(x => x.SelectedDate)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(LoadMoreIfNeeded);

            this.WhenAnyValue(x => x.SelectedDate)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(_ => HideEditViewIfNeeded());

            Toggl.TimelineSelectedDate
            .Select(dateTime => dateTime.Date == DateTime.Today.Date)
            .ToPropertyEx(this, x => x.IsTodaySelected);

            SelectPreviousDay = ReactiveCommand.Create(Toggl.ViewTimelinePreviousDay);
            SelectNextDay     = ReactiveCommand.Create(Toggl.ViewTimelineNextDay);
            IncreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(-1));
            DecreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(1));
            var scaleModeObservable = this.WhenAnyValue(x => x.SelectedScaleMode);

            scaleModeObservable.Subscribe(_ =>
                                          HourHeightView = TimelineConstants.ScaleModes[SelectedScaleMode] * GetHoursInLine(SelectedScaleMode));
            scaleModeObservable.Select(GetHoursListFromScale).ToPropertyEx(this, x => x.HourViews);
            scaleModeObservable.Select(mode => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, mode))
            .Subscribe(h => CurrentTimeOffset = h);

            Toggl.TimelineChunks.CombineLatest(scaleModeObservable, (items, mode) => ConvertChunksToActivityBlocks(items, mode, SelectedDate))
            .ToPropertyEx(this, x => x.ActivityBlocks);
            Toggl.TimelineTimeEntries.CombineLatest(scaleModeObservable, (items, mode) => ConvertTimeEntriesToBlocks(items, mode, SelectedDate))
            .ToPropertyEx(this, x => x.TimeEntryBlocks);
            Toggl.TimelineTimeEntries.CombineLatest(scaleModeObservable, GenerateGapTimeEntryBlocks)
            .ToPropertyEx(this, x => x.GapTimeEntryBlocks);

            this.WhenAnyValue(x => x.TimeEntryBlocks)
            .Where(blocks => blocks != null && blocks.Any())
            .Select(blocks => blocks.Min(te => te.VerticalOffset))
            .ToPropertyEx(this, x => x.FirstTimeEntryOffset);

            Toggl.OnTimeEntryList   += HandleTimeEntryListChanged;
            Toggl.OnTimeEntryEditor += (open, te, field) =>
                                       SelectedForEditTEId = open ? te.GUID : SelectedForEditTEId;
            this.WhenAnyValue(x => x.SelectedForEditTEId, x => x.TimeEntryBlocks)
            .ObserveOn(RxApp.TaskpoolScheduler).Subscribe(_ =>
                                                          TimeEntryBlocks?.ForEach(te => te.IsEditViewOpened = SelectedForEditTEId == te.TimeEntryId));
            Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1))
            .Select(_ => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, SelectedScaleMode))
            .Subscribe(h => CurrentTimeOffset = h);
        }
Esempio n. 2
0
        public TimelineViewModel()
        {
            this.WhenAnyValue(x => x.RecordActivity).ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(value => Toggl.SetTimelineRecordingEnabled(value));
            OpenTogglHelpUri = ReactiveCommand.Create(() =>
                                                      Toggl.OpenInBrowser("https://support.toggl.com/en/articles/3836325-toggl-desktop-for-windows"));
            this.WhenAnyValue(x => x.SelectedDate).Subscribe(HandleSelectedDateChanged);
            SelectPreviousDay = ReactiveCommand.Create(Toggl.ViewTimelinePreviousDay);
            SelectNextDay     = ReactiveCommand.Create(Toggl.ViewTimelineNextDay);
            IncreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(-1));
            DecreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(1));
            var scaleModeObservable = this.WhenAnyValue(x => x.SelectedScaleMode);

            scaleModeObservable.Subscribe(_ =>
                                          HourHeightView = ScaleModes[SelectedScaleMode] * GetHoursInLine(SelectedScaleMode));
            scaleModeObservable.Where(_ => _timelineChunks != null)
            .Subscribe(_ => ConvertChunksToActivityBlocks(_timelineChunks));
            scaleModeObservable.Where(_ => _timeEntries != null)
            .Subscribe(_ => ConvertTimeEntriesToBlocks(_timeEntries));
            scaleModeObservable.Select(GetHoursListFromScale).ToPropertyEx(this, x => x.HourViews);
            scaleModeObservable.Select(mode => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, mode))
            .Subscribe(h => CurrentTimeOffset = h);
            Toggl.OnTimeline        += HandleDisplayTimeline;
            Toggl.OnTimeEntryList   += HandleTimeEntryListChanged;
            Toggl.OnTimeEntryEditor += (open, te, field) =>
                                       SelectedForEditTEId = open ? te.GUID : SelectedForEditTEId;
            this.WhenAnyValue(x => x.SelectedForEditTEId, x => x.TimeEntryBlocks)
            .ObserveOn(RxApp.TaskpoolScheduler).Subscribe(_ =>
                                                          TimeEntryBlocks?.ForEach(te => te.IsEditViewOpened = SelectedForEditTEId == te.TimeEntryId));
            HourViews = GetHoursListFromScale(SelectedScaleMode);
            Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(1))
            .Select(_ => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, SelectedScaleMode))
            .Subscribe(h => CurrentTimeOffset = h);
            this.WhenAnyValue(x => x.SelectedDate)
            .Select(dateTime => dateTime.Date == DateTime.Today.Date)
            .ToPropertyEx(this, x => x.IsTodaySelected);
        }
Esempio n. 3
0
        public TimelineViewModel()
        {
            this.WhenAnyValue(x => x.RecordActivity).ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(value => Toggl.SetTimelineRecordingEnabled(value));
            OpenTogglHelpUri = ReactiveCommand.Create(() =>
                                                      Toggl.OpenInBrowser("https://support.toggl.com/en/articles/3836325-toggl-desktop-for-windows"));

            Toggl.TimelineSelectedDate.Subscribe(date => SelectedDate = date);

            this.WhenAnyValue(x => x.SelectedDate)
            .Where(date => date != Toggl.TimelineSelectedDate.Value)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(date => Toggl.SetViewTimelineDay(Toggl.UnixFromDateTime(date)));

            this.WhenAnyValue(x => x.SelectedDate)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(LoadMoreIfNeeded);

            this.WhenAnyValue(x => x.SelectedDate)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(_ => HideEditViewIfNeeded());

            Toggl.TimelineSelectedDate
            .Select(dateTime => dateTime.Date == DateTime.Today.Date)
            .ToPropertyEx(this, x => x.IsTodaySelected);

            SelectPreviousDay = ReactiveCommand.Create(Toggl.ViewTimelinePreviousDay);
            SelectNextDay     = ReactiveCommand.Create(Toggl.ViewTimelineNextDay);
            IncreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(-1));
            DecreaseScale     = ReactiveCommand.Create(() => SelectedScaleMode = ChangeScaleMode(1));
            var activeBlockObservable  = this.WhenAnyValue(x => x.ActiveTimeEntryBlock);
            var isNotRunningObservable = activeBlockObservable.Select(next => next != null && next.DurationInSeconds >= 0);

            ContinueEntry = ReactiveCommand.Create(() => Toggl.Continue(ActiveTimeEntryBlock.TimeEntryId), isNotRunningObservable);
            CreateFromEnd = ReactiveCommand.Create(() => TimelineUtils.CreateAndEditTimeEntry(ActiveTimeEntryBlock.Ended, ActiveTimeEntryBlock.Ended + TimelineConstants.DefaultTimeEntryLengthInSeconds), isNotRunningObservable);
            StartFromEnd  = ReactiveCommand.Create(() => TimelineUtils.CreateAndEditRunningTimeEntryFrom(ActiveTimeEntryBlock.Ended), isNotRunningObservable);
            Delete        = ReactiveCommand.Create(() => ActiveTimeEntryBlock.DeleteTimeEntry(), activeBlockObservable.Select(next => next != null));
            var isOverlapping = activeBlockObservable.Select(next => next != null && next.IsOverlapping);

            ChangeFirstTimeEntryStopCommand =
                ReactiveCommand.Create(() => ChangeFirstEntryStop(ActiveTimeEntryBlock, SortedTimeEntryBlocks), isOverlapping);
            ChangeLastTimeEntryStartCommand =
                ReactiveCommand.Create(() => ChangeLastEntryStart(ActiveTimeEntryBlock, SortedTimeEntryBlocks), isOverlapping);
            var scaleModeObservable = this.WhenAnyValue(x => x.SelectedScaleMode);

            scaleModeObservable.Subscribe(_ =>
                                          HourHeightView = TimelineConstants.ScaleModes[SelectedScaleMode] * GetHoursInLine(SelectedScaleMode));
            scaleModeObservable.Select(GetHoursListFromScale).ToPropertyEx(this, x => x.HourViews);
            scaleModeObservable.Select(mode => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, mode))
            .Subscribe(h => CurrentTimeOffset = h);

            Toggl.TimelineChunks.CombineLatest(scaleModeObservable, (items, mode) => ConvertChunksToActivityBlocks(items, mode, SelectedDate))
            .ToPropertyEx(this, x => x.ActivityBlocks);
            var blocksObservable = Toggl.TimelineTimeEntries
                                   .CombineLatest(Toggl.RunningTimeEntry, scaleModeObservable,
                                                  (list, running, mode) => ConvertTimeEntriesToBlocks(list, running, mode, SelectedDate));
            var blocksWithRunningObservable = blocksObservable.CombineLatest(Toggl.RunningTimeEntry,
                                                                             (list, te) => (TimeEntries: list, Running: te))
                                              .Where(_ => (TimeEntryBlocks == null || !TimeEntryBlocks.Any(item => item.Value.IsDragged)) &&
                                                     (RunningTimeEntryBlock == null || !RunningTimeEntryBlock.IsDragged));

            blocksWithRunningObservable.Select(tuple =>
                                               tuple.Running.HasValue ? tuple.TimeEntries.GetValueOrDefault(tuple.Running.Value.GUID) : null)
            .ToPropertyEx(this, x => x.RunningTimeEntryBlock);
            blocksWithRunningObservable.Select(tuple =>
                                               tuple.TimeEntries.Where(b => b.Key != tuple.Running?.GUID)
                                               .ToDictionary(pair => pair.Key, pair => pair.Value))
            .ToPropertyEx(this, x => x.TimeEntryBlocks);
            var sortedTimeEntriesObservable = blocksObservable.Select(blocks =>
            {
                var timeEntries = blocks.Values.ToList();
                timeEntries.Sort((te1, te2) => te1.VerticalOffset.CompareTo(te2.VerticalOffset));
                return(timeEntries);
            });

            sortedTimeEntriesObservable.ToPropertyEx(this, x => x.SortedTimeEntryBlocks);
            sortedTimeEntriesObservable.Select(GenerateGapTimeEntryBlocks)
            .ToPropertyEx(this, x => x.GapTimeEntryBlocks);
            blocksWithRunningObservable
            .Select(tuple =>
                    GenerateRunningGapBlock(tuple.TimeEntries.Values, tuple.Running, CurrentTimeOffset, SelectedDate))
            .ToPropertyEx(this, x => x.RunningGapTimeEntryBlock);

            this.WhenAnyValue(x => x.TimeEntryBlocks)
            .Where(blocks => blocks != null && blocks.Any())
            .Select(blocks => blocks.Min(te => te.Value.VerticalOffset))
            .ToPropertyEx(this, x => x.FirstTimeEntryOffset);

            Toggl.OnTimeEntryList   += HandleTimeEntryListChanged;
            Toggl.OnTimeEntryEditor += (open, te, field) =>
                                       SelectedForEditTEId = open ? te.GUID : SelectedForEditTEId;
            this.WhenAnyValue(x => x.SelectedForEditTEId, x => x.TimeEntryBlocks)
            .ObserveOn(RxApp.TaskpoolScheduler).Subscribe(_ =>
                                                          TimeEntryBlocks?.ForEach(te => te.Value.IsEditViewOpened = SelectedForEditTEId == te.Key));
            this.WhenAnyValue(x => x.SelectedForEditTEId, x => x.RunningTimeEntryBlock)
            .Where(pair => pair.Item2 != null)
            .Subscribe(pair => pair.Item2.IsEditViewOpened = pair.Item1 == pair.Item2.TimeEntryId);
            var curOffsetObservable = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
                                      .Select(_ => ConvertTimeIntervalToHeight(DateTime.Today, DateTime.Now, SelectedScaleMode));

            curOffsetObservable.Subscribe(h => CurrentTimeOffset = h);
            curOffsetObservable.Select(offset => (Offset: offset,
                                                  Block: RunningTimeEntryBlock as TimelineBlockViewModel ?? RunningGapTimeEntryBlock))
            .Where(tuple => tuple.Block != null)
            .Subscribe(tuple => tuple.Block.Height = tuple.Offset - tuple.Block.VerticalOffset);
            this.WhenAnyValue(x => x.TimeEntryBlocks, x => x.RunningTimeEntryBlock, x => x.IsTodaySelected,
                              (blocks, running, isToday) => blocks?.Any() == true || (running != null && isToday))
            .ToPropertyEx(this, x => x.AnyTimeEntries);
        }