Browse Source

Merge pull request #1050 from owncloud/favourites_context_menu

'Kept-in-sync' renamed as 'Favourites' and added to context menu in list of files
David A. Velasco 9 years ago
parent
commit
c21fa6c6e5

+ 3 - 3
res/layout/file_details_fragment.xml

@@ -160,16 +160,16 @@
 			>
 			
 			<CheckBox
-				android:id="@+id/fdKeepInSync"
+				android:id="@+id/fdFavorite"
 				android:layout_width="wrap_content"
 				android:layout_height="wrap_content"
 				android:layout_centerHorizontal="true"
-				android:text="@string/fd_keep_in_sync" />
+				android:text="@string/favorite" />
 
 			<LinearLayout
 				android:layout_width="match_parent"
 				android:layout_height="wrap_content"
-				android:layout_below="@id/fdKeepInSync"
+				android:layout_below="@id/fdFavorite"
 				android:orientation="vertical" >
 				
     			<TextView 

+ 2 - 0
res/menu/file_actions_menu.xml

@@ -30,6 +30,8 @@
     <item 	android:id="@+id/action_move"					android:title="@string/actionbar_move"				android:icon="@android:drawable/ic_menu_set_as"					android:orderInCategory="1" />
     <item 	android:id="@+id/action_remove_file"			android:title="@string/common_remove"				android:icon="@android:drawable/ic_menu_delete"					android:orderInCategory="1" />
     <item 	android:id="@+id/action_send_file"				android:title="@string/actionbar_send_file"			android:icon="@android:drawable/ic_menu_set_as"					android:orderInCategory="1" />
+    <item 	android:id="@+id/action_favorite_file"			android:title="@string/favorite"		    	android:icon="@android:drawable/ic_menu_set_as"					android:orderInCategory="1" />
+    <item 	android:id="@+id/action_unfavorite_file"		android:title="@string/unfavorite"		    	    android:icon="@android:drawable/ic_menu_set_as"					android:orderInCategory="1" />
     <item 	android:id="@+id/action_see_details"			android:title="@string/actionbar_see_details"		android:icon="@android:drawable/ic_menu_info_details"			android:orderInCategory="1" />
 
 </menu>

+ 2 - 1
res/values/strings.xml

@@ -200,7 +200,8 @@
 	<string name="auth_can_not_auth_against_server">Cannot authenticate against this server</string>
     <string name="auth_account_does_not_exist">Account does not exist in the device yet</string>
     
-    <string name="fd_keep_in_sync">Keep file up to date</string>
+    <string name="favorite">Favorite</string>
+    <string name="unfavorite">Unfavorite</string>
     <string name="common_rename">Rename</string>
     <string name="common_remove">Remove</string>
     <string name="confirmation_remove_alert">"Do you really want to remove %1$s?"</string>

+ 5 - 5
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -190,7 +190,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
-        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
@@ -300,7 +300,7 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
             cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
             cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
-            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+            cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
             cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
@@ -377,7 +377,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
         cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
