示例#1
0
  /**
   * Show a new notification about the given task. Returns false if there was some sort of error or
   * the alarm should be disabled.
   */
  public boolean showTaskNotification(long id, int type, String reminder) {
    Task task;
    try {
      task =
          taskDao.fetch(
              id,
              Task.ID,
              Task.TITLE,
              Task.HIDE_UNTIL,
              Task.COMPLETION_DATE,
              Task.DUE_DATE,
              Task.DELETION_DATE,
              Task.REMINDER_FLAGS);
      if (task == null)
        throw new IllegalArgumentException("cound not find item with id"); // $NON-NLS-1$

    } catch (Exception e) {
      exceptionService.reportError("show-notif", e); // $NON-NLS-1$
      return false;
    }

    // you're done - don't sound, do delete
    if (task.isCompleted() || task.isDeleted()) return false;

    // it's hidden - don't sound, don't delete
    if (task.isHidden() && type == ReminderService.TYPE_RANDOM) return true;

    // task due date was changed, but alarm wasn't rescheduled
    if ((type == ReminderService.TYPE_DUE || type == ReminderService.TYPE_OVERDUE)
        && (!task.hasDueDate() || task.getValue(Task.DUE_DATE) > DateUtilities.now())) return true;

    // read properties
    String taskTitle = task.getValue(Task.TITLE);
    boolean nonstopMode = task.getFlag(Task.REMINDER_FLAGS, Task.NOTIFY_MODE_NONSTOP);
    boolean ringFiveMode = task.getFlag(Task.REMINDER_FLAGS, Task.NOTIFY_MODE_FIVE);
    int ringTimes = nonstopMode ? -1 : (ringFiveMode ? 5 : 1);

    // update last reminder time
    task.setValue(Task.REMINDER_LAST, DateUtilities.now());
    taskDao.saveExisting(task);

    Context context = ContextManager.getContext();
    String title = context.getString(R.string.app_name);
    String text = reminder + " " + taskTitle; // $NON-NLS-1$

    Intent notifyIntent = new Intent(context, NotificationActivity.class);
    notifyIntent.setAction("NOTIFY" + id); // $NON-NLS-1$
    notifyIntent.putExtra(NotificationActivity.TOKEN_ID, id);
    notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);

    showNotification((int) id, notifyIntent, type, title, text, ringTimes);
    return true;
  }
示例#2
0
  /** Clean up tasks. Typically called on startup */
  public void deleteTasksWithEmptyTitles() {
    TodorooCursor<Task> cursor =
        taskDao.query(Query.select(Task.ID).where(TaskDao.TaskCriteria.hasNoTitle()));
    try {
      if (cursor.getCount() == 0) {
        return;
      }

      for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
        long id = cursor.getLong(0);
        taskDao.delete(id);
      }
    } finally {
      cursor.close();
    }
  }
示例#3
0
  public static ActFmSyncThread initializeSyncComponents(
      TaskDao taskDao,
      TagDataDao tagDataDao,
      UserActivityDao userActivityDao,
      TaskAttachmentDao taskAttachmentDao,
      TaskListMetadataDao taskListMetadataDao) {
    if (instance == null) {
      synchronized (ActFmSyncThread.class) {
        if (instance == null) {
          List<ClientToServerMessage<?>> syncQueue =
              Collections.synchronizedList(new LinkedList<ClientToServerMessage<?>>());
          ActFmSyncMonitor monitor = ActFmSyncMonitor.getInstance();
          ActFmSyncWaitingPool waitingPool = ActFmSyncWaitingPool.getInstance();

          instance = new ActFmSyncThread(syncQueue, monitor);

          taskDao.addListener(new SyncDatabaseListener<Task>(instance, ModelType.TYPE_TASK));
          tagDataDao.addListener(new SyncDatabaseListener<TagData>(instance, ModelType.TYPE_TAG));
          userActivityDao.addListener(
              new SyncDatabaseListener<UserActivity>(instance, ModelType.TYPE_ACTIVITY));
          taskAttachmentDao.addListener(
              new SyncDatabaseListener<TaskAttachment>(instance, ModelType.TYPE_ATTACHMENT));
          taskListMetadataDao.addListener(
              new TaskListMetadataSyncDatabaseListener(
                  instance, waitingPool, ModelType.TYPE_TASK_LIST_METADATA));

          instance.startSyncThread();
        }
      }
    }
    return instance;
  }
