public override void ConfirmStopTimer(StopTimerIntent intent, Action <StopTimerIntentResponse> completion)
        {
            if (togglAPI == null)
            {
                var userActivity = new NSUserActivity(stopTimerActivityType);
                userActivity.SetResponseText("Log in to use this shortcut.");
                completion(new StopTimerIntentResponse(StopTimerIntentResponseCode.FailureNoApiToken, userActivity));
                return;
            }

            var lastUpdated = SharedStorage.instance.GetLastUpdateDate();

            togglAPI.TimeEntries.GetAll()
            .Select(checkSyncConflicts(lastUpdated))
            .Select(getRunningTimeEntry)
            .Subscribe(
                runningTE =>
            {
                runningEntry     = runningTE;
                var userActivity = new NSUserActivity(stopTimerActivityType);
                userActivity.SetEntryDescription(runningTE.Description);
                completion(new StopTimerIntentResponse(StopTimerIntentResponseCode.Ready, userActivity));
            },
                exception =>
            {
                SharedStorage.instance.AddSiriTrackingEvent(SiriTrackingEvent.Error(exception.Message));
                completion(responseFromException(exception));
            });
        }
        public override void ConfirmContinueTimer(ContinueTimerIntent intent, Action <ContinueTimerIntentResponse> completion)
        {
            if (togglAPI == null)
            {
                completion(new ContinueTimerIntentResponse(ContinueTimerIntentResponseCode.FailureNoApiToken, null));
                return;
            }

            togglAPI.TimeEntries.GetAll()
            .ToObservable()
            .FirstAsync()
            .Select(timeEntries => timeEntries.First())
            .Subscribe(
                timeEntry =>
            {
                lastEntry        = timeEntry;
                var userActivity = new NSUserActivity(continueTimerActivityType);
                userActivity.SetEntryDescription(timeEntry.Description);
                completion(new ContinueTimerIntentResponse(ContinueTimerIntentResponseCode.Ready, userActivity));
            },
                exception =>
            {
                completion(new ContinueTimerIntentResponse(ContinueTimerIntentResponseCode.Failure, null));
            });
        }
        public override void ConfirmStopTimer(StopTimerIntent intent, Action <StopTimerIntentResponse> completion)
        {
            if (togglAPI == null)
            {
                var userActivity = new NSUserActivity(stopTimerActivityType);
                userActivity.SetResponseText(Resources.SiriShortcutLoginToUseShortcut);
                completion(new StopTimerIntentResponse(StopTimerIntentResponseCode.FailureNoApiToken, userActivity));
                return;
            }

            togglAPI.TimeEntries.GetAll()
            .Select(getRunningTimeEntry)
            .Subscribe(
                runningTE =>
            {
                runningEntry     = runningTE;
                var userActivity = new NSUserActivity(stopTimerActivityType);
                userActivity.SetEntryDescription(runningTE.Description);
                completion(new StopTimerIntentResponse(StopTimerIntentResponseCode.Ready, userActivity));
            },
                exception =>
            {
                SharedStorage.instance.AddSiriTrackingEvent(SiriTrackingEvent.Error(exception.Message));
                completion(responseFromException(exception));
            });
        }
Beispiel #4
0
        public void DonateStartTimeEntry(IWorkspace workspace, ITimeEntry timeEntry)
        {
            if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
            {
                return;
            }

            var intent = new StartTimerIntent();

            intent.Workspace = new INObject(workspace.Id.ToString(), workspace.Name);
            if (!string.IsNullOrEmpty(timeEntry.Description))
            {
                // If any of the tags or the project id were just created and haven't sync we ignore this action until the user repeats it
                if (timeEntry.ProjectId < 0 || timeEntry.TagIds.Any(tagId => tagId < 0))
                {
                    return;
                }

                intent.EntryDescription          = timeEntry.Description;
                intent.ProjectId                 = new INObject(timeEntry.ProjectId.ToString(), timeEntry.ProjectId.ToString());
                intent.Tags                      = timeEntry.TagIds.Select(tag => new INObject(tag.ToString(), tag.ToString())).ToArray();
                intent.Billable                  = new INObject(timeEntry.Billable.ToString(), timeEntry.Billable.ToString());
                intent.SuggestedInvocationPhrase = timeEntry.Description;
            }
            else
            {
                intent.SuggestedInvocationPhrase = "Start timer";
            }

            var interaction = new INInteraction(intent, null);

            interaction.DonateInteraction(onCompletion);
        }
