Add a "Shared with me" section.

This commit is contained in:
Jimmy Shih
2013-02-05 10:58:49 -08:00
parent b5fa77a98d
commit 69f2b18f10
5 changed files with 220 additions and 18 deletions
@@ -0,0 +1,168 @@
/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.android.apps.mytracks;
import com.google.android.apps.mytracks.content.TracksColumns;
import com.google.android.maps.mytracks.R;
import android.content.Context;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.support.v4.widget.ResourceCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* A section based resource cursor adapter. Currently only supports one
* additional section header, "Shared with me".
*
* @author Jimmy Shih
*/
public abstract class SectionResourceCursorAdapter extends ResourceCursorAdapter {
private enum ItemType {
TRACK, HEADER
}
private final LayoutInflater layoutInflater;
private int sharedWithMeIndex = -1;
public SectionResourceCursorAdapter(Context context, int layout, Cursor cursor, int flags) {
super(context, layout, cursor, flags);
this.layoutInflater = LayoutInflater.from(context);
if (cursor != null) {
sharedWithMeIndex = getSharedWithMeIndex();
cursor.registerDataSetObserver(dataSetObserver);
}
}
private DataSetObserver dataSetObserver = new DataSetObserver() {
@Override
public void onChanged() {
sharedWithMeIndex = getSharedWithMeIndex();
};
@Override
public void onInvalidated() {
sharedWithMeIndex = -1;
};
};
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (getItemViewType(position) == ItemType.TRACK.ordinal()) {
return super.getView(getCursorPosition(position), convertView, parent);
} else {
TextView textView;
if (convertView == null) {
textView = (TextView) layoutInflater.inflate(R.layout.track_list_header, parent, false);
} else {
textView = (TextView) convertView;
}
return textView;
}
}
@Override
public int getViewTypeCount() {
return ItemType.values().length;
}
@Override
public int getCount() {
int count = super.getCount();
return count != 0 && sharedWithMeIndex != -1 ? count + 1 : count;
}
@Override
public boolean isEnabled(int position) {
return getItemViewType(position) == ItemType.TRACK.ordinal();
}
@Override
public Object getItem(int position) {
if (getItemViewType(position) == ItemType.TRACK.ordinal()) {
return super.getItem(getCursorPosition(position));
}
return null;
}
@Override
public long getItemId(int position) {
if (getItemViewType(position) == ItemType.TRACK.ordinal()) {
return super.getItemId(getCursorPosition(position));
}
return -1L;
}
@Override
public int getItemViewType(int position) {
if (sharedWithMeIndex != -1 && sharedWithMeIndex == position) {
return ItemType.HEADER.ordinal();
}
return ItemType.TRACK.ordinal();
}
@Override
public Cursor swapCursor(Cursor newCursor) {
if (getCursor() != null) {
getCursor().unregisterDataSetObserver(dataSetObserver);
}
Cursor oldCursor = super.swapCursor(newCursor);
if (newCursor != null) {
sharedWithMeIndex = getSharedWithMeIndex();
newCursor.registerDataSetObserver(dataSetObserver);
}
return oldCursor;
}
/**
* Gets the Shared with me header index.
*/
private int getSharedWithMeIndex() {
int i = 0;
Cursor cursor = getCursor();
if (cursor != null && cursor.moveToFirst()) {
int index = cursor.getColumnIndex(TracksColumns.SHAREDWITHME);
do {
int sharedWithMe = cursor.getInt(index);
if (sharedWithMe == 1) {
// Returns the index where sharedWithMe == 1
return i;
}
i++;
} while (cursor.moveToNext());
}
return -1;
}
/**
* Gets the underlying cursor position.
*
* @param position the requested position
*/
private int getCursorPosition(int position) {
if (sharedWithMeIndex != -1 && position > sharedWithMeIndex) {
return position - 1;
}
return position;
}
}
@@ -66,7 +66,6 @@ import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.ResourceCursorAdapter;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -97,7 +96,8 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
private static final int GOOGLE_PLAY_SERVICES_REQUEST_CODE = 0;
private static final String[] PROJECTION = new String[] { TracksColumns._ID, TracksColumns.NAME,
TracksColumns.DESCRIPTION, TracksColumns.CATEGORY, TracksColumns.STARTTIME,
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON };
TracksColumns.TOTALDISTANCE, TracksColumns.TOTALTIME, TracksColumns.ICON,
TracksColumns.SHAREDWITHME};
// Callback when the trackRecordingServiceConnection binding changes.
private final Runnable bindChangedCallback = new Runnable() {
@@ -180,7 +180,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
boolean isRecording = recordingTrackId
!= PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
updateMenuItems(isRecording);
resourceCursorAdapter.notifyDataSetChanged();
sectionResourceCursorAdapter.notifyDataSetChanged();
trackController.update(isRecording, recordingTrackPaused);
}
});
@@ -333,7 +333,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
private TrackRecordingServiceConnection trackRecordingServiceConnection;
private TrackController trackController;
private ListView listView;
private ResourceCursorAdapter resourceCursorAdapter;
private SectionResourceCursorAdapter sectionResourceCursorAdapter;
private TrackDataHub trackDataHub;
// Preferences
@@ -379,7 +379,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
startActivity(intent);
}
});
resourceCursorAdapter = new ResourceCursorAdapter(this, R.layout.list_item, null, 0) {
sectionResourceCursorAdapter = new SectionResourceCursorAdapter(this, R.layout.list_item, null, 0) {
@Override
public void bindView(View view, Context context, Cursor cursor) {
int idIndex = cursor.getColumnIndex(TracksColumns._ID);
@@ -406,7 +406,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
totalDistance, startTimeDisplay, cursor.getString(descriptionIndex));
}
};
listView.setAdapter(resourceCursorAdapter);
listView.setAdapter(sectionResourceCursorAdapter);
ApiAdapterFactory.getApiAdapter()
.configureListViewContextualMenu(this, listView, contextualActionModeCallback);
@@ -414,17 +414,17 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
return new CursorLoader(TrackListActivity.this, TracksColumns.CONTENT_URI, PROJECTION, null,
null, TracksColumns._ID + " DESC");
null, TracksColumns.SHAREDWITHME + " ASC, " + TracksColumns._ID + " DESC");
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
resourceCursorAdapter.swapCursor(cursor);
sectionResourceCursorAdapter.swapCursor(cursor);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
resourceCursorAdapter.swapCursor(null);
sectionResourceCursorAdapter.swapCursor(null);
}
});
trackDataHub = TrackDataHub.newInstance(this);
@@ -462,7 +462,7 @@ public class TrackListActivity extends FragmentActivity implements DeleteOneTrac
// Update UI
boolean isRecording = recordingTrackId != PreferencesUtils.RECORDING_TRACK_ID_DEFAULT;
updateMenuItems(isRecording);
resourceCursorAdapter.notifyDataSetChanged();
sectionResourceCursorAdapter.notifyDataSetChanged();
trackController.update(isRecording, recordingTrackPaused);
}
@@ -161,14 +161,18 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter {
context, R.string.drive_deleted_list_key, PreferencesUtils.DRIVE_DELETED_LIST_DEFAULT);
String deletedIds[] = TextUtils.split(driveDeletedList, ";");
for (String id : deletedIds) {
File driveFile = drive.files().get(id).execute();
if (SyncUtils.isInFolder(driveFile, folderId)) {
if (!driveFile.getLabels().getTrashed()) {
drive.files().trash(id).execute();
try {
File driveFile = drive.files().get(id).execute();
if (SyncUtils.isInFolder(driveFile, folderId)) {
if (!driveFile.getLabels().getTrashed()) {
drive.files().trash(id).execute();
}
// if trashed, ignore
} else if (SyncUtils.isSharedWithMe(driveFile)) {
drive.files().delete(id).execute();
}
// if trashed, ignore
} else if (SyncUtils.isSharedWithMe(driveFile)) {
drive.files().delete(id).execute();
} catch (IOException e) {
// safe to ignore
}
}
PreferencesUtils.setString(