-        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
+        cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.isFavorite() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
@@ -877,7 +877,7 @@ public class FileDataStorageManager {
                     .getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
             file.setLastSyncDateForData(c.getLong(c.
                     getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
-            file.setKeepInSync(c.getInt(
+            file.setFavorite(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
             file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG)));
             file.setShareByLink(c.getInt(
@@ -1261,7 +1261,7 @@ public class FileDataStorageManager {
                     ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, 
                     file.getLastSyncDateForData()
                 );
-                cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
+                cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.isFavorite() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
                 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());

+ 10 - 10
src/com/owncloud/android/datamodel/OCFile.java

@@ -60,7 +60,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
     private boolean mNeedsUpdating;
     private long mLastSyncDateForProperties;
     private long mLastSyncDateForData;
-    private boolean mKeepInSync;
+    private boolean mFavorite;
 
     private String mEtag;
 
@@ -107,7 +107,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mLocalPath = source.readString();
         mMimeType = source.readString();
         mNeedsUpdating = source.readInt() == 0;
-        mKeepInSync = source.readInt() == 1;
+        mFavorite = source.readInt() == 1;
         mLastSyncDateForProperties = source.readLong();
         mLastSyncDateForData = source.readLong();
         mEtag = source.readString();
@@ -132,7 +132,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         dest.writeString(mLocalPath);
         dest.writeString(mMimeType);
         dest.writeInt(mNeedsUpdating ? 1 : 0);
-        dest.writeInt(mKeepInSync ? 1 : 0);
+        dest.writeInt(mFavorite ? 1 : 0);
         dest.writeLong(mLastSyncDateForProperties);
         dest.writeLong(mLastSyncDateForData);
         dest.writeString(mEtag);
@@ -346,7 +346,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mModifiedTimestampAtLastSyncForData = 0;
         mLastSyncDateForProperties = 0;
         mLastSyncDateForData = 0;
-        mKeepInSync = false;
+        mFavorite = false;
         mNeedsUpdating = false;
         mEtag = null;
         mShareByLink = false;
@@ -444,12 +444,12 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
         mLastSyncDateForData = lastSyncDate;
     }
 
-    public void setKeepInSync(boolean keepInSync) {
-        mKeepInSync = keepInSync;
+    public void setFavorite(boolean favorite) {
+        mFavorite = favorite;
     }
 
-    public boolean keepInSync() {
-        return mKeepInSync;
+    public boolean isFavorite() {
+        return mFavorite;
     }
 
     @Override
@@ -483,8 +483,8 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
 
     @Override
     public String toString() {
-        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, keepInSync=%s etag=%s]";
-        asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mKeepInSync), mEtag);
+        String asString = "[id=%s, name=%s, mime=%s, downloaded=%s, local=%s, remote=%s, parentId=%s, favorite=%s etag=%s]";
+        asString = String.format(asString, Long.valueOf(mId), getFileName(), mMimeType, isDown(), mLocalPath, mRemotePath, Long.valueOf(mParentId), Boolean.valueOf(mFavorite), mEtag);
         return asString;
     }
 

+ 14 - 0
src/com/owncloud/android/files/FileMenuFilter.java

@@ -215,6 +215,20 @@ public class FileMenuFilter {
             toShow.add(R.id.action_send_file);
         }
 
+        // FAVORITES
+        if (mFile == null || downloading || uploading || mFile.isFolder() || mFile.isFavorite()) {
+            toHide.add(R.id.action_favorite_file);
+        } else {
+            toShow.add(R.id.action_favorite_file);
+        }
+
+        // UNFAVORITES
+        if (mFile == null || downloading || uploading || mFile.isFolder() || !mFile.isFavorite()) {
+            toHide.add(R.id.action_unfavorite_file);
+        } else {
+            toShow.add(R.id.action_unfavorite_file);
+        }
+
     }
 
 }

+ 21 - 2
src/com/owncloud/android/files/FileOperationsHelper.java

@@ -40,6 +40,7 @@ import com.owncloud.android.lib.common.network.WebdavUtils;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
 import com.owncloud.android.services.OperationsService;
+import com.owncloud.android.services.observer.FileObserverService;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.dialog.ShareLinkToDialog;
 
@@ -223,6 +224,24 @@ public class FileOperationsHelper {
             mFileActivity.startService(intent);
         }
     }