Beispiel #5
0
 private async Task stopTimeEntry(ITimeEntry timeEntry)
 {
     var duration = (long)(DateTime.Now - timeEntry.Start).TotalSeconds;
     await togglApi.TimeEntries.Update(
         TimeEntry.From(timeEntry).With(duration)
         );
 }
Beispiel #6
0
        private bool isInLastTwoWeeks(ITimeEntry timeEntry)
        {
            var twoWeeks = TimeSpan.FromDays(14);
            var delta    = timeService.CurrentDateTime - timeEntry.Start;

            return(delta <= twoWeeks);
        }
Beispiel #7
0
        public RealmTimeEntry(ITimeEntry entity, Realms.Realm realm)
        {
            Id = entity.Id;
            var skipWorkspaceFetch = entity?.WorkspaceId == null || entity.WorkspaceId == 0;

            RealmWorkspace = skipWorkspaceFetch ? null :realm.All <RealmWorkspace>().Single(x => x.Id == entity.WorkspaceId);
            var skipProjectFetch = entity?.ProjectId == null || entity.ProjectId == 0;

            RealmProject = skipProjectFetch ? null :realm.All <RealmProject>().Single(x => x.Id == entity.ProjectId);
            var skipTaskFetch = entity?.TaskId == null || entity.TaskId == 0;

            RealmTask       = skipTaskFetch ? null :realm.All <RealmTask>().Single(x => x.Id == entity.TaskId);
            Billable        = entity.Billable;
            Start           = entity.Start;
            Stop            = entity.Stop;
            Duration        = entity.Duration;
            Description     = entity.Description;
            Tags            = entity.Tags;
            TagIds          = entity.TagIds;
            At              = entity.At;
            ServerDeletedAt = entity.ServerDeletedAt;
            var skipUserFetch = entity?.UserId == null || entity.UserId == 0;

            RealmUser   = skipUserFetch ? null :realm.All <RealmUser>().Single(x => x.Id == entity.UserId);
            CreatedWith = entity.CreatedWith;
            IsDirty     = true;
        }
Beispiel #8
0
        public IObservable <ITimeEntry> Create(ITimeEntry timeEntry)
        {
            var endPoint      = endPoints.Post(timeEntry.WorkspaceId);
            var timeEntryCopy = timeEntry as TimeEntry ?? new TimeEntry(timeEntry);
            var observable    = CreateObservable(endPoint, AuthHeader, timeEntryCopy, SerializationReason.Post);

            return(observable);
        }
Beispiel #9
0
 public TimeEntryViewModel(ITimeEntry timeEntry, string projectName, string projectColor, string taskName, string clientName)
 {
     TimeEntry    = timeEntry;
     ProjectName  = projectName;
     ProjectColor = projectColor;
     TaskName     = taskName;
     ClientName   = clientName;
 }
        private IObservable <ITimeEntry> stopTimeEntry(ITimeEntry timeEntry)
        {
            var duration = (long)(DateTime.Now - timeEntry.Start).TotalSeconds;

            return(togglAPI.TimeEntries.Update(
                       TimeEntry.from(timeEntry).with(duration)
                       ));
        }
 public static StartTimeEntryEvent With(TimeEntryStartOrigin origin, ITimeEntry timeEntry)
 => new StartTimeEntryEvent(
     origin,
     string.IsNullOrWhiteSpace(timeEntry.Description),
     timeEntry.ProjectId != null,
     timeEntry.TaskId != null,
     timeEntry.TagIds.Count(),
     timeEntry.Billable,
     timeEntry.IsRunning());
        public override IFightConfigurationTeamEntry Get()
        {
            this.Position    = this.Section.GetValue <IVectorEntry>(this.FieldKey + ".pos");
            this.StartX      = this.Section.GetValue <int>(this.FieldKey + ".start.x");
            this.Counter     = this.Section.GetValue <ITextEntry>(this.FieldKey + ".counter");
            this.Text        = this.Section.GetValue <ITextEntry>(this.FieldKey + ".text");
            this.DisplayTime = this.Section.GetValue <ITimeEntry>(this.FieldKey + ".displaytime");

            return(this);
        }
