Merge remote-tracking branch 'origin/121018_sb_friend_statuses'

pull/14/head
Sam Bosley 13 years ago
commit 2978c9dad1

@ -58,6 +58,15 @@ public final class User extends RemoteModel {
public static final LongProperty REMOTE_ID = new LongProperty(
TABLE, REMOTE_ID_PROPERTY_NAME);
/** Friendship status. One of the STATUS constants below */
public static final StringProperty STATUS = new StringProperty(
TABLE, "status");
/** Friendship tatus that needs to be reported to the server.
* One of the PENDING constants below */
public static final StringProperty PENDING_STATUS = new StringProperty(
TABLE, "pendingStatus");
/** List of all properties for this model */
public static final Property<?>[] PROPERTIES = generateProperties(User.class);
@ -70,6 +79,8 @@ public final class User extends RemoteModel {
defaultValues.put(NAME.name, "");
defaultValues.put(EMAIL.name, "");
defaultValues.put(PICTURE.name, "");
defaultValues.put(STATUS.name, "");
defaultValues.put(PENDING_STATUS.name, "");
}
@Override
@ -77,6 +88,17 @@ public final class User extends RemoteModel {
return defaultValues;
}
public static final String STATUS_PENDING = "pending";
public static final String STATUS_OTHER_PENDING = "other_pending";
public static final String STATUS_FRIENDS = "friends";
public static final String STATUS_IGNORED = "ignored";
public static final String STATUS_BLOCKED = "blocked";
public static final String PENDING_REQUEST = "request";
public static final String PENDING_APPROVE = "approve";
public static final String PENDING_IGNORE = "ignore";
public static final String PENDING_UNFRIEND = "unfriend";
// --- data access boilerplate
public User() {

@ -55,6 +55,7 @@ import com.todoroo.astrid.dao.TagDataDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.dao.UpdateDao;
import com.todoroo.astrid.dao.UserDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.MetadataApiDao.MetadataCriteria;
import com.todoroo.astrid.data.RemoteModel;
@ -99,6 +100,7 @@ public final class ActFmSyncService {
@Autowired TaskDao taskDao;
@Autowired TagDataDao tagDataDao;
@Autowired UpdateDao updateDao;
@Autowired UserDao userDao;
@Autowired MetadataDao metadataDao;
@Autowired ABTestEventReportingService abTestEventReportingService;
@ -867,22 +869,31 @@ public final class ActFmSyncService {
return result.optInt("time", 0);
}
private void saveUsers(JSONArray users, HashSet<Long> ids) throws JSONException {
for (int i = 0; i < users.length(); i++) {
JSONObject userObject = users.getJSONObject(i);
ids.add(userObject.optLong("id"));
actFmDataService.saveUserData(userObject); }
}
public int fetchUsers() throws JSONException, IOException {
if (!checkForToken())
return 0;
JSONObject result = actFmInvoker.invoke("user_list",
"token", token);
JSONObject suggestedResult = actFmInvoker.invoke("suggested_user_list",
"token", token);
JSONArray users = result.getJSONArray("list");
JSONArray suggestedUsers = suggestedResult.getJSONArray("list");
HashSet<Long> ids = new HashSet<Long>();
if (users.length() > 0)
if (users.length() > 0 || suggestedUsers.length() > 0)
Preferences.setBoolean(R.string.p_show_friends_view, true);
for (int i = 0; i < users.length(); i++) {
JSONObject userObject = users.getJSONObject(i);
ids.add(userObject.optLong("id"));
actFmDataService.saveUserData(userObject);
}
saveUsers(users, ids);
saveUsers(suggestedUsers, ids);
Long[] idsArray = ids.toArray(new Long[ids.size()]);
actFmDataService.userDao.deleteWhere(Criterion.not(User.REMOTE_ID.in(idsArray)));
@ -890,6 +901,34 @@ public final class ActFmSyncService {
return result.optInt("time", 0);
}
public void pushUser(User model) {
if (TextUtils.isEmpty(model.getValue(User.PENDING_STATUS)))
return;
if (model.getValue(User.REMOTE_ID) == 0)
return;
if (!checkForToken())
return;
try {
ArrayList<Object> params = new ArrayList<Object>();
params.add("token"); params.add(token);
params.add("id"); params.add(model.getValue(User.REMOTE_ID));
params.add("status"); params.add(model.getValue(User.PENDING_STATUS));
JSONObject result = actFmInvoker.invoke("user_set_status", params.toArray(new Object[params.size()]));
if (result.optString("status").equals("success")) {
String newStatus = result.optString("friendship_status");
if (!TextUtils.isEmpty(newStatus)) {
model.setValue(User.STATUS, newStatus);
model.setValue(User.PENDING_STATUS, "");
userDao.saveExisting(model);
}
}
} catch (IOException e) {
handleException("user-status", e);
}
}
/**
* Fetch active tasks asynchronously
@ -1426,6 +1465,7 @@ public final class ActFmSyncService {
model.setValue(User.NAME, json.optString("name"));
model.setValue(User.EMAIL, json.optString("email"));
model.setValue(User.PICTURE, json.optString("picture"));
model.setValue(User.STATUS, json.optString("status"));
}
public static void jsonFromUser(JSONObject json, User model) throws JSONException {

@ -29,6 +29,7 @@ import com.todoroo.astrid.billing.BillingConstants;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.dao.UserDao;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
@ -60,6 +61,8 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
@Autowired MetadataService metadataService;
@Autowired UserDao userDao;
@Autowired Database database;
private final PushQueuedArgs<Task> taskPusher = new PushQueuedArgs<Task>() {
@ -92,6 +95,19 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
}
};
private final PushQueuedArgs<User> userPusher = new PushQueuedArgs<User>() {
@Override
public User getRemoteModelInstance(TodorooCursor<User> cursor) {
return new User(cursor);
}
@Override
public void pushRemoteModel(User model) {
actFmSyncService.pushUser(model);
}
};
private final PushQueuedArgs<Metadata> filesPusher = new PushQueuedArgs<Metadata>() {
@Override
@ -160,7 +176,7 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
actFmPreferenceService.recordSyncStart();
updateUserStatus();
startUsersFetcher(callback, finisher);
startUsersSync(callback, finisher);
startTagFetcher(callback, finisher);
@ -207,13 +223,14 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
}
/** fetch changes to users/friends */
private void startUsersFetcher(final SyncResultCallback callback,
private void startUsersSync(final SyncResultCallback callback,
final AtomicInteger finisher) {
new Thread(new Runnable() {
@Override
public void run() {
int time = Preferences.getInt(LAST_USERS_FETCH_TIME, 0);
try {
pushQueuedUsers(callback, finisher);
time = actFmSyncService.fetchUsers();
Preferences.setInt(LAST_USERS_FETCH_TIME, time);
} catch (JSONException e) {
@ -397,6 +414,17 @@ public class ActFmSyncV2Provider extends SyncV2Provider {
}
private void pushQueuedUsers(final SyncResultCallback callback,
final AtomicInteger finisher) {
TodorooCursor<User> users = userDao.query(Query.select(User.PROPERTIES).where(
Criterion.and(User.PENDING_STATUS.isNotNull(), Functions.length(User.PENDING_STATUS).gt(0))));
try {
pushQueued(callback, finisher, users, true, userPusher);
} finally {
users.close();
}
}
// --- synchronize list
@Override

@ -8,13 +8,11 @@ import com.todoroo.astrid.activity.FilterModeSpec;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.Filter;
import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.api.FilterWithUpdate;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.ui.MainMenuPopover;
public class PeopleFilterMode implements FilterModeSpec {
private AsyncImageView imageView;
// private AsyncImageView imageView;
@Override
public Filter getDefaultFilter(Context context) {
@ -29,17 +27,17 @@ public class PeopleFilterMode implements FilterModeSpec {
@Override
public void onFilterItemClickedCallback(FilterListItem item) {
if (imageView == null)
return;
if (item instanceof FilterWithUpdate)
imageView.setUrl(((FilterWithUpdate) item).imageUrl);
else
imageView.setUrl(null);
}
public void setImageView(AsyncImageView imageView) {
this.imageView = imageView;
// if (imageView == null)
// return;
// if (item instanceof FilterWithUpdate)
// imageView.setUrl(((FilterWithUpdate) item).imageUrl);
// else
// imageView.setUrl(null);
}
//
// public void setImageView(AsyncImageView imageView) {
// this.imageView = imageView;
// }
@Override
public int[] getForbiddenMenuItems() {

@ -9,6 +9,7 @@ import android.content.Intent;
import android.support.v4.view.Menu;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.timsu.astrid.R;
@ -17,10 +18,12 @@ import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncService;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.api.AstridApiConstants;
import com.todoroo.astrid.dao.UserDao;
import com.todoroo.astrid.data.User;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.helper.ProgressBarSyncResultCallback;
import com.todoroo.astrid.service.SyncV2Service;
import com.todoroo.astrid.service.ThemeService;
@ -41,6 +44,12 @@ public class PersonViewFragment extends TaskListFragment {
@Autowired ActFmPreferenceService actFmPreferenceService;
@Autowired ActFmSyncService actFmSyncService;
private AsyncImageView userImage;
private TextView userSubtitle;
private TextView userStatusButton;
private User user;
@Override
@ -50,6 +59,19 @@ public class PersonViewFragment extends TaskListFragment {
user = userDao.fetch(extras.getLong(EXTRA_USER_ID_LOCAL), User.PROPERTIES);
}
((TextView) getView().findViewById(android.R.id.empty)).setText(getEmptyDisplayString());
setupUserHeader();
}
private void setupUserHeader() {
if (user != null) {
userImage.setDefaultImageResource(R.drawable.icn_default_person_image);
userImage.setUrl(user.getValue(User.PICTURE));
userSubtitle.setText(getUserSubtitleText());
setupUserStatusButton();
} else {
getView().findViewById(R.id.user_header).setVisibility(View.GONE);
}
}
@Override
@ -67,6 +89,65 @@ public class PersonViewFragment extends TaskListFragment {
}
private String getUserSubtitleText() {
String status = user.getValue(User.STATUS);
String userName = user.getDisplayName();
if (User.STATUS_PENDING.equals(status))
return getString(R.string.actfm_friendship_pending, userName);
else if (User.STATUS_BLOCKED.equals(status))
return getString(R.string.actfm_friendship_blocked, userName);
else if (User.STATUS_FRIENDS.equals(status))
return getString(R.string.actfm_friendship_friends, userName);
else if (User.STATUS_OTHER_PENDING.equals(status))
return getString(R.string.actfm_friendship_other_pending, userName);
else return getString(R.string.actfm_friendship_no_status, userName);
}
private void setupUserStatusButton() {
String status = user.getValue(User.STATUS);
userStatusButton.setVisibility(View.VISIBLE);
if (TextUtils.isEmpty(status))
userStatusButton.setText(getString(R.string.actfm_friendship_connect));
else if (User.STATUS_OTHER_PENDING.equals(status))
userStatusButton.setText(getString(R.string.actfm_friendship_accept));
else
userStatusButton.setVisibility(View.GONE);
}
@Override
protected void setUpUiComponents() {
super.setUpUiComponents();
userImage = (AsyncImageView) getView().findViewById(R.id.user_image);
userSubtitle = (TextView) getView().findViewById(R.id.user_subtitle);
userStatusButton = (TextView) getActivity().findViewById(R.id.person_image);
}
@Override
protected View getListBody(ViewGroup root) {
ViewGroup parent = (ViewGroup) getActivity().getLayoutInflater().inflate(R.layout.task_list_body_user, root, false);
View taskListView = super.getListBody(parent);
parent.addView(taskListView);
return parent;
}
public void handleStatusButtonClicked() {
String status = user.getValue(User.STATUS);
if (TextUtils.isEmpty(status)) { // Add friend case
user.setValue(User.PENDING_STATUS, User.PENDING_REQUEST);
} else if (User.STATUS_OTHER_PENDING.equals(status)) { // Accept friend case
user.setValue(User.PENDING_STATUS, User.PENDING_APPROVE);
}
if (user.getSetValues().containsKey(User.PENDING_STATUS.name)) {
userDao.saveExisting(user);
userStatusButton.setVisibility(View.GONE);
refreshData(false);
}
}
@Override
protected void addSyncRefreshMenuItem(Menu menu, int themeFlags) {
if(actFmPreferenceService.isLoggedIn()) {
@ -98,21 +179,35 @@ public class PersonViewFragment extends TaskListFragment {
}
}
@Override
protected void refresh() {
super.refresh();
setupUserHeader();
}
private void refreshData(final boolean manual) {
if (user != null) {
((TextView) getView().findViewById(android.R.id.empty)).setText(R.string.DLG_loading);
syncService.synchronizeList(user, manual, new ProgressBarSyncResultCallback(getActivity(), this,
R.id.progressBar, new Runnable() {
new Thread() {
@Override
public void run() {
if (manual)
ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
else
refresh();
((TextView) getView().findViewById(android.R.id.empty)).setText(getEmptyDisplayString());
if (!TextUtils.isEmpty(user.getValue(User.PENDING_STATUS))) {
actFmSyncService.pushUser(user);
user = userDao.fetch(user.getId(), User.PROPERTIES);
}
syncService.synchronizeList(user, manual, new ProgressBarSyncResultCallback(getActivity(), PersonViewFragment.this,
R.id.progressBar, new Runnable() {
@Override
public void run() {
if (manual)
ContextManager.getContext().sendBroadcast(new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH));
else
refresh();
((TextView) getView().findViewById(android.R.id.empty)).setText(getEmptyDisplayString());
}
}));
}
}));
}.start();
}
}

@ -54,11 +54,15 @@
</RelativeLayout>
</LinearLayout>
<com.todoroo.astrid.helper.AsyncImageView
<TextView
android:id="@+id/person_image"
android:layout_width="51dip"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:gravity="center_vertical"
android:singleLine="true"
android:paddingRight="5dip"
style="@style/TextAppearance.ActionBar_ListsHeader"
android:textSize="16sp"
android:visibility="gone"/>
<Button

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
** Copyright (c) 2012 Todoroo Inc
**
** See the file "LICENSE" for the full license governing this code.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="100">
<RelativeLayout
android:id="@+id/user_header"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dip"
android:background="?attr/asMembersHeaderBackground">
<com.todoroo.astrid.helper.AsyncImageView
android:id="@+id/user_image"
android:layout_height="50dip"
android:layout_width="50dip"
android:scaleType="fitCenter"
android:layout_marginRight="8dip"
android:layout_centerVertical="true"/>
<TextView
android:id="@+id/user_subtitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignTop="@id/user_image"
android:layout_toRightOf="@id/user_image"/>
</RelativeLayout>
<!-- List body goes here -->
</LinearLayout>

@ -52,6 +52,22 @@
<!-- Empty list for the "My Shared Tasks" filter -->
<string name="actfm_my_shared_tasks_empty">No shared tasks</string>
<!-- ===================== Friendship connections -->
<string name="actfm_friendship_pending">You\'ve sent a friend request to %s!</string>
<string name="actfm_friendship_blocked">You\'ve blocked %s.</string>
<string name="actfm_friendship_friends">You\'re friends with %s! Add tasks for them below.</string>
<string name="actfm_friendship_other_pending">%s wants to be friends with you!</string>
<string name="actfm_friendship_no_status">Connect with %s to share and see activity on public tasks!</string>
<string name="actfm_friendship_connect">Add friend</string>
<string name="actfm_friendship_accept">Accept</string>
<!-- ================================================== TagViewActivity == -->
<!-- Tag View Activity: Add Comment hint -->

@ -48,8 +48,8 @@ import com.todoroo.astrid.api.FilterListItem;
import com.todoroo.astrid.core.CustomFilterExposer;
import com.todoroo.astrid.data.TagData;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.helper.AsyncImageView;
import com.todoroo.astrid.people.PeopleFilterMode;
import com.todoroo.astrid.people.PersonViewFragment;
import com.todoroo.astrid.service.StatisticsConstants;
import com.todoroo.astrid.service.StatisticsService;
import com.todoroo.astrid.service.ThemeService;
@ -89,7 +89,7 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
private ImageView listsNavDisclosure;
private TextView lists;
private ImageView mainMenu;
private AsyncImageView personImage;
private TextView personStatus;
private Button commentsButton;
private int filterMode;
private FilterModeSpec filterModeSpec;
@ -141,6 +141,16 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
}
};
private final OnClickListener friendStatusClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
TaskListFragment tlf = getTaskListFragment();
if (tlf == null || !(tlf instanceof PersonViewFragment))
return;
((PersonViewFragment) tlf).handleStatusButtonClicked();
}
};
/**
* @see android.app.Activity#onCreate(Bundle)
*/
@ -164,14 +174,14 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
listsNavDisclosure = (ImageView) actionBar.getCustomView().findViewById(R.id.list_disclosure_arrow);
lists = (TextView) actionBar.getCustomView().findViewById(R.id.list_title);
mainMenu = (ImageView) actionBar.getCustomView().findViewById(R.id.main_menu);
personImage = (AsyncImageView) actionBar.getCustomView().findViewById(R.id.person_image);
personImage.setDefaultImageResource(R.drawable.icn_default_person_image);
personStatus = (TextView) actionBar.getCustomView().findViewById(R.id.person_image);
commentsButton = (Button) actionBar.getCustomView().findViewById(R.id.comments);
initializeFragments(actionBar);
createMainMenuPopover();
mainMenu.setOnClickListener(mainMenuClickListener);
commentsButton.setOnClickListener(commentsButtonClickListener);
personStatus.setOnClickListener(friendStatusClickListener);
Bundle extras = getIntent().getExtras();
if (extras != null)
@ -734,11 +744,10 @@ public class TaskListActivity extends AstridActivity implements MainMenuListener
setupPopoverWithFilterList((FilterListFragment) setupFragment(FilterListFragment.TAG_FILTERLIST_FRAGMENT, 0,
filterModeSpec.getFilterListClass(), true, true));
if (mode == FILTER_MODE_PEOPLE) {
personImage.setVisibility(View.VISIBLE);
personStatus.setVisibility(View.VISIBLE);
commentsButton.setVisibility(View.GONE);
((PeopleFilterMode) filterModeSpec).setImageView(personImage);
} else {
personImage.setVisibility(View.GONE);
personStatus.setVisibility(View.GONE);
commentsButton.setVisibility(View.VISIBLE);
}

@ -40,7 +40,7 @@ public class Database extends AbstractDatabase {
* Database version number. This variable must be updated when database
* tables are updated, as it determines whether a database needs updating.
*/
public static final int VERSION = 25;
public static final int VERSION = 26;
/**
* Database name (must be unique)
@ -330,6 +330,16 @@ public class Database extends AbstractDatabase {
Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e);
}
case 25: try {
database.execSQL("ALTER TABLE " + User.TABLE.name + " ADD " +
User.STATUS.accept(visitor, null));
database.execSQL("ALTER TABLE " + User.TABLE.name + " ADD " +
User.PENDING_STATUS.accept(visitor, null));
} catch (SQLiteException e) {
Log.e("astrid", "db-upgrade-" + oldVersion + "-" + newVersion, e);
}
return true;
}

Loading…
Cancel
Save