+
+    public void toggleFavorite(OCFile file, boolean isFavorite) {
+        file.setFavorite(isFavorite);
+        mFileActivity.getStorageManager().saveFile(file);
+
+        /// register the OCFile instance in the observer service to monitor local updates
+        Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
+                mFileActivity,
+                file,
+                mFileActivity.getAccount(),
+                isFavorite);
+        mFileActivity.startService(observedFileIntent);
+
+        /// immediate content synchronization
+        if (file.isFavorite()) {
+            syncFile(file);
+        }
+    }
     
     public void renameFile(OCFile file, String newFilename) {
         // RenameFile
@@ -282,8 +301,8 @@ public class FileOperationsHelper {
             downloaderBinder.cancel(account, file);
 
             // TODO - review why is this here, and solve in a better way
-            // Remove etag for parent, if file is a keep_in_sync
-            if (file.keepInSync()) {
+            // Remove etag for parent, if file is a favorite
+            if (file.isFavorite()) {
                 OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId());
                 parent.setEtag("");
                 mFileActivity.getStorageManager().saveFile(parent);

+ 2 - 2
src/com/owncloud/android/operations/RefreshFolderOperation.java

@@ -365,7 +365,7 @@ public class RefreshFolderOperation extends RemoteOperation {
             if (localFile != null) {
                 // some properties of local state are kept unmodified
                 remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setKeepInSync(localFile.keepInSync());
+                remoteFile.setFavorite(localFile.isFavorite());
                 remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
                 remoteFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
@@ -397,7 +397,7 @@ public class RefreshFolderOperation extends RemoteOperation {
             searchForLocalFileInDefaultPath(remoteFile);    // legacy   
 
             /// prepare content synchronization for kept-in-sync files
-            if (remoteFile.keepInSync()) {
+            if (remoteFile.isFavorite()) {
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(  localFile,        
                                                                                     remoteFile, 
                                                                                     mAccount, 

+ 3 - 3
src/com/owncloud/android/operations/SynchronizeFileOperation.java

@@ -245,12 +245,12 @@ public class SynchronizeFileOperation extends SyncOperation {
                     
                     if (mSyncFileContents) {
                         requestForDownload(mLocalFile); // local, not server; we won't to keep
-                        // the value of keepInSync!
+                        // the value of favorite!
                         // the update of local data will be done later by the FileUploader
                         // service when the upload finishes
                     } else {
                         // TODO CHECK: is this really useful in some point in the code?
-                        mServerFile.setKeepInSync(mLocalFile.keepInSync());
+                        mServerFile.setFavorite(mLocalFile.isFavorite());
                         mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
                         mServerFile.setStoragePath(mLocalFile.getStoragePath());
                         mServerFile.setParentId(mLocalFile.getParentId());
@@ -285,7 +285,7 @@ public class SynchronizeFileOperation extends SyncOperation {
         i.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
         i.putExtra(FileUploader.KEY_FILE, file);
         /*i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);
-        // doing this we would lose the value of keepInSync in the road, and maybe
+        // doing this we would lose the value of isFavorite in the road, and maybe
         // it's not updated in the database when the FileUploader service gets it!
         i.putExtra(FileUploader.KEY_LOCAL_FILE, localFile.getStoragePath());*/
         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);

+ 2 - 2
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -321,7 +321,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
             if (localFile != null) {
                 // some properties of local state are kept unmodified
                 remoteFile.setFileId(localFile.getFileId());
-                remoteFile.setKeepInSync(localFile.keepInSync());
+                remoteFile.setFavorite(localFile.isFavorite());
                 remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
                 remoteFile.setModificationTimestampAtLastSyncForData(
                         localFile.getModificationTimestampAtLastSyncForData()
@@ -360,7 +360,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
                     startSyncFolderOperation(remoteFile.getRemotePath());
                 }
 
-            } else if (remoteFile.keepInSync()) {
+            } else if (remoteFile.isFavorite()) {
                 /// prepare content synchronization for kept-in-sync files
                 SynchronizeFileOperation operation = new SynchronizeFileOperation(
                         localFile,

+ 1 - 1
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -407,7 +407,7 @@ public class UploadFileOperation extends RemoteOperation {
         newFile.setModificationTimestampAtLastSyncForData(
                 mFile.getModificationTimestampAtLastSyncForData());
         // newFile.setEtag(mFile.getEtag())
-        newFile.setKeepInSync(mFile.keepInSync());
+        newFile.setFavorite(mFile.isFavorite());
         newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
         newFile.setLastSyncDateForData(mFile.getLastSyncDateForData());
         newFile.setStoragePath(mFile.getStoragePath());

+ 121 - 93
src/com/owncloud/android/ui/activity/FileActivity.java

@@ -67,6 +67,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.CreateShareOperation;
+import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.SynchronizeFolderOperation;
 import com.owncloud.android.operations.UnshareLinkOperation;
 import com.owncloud.android.services.OperationsService;
@@ -75,6 +76,8 @@ import com.owncloud.android.ui.NavigationDrawerItem;
 import com.owncloud.android.ui.adapter.NavigationDrawerListAdapter;
 import com.owncloud.android.ui.dialog.LoadingDialog;
 import com.owncloud.android.ui.dialog.SharePasswordDialogFragment;
+import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.utils.ErrorMessageAdapter;
 
 import java.util.ArrayList;
@@ -93,49 +96,49 @@ public class FileActivity extends ActionBarActivity
             "com.owncloud.android.ui.activity.WAITING_TO_PREVIEW";
     public static final String EXTRA_FROM_NOTIFICATION =
             "com.owncloud.android.ui.activity.FROM_NOTIFICATION";
-    
+
     public static final String TAG = FileActivity.class.getSimpleName();
-    
+
     private static final String DIALOG_WAIT_TAG = "DIALOG_WAIT";
     private static final String KEY_WAITING_FOR_OP_ID = "WAITING_FOR_OP_ID";
     private static final String DIALOG_SHARE_PASSWORD = "DIALOG_SHARE_PASSWORD";
     private static final String KEY_TRY_SHARE_AGAIN = "TRY_SHARE_AGAIN";
     private static final String KEY_ACTION_BAR_TITLE = "ACTION_BAR_TITLE";
-    
+
     protected static final long DELAY_TO_REQUEST_OPERATION_ON_ACTIVITY_RESULTS = 200;
-    
-    
+
+
     /** OwnCloud {@link Account} where the main {@link OCFile} handled by the activity is located.*/
     private Account mAccount;
-    
+
     /** Main {@link OCFile} handled by the activity.*/
     private OCFile mFile;
-    
+
     /** Flag to signal that the activity will is finishing to enforce the creation of an ownCloud
      * {@link Account} */
     private boolean mRedirectingToSetupAccount = false;
-    
-    /** Flag to signal when the value of mAccount was set */ 
+
+    /** Flag to signal when the value of mAccount was set */
     protected boolean mAccountWasSet;
-    
-    /** Flag to signal when the value of mAccount was restored from a saved state */ 
+
+    /** Flag to signal when the value of mAccount was restored from a saved state */
     protected boolean mAccountWasRestored;
-    
+
     /** Flag to signal if the activity is launched by a notification */
     private boolean mFromNotification;
-    
+
     /** Messages handler associated to the main thread and the life cycle of the activity */
     private Handler mHandler;
-    
+
     /** Access point to the cached database for the current ownCloud {@link Account} */
     private FileDataStorageManager mStorageManager = null;
-    
+
     private FileOperationsHelper mFileOperationsHelper;
-    
+
     private ServiceConnection mOperationsServiceConnection = null;
-    
+
     private OperationsServiceBinder mOperationsServiceBinder = null;
-    
+
     protected FileDownloaderBinder mDownloaderBinder = null;
     protected FileUploaderBinder mUploaderBinder = null;
     private ServiceConnection mDownloadServiceConnection, mUploadServiceConnection = null;
@@ -158,12 +161,12 @@ public class FileActivity extends ActionBarActivity
 
     // TODO re-enable when "Accounts" is available in Navigation Drawer
 //    protected boolean mShowAccounts = false;
-    
+
     /**
-     * Loads the ownCloud {@link Account} and main {@link OCFile} to be handled by the instance of 
+     * Loads the ownCloud {@link Account} and main {@link OCFile} to be handled by the instance of
      * the {@link FileActivity}.
-     * 
-     * Grants that a valid ownCloud {@link Account} is associated to the instance, or that the user 
+     *
+     * Grants that a valid ownCloud {@link Account} is associated to the instance, or that the user
      * is requested to create a new one.
      */
     @Override
@@ -191,11 +194,11 @@ public class FileActivity extends ActionBarActivity
                                                  // or database
 
         setAccount(account, savedInstanceState != null);
-        
+
         mOperationsServiceConnection = new OperationsServiceConnection();
         bindService(new Intent(this, OperationsService.class), mOperationsServiceConnection,
                 Context.BIND_AUTO_CREATE);
-        
+
         mDownloadServiceConnection = newTransferenceServiceConnection();
         if (mDownloadServiceConnection != null) {
             bindService(new Intent(this, FileDownloader.class), mDownloadServiceConnection,
@@ -220,8 +223,8 @@ public class FileActivity extends ActionBarActivity
     }
 
     /**
-     *  Since ownCloud {@link Account}s can be managed from the system setting menu, 
-     *  the existence of the {@link Account} associated to the instance must be checked 
+     *  Since ownCloud {@link Account}s can be managed from the system setting menu,
+     *  the existence of the {@link Account} associated to the instance must be checked
      *  every time it is restarted.
      */
     @Override
@@ -235,8 +238,8 @@ public class FileActivity extends ActionBarActivity
         Log_OC.v(TAG, "onRestart() end");
     }
 
-    
-    @Override 
+
+    @Override
     protected void onStart() {
         super.onStart();
 
@@ -244,26 +247,26 @@ public class FileActivity extends ActionBarActivity
             onAccountSet(mAccountWasRestored);
         }
     }
-    
+
     @Override
     protected void onResume() {
         super.onResume();
-        
+
         if (mOperationsServiceBinder != null) {
             doOnResumeAndBound();
         }
     }
-    
+
     @Override
     protected void onPause()  {
         if (mOperationsServiceBinder != null) {
             mOperationsServiceBinder.removeOperationListener(this);
         }
-        
+
         super.onPause();
     }
-    
-    
+
+
     @Override
     protected void onDestroy() {
         if (mOperationsServiceConnection != null) {
@@ -435,12 +438,12 @@ public class FileActivity extends ActionBarActivity
 
 
     /**
-     *  Sets and validates the ownCloud {@link Account} associated to the Activity. 
-     * 
+     *  Sets and validates the ownCloud {@link Account} associated to the Activity.
+     *
      *  If not valid, tries to swap it for other valid and existing ownCloud {@link Account}.
-     *  
-     *  POSTCONDITION: updates {@link #mAccountWasSet} and {@link #mAccountWasRestored}. 
-     * 
+     *
+     *  POSTCONDITION: updates {@link #mAccountWasSet} and {@link #mAccountWasRestored}.
+     *
      *  @param account          New {@link Account} to set.
      *  @param savedAccount     When 'true', account was retrieved from a saved instance state.
      */
@@ -453,19 +456,19 @@ public class FileActivity extends ActionBarActivity
             mAccount = account;
             mAccountWasSet = true;
             mAccountWasRestored = (savedAccount || mAccount.equals(oldAccount));
-            
+
         } else {
             swapToDefaultAccount();
         }
     }
 
-    
+
     /**
-     *  Tries to swap the current ownCloud {@link Account} for other valid and existing. 
-     * 
-     *  If no valid ownCloud {@link Account} exists, the the user is requested 
+     *  Tries to swap the current ownCloud {@link Account} for other valid and existing.
+     *
+     *  If no valid ownCloud {@link Account} exists, the the user is requested
      *  to create a new ownCloud {@link Account}.
-     *  
+     *
      *  POSTCONDITION: updates {@link #mAccountWasSet} and {@link #mAccountWasRestored}.
      */
     private void swapToDefaultAccount() {
@@ -477,7 +480,7 @@ public class FileActivity extends ActionBarActivity
             mRedirectingToSetupAccount = true;
             mAccountWasSet = false;
             mAccountWasRestored = false;
-            
+
         } else {
             mAccountWasSet = true;
             mAccountWasRestored = (newAccount.equals(mAccount));
@@ -500,7 +503,7 @@ public class FileActivity extends ActionBarActivity
                 null);
     }
 
-    
+
     /**
      * {@inheritDoc}
      */
@@ -513,32 +516,32 @@ public class FileActivity extends ActionBarActivity
         outState.putBoolean(KEY_TRY_SHARE_AGAIN, mTryShareAgain);
         outState.putString(KEY_ACTION_BAR_TITLE, getSupportActionBar().getTitle().toString());
     }
-    
-    
+
+
     /**
      * Getter for the main {@link OCFile} handled by the activity.
-     * 
+     *
      * @return  Main {@link OCFile} handled by the activity.
      */
     public OCFile getFile() {
         return mFile;
     }
 
-    
+
     /**
      * Setter for the main {@link OCFile} handled by the activity.
-     * 
+     *
      * @param file  Main {@link OCFile} to be handled by the activity.
      */
     public void setFile(OCFile file) {
         mFile = file;
     }
 
-    
+
     /**
      * Getter for the ownCloud {@link Account} where the main {@link OCFile} handled by the activity
      * is located.
-     * 
+     *
      * @return  OwnCloud {@link Account} where the main {@link OCFile} handled by the activity
      *          is located.
      */
@@ -556,7 +559,7 @@ public class FileActivity extends ActionBarActivity
     public boolean fromNotification() {
         return mFromNotification;
     }
-    
+
     /**
      * @return  'True' when the Activity is finishing to enforce the setup of a new account.
      */
@@ -571,11 +574,11 @@ public class FileActivity extends ActionBarActivity
     public void setTryShareAgain(boolean tryShareAgain) {
        mTryShareAgain = tryShareAgain;
     }
-    
+
     public OperationsServiceBinder getOperationsServiceBinder() {
         return mOperationsServiceBinder;
     }
-    
+
     protected ServiceConnection newTransferenceServiceConnection() {
         return null;
     }
@@ -583,7 +586,7 @@ public class FileActivity extends ActionBarActivity
     /**
      * Helper class handling a callback from the {@link AccountManager} after the creation of
      * a new ownCloud {@link Account} finished, successfully or not.
-     * 
+     *
      * At this moment, only called after the creation of the first account.
      */
     public class AccountCreationCallback implements AccountManagerCallback<Bundle> {
@@ -604,11 +607,11 @@ public class FileActivity extends ActionBarActivity
                     }
                 } catch (OperationCanceledException e) {
                     Log_OC.d(TAG, "Account creation canceled");
-                    
+
                 } catch (Exception e) {
                     Log_OC.e(TAG, "Account creation finished in exception: ", e);
                 }
-                    
+
             } else {
                 Log_OC.e(TAG, "Account creation callback with null bundle");
             }
@@ -616,19 +619,19 @@ public class FileActivity extends ActionBarActivity
                 moveTaskToBack(true);
             }
         }
-        
+
     }
-    
-    
+
+
     /**
      *  Called when the ownCloud {@link Account} associated to the Activity was just updated.
-     * 
+     *
      *  Child classes must grant that state depending on the {@link Account} is updated.
      */
     protected void onAccountSet(boolean stateWasRecovered) {
         if (getAccount() != null) {
             mStorageManager = new FileDataStorageManager(getAccount(), getContentResolver());
-            
+
         } else {
             Log_OC.wtf(TAG, "onAccountChanged was called with NULL account associated!");
         }
@@ -648,13 +651,13 @@ public class FileActivity extends ActionBarActivity
     public Handler getHandler() {
         return mHandler;
     }
-    
+
     public FileOperationsHelper getFileOperationsHelper() {
         return mFileOperationsHelper;
     }
-    
+
     /**
-     * 
+     *
      * @param operation     Removal operation performed.
      * @param result        Result of the removal.
      */
@@ -662,17 +665,17 @@ public class FileActivity extends ActionBarActivity
     public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) {
         Log_OC.d(TAG, "Received result of operation in FileActivity - common behaviour for all the "
                 + "FileActivities ");
-        
+
         mFileOperationsHelper.setOpIdWaitingFor(Long.MAX_VALUE);
-        
+
         if (!result.isSuccess() && (
-                result.getCode() == ResultCode.UNAUTHORIZED || 
+                result.getCode() == ResultCode.UNAUTHORIZED ||
                 result.isIdPRedirection() ||
                 (result.isException() && result.getException() instanceof AuthenticatorException)
                 )) {
-            
+
             requestCredentialsUpdate();
-            
+
             if (result.getCode() == ResultCode.UNAUTHORIZED) {
                 dismissLoadingDialog();
                 Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result,
@@ -684,13 +687,16 @@ public class FileActivity extends ActionBarActivity
 
         } else if (operation instanceof CreateShareOperation) {
             onCreateShareOperationFinish((CreateShareOperation) operation, result);
-            
+
         } else if (operation instanceof UnshareLinkOperation) {
             onUnshareLinkOperationFinish((UnshareLinkOperation)operation, result);
-        
+
         } else if (operation instanceof SynchronizeFolderOperation) {
             onSynchronizeFolderOperationFinish((SynchronizeFolderOperation)operation, result);
 
+        }else if (operation instanceof SynchronizeFileOperation) {
+            onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);
+
         }
     }
 
@@ -698,12 +704,12 @@ public class FileActivity extends ActionBarActivity
         Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
         updateAccountCredentials.putExtra(AuthenticatorActivity.EXTRA_ACCOUNT, getAccount());
         updateAccountCredentials.putExtra(
-                AuthenticatorActivity.EXTRA_ACTION, 
+                AuthenticatorActivity.EXTRA_ACTION,
                 AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN);
         updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
         startActivity(updateAccountCredentials);
     }
-    
+
 
     private void onCreateShareOperationFinish(CreateShareOperation operation,
                                               RemoteOperationResult result) {
@@ -711,7 +717,7 @@ public class FileActivity extends ActionBarActivity
         if (result.isSuccess()) {
             mTryShareAgain = false;
             updateFileFromDB();
-            
+
             Intent sendIntent = operation.getSendIntent();
             startActivity(sendIntent);
         } else {
@@ -735,22 +741,22 @@ public class FileActivity extends ActionBarActivity
                         Toast.LENGTH_LONG);
                 t.show();
             }
-        } 
+        }
     }
-    
-    
+
+
     private void onUnshareLinkOperationFinish(UnshareLinkOperation operation,
                                               RemoteOperationResult result) {
         dismissLoadingDialog();
-        
+
         if (result.isSuccess()){
             updateFileFromDB();
-            
+
         } else {
             Toast t = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result,
                             operation, getResources()), Toast.LENGTH_LONG);
             t.show();
-        } 
+        }
     }
 
     private void onSynchronizeFolderOperationFinish(
@@ -762,7 +768,28 @@ public class FileActivity extends ActionBarActivity
             t.show();
         }
     }