示例#4
0
  private void write(GtasksTaskContainer task) throws IOException {
    //  merge astrid dates with google dates
    if (!task.task.isSaved() && actFmPreferenceService.isLoggedIn()) titleMatchWithActFm(task.task);

    if (task.task.isSaved()) {
      Task local =
          PluginServices.getTaskService()
              .fetchById(task.task.getId(), Task.DUE_DATE, Task.COMPLETION_DATE);
      if (local == null) {
        task.task.clearValue(Task.ID);
      } else {
        mergeDates(task.task, local);
        if (task.task.isCompleted() && !local.isCompleted())
          StatisticsService.reportEvent(StatisticsConstants.GTASKS_TASK_COMPLETED);
      }
    } else { // Set default importance and reminders for remotely created tasks
      task.task.setValue(
          Task.IMPORTANCE,
          Preferences.getIntegerFromString(
              R.string.p_default_importance_key, Task.IMPORTANCE_SHOULD_DO));
      TaskDao.setDefaultReminders(task.task);
    }
    if (!TextUtils.isEmpty(task.task.getValue(Task.TITLE))) {
      task.task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
      gtasksMetadataService.saveTaskAndMetadata(task);
    }
  }
示例#5
0
  /**
   * Schedules alarms for a single task
   *
   * @param shouldPerformPropertyCheck whether to check if task has requisite properties
   */
  private void scheduleAlarm(Task task, boolean shouldPerformPropertyCheck) {
    if (task == null || !task.isSaved()) return;

    // read data if necessary
    if (shouldPerformPropertyCheck) {
      for (Property<?> property : NOTIFICATION_PROPERTIES) {
        if (!task.containsValue(property)) {
          task = taskDao.fetch(task.getId(), NOTIFICATION_PROPERTIES);
          if (task == null) return;
          break;
        }
      }
    }

    // Make sure no alarms are scheduled other than the next one. When that one is shown, it
    // will schedule the next one after it, and so on and so forth.
    clearAllAlarms(task);
    if (task.isCompleted()
        || task.isDeleted()
        || !Task.USER_ID_SELF.equals(task.getValue(Task.USER_ID))) {
      return;
    }

    // snooze reminder
    long whenSnooze = calculateNextSnoozeReminder(task);

    // random reminders
    long whenRandom = calculateNextRandomReminder(task);

    // notifications at due date
    long whenDueDate = calculateNextDueDateReminder(task);

    // notifications after due date
    long whenOverdue = calculateNextOverdueReminder(task);

    // For alarms around/before now, increment the now value so the next one will be later
    if (whenDueDate <= now || whenOverdue <= now) {
      whenDueDate = now;
      whenOverdue = now;
      now +=
          30 * DateUtilities.ONE_MINUTE; // Prevents overdue tasks from being scheduled all at once
    }

    // if random reminders are too close to due date, favor due date
    if (whenRandom != NO_ALARM && whenDueDate - whenRandom < DateUtilities.ONE_DAY)
      whenRandom = NO_ALARM;

    // snooze trumps all
    if (whenSnooze != NO_ALARM) {
      scheduler.createAlarm(task, whenSnooze, TYPE_SNOOZE);
    } else if (whenRandom < whenDueDate && whenRandom < whenOverdue) {
      scheduler.createAlarm(task, whenRandom, TYPE_RANDOM);
    } else if (whenDueDate < whenOverdue) {
      scheduler.createAlarm(task, whenDueDate, TYPE_DUE);
    } else if (whenOverdue != NO_ALARM) {
      scheduler.createAlarm(task, whenOverdue, TYPE_OVERDUE);
    } else {
      scheduler.createAlarm(task, 0, 0);
    }
  }
示例#6
0
  protected Task createTask(String title) {
    Task task = new Task();
    task.setTitle(title);
    task.setImportance(SYNC_TASK_IMPORTANCE);

    taskDao.createNew(task);
    return task;
  }
示例#7
0
 /**
  * Gets a listing of all tasks that are active &
  *
  * @param properties
  * @return todoroo cursor. PLEASE CLOSE THIS CURSOR!
  */
 private TodorooCursor<Task> getTasksWithReminders(Property<?>... properties) {
   return taskDao.query(
       Query.select(properties)
           .where(
               Criterion.and(
                   TaskCriteria.isActive(),
                   TaskCriteria.ownedByMe(),
                   Criterion.or(Task.REMINDER_FLAGS.gt(0), Task.REMINDER_PERIOD.gt(0)))));
 }
