예제 #1
0
  /**
   * Get details for this tag
   *
   * @param tagData
   * @throws IOException
   * @throws JSONException
   */
  public void fetchTag(final TagData tagData) throws IOException, JSONException {
    JSONObject result;
    if (!checkForToken()) return;

    if (tagData.getValue(TagData.REMOTE_ID) == 0)
      result =
          actFmInvoker.invoke("tag_show", "name", tagData.getValue(TagData.NAME), "token", token);
    else
      result =
          actFmInvoker.invoke(
              "tag_show", "id", tagData.getValue(TagData.REMOTE_ID), "token", token);

    JsonHelper.tagFromJson(result, tagData);
    Flags.set(Flags.SUPPRESS_SYNC);
    tagDataService.save(tagData);
  }
예제 #2
0
  /** Synchronize with server when data changes */
  public void pushUpdateOnSave(Update update, ContentValues values) {
    if (!values.containsKey(Update.MESSAGE.name)) return;

    ArrayList<Object> params = new ArrayList<Object>();
    params.add("message");
    params.add(update.getValue(Update.MESSAGE));

    if (update.getValue(Update.TAG) > 0) {
      TagData tagData = tagDataService.fetchById(update.getValue(Update.TAG), TagData.REMOTE_ID);
      if (tagData == null || tagData.getValue(TagData.REMOTE_ID) == 0) return;
      params.add("tag_id");
      params.add(tagData.getValue(TagData.REMOTE_ID));
    }

    if (update.getValue(Update.TASK) > 0) {
      params.add("task_id");
      params.add(update.getValue(Update.TASK));
    }
    if (!checkForToken()) return;

    try {
      params.add("token");
      params.add(token);
      JSONObject result =
          actFmInvoker.invoke("comment_add", params.toArray(new Object[params.size()]));
      update.setValue(Update.REMOTE_ID, result.optLong("id"));
      updateDao.saveExisting(update);
    } catch (IOException e) {
      handleException("task-save", e);
    }
  }
예제 #3
0
 /** invoke authenticated method against the server */
 public JSONObject invoke(String method, Object... getParameters)
     throws IOException, ActFmServiceException {
   if (!checkForToken()) throw new ActFmServiceException("not logged in");
   Object[] parameters = new Object[getParameters.length + 2];
   parameters[0] = "token";
   parameters[1] = token;
   for (int i = 0; i < getParameters.length; i++) parameters[i + 2] = getParameters[i];
   return actFmInvoker.invoke(method, parameters);
 }
예제 #4
0
  /** Fetch all tags */
  public void fetchTags() throws JSONException, IOException {
    if (!checkForToken()) return;

    JSONObject result = actFmInvoker.invoke("tag_list", "token", token);
    JSONArray tags = result.getJSONArray("list");
    for (int i = 0; i < tags.length(); i++) {
      JSONObject tagObject = tags.getJSONObject(i);
      actFmDataService.saveTagData(tagObject);
    }
  }
예제 #5
0
  /**
   * Update tag picture
   *
   * @param path
   * @throws IOException
   * @throws ActFmServiceException
   */
  public String setTagPicture(long tagId, Bitmap bitmap) throws ActFmServiceException, IOException {
    if (!checkForToken()) return null;

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    if (bitmap.getWidth() > 512 || bitmap.getHeight() > 512) {
      float scale = Math.min(512f / bitmap.getWidth(), 512f / bitmap.getHeight());
      bitmap =
          Bitmap.createScaledBitmap(
              bitmap, (int) (scale * bitmap.getWidth()), (int) (scale * bitmap.getHeight()), false);
    }
    bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
    byte[] bytes = baos.toByteArray();
    MultipartEntity data = new MultipartEntity();
    data.addPart("picture", new ByteArrayBody(bytes, "image/jpg", "image.jpg"));
    JSONObject result = actFmInvoker.post("tag_set_picture", data, "id", tagId, "token", token);
    return result.optString("url");
  }