-    
+
+    private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation,
+                                                  RemoteOperationResult result) {
+        dismissLoadingDialog();
+        OCFile syncedFile = operation.getLocalFile();
+        if (!result.isSuccess()) {
+            if (result.getCode() == ResultCode.SYNC_CONFLICT) {
+                Intent i = new Intent(this, ConflictsResolveActivity.class);
+                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, syncedFile);
+                i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, getAccount());
+                startActivity(i);
+
+            }
+        } else {
+            if (!operation.transferWasRequested()) {
+                Toast msg = Toast.makeText(this, ErrorMessageAdapter.getErrorCauseMessage(result,
+                        operation, getResources()), Toast.LENGTH_LONG);
+                msg.show();
+            }
+        }
+    }
+
     protected void updateFileFromDB(){
         OCFile file = getFile();
         if (file != null) {
@@ -770,9 +797,10 @@ public class FileActivity extends ActionBarActivity
             setFile(file);
         }
     }
-    
+
+
     /**
-     * Show loading dialog 
+     * Show loading dialog
      */
     public void showLoadingDialog() {
         // Construct dialog
@@ -780,10 +808,10 @@ public class FileActivity extends ActionBarActivity
         FragmentManager fm = getSupportFragmentManager();
         FragmentTransaction ft = fm.beginTransaction();
         loading.show(ft, DIALOG_WAIT_TAG);
-        
+
     }
 