示例#8
0
 private int countTasks(Filter filter) {
   String queryTemplate = PermaSql.replacePlaceholders(filter.getSqlQuery());
   TodorooCursor<Task> cursor =
       taskDao.query(Query.select(Task.ID).withQueryTemplate(queryTemplate));
   try {
     return cursor.getCount();
   } finally {
     cursor.close();
   }
 }
示例#9
0
  @SuppressWarnings("nls")
  public void initialize() {
    new Thread(
            new Runnable() {
              public void run() {
                while (true) {
                  SyncOnSaveOperation op;
                  try {
                    op = operationQueue.take();
                  } catch (InterruptedException e) {
                    continue;
                  }
                  try {
                    if (!gtasksPreferenceService.isOngoing()) {
                      GtasksInvoker invoker = new GtasksInvoker(gtasksPreferenceService.getToken());
                      if (op instanceof TaskPushOp) {
                        TaskPushOp taskPush = (TaskPushOp) op;
                        if (DateUtilities.now() - taskPush.creationDate < 1000)
                          AndroidUtilities.sleepDeep(
                              1000 - (DateUtilities.now() - taskPush.creationDate));
                        pushTaskOnSave(
                            taskPush.model, taskPush.model.getMergedValues(), invoker, false);
                      } else if (op instanceof MoveOp) {
                        MoveOp move = (MoveOp) op;
                        pushMetadataOnSave(move.metadata, invoker);
                      }
                    }
                  } catch (IOException e) {
                    Crittercism.logHandledException(e);
                    Log.w("gtasks-sync-error", "Sync on save failed", e);
                  }
                }
              }
            })
        .start();

    taskDao.addListener(
        new ModelUpdateListener<Task>() {
          public void onModelUpdated(final Task model) {
            if (model.checkAndClearTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC)) return;
            if (gtasksPreferenceService
                .isOngoing()) // Don't try and sync changes that occur during a normal sync
            return;
            final ContentValues setValues = model.getSetValues();
            if (setValues == null || !checkForToken()) return;
            if (!checkValuesForProperties(
                setValues, TASK_PROPERTIES)) // None of the properties we sync were updated
            return;

            Task toPush = taskDao.fetch(model.getId(), TASK_PROPERTIES);
            operationQueue.offer(new TaskPushOp(toPush));
          }
        });
  }
示例#10
0
  public void delete(Task item) {
    if (!item.isSaved()) {
      return;
    }

    if (item.containsValue(Task.TITLE) && item.getTitle().length() == 0) {
      taskDao.delete(item.getId());
      item.setId(Task.NO_ID);
    } else {
      long id = item.getId();
      item.clear();
      item.setId(id);
      gcalHelper.deleteTaskEvent(item);
      item.setDeletionDate(DateUtilities.now());
      taskService.save(item);
    }
  }