예제 #6
0
  private void sync() {
    try {
      int batchSize = 4;
      List<ClientToServerMessage<?>> messageBatch = new ArrayList<ClientToServerMessage<?>>();
      while (true) {
        synchronized (monitor) {
          while ((pendingMessages.isEmpty() && !timeForBackgroundSync())
              || !actFmPreferenceService.isLoggedIn()
              || !syncMigration) {
            try {
              if ((pendingMessages.isEmpty() || !actFmPreferenceService.isLoggedIn())
                  && notificationId >= 0) {
                notificationManager.cancel(notificationId);
                notificationId = -1;
              }
              monitor.wait();
              AndroidUtilities.sleepDeep(
                  500L); // Wait briefly for large database operations to finish (e.g. adding a task
                         // with several tags may trigger a message before all saves are done--fix
                         // this?)

              if (!syncMigration) {
                syncMigration =
                    Preferences.getBoolean(AstridNewSyncMigrator.PREF_SYNC_MIGRATION, false);
              }
            } catch (InterruptedException e) {
              // Ignored
            }
          }
        }

        boolean recordSyncSuccess = true;
        if (timeForBackgroundSync()) {
          repopulateQueueFromOutstandingTables();
          enqueueMessage(
              BriefMe.instantiateBriefMeForClass(
                  TaskListMetadata.class, NameMaps.PUSHED_AT_TASK_LIST_METADATA),
              DEFAULT_REFRESH_RUNNABLE);
          enqueueMessage(
              BriefMe.instantiateBriefMeForClass(Task.class, NameMaps.PUSHED_AT_TASKS),
              DEFAULT_REFRESH_RUNNABLE);
          enqueueMessage(
              BriefMe.instantiateBriefMeForClass(TagData.class, NameMaps.PUSHED_AT_TAGS),
              DEFAULT_REFRESH_RUNNABLE);
          enqueueMessage(
              BriefMe.instantiateBriefMeForClass(User.class, NameMaps.PUSHED_AT_USERS),
              DEFAULT_REFRESH_RUNNABLE);
          setTimeForBackgroundSync(false);
        }

        while (messageBatch.size() < batchSize && !pendingMessages.isEmpty()) {
          ClientToServerMessage<?> message = pendingMessages.remove(0);
          if (message != null) {
            messageBatch.add(message);
          }
        }

        if (!messageBatch.isEmpty() && checkForToken()) {
          JSONPayloadBuilder payload = new JSONPayloadBuilder();
          MultipartEntity entity = new MultipartEntity();
          boolean containsChangesHappened = false;
          for (int i = 0; i < messageBatch.size(); i++) {
            ClientToServerMessage<?> message = messageBatch.get(i);
            boolean success = payload.addMessage(message, entity);
            if (success) {
              if (message instanceof ChangesHappened) {
                containsChangesHappened = true;
              }
            } else {
              messageBatch.remove(i);
              i--;
            }
          }

          if (payload.getMessageCount() == 0) {
            messageBatch.clear();
            continue;
          }

          setupNotification();

          payload.addJSONObject(getClientVersion());

          JSONArray errors = null;
          try {
            JSONObject response =
                actFmInvoker.postSync(
                    payload.closeAndReturnString(), entity, containsChangesHappened, token);
            // process responses
            String time = response.optString("time");
            JSONArray serverMessagesJson = response.optJSONArray("messages");
            if (serverMessagesJson != null) {
              setWidgetSuppression(true);
              for (int i = 0; i < serverMessagesJson.length(); i++) {
                JSONObject serverMessageJson = serverMessagesJson.optJSONObject(i);
                if (serverMessageJson != null) {
                  ServerToClientMessage serverMessage =
                      ServerToClientMessage.instantiateMessage(serverMessageJson);
                  if (serverMessage != null) {
                    serverMessage.processMessage(time);
                  } else {
                    syncLog(
                        "Index "
                            + i
                            + " unable to instantiate message "
                            + serverMessageJson.toString());
                  }
                }
              }
              errors = response.optJSONArray("errors");
              boolean errorsExist = (errors != null && errors.length() > 0);
              replayOutstandingChanges(errorsExist);
              setWidgetSuppression(false);
            }

            batchSize = Math.max(12, Math.min(batchSize, messageBatch.size()) * 2);

            if (recordSyncSuccess) {
              actFmPreferenceService.setLastError(null, null);
              actFmPreferenceService.recordSuccessfulSync();
            }
          } catch (IOException e) {
            Log.e(ERROR_TAG, "IOException", e);
            batchSize = Math.max(batchSize / 2, 1);
          }

          Set<SyncMessageCallback> callbacksExecutedThisLoop = new HashSet<SyncMessageCallback>();
          Map<Integer, List<JSONArray>> errorMap = buildErrorMap(errors);
          for (int i = 0; i < messageBatch.size(); i++) {
            ClientToServerMessage<?> message = messageBatch.get(i);
            try {
              SyncMessageCallback r = pendingCallbacks.remove(message);
              if (r != null && !callbacksExecutedThisLoop.contains(r)) {
                List<JSONArray> errorList = errorMap.get(i);
                if (errorList == null || errorList.isEmpty()) {
                  r.runOnSuccess();
                } else {
                  r.runOnErrors(errorList);
                }

                callbacksExecutedThisLoop.add(r);
              }
            } catch (Exception e) {
              Log.e(ERROR_TAG, "Unexpected exception executing sync callback", e);
            }
          }

          messageBatch.clear();
        }
      }
    } catch (Exception e) {
      // In the worst case, restart thread if something goes wrong
      Log.e(ERROR_TAG, "Unexpected sync thread exception", e);
      thread = null;
      startSyncThread();
    }
  }