-    
+
     /**
      * Dismiss loading dialog
      */
@@ -795,7 +823,7 @@ public class FileActivity extends ActionBarActivity
         }
     }
 
-    
+
     private void doOnResumeAndBound() {
         mOperationsServiceBinder.addOperationListener(FileActivity.this, mHandler);
         long waitingForOpId = mFileOperationsHelper.getOpIdWaitingFor();
@@ -809,8 +837,8 @@ public class FileActivity extends ActionBarActivity
     }
 
 
-    /** 
-     * Implements callback methods for service binding. Passed as a parameter to { 
+    /**
+     * Implements callback methods for service binding. Passed as a parameter to {
      */
     private class OperationsServiceConnection implements ServiceConnection {
 
@@ -828,7 +856,7 @@ public class FileActivity extends ActionBarActivity
                 return;
             }
         }
-        
+
 
         @Override
         public void onServiceDisconnected(ComponentName component) {

+ 1 - 0
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -1457,6 +1457,7 @@ public class FileDisplayActivity extends HookActivity
                                 operation, getResources()), Toast.LENGTH_LONG);
                 msg.show();
             }
+            invalidateOptionsMenu();
         }
     }
 

+ 1 - 1
src/com/owncloud/android/ui/adapter/FileListListAdapter.java

@@ -285,7 +285,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
             
             // this if-else is needed even though favorite icon is visible by default
             // because android reuses views in listview