示例#11
0
  /** Synchronize with server when data changes */
  public void pushTaskOnSave(Task task, ContentValues values, GtasksInvoker invoker, boolean sleep)
      throws IOException {
    if (sleep) AndroidUtilities.sleepDeep(1000L); // Wait for metadata to be saved

    Metadata gtasksMetadata = gtasksMetadataService.getTaskMetadata(task.getId());
    com.google.api.services.tasks.model.Task remoteModel = null;
    boolean newlyCreated = false;

    String remoteId = null;
    String listId = Preferences.getStringValue(GtasksPreferenceService.PREF_DEFAULT_LIST);
    if (listId == null) {
      com.google.api.services.tasks.model.TaskList defaultList = invoker.getGtaskList(DEFAULT_LIST);
      if (defaultList != null) {
        listId = defaultList.getId();
        Preferences.setString(GtasksPreferenceService.PREF_DEFAULT_LIST, listId);
      } else {
        listId = DEFAULT_LIST;
      }
    }

    if (gtasksMetadata == null
        || !gtasksMetadata.containsNonNullValue(GtasksMetadata.ID)
        || TextUtils.isEmpty(gtasksMetadata.getValue(GtasksMetadata.ID))) { // Create case
      if (gtasksMetadata == null) {
        gtasksMetadata = GtasksMetadata.createEmptyMetadata(task.getId());
      }
      if (gtasksMetadata.containsNonNullValue(GtasksMetadata.LIST_ID)) {
        listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
      }

      remoteModel = new com.google.api.services.tasks.model.Task();
      newlyCreated = true;
    } else { // update case
      remoteId = gtasksMetadata.getValue(GtasksMetadata.ID);
      listId = gtasksMetadata.getValue(GtasksMetadata.LIST_ID);
      remoteModel = new com.google.api.services.tasks.model.Task();
      remoteModel.setId(remoteId);
    }

    // If task was newly created but without a title, don't sync--we're in the middle of
    // creating a task which may end up being cancelled
    if (newlyCreated
        && (!values.containsKey(Task.TITLE.name) || TextUtils.isEmpty(task.getValue(Task.TITLE)))) {
      return;
    }

    // Update the remote model's changed properties
    if (values.containsKey(Task.DELETION_DATE.name) && task.isDeleted()) {
      remoteModel.setDeleted(true);
    }

    if (values.containsKey(Task.TITLE.name)) {
      remoteModel.setTitle(task.getValue(Task.TITLE));
    }
    if (values.containsKey(Task.NOTES.name)) {
      remoteModel.setNotes(task.getValue(Task.NOTES));
    }
    if (values.containsKey(Task.DUE_DATE.name) && task.hasDueDate()) {
      remoteModel.setDue(GtasksApiUtilities.unixTimeToGtasksDueDate(task.getValue(Task.DUE_DATE)));
    }
    if (values.containsKey(Task.COMPLETION_DATE.name)) {
      if (task.isCompleted()) {
        remoteModel.setCompleted(
            GtasksApiUtilities.unixTimeToGtasksCompletionTime(task.getValue(Task.COMPLETION_DATE)));
        remoteModel.setStatus("completed"); // $NON-NLS-1$
      } else {
        remoteModel.setCompleted(null);
        remoteModel.setStatus("needsAction"); // $NON-NLS-1$
      }
    }

    if (!newlyCreated) {
      invoker.updateGtask(listId, remoteModel);
    } else {
      String parent = gtasksMetadataService.getRemoteParentId(gtasksMetadata);
      String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, gtasksMetadata);

      CreateRequest create = new CreateRequest(invoker, listId, remoteModel, parent, priorSibling);
      com.google.api.services.tasks.model.Task created = create.executePush();

      if (created != null) {
        // Update the metadata for the newly created task
        gtasksMetadata.setValue(GtasksMetadata.ID, created.getId());
        gtasksMetadata.setValue(GtasksMetadata.LIST_ID, listId);
      } else return;
    }

    task.setValue(Task.MODIFICATION_DATE, DateUtilities.now());
    gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
    metadataService.save(gtasksMetadata);
    task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
    taskDao.saveExistingWithSqlConstraintCheck(task);
  }
示例#12
0
 /** Permanently delete the given task. */
 public void purge(long taskId) {
   taskDao.delete(taskId);
 }
示例#13
0
 public int purgeDeletedTasks() {
   return taskDao.deleteWhere(Task.DELETION_DATE.gt(0));
 }
示例#14
0
  public void initialize() {
    taskDao.addListener(
        new ModelUpdateListener<Task>() {
          @Override
          public void onModelUpdated(final Task model) {
            if (Flags.checkAndClear(Flags.SUPPRESS_SYNC)) return;
            final ContentValues setValues = model.getSetValues();
            if (setValues == null
                || !checkForToken()
                || setValues.containsKey(RemoteModel.REMOTE_ID_PROPERTY_NAME)) return;

            new Thread(
                    new Runnable() {
                      @Override
                      public void run() {
                        // sleep so metadata associated with task is saved
                        AndroidUtilities.sleepDeep(1000L);
                        pushTaskOnSave(model, setValues);
                      }
                    })
                .start();
          }
        });

    updateDao.addListener(
        new ModelUpdateListener<Update>() {
          @Override
          public void onModelUpdated(final Update model) {
            if (Flags.checkAndClear(Flags.SUPPRESS_SYNC)) return;
            final ContentValues setValues = model.getSetValues();
            if (setValues == null || !checkForToken() || model.getValue(Update.REMOTE_ID) > 0)
              return;

            new Thread(
                    new Runnable() {
                      @Override
                      public void run() {
                        pushUpdateOnSave(model, setValues);
                      }
                    })
                .start();
          }
        });

    tagDataDao.addListener(
        new ModelUpdateListener<TagData>() {
          @Override
          public void onModelUpdated(final TagData model) {
            if (Flags.checkAndClear(Flags.SUPPRESS_SYNC)) return;
            final ContentValues setValues = model.getSetValues();
            if (setValues == null
                || !checkForToken()
                || setValues.containsKey(RemoteModel.REMOTE_ID_PROPERTY_NAME)) return;

            new Thread(
                    new Runnable() {
                      @Override
                      public void run() {
                        pushTagDataOnSave(model, setValues);
                      }
                    })
                .start();
          }
        });
  }