Beispiel #13
0
        private bool isWithinThresholdAndHasDescription(ITimeEntry timeEntry)
        {
            if (string.IsNullOrEmpty(timeEntry.Description))
            {
                return(false);
            }

            var delta = timeService.CurrentDateTime - timeEntry.Start;

            return(delta <= thresholdPeriod);
        }
 public static SiriTrackingEvent StartTimer(ITimeEntry te)
 {
     return(new SiriTrackingEvent(SiriTrackingEventType.StartTimer, new Dictionary <string, string>
     {
         [SiriStartTimerEventKeys.HasEmptyDescription] = string.IsNullOrEmpty(te.Description).ToString(),
         [SiriStartTimerEventKeys.HasProject] = (te.ProjectId != null).ToString(),
         [SiriStartTimerEventKeys.HasTask] = (te.TaskId != null).ToString(),
         [SiriStartTimerEventKeys.NumberOfTags] = te.TagIds.Count().ToString(),
         [SiriStartTimerEventKeys.IsBillable] = te.Billable.ToString()
     }));
 }
Beispiel #15
0
 public async Task Delete(ITimeEntry timeEntry)
 {
     try
     {
         var deleteEndpoint = endPoints.Delete(timeEntry.WorkspaceId, timeEntry.Id);
         await SendRequest <ITimeEntry>(deleteEndpoint, AuthHeader)
         .ConfigureAwait(false);
     }
     catch (NotFoundException)
     {
     }
 }
Beispiel #16
0
        private Task <ITimeEntry> pushTimeEntry(Endpoint endPoint, ITimeEntry timeEntry, SerializationReason reason)
        {
            var timeEntryCopy = timeEntry as TimeEntry ?? new TimeEntry(timeEntry);

            if (reason == SerializationReason.Post)
            {
                timeEntryCopy.CreatedWith = userAgent.ToString();
            }

            return(SendRequest(endPoint, AuthHeader, timeEntryCopy, reason)
                   .Upcast <ITimeEntry, TimeEntry>());
        }
        public override IImageEntry Get()
        {
            this.Sprite    = this.Section.GetValue <IVectorEntry>(this.FieldKey + ".spr");
            this.Offset    = this.Section.GetValue <IVectorEntry>(this.FieldKey + ".offset");
            this.Scale     = this.Section.GetValue <IVectorEntry>(this.FieldKey + ".scale");
            this.Facing    = this.Section.GetValue <int>(this.FieldKey + ".facing");
            this.Window    = this.Section.GetValue <IVectorEntry>(this.FieldKey + ".window");
            this.Animation = this.Section.GetValue <int>(this.FieldKey + ".anim");
            this.Time      = this.Section.GetValue <ITimeEntry>(this.FieldKey + ".time");
            this.StartTime = this.Section.GetValue <ITimeEntry>(this.FieldKey + ".starttime");

            return(this);
        }
Beispiel #18
0
        private IObservable <IThreadSafeProject> createProjectPlaceholder(ITimeEntry timeEntry)
        {
            var placeholder = Project.Builder.Create(timeEntry.ProjectId.Value)
                              .SetName(Resources.InaccessibleProject)
                              .SetWorkspaceId(timeEntry.WorkspaceId)
                              .SetColor(Helper.Colors.NoProject)
                              .SetActive(false)
                              .SetAt(default(DateTimeOffset))
                              .SetSyncStatus(SyncStatus.RefetchingNeeded)
                              .Build();

            return(dataSource.Create(placeholder));
        }