-            if (!file.keepInSync()) {
+            if (!file.isFavorite()) {
                 view.findViewById(R.id.favoriteIcon).setVisibility(View.GONE);
             } else {
                 view.findViewById(R.id.favoriteIcon).setVisibility(View.VISIBLE);

+ 6 - 6
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java

@@ -110,21 +110,21 @@ implements ConfirmationDialogFragmentListener {
         
         FileDataStorageManager storageManager = cg.getStorageManager();
         
-        boolean containsKeepInSync = false;
+        boolean containsFavorite = false;
         if (mTargetFile.isFolder()) {
             // TODO Enable when "On Device" is recovered ?
             Vector<OCFile> files = storageManager.getFolderContent(mTargetFile/*, false*/);
             for(OCFile file: files) {
-                containsKeepInSync = file.keepInSync() || containsKeepInSync;
+                containsFavorite = file.isFavorite() || containsFavorite;
 
-                if (containsKeepInSync)
+                if (containsFavorite)
                     break;
             }
         }
 
-        // Remove etag for parent, if file is a keep_in_sync 
-        // or is a folder and contains keep_in_sync        
-        if (mTargetFile.keepInSync() || containsKeepInSync) {
+        // Remove etag for parent, if file is a favorite
+        // or is a folder and contains favorite
+        if (mTargetFile.isFavorite() || containsFavorite) {
             OCFile folder = null;
             if (mTargetFile.isFolder()) {
                 folder = mTargetFile;

+ 18 - 29
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -131,7 +131,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
         mView = inflater.inflate(mLayout, null);
         
         if (mLayout == R.layout.file_details_fragment) {
-            mView.findViewById(R.id.fdKeepInSync).setOnClickListener(this);
+            mView.findViewById(R.id.fdFavorite).setOnClickListener(this);
             ProgressBar progressBar = (ProgressBar)mView.findViewById(R.id.fdProgressBar);
             mProgressListener = new ProgressListener(progressBar);
             mView.findViewById(R.id.fdCancelBtn).setOnClickListener(this);
@@ -259,6 +259,14 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 }
                 return true;
             }
+            case R.id.action_favorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
+                return true;
+            }
+            case R.id.action_unfavorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
+                return true;
+            }
             default:
                 return false;
         }
@@ -267,8 +275,9 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
     @Override
     public void onClick(View v) {
         switch (v.getId()) {
-            case R.id.fdKeepInSync: {
-                toggleKeepInSync();
+            case R.id.fdFavorite: {
+                CheckBox cb = (CheckBox) getView().findViewById(R.id.fdFavorite);
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(),cb.isChecked());
                 break;
             }
             case R.id.fdCancelBtn: {
@@ -279,27 +288,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
                 Log_OC.e(TAG, "Incorrect view clicked!");
         }
     }
-    
-    
-    private void toggleKeepInSync() {
-        CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);
-        OCFile file = getFile();
-        file.setKeepInSync(cb.isChecked());
-        mContainerActivity.getStorageManager().saveFile(file);
-        
-        /// register the OCFile instance in the observer service to monitor local updates
-        Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
-                getActivity(),
-                file, 
-                mAccount,
-                cb.isChecked());
-        getActivity().startService(observedFileIntent);
-        
-        /// immediate content synchronization
-        if (file.keepInSync()) {
-            mContainerActivity.getFileOperationsHelper().syncFile(getFile());
-        }
-    }
+
 
     /**
      * Check if the fragment was created with an empty layout. An empty fragment can't show file details, must be replaced.
@@ -348,8 +337,8 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
 
             setTimeModified(file.getModificationTimestamp());
             
-            CheckBox cb = (CheckBox)getView().findViewById(R.id.fdKeepInSync);
-            cb.setChecked(file.keepInSync());
+            CheckBox cb = (CheckBox)getView().findViewById(R.id.fdFavorite);
+            cb.setChecked(file.isFavorite());
 
             // configure UI for depending upon local state of the file
             FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
@@ -437,7 +426,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
     private void setButtonsForTransferring() {
         if (!isEmpty()) {
             // let's protect the user from himself ;)
-            getView().findViewById(R.id.fdKeepInSync).setEnabled(false);
+            getView().findViewById(R.id.fdFavorite).setEnabled(false);
             
             // show the progress bar for the transfer
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.VISIBLE);
@@ -459,7 +448,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
      */
     private void setButtonsForDown() {
         if (!isEmpty()) {
-            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+            getView().findViewById(R.id.fdFavorite).setEnabled(true);
             
             // hides the progress bar
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);
@@ -473,7 +462,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
      */
     private void setButtonsForRemote() {
         if (!isEmpty()) {
-            getView().findViewById(R.id.fdKeepInSync).setEnabled(true);
+            getView().findViewById(R.id.fdFavorite).setEnabled(true);
             
             // hides the progress bar
             getView().findViewById(R.id.fdProgressBlock).setVisibility(View.GONE);

+ 10 - 3
src/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -341,6 +341,14 @@ public class OCFileListFragment extends ExtendedListFragment {
                 getActivity().startActivityForResult(action, FileDisplayActivity.ACTION_MOVE_FILES);
                 return true;
             }
+            case R.id.action_favorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
+                return true;
+            }
+            case R.id.action_unfavorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
+                return true;
+            }
             default:
                 return super.onContextItemSelected(item); 
         }
@@ -492,8 +500,7 @@ public class OCFileListFragment extends ExtendedListFragment {
 
     public void sortBySize(boolean descending) {
         mAdapter.setSortOrder(FileStorageUtils.SORT_SIZE, descending);
-    }  
-    
-   
+    }
+
     
 }