示例#15
0
  /** Synchronize with server when data changes */
  public void pushTaskOnSave(Task task, ContentValues values) {
    long remoteId;
    if (task.containsValue(Task.REMOTE_ID)) remoteId = task.getValue(Task.REMOTE_ID);
    else {
      Task taskForRemote = taskService.fetchById(task.getId(), Task.REMOTE_ID);
      if (taskForRemote == null) return;
      remoteId = taskForRemote.getValue(Task.REMOTE_ID);
    }
    boolean newlyCreated = remoteId == 0;

    ArrayList<Object> params = new ArrayList<Object>();

    if (values.containsKey(Task.TITLE.name)) {
      params.add("title");
      params.add(task.getValue(Task.TITLE));
    }
    if (values.containsKey(Task.DUE_DATE.name)) {
      params.add("due");
      params.add(task.getValue(Task.DUE_DATE) / 1000L);
      params.add("has_due_time");
      params.add(task.hasDueTime() ? 1 : 0);
    }
    if (values.containsKey(Task.NOTES.name)) {
      params.add("notes");
      params.add(task.getValue(Task.NOTES));
    }
    if (values.containsKey(Task.DELETION_DATE.name)) {
      params.add("deleted_at");
      params.add(task.getValue(Task.DELETION_DATE) / 1000L);
    }
    if (values.containsKey(Task.COMPLETION_DATE.name)) {
      params.add("completed");
      params.add(task.getValue(Task.COMPLETION_DATE) / 1000L);
    }
    if (values.containsKey(Task.IMPORTANCE.name)) {
      params.add("importance");
      params.add(task.getValue(Task.IMPORTANCE));
    }
    if (values.containsKey(Task.RECURRENCE.name)) {
      params.add("repeat");
      params.add(task.getValue(Task.RECURRENCE));
    }
    if (values.containsKey(Task.USER_ID.name) && task.getValue(Task.USER_ID) >= 0) {
      params.add("user_id");
      if (task.getValue(Task.USER_ID) == 0) params.add(ActFmPreferenceService.userId());
      else params.add(task.getValue(Task.USER_ID));
    }
    if (Flags.checkAndClear(Flags.TAGS_CHANGED) || newlyCreated) {
      TodorooCursor<Metadata> cursor = TagService.getInstance().getTags(task.getId());
      try {
        if (cursor.getCount() == 0) {
          params.add("tags");
          params.add("");
        } else {
          Metadata metadata = new Metadata();
          for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            metadata.readFromCursor(cursor);
            if (metadata.containsNonNullValue(TagService.REMOTE_ID)
                && metadata.getValue(TagService.REMOTE_ID) > 0) {
              params.add("tag_ids[]");
              params.add(metadata.getValue(TagService.REMOTE_ID));
            } else {
              params.add("tags[]");
              params.add(metadata.getValue(TagService.TAG));
            }
          }
        }
      } finally {
        cursor.close();
      }
    }

    if (params.size() == 0 || !checkForToken()) return;

    System.err.println("PUSHN ON SAVE: " + task.getMergedValues());
    System.err.println("SETVALUES: " + values);

    if (!newlyCreated) {
      params.add("id");
      params.add(remoteId);
    } else if (!params.contains(Task.TITLE.name)) return;

    try {
      params.add("token");
      params.add(token);
      JSONObject result =
          actFmInvoker.invoke("task_save", params.toArray(new Object[params.size()]));
      ArrayList<Metadata> metadata = new ArrayList<Metadata>();
      JsonHelper.taskFromJson(result, task, metadata);
      task.setValue(Task.MODIFICATION_DATE, DateUtilities.now());
      task.setValue(Task.LAST_SYNC, DateUtilities.now());
      Flags.set(Flags.SUPPRESS_SYNC);
      taskDao.saveExisting(task);
    } catch (JSONException e) {
      handleException("task-save-json", e);
    } catch (IOException e) {
      handleException("task-save-io", e);
    }
  }