Beispiel #19
0
        private IObservable <ITimeEntry> pushTimeEntry(Endpoint endPoint, ITimeEntry timeEntry, SerializationReason reason)
        {
            var timeEntryCopy = timeEntry as TimeEntry ?? new TimeEntry(timeEntry);

            if (reason == SerializationReason.Post)
            {
                timeEntryCopy.CreatedWith = userAgent.ToString();
            }

            var observable = CreateObservable(endPoint, AuthHeader, timeEntryCopy, reason);

            return(observable);
        }
        public void DonateStartTimeEntry(IWorkspace workspace, ITimeEntry timeEntry)
        {
            if (!UIDevice.CurrentDevice.CheckSystemVersion(12, 0))
            {
                return;
            }

            var relevantShortcuts = new List <INRelevantShortcut>();

            var intent = new StartTimerIntent();

            intent.Workspace = new INObject(workspace.Id.ToString(), workspace.Name);
            if (!string.IsNullOrEmpty(timeEntry.Description))
            {
                // If any of the tags or the project id were just created and haven't sync we ignore this action until the user repeats it
                if (timeEntry.ProjectId < 0 || timeEntry.TagIds.Any(tagId => tagId < 0))
                {
                    return;
                }

                intent.EntryDescription          = timeEntry.Description;
                intent.ProjectId                 = new INObject(timeEntry.ProjectId.ToString(), timeEntry.ProjectId.ToString());
                intent.Tags                      = timeEntry.TagIds.Select(tag => new INObject(tag.ToString(), tag.ToString())).ToArray();
                intent.Billable                  = new INObject(timeEntry.Billable.ToString(), timeEntry.Billable.ToString());
                intent.SuggestedInvocationPhrase = $"Track {timeEntry.Description}";

                // Relevant shortcut for the Siri Watch Face
                var shortcut = createRelevantShortcut(intent);
                relevantShortcuts.Add(shortcut);
            }
            else
            {
                intent.SuggestedInvocationPhrase = Resources.StartTimerInvocationPhrase;
            }

            var interaction = new INInteraction(intent, null);

            interaction.DonateInteraction(trackError);

            // Descriptionless Relevant Shortcut. Always added even if the intent has one
            var descriptionlessIntent = new StartTimerIntent();

            descriptionlessIntent.Workspace = new INObject(workspace.Id.ToString(), workspace.Name);
            var descriptionlessShortcut = createRelevantShortcut(descriptionlessIntent);

            relevantShortcuts.Add(descriptionlessShortcut);

            donateRelevantShortcuts(relevantShortcuts.ToArray());
        }
 private ITimeEntry continueTimeEntry(ITimeEntry originalTE) =>
 new TimeEntry(
     originalTE.WorkspaceId,
     originalTE.ProjectId,
     originalTE.TaskId,
     originalTE.Billable,
     DateTimeOffset.Now,
     null,
     originalTE.Description,
     originalTE.TagIds ?? new long[0],
     originalTE.UserId,
     0,
     null,
     DateTimeOffset.Now
     );
 public TimeEntry(ITimeEntry entity)
 {
     Id              = entity.Id;
     WorkspaceId     = entity.WorkspaceId;
     ProjectId       = entity.ProjectId;
     TaskId          = entity.TaskId;
     Billable        = entity.Billable;
     Start           = entity.Start;
     Duration        = entity.Duration;
     Description     = entity.Description;
     TagIds          = entity.TagIds;
     UserId          = entity.UserId;
     At              = entity.At;
     ServerDeletedAt = entity.ServerDeletedAt;
 }