+ 12 - 0
src/com/owncloud/android/ui/preview/PreviewImageActivity.java

@@ -55,6 +55,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.CreateShareOperation;
 import com.owncloud.android.operations.RemoveFileOperation;
+import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.operations.UnshareLinkOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
@@ -234,6 +235,9 @@ public class PreviewImageActivity extends FileActivity implements
             
         } else if (operation instanceof RemoveFileOperation) {
             finish();
+        } else if (operation instanceof SynchronizeFileOperation) {
+            onSynchronizeFileOperationFinish((SynchronizeFileOperation) operation, result);
+
         }
     }
     
@@ -263,6 +267,14 @@ public class PreviewImageActivity extends FileActivity implements
         }
     }
 
+    private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation,
+                                                  RemoteOperationResult result) {
+        if (result.isSuccess()) {
+            invalidateOptionsMenu();
+        }
+
+    }
+
     @Override
     protected ServiceConnection newTransferenceServiceConnection() {
         return new PreviewImageServiceConnection();

+ 8 - 1
src/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -306,7 +306,14 @@ public class PreviewImageFragment extends FileFragment {
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 return true;
             }
-            
+            case R.id.action_favorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
+                return true;
+            }
+            case R.id.action_unfavorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
+                return true;
+            }
             default:
                 return false;
         }

+ 8 - 1
src/com/owncloud/android/ui/preview/PreviewMediaFragment.java

@@ -341,7 +341,14 @@ public class PreviewMediaFragment extends FileFragment implements
                 mContainerActivity.getFileOperationsHelper().syncFile(getFile());
                 return true;
             }
-
+            case R.id.action_favorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), true);
+                return true;
+            }
+            case R.id.action_unfavorite_file:{
+                mContainerActivity.getFileOperationsHelper().toggleFavorite(getFile(), false);
+                return true;
+            }
             default:
                 return false;
         }