예제 #7
0
  /**
   * Send tagData changes to server
   *
   * @param setValues
   */
  public void pushTagDataOnSave(TagData tagData, ContentValues values) {
    long remoteId;
    if (tagData.containsValue(TagData.REMOTE_ID)) remoteId = tagData.getValue(TagData.REMOTE_ID);
    else {
      TagData forRemote = tagDataService.fetchById(tagData.getId(), TagData.REMOTE_ID);
      if (forRemote == null) return;
      remoteId = forRemote.getValue(TagData.REMOTE_ID);
    }
    boolean newlyCreated = remoteId == 0;

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

    if (values.containsKey(TagData.NAME.name)) {
      params.add("name");
      params.add(tagData.getValue(TagData.NAME));
    }

    if (values.containsKey(TagData.MEMBERS.name)) {
      params.add("members");
      try {
        JSONArray members = new JSONArray(tagData.getValue(TagData.MEMBERS));
        if (members.length() == 0) params.add("");
        else {
          ArrayList<Object> array = new ArrayList<Object>(members.length());
          for (int i = 0; i < members.length(); i++) {
            JSONObject person = members.getJSONObject(i);
            if (person.has("id")) array.add(person.getLong("id"));
            else {
              if (person.has("name"))
                array.add(person.getString("name") + " <" + person.getString("email") + ">");
              else array.add(person.getString("email"));
            }
          }
          params.add(array);
        }
      } catch (JSONException e) {
        throw new RuntimeException(e);
      }
    }

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

    if (!newlyCreated) {
      params.add("id");
      params.add(remoteId);
    }

    boolean success;
    try {
      params.add("token");
      params.add(token);
      JSONObject result =
          actFmInvoker.invoke("tag_save", params.toArray(new Object[params.size()]));
      if (newlyCreated) {
        tagData.setValue(TagData.REMOTE_ID, result.optLong("id"));
        Flags.set(Flags.SUPPRESS_SYNC);
        tagDataDao.saveExisting(tagData);
      }
      success = true;
    } catch (IOException e) {
      handleException("tag-save", e);
      success = false;
    }
    if (!Flags.checkAndClear(Flags.TOAST_ON_SAVE)) return;

    final boolean finalSuccess = success;
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(
        new Runnable() {
          @Override
          public void run() {
            if (finalSuccess)
              Toast.makeText(
                      ContextManager.getContext(), R.string.actfm_toast_success, Toast.LENGTH_LONG)
                  .show();
            else
              Toast.makeText(
                      ContextManager.getContext(), R.string.actfm_toast_error, Toast.LENGTH_LONG)
                  .show();
          }
        });
  }
예제 #8
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);
    }
  }