Beispiel #23
0
        public void SetRunningTimeEntry(ITimeEntry timeEntry, string projectName = "", string projectColor = "", string taskName = "", string clientName = "")
        {
            if (timeEntry == null)
            {
                userDefaults.RemoveObject(runningTimeEntry);
                return;
            }

            var dict = new NSMutableDictionary();

            dict.SetLongForKey(timeEntry.Id, timeEntryId);
            dict.SetLongForKey(timeEntry.WorkspaceId, timeEntryWorkspaceId);
            dict.SetLongForKey(timeEntry.UserId, timeEntryUserId);

            dict.SetStringForKey(timeEntry.Description, timeEntryDescription);
            dict.SetDateTimeOffsetForKey(timeEntry.Start, timeEntryStartTime);

            if (timeEntry.Duration.HasValue)
            {
                dict.SetLongForKey(timeEntry.Duration.Value, timeEntryDuration);
            }

            dict.SetBoolForKey(timeEntry.Billable, timeEntryIsBillable);

            if (timeEntry.ProjectId.HasValue)
            {
                dict.SetLongForKey(timeEntry.ProjectId.Value, timeEntryProjectId);
                dict.SetStringForKey(projectName, timeEntryProjectName);
                dict.SetStringForKey(projectColor, timeEntryProjectColor);
                dict.SetStringForKey(clientName, timeEntryClientName);
            }

            if (timeEntry.TaskId.HasValue)
            {
                dict.SetLongForKey(timeEntry.TaskId.Value, timeEntryTaskId);
                dict.SetStringForKey(taskName, timeEntryTaskName);
            }

            if (timeEntry.ServerDeletedAt.HasValue)
            {
                dict.SetDateTimeOffsetForKey(timeEntry.ServerDeletedAt.Value, timeEntryServerDeletedAt);
            }

            dict.SetDateTimeOffsetForKey(timeEntry.At, timeEntryAt);

            userDefaults[new NSString(runningTimeEntry)] = dict;
            userDefaults.Synchronize();
        }
        public static SiriTrackingEvent StartTimer(ITimeEntry te)
        {
            var dict = new Dictionary <string, string>
            {
                ["HasEmptyDescription"] = string.IsNullOrEmpty(te.Description).ToString(),
                ["HasProject"]          = (te.ProjectId != null).ToString(),
                ["HasTask"]             = (te.TaskId != null).ToString(),
                ["NumberOfTags"]        = te.TagIds.Count().ToString(),
                ["IsBillable"]          = te.Billable.ToString()
            };

            var nativeDict = NSDictionary <NSString, NSString>
                             .FromObjectsAndKeys(dict.Values.ToArray(), dict.Keys.ToArray());

            return(new SiriTrackingEvent(new NSString(SiriStartTimerEventName), nativeDict));
        }
Beispiel #25
0
 public static TimeEntry from(ITimeEntry entry)
 {
     return(new TimeEntry(
                entry.WorkspaceId,
                entry.ProjectId,
                entry.TaskId,
                entry.Billable,
                entry.Start,
                entry.Duration,
                entry.Description,
                entry.TagIds ?? new List <long>(),
                entry.UserId,
                entry.Id,
                entry.ServerDeletedAt,
                entry.At
                ));
 }
Beispiel #26
0
 public TimeEntry(ITimeEntry entity)
 {
     Id              = entity.Id;
     WorkspaceId     = entity.WorkspaceId;
     ProjectId       = entity.ProjectId;
     TaskId          = entity.TaskId;
     Billable        = entity.Billable;
     Start           = entity.Start;
     Stop            = entity.Stop;
     Description     = entity.Description;
     TagNames        = entity.TagNames;
     TagIds          = entity.TagIds;
     At              = entity.At;
     ServerDeletedAt = entity.ServerDeletedAt;
     UserId          = entity.UserId;
     CreatedWith     = entity.CreatedWith;
 }
Beispiel #27
0
 private TimeEntry(ITimeEntry entity, SyncStatus syncStatus, string lastSyncErrorMessage, bool isDeleted = false)
 {
     Id                   = entity.Id;
     WorkspaceId          = entity.WorkspaceId;
     ProjectId            = entity.ProjectId;
     TaskId               = entity.TaskId;
     Billable             = entity.Billable;
     Start                = entity.Start;
     Duration             = entity.Duration;
     Description          = entity.Description;
     TagIds               = entity.TagIds;
     UserId               = entity.UserId;
     At                   = entity.At;
     ServerDeletedAt      = entity.ServerDeletedAt;
     SyncStatus           = syncStatus;
     LastSyncErrorMessage = lastSyncErrorMessage;
     IsDeleted            = isDeleted;
 }
 private TimeEntry(ITimeEntry entity, bool isDirty, bool isDeleted = false)
 {
     Id              = entity.Id;
     WorkspaceId     = entity.WorkspaceId;
     ProjectId       = entity.ProjectId;
     TaskId          = entity.TaskId;
     Billable        = entity.Billable;
     Start           = entity.Start;
     Stop            = entity.Stop;
     Description     = entity.Description;
     TagNames        = entity.TagNames;
     TagIds          = entity.TagIds;
     At              = entity.At;
     ServerDeletedAt = entity.ServerDeletedAt;
     UserId          = entity.UserId;
     CreatedWith     = entity.CreatedWith;
     IsDirty         = isDirty;
     IsDeleted       = isDeleted;
 }
Beispiel #29
0
 public RealmTimeEntry(ITimeEntry entity, Realms.Realm realm)
 {
     Id              = entity.Id;
     RealmWorkspace  = realm.All <RealmWorkspace>().Single(x => x.Id == WorkspaceId);
     RealmProject    = realm.All <RealmProject>().Single(x => x.Id == ProjectId);
     RealmTask       = realm.All <RealmTask>().Single(x => x.Id == TaskId);
     Billable        = entity.Billable;
     Start           = entity.Start;
     Stop            = entity.Stop;
     Duration        = entity.Duration;
     Description     = entity.Description;
     Tags            = entity.Tags;
     TagIds          = entity.TagIds;
     At              = entity.At;
     ServerDeletedAt = entity.ServerDeletedAt;
     RealmUser       = realm.All <RealmUser>().Single(x => x.Id == UserId);
     CreatedWith     = entity.CreatedWith;
     IsDirty         = true;
 }
Beispiel #30
0
 public static ITimeEntry With(
     this ITimeEntry timeEntry,
     New <long> workspaceId           = default(New <long>),
     New <IEnumerable <long> > tagIds = default(New <IEnumerable <long> >),
     New <long?> taskId    = default(New <long?>),
     New <long?> projectId = default(New <long?>))
 => new TimeEntry
 {
     Id = timeEntry.Id,
     ServerDeletedAt = timeEntry.ServerDeletedAt,
     At          = timeEntry.At,
     WorkspaceId = workspaceId.ValueOr(timeEntry.WorkspaceId),
     ProjectId   = projectId.ValueOr(timeEntry.ProjectId),
     TaskId      = taskId.ValueOr(timeEntry.TaskId),
     Billable    = timeEntry.Billable,
     Start       = timeEntry.Start,
     Duration    = timeEntry.Duration,
     Description = timeEntry.Description,
     TagIds      = tagIds.ValueOr(timeEntry.TagIds),
     UserId      = timeEntry.UserId
 };
        private void SaveTimeSpends(ITimeEntry[] timeEntries)
        {
            TimeTrackingEngine timeTrackingEngine = _engineFactory.GetTimeTrackingEngine();
            foreach (var timeEntry in timeEntries)
            {
                try
                {
                    TimeSpend newTimeSpend = new TimeSpend()
                                                 {
                                                     Hours = (float)timeEntry.Hours,
                                                     Date = timeEntry.Date,
                                                     Note = timeEntry.Description,
                                                     Task = new Task { ID = timeEntry.ToDoItemID != -1 ? FindTask(timeEntry.ToDoItemID) : 0, Project = new Project { ID = FindProject(timeEntry.ProjectID) } },
                                                     Person = FindUser(timeEntry.PersonID)
                                                 };

                    timeTrackingEngine.SaveOrUpdate(newTimeSpend, true);
                }
                catch (Exception e)
                {
                    Status.LogError(string.Format(SettingsResource.FailedToSaveTimeSpend, timeEntry.ID), e);
                    LogError(string.Format("time spend '{0}' failed", timeEntry.ID), e);
                }
            }
        }