<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>
- <string name="confirmation_remove_local">Local only</string>
- <string name="confirmation_remove_remote">Remove from server</string>
- <string name="confirmation_remove_remote_and_local">Remote and local</string>
+ <string name="confirmation_remove_alert">"Do you really want to remove %1$s ?"</string>
+ <string name="confirmation_remove_local">Local only</string>
+ <string name="confirmation_remove_remote">Remove from server</string>
+ <string name="confirmation_remove_remote_and_local">Remote and local</string>
<string name="remove_success_msg">"Successful removal"</string>
<string name="remove_fail_msg">"Removal could not be completed"</string>
<string name="rename_local_fail_msg">"Local copy could not be renamed; try a differente new name"</string>
<string name="rename_server_fail_msg">"Rename could not be completed"</string>
+ <string name="sync_file_fail_msg">Remote file could not be checked</string>
+ <string name="sync_file_nothing_to_do_msg">File contents already synchronized</string>
+
<string name="create_dir_fail_msg">Directory could not be created</string>
<string name="wait_a_moment">Wait a moment</string>
if (!file.isDirectory())
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
- cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
+ 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);
if (fileExists(file.getRemotePath())) {
if (!file.isDirectory())
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
- cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDate());
+ 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);
if (fileExists(file.getRemotePath())) {
.getColumnIndex(ProviderTableMeta.FILE_CREATION)));
file.setModificationTimestamp(c.getLong(c
.getColumnIndex(ProviderTableMeta.FILE_MODIFIED)));
- file.setLastSyncDate(c.getLong(c
+ file.setLastSyncDateForProperties(c.getLong(c
.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE)));
+ file.setLastSyncDateForData(c.getLong(c.
+ getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA)));
file.setKeepInSync(c.getInt(
c.getColumnIndex(ProviderTableMeta.FILE_KEEP_IN_SYNC)) == 1 ? true : false);
}
private String mLocalPath;
private String mMimeType;
private boolean mNeedsUpdating;
- private long mLastSyncDate;
+ private long mLastSyncDateForProperties;
+ private long mLastSyncDateForData;
private boolean mKeepInSync;
+ private String mEtag;
+
/**
* Create new {@link OCFile} with given path.
*
mMimeType = source.readString();
mNeedsUpdating = source.readInt() == 0;
mKeepInSync = source.readInt() == 1;
- mLastSyncDate = source.readLong();
+ mLastSyncDateForProperties = source.readLong();
+ mLastSyncDateForData = source.readLong();
}
@Override
dest.writeString(mMimeType);
dest.writeInt(mNeedsUpdating ? 1 : 0);
dest.writeInt(mKeepInSync ? 1 : 0);
- dest.writeLong(mLastSyncDate);
+ dest.writeLong(mLastSyncDateForProperties);
+ dest.writeLong(mLastSyncDateForData);
}
/**
mLength = 0;
mCreationTimestamp = 0;
mModifiedTimestamp = 0;
- mLastSyncDate = 0;
+ mLastSyncDateForProperties = 0;
+ mLastSyncDateForData = 0;
mKeepInSync = false;
mNeedsUpdating = false;
}
return mNeedsUpdating;
}
- public long getLastSyncDate() {
- return mLastSyncDate;
+ public long getLastSyncDateForProperties() {
+ return mLastSyncDateForProperties;
+ }
+
+ public void setLastSyncDateForProperties(long lastSyncDate) {
+ mLastSyncDateForProperties = lastSyncDate;
}
- public void setLastSyncDate(long lastSyncDate) {
- mLastSyncDate = lastSyncDate;
+ public long getLastSyncDateForData() {
+ return mLastSyncDateForData;
+ }
+
+ public void setLastSyncDateForData(long lastSyncDate) {
+ mLastSyncDateForData = lastSyncDate;
}
public void setKeepInSync(boolean keepInSync) {
return asString;
}
+ public String getEtag() {
+ return mEtag;
+ }
+
+ public long getLocalModificationTimestamp() {
+ if (mLocalPath != null && mLocalPath.length() > 0) {
+ File f = new File(mLocalPath);
+ return f.lastModified();
+ }
+ return 0;
+ }
+
}
public static final String AUTHORITY_FILES = "org.owncloud";\r
public static final String DB_FILE = "owncloud.db";\r
public static final String DB_NAME = "filelist";\r
- public static final int DB_VERSION = 2;\r
+ //public static final int DB_VERSION = 2;\r
+ public static final int DB_VERSION = 3;\r
\r
private ProviderMeta() {\r
}\r
public static final String FILE_STORAGE_PATH = "media_path";\r
public static final String FILE_PATH = "path";\r
public static final String FILE_ACCOUNT_OWNER = "file_owner";\r
- public static final String FILE_LAST_SYNC_DATE = "last_sync_date";\r
+ public static final String FILE_LAST_SYNC_DATE = "last_sync_date"; // _for_properties, but let's keep it as it is\r
+ public static final String FILE_LAST_SYNC_DATE_FOR_DATA = "last_sync_date_for_data";\r
public static final String FILE_KEEP_IN_SYNC = "keep_in_sync";\r
\r
public static final String DEFAULT_SORT_ORDER = FILE_NAME\r
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.files.OwnCloudFileObserver.FileObserverStatusListener.Status;
-import com.owncloud.android.files.services.FileUploader;
import com.owncloud.android.network.OwnCloudClientUtils;
import com.owncloud.android.operations.RemoteOperationResult;
import com.owncloud.android.operations.SynchronizeFileOperation;
import android.accounts.Account;
import android.content.Context;
-import android.content.Intent;
import android.os.FileObserver;
import android.util.Log;
Log.wtf(TAG, "Incorrect event " + event + " sent for file " + mPath + ((path != null) ? File.separator + path : "") +
" with registered for " + mMask + " and original path " +
mPath);
+ /* Unexpected event that will be ignored; no reason to propagate it
for (FileObserverStatusListener l : mListeners)
l.OnObservedFileStatusUpdate(mPath, getRemotePath(), mOCAccount, Status.INCORRECT_MASK);
+ */
return;
}
WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mOCAccount, mContext);
- SynchronizeFileOperation sfo = new SynchronizeFileOperation(mFile.getRemotePath(), mStorage, mOCAccount);
+ SynchronizeFileOperation sfo = new SynchronizeFileOperation(getRemotePath(), mStorage, mOCAccount, true, false, mContext);
RemoteOperationResult result = sfo.execute(wc);
-
- if (result.getExtraData() == Boolean.TRUE) {
- // inform user about conflict and let him decide what to do
- for (FileObserverStatusListener l : mListeners)
- l.OnObservedFileStatusUpdate(mPath, getRemotePath(), mOCAccount, Status.CONFLICT);
- return;
+ for (FileObserverStatusListener l : mListeners) {
+ l.onObservedFileStatusUpdate(mPath, getRemotePath(), mOCAccount, result);
}
-
- for (FileObserverStatusListener l : mListeners)
- l.OnObservedFileStatusUpdate(mPath, getRemotePath(), mOCAccount, Status.SENDING_TO_UPLOADER);
- Intent i = new Intent(mContext, FileUploader.class);
- i.putExtra(FileUploader.KEY_ACCOUNT, mOCAccount);
- i.putExtra(FileUploader.KEY_REMOTE_FILE, mFile.getRemotePath());
- i.putExtra(FileUploader.KEY_LOCAL_FILE, mPath);
- i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
- i.putExtra(FileUploader.KEY_FORCE_OVERWRITE, true);
- mContext.startService(i);
}
public interface FileObserverStatusListener {
- public enum Status {
- SENDING_TO_UPLOADER,
- CONFLICT,
- INCORRECT_MASK
- }
-
- public void OnObservedFileStatusUpdate(String localPath,
+ public void onObservedFileStatusUpdate(String localPath,
String remotePath,
Account account,
- FileObserverStatusListener.Status status);
+ RemoteOperationResult result);
}
public OCFile getOCFile() {
public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
public static final String EXTRA_FILE = "FILE";\r
\r
+ public static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";\r
public static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";\r
public static final String EXTRA_DOWNLOAD_RESULT = "RESULT"; \r
public static final String EXTRA_FILE_PATH = "FILE_PATH";\r
*/\r
private void saveDownloadedFile() {\r
OCFile file = mCurrentDownload.getFile();\r
- file.setLastSyncDate(System.currentTimeMillis());\r
+ long syncDate = System.currentTimeMillis();\r
+ file.setLastSyncDateForProperties(syncDate);\r
+ file.setLastSyncDateForData(syncDate);\r
file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());\r
// file.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where available\r
file.setMimetype(mCurrentDownload.getMimeType());\r
import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
import com.owncloud.android.files.OwnCloudFileObserver;
import com.owncloud.android.files.OwnCloudFileObserver.FileObserverStatusListener;
+import com.owncloud.android.operations.RemoteOperationResult;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.ui.activity.ConflictsResolveActivity;
import com.owncloud.android.utils.FileStorageUtils;
}
@Override
- public void OnObservedFileStatusUpdate(String localPath, String remotePath, Account account, Status status) {
- switch (status) {
- case CONFLICT:
- {
+ public void onObservedFileStatusUpdate(String localPath, String remotePath, Account account, RemoteOperationResult result) {
+ if (!result.isSuccess()) {
+ if (result.getCode() == ResultCode.SYNC_CONFLICT) {
// ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred
Intent i = new Intent(getApplicationContext(), ConflictsResolveActivity.class);
i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("localpath", localPath);
i.putExtra("account", account);
startActivity(i);
- break;
+
+ } else {
+ // TODO send notification to the notification bar?
}
- case SENDING_TO_UPLOADER:
- case INCORRECT_MASK:
- break;
- default:
- Log.wtf(TAG, "Unhandled status " + status);
- }
+ } // else, nothing else to do; now it's duty of FileUploader service
}
private class DownloadCompletedReceiver extends BroadcastReceiver {
public static final String EXTRA_UPLOAD_RESULT = "RESULT";
public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
public static final String EXTRA_FILE_PATH = "FILE_PATH";
+ public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
public static final String KEY_LOCAL_FILE = "LOCAL_FILE";
public static final String KEY_REMOTE_FILE = "REMOTE_FILE";
+ public static final String KEY_MIME_TYPE = "MIME_TYPE";
+
public static final String KEY_ACCOUNT = "ACCOUNT";
+
public static final String KEY_UPLOAD_TYPE = "UPLOAD_TYPE";
public static final String KEY_FORCE_OVERWRITE = "KEY_FORCE_OVERWRITE";
- public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
- public static final String KEY_MIME_TYPE = "MIME_TYPE";
public static final String KEY_INSTANT_UPLOAD = "INSTANT_UPLOAD";
public static final int UPLOAD_SINGLE_FILE = 0;
try {
for (int i=0; i < localPaths.length; i++) {
uploadKey = buildRemoteName(account, remotePaths[i]);
- file = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes!=null)?mimeTypes[i]:(String)null), isInstant, forceOverwrite, storageManager);
+ file = storageManager.getFileByLocalPath(remotePaths[i]);
+ if (file != null) {
+ Log.d(TAG, "Upload of file already in server: " + remotePaths[i]);
+ // TODO - review handling of input OCFiles in FileDownloader and FileUploader ; some times retrieving them from database can be necessary, some times not; we should make something consistent
+ } else {
+ Log.d(TAG, "Upload of new file: " + remotePaths[i]);
+ file = obtainNewOCFileToUpload(remotePaths[i], localPaths[i], ((mimeTypes!=null)?mimeTypes[i]:(String)null), isInstant, storageManager);
+ }
if (chunked) {
newUpload = new ChunkedUploadFileOperation(account, file, isInstant, forceOverwrite);
} else {
propfind.releaseConnection();
}
- if (!result.isSuccess()) {
+ long syncDate = System.currentTimeMillis();
+ if (result.isSuccess()) {
+ file.setLastSyncDateForProperties(syncDate);
+
+ } else {
// file was successfully uploaded, but the new time stamp and Etag in the server could not be read;
// just keeping old values :(
if (!mCurrentUpload.getRemotePath().equals(file.getRemotePath())) {
newFile.setCreationTimestamp(file.getCreationTimestamp());
newFile.setFileLength(file.getFileLength());
newFile.setMimetype(file.getMimetype());
- newFile.setModificationTimestamp(file.getModificationTimestamp()); // this is specially BAD
+ newFile.setModificationTimestamp(file.getModificationTimestamp());
+ newFile.setLastSyncDateForProperties(file.getLastSyncDateForProperties());
+ newFile.setKeepInSync(file.keepInSync());
// newFile.setEtag(file.getEtag()) // TODO and this is still worse
file = newFile;
}
}
-
- file.setLastSyncDate(System.currentTimeMillis());
+ file.setLastSyncDateForData(syncDate);
mStorageManager.saveFile(file);
}
}
- private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, boolean isInstant, boolean forceOverwrite, FileDataStorageManager storageManager) {
+ private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, boolean isInstant, FileDataStorageManager storageManager) {
OCFile newFile = new OCFile(remotePath);
newFile.setStoragePath(localPath);
- newFile.setLastSyncDate(0);
- newFile.setKeepInSync(forceOverwrite);
+ newFile.setLastSyncDateForProperties(0);
+ newFile.setLastSyncDateForData(0);
// size
if (localPath != null && localPath.length() > 0) {
*/
public class RemoteOperationResult implements Serializable {
- /** Generated - to refresh every time the class changes */
- private static final long serialVersionUID = -7805531062432602444L;
+ /** Generated - should be refreshed every time the class changes!! */
+ private static final long serialVersionUID = 5336333154035462033L;
public enum ResultCode {
CANCELLED,
INVALID_LOCAL_FILE_NAME,
INVALID_OVERWRITE,
- CONFLICT
+ CONFLICT,
+ SYNC_CONFLICT
}
private boolean mSuccess = false;
file.setFileId(mFile.getFileId());
file.setFileLength(mFile.getFileLength());
file.setKeepInSync(mFile.keepInSync());
- file.setLastSyncDate(mFile.getLastSyncDate());
+ file.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
+ file.setLastSyncDateForData(mFile.getLastSyncDateForData());
file.setMimetype(mFile.getMimetype());
file.setModificationTimestamp(mFile.getModificationTimestamp());
file.setParentId(mFile.getParentId());
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import android.accounts.Account;
+import android.content.Context;
+import android.content.Intent;
import android.util.Log;
import com.owncloud.android.datamodel.DataStorageManager;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
+import com.owncloud.android.files.services.FileUploader;
+import com.owncloud.android.operations.RemoteOperationResult.ResultCode;
import eu.alefzero.webdav.WebdavClient;
import eu.alefzero.webdav.WebdavEntry;
public class SynchronizeFileOperation extends RemoteOperation {
private String TAG = SynchronizeFileOperation.class.getSimpleName();
-
private String mRemotePath;
-
private DataStorageManager mStorageManager;
-
private Account mAccount;
+ private boolean mSyncFileContents;
+ private boolean mLocalChangeAlreadyKnown;
+ private Context mContext;
+
+ private boolean mTransferWasRequested = false;
public SynchronizeFileOperation(
String remotePath,
DataStorageManager dataStorageManager,
- Account account) {
+ Account account,
+ boolean syncFileContents,
+ boolean localChangeAlreadyKnown,
+ Context context) {
+
mRemotePath = remotePath;
mStorageManager = dataStorageManager;
mAccount = account;
+ mSyncFileContents = syncFileContents;
+ mLocalChangeAlreadyKnown = localChangeAlreadyKnown;
+ mContext = context;
}
+
@Override
protected RemoteOperationResult run(WebdavClient client) {
+
PropFindMethod propfind = null;
RemoteOperationResult result = null;
+ mTransferWasRequested = false;
try {
- propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
- int status = client.executeMethod(propfind);
- boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS;
- Boolean isConflict = Boolean.FALSE;
- if (isMultiStatus) {
- MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
- WebdavEntry we = new WebdavEntry(resp.getResponses()[0],
+ OCFile localFile = mStorageManager.getFileByPath(mRemotePath);
+
+ if (!localFile.isDown()) {
+ /// easy decision
+ requestForDownload(localFile);
+ result = new RemoteOperationResult(ResultCode.OK);
+
+ } else {
+ /// local copy in the device -> need to think a bit more before do nothing
+
+ propfind = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
+ int status = client.executeMethod(propfind);
+ boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS;
+ if (isMultiStatus) {
+ MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
+ WebdavEntry we = new WebdavEntry(resp.getResponses()[0],
client.getBaseUri().getPath());
- OCFile file = fillOCFile(we);
- OCFile oldFile = mStorageManager.getFileByPath(file.getRemotePath());
- if (oldFile.getFileLength() != file.getFileLength() ||
- oldFile.getModificationTimestamp() != file.getModificationTimestamp()) {
- isConflict = Boolean.TRUE;
- }
+ OCFile serverFile = fillOCFile(we);
+
+ /// check changes in server and local file
+ boolean serverChanged = false;
+ if (serverFile.getEtag() != null) {
+ serverChanged = (!serverFile.getEtag().equals(localFile.getEtag()));
+ } else {
+ // server without etags
+ serverChanged = (serverFile.getModificationTimestamp() > localFile.getModificationTimestamp());
+ }
+ boolean localChanged = (mLocalChangeAlreadyKnown || localFile.getLocalModificationTimestamp() > localFile.getLastSyncDateForData());
+
+ /// decide action to perform depending upon changes
+ if (localChanged && serverChanged) {
+ // conflict
+ result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+
+ } else if (localChanged) {
+ if (mSyncFileContents) {
+ requestForUpload(localFile);
+ // the local update of file properties will be done by the FileUploader service when the upload finishes
+ } else {
+ // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid;
+ // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect
+ // that an upload is necessary (for instance, in FileObserverService).
+ }
+ result = new RemoteOperationResult(ResultCode.OK);
+
+ } else if (serverChanged) {
+ if (mSyncFileContents) {
+ requestForDownload(serverFile);
+ // 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?
+ serverFile.setKeepInSync(localFile.keepInSync());
+ serverFile.setParentId(localFile.getParentId());
+ mStorageManager.saveFile(serverFile);
+
+ }
+ result = new RemoteOperationResult(ResultCode.OK);
- } else {
- client.exhaustResponse(propfind.getResponseBodyAsStream());
- }
+ } else {
+ // nothing changed, nothing to do
+ result = new RemoteOperationResult(ResultCode.OK);
+ }
+
+ } else {
+ client.exhaustResponse(propfind.getResponseBodyAsStream());
+ result = new RemoteOperationResult(false, status);
+ }
+
+ }
+
+ Log.i(TAG, "Synchronizing " + mAccount.name + ", file " + mRemotePath + ": " + result.getLogMessage());
- result = new RemoteOperationResult(isMultiStatus, status);
- result.setExtraData(isConflict);
- Log.i(TAG, "Synchronizing " + mAccount.name + ", file " + mRemotePath + ": " + result.getLogMessage());
} catch (Exception e) {
result = new RemoteOperationResult(e);
Log.e(TAG, "Synchronizing " + mAccount.name + ", file " + mRemotePath + ": " + result.getLogMessage(), result.getException());
}
return result;
}
+
/**
+ * Requests for an upload to the FileUploader service
+ *
+ * @param localFile OCFile object representing the file to upload
+ */
+ private void requestForUpload(OCFile localFile) {
+ Intent i = new Intent(mContext, FileUploader.class);
+ i.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
+ i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);
+ i.putExtra(FileUploader.KEY_LOCAL_FILE, localFile.getStoragePath());
+ i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
+ i.putExtra(FileUploader.KEY_FORCE_OVERWRITE, true);
+ mContext.startService(i);
+ mTransferWasRequested = true;
+ }
+
+
+ /**
+ * Requests for a download to the FileDownloader service
+ *
+ * @param file OCFile object representing the file to download
+ */
+ private void requestForDownload(OCFile file) {
+ Intent i = new Intent(mContext, FileDownloader.class);
+ i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);
+ i.putExtra(FileDownloader.EXTRA_FILE, file);
+ mContext.startService(i);
+ mTransferWasRequested = true;
+ }
+
+
+ /**
* Creates and populates a new {@link OCFile} object with the data read from the server.
*
* @param we WebDAV entry read from the server for a WebDAV resource (remote file or folder).
file.setFileLength(we.contentLength());
file.setMimetype(we.contentType());
file.setModificationTimestamp(we.modifiedTimesamp());
- file.setLastSyncDate(System.currentTimeMillis());
+ file.setLastSyncDateForProperties(System.currentTimeMillis());
+ file.setLastSyncDateForData(0);
return file;
}
+
+ public boolean transferWasRequested() {
+ return mTransferWasRequested;
+ }
+
}
String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
for (int i=0; i < mChildren.size(); ) {
file = mChildren.get(i);
- if (file.getLastSyncDate() != mCurrentSyncTime) {
+ if (file.getLastSyncDateForProperties() != mCurrentSyncTime) {
Log.d(TAG, "removing file: " + file);
mStorageManager.removeFile(file, (file.isDown() && file.getStoragePath().startsWith(currentSavePath)));
mChildren.remove(i);
file.setFileLength(we.contentLength());
file.setMimetype(we.contentType());
file.setModificationTimestamp(we.modifiedTimesamp());
- file.setLastSyncDate(mCurrentSyncTime);
+ file.setLastSyncDateForProperties(mCurrentSyncTime);
return file;
}
ProviderTableMeta.FILE_STORAGE_PATH);\r
mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE,\r
ProviderTableMeta.FILE_LAST_SYNC_DATE);\r
+ mProjectionMap.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA,\r
+ ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA);\r
mProjectionMap.put(ProviderTableMeta.FILE_KEEP_IN_SYNC,\r
ProviderTableMeta.FILE_KEEP_IN_SYNC);\r
mProjectionMap.put(ProviderTableMeta.FILE_ACCOUNT_OWNER,\r
+ ProviderTableMeta.FILE_STORAGE_PATH + " TEXT, "\r
+ ProviderTableMeta.FILE_ACCOUNT_OWNER + " TEXT, "\r
+ ProviderTableMeta.FILE_LAST_SYNC_DATE + " INTEGER, "\r
- + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER );");\r
+ + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER, "\r
+ + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER );"\r
+ );\r
}\r
\r
@Override\r
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {\r
Log.i("SQL", "Entering in onUpgrade");\r
+ boolean upgraded = false; \r
if (oldVersion == 1 && newVersion >= 2) {\r
- Log.i("SQL", "Entering in the ADD in onUpgrade");\r
+ Log.i("SQL", "Entering in the #1 ADD in onUpgrade");\r
db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +\r
" ADD COLUMN " + ProviderTableMeta.FILE_KEEP_IN_SYNC + " INTEGER " +\r
" DEFAULT 0");\r
- } else Log.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);\r
+ upgraded = true;\r
+ }\r
+ if (oldVersion < 3 && newVersion >= 3) {\r
+ Log.i("SQL", "Entering in the #2 ADD in onUpgrade");\r
+ db.execSQL("ALTER TABLE " + ProviderTableMeta.DB_NAME +\r
+ " ADD COLUMN " + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA + " INTEGER " +\r
+ " DEFAULT 0");\r
+ upgraded = true;\r
+ }\r
+ if (!upgraded)\r
+ Log.i("SQL", "OUT of the ADD in onUpgrade; oldVersion == " + oldVersion + ", newVersion == " + newVersion);\r
}\r
\r
}\r
import com.owncloud.android.operations.RemoteOperationResult.ResultCode;\r
import com.owncloud.android.operations.RemoveFileOperation;\r
import com.owncloud.android.operations.RenameFileOperation;\r
+import com.owncloud.android.operations.SynchronizeFileOperation;\r
+import com.owncloud.android.ui.activity.ConflictsResolveActivity;\r
import com.owncloud.android.ui.activity.FileDetailActivity;\r
import com.owncloud.android.ui.activity.FileDisplayActivity;\r
import com.owncloud.android.ui.activity.TransferServiceGetter;\r
private Handler mHandler;\r
private RemoteOperation mLastRemoteOperation;\r
\r
- private static final String TAG = "FileDetailFragment";\r
+ private static final String TAG = FileDetailFragment.class.getSimpleName();\r
public static final String FTAG = "FileDetails"; \r
public static final String FTAG_CONFIRMATION = "REMOVE_CONFIRMATION_FRAGMENT";\r
\r
\r
@Override\r
public void onClick(View v) {\r
+ FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
switch (v.getId()) {\r
case R.id.fdDownloadBtn: {\r
//if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath())) {\r
}\r
\r
} else {\r
- // ISSUE 6: this button should be promoted to 'synchronize' if the file is DOWN, not just redownload\r
- Intent i = new Intent(getActivity(), FileDownloader.class);\r
- i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount);\r
- i.putExtra(FileDownloader.EXTRA_FILE, mFile);\r
- /*i.putExtra(FileDownloader.EXTRA_REMOTE_PATH, mFile.getRemotePath());\r
- i.putExtra(FileDownloader.EXTRA_FILE_PATH, mFile.getRemotePath());\r
- i.putExtra(FileDownloader.EXTRA_FILE_SIZE, mFile.getFileLength());*/\r
+ mLastRemoteOperation = new SynchronizeFileOperation(mFile.getRemotePath(), fdsm, mAccount, true, false, getActivity());\r
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(mAccount, getSherlockActivity().getApplicationContext());\r
+ mLastRemoteOperation.execute(wc, this, mHandler);\r
\r
// update ui \r
- setButtonsForTransferring();\r
- \r
- getActivity().startService(i);\r
- mContainerActivity.onFileStateChanged(); // this is not working; it is performed before the fileDownloadService registers it as 'in progress'\r
+ boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
+ getActivity().showDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
+ setButtonsForTransferring(); // disable button immediately, although the synchronization does not result in a file transference\r
+ \r
}\r
break;\r
}\r
case R.id.fdKeepInSync: {\r
CheckBox cb = (CheckBox) getView().findViewById(R.id.fdKeepInSync);\r
mFile.setKeepInSync(cb.isChecked());\r
- FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
fdsm.saveFile(mFile);\r
\r
/* NOT HERE\r
\r
} else if (operation instanceof RenameFileOperation) {\r
onRenameFileOperationFinish((RenameFileOperation)operation, result);\r
+ \r
+ } else if (operation instanceof SynchronizeFileOperation) {\r
+ onSynchronizeFileOperationFinish((SynchronizeFileOperation)operation, result);\r
}\r
}\r
}\r
}\r
}\r
\r
+ private void onSynchronizeFileOperationFinish(SynchronizeFileOperation operation, RemoteOperationResult result) {\r
+ boolean inDisplayActivity = getActivity() instanceof FileDisplayActivity;\r
+ getActivity().dismissDialog((inDisplayActivity)? FileDisplayActivity.DIALOG_SHORT_WAIT : FileDetailActivity.DIALOG_SHORT_WAIT);\r
+\r
+ if (!result.isSuccess()) {\r
+ if (result.getCode() == ResultCode.SYNC_CONFLICT) {\r
+ Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);\r
+ //i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);\r
+ i.putExtra("remotepath", mFile.getRemotePath());\r
+ i.putExtra("localpath", mFile.getStoragePath());\r
+ i.putExtra("account", mAccount);\r
+ startActivity(i);\r
+ \r
+ } else {\r
+ Toast msg = Toast.makeText(getActivity(), R.string.sync_file_fail_msg, Toast.LENGTH_LONG); \r
+ msg.show();\r
+ }\r
+ \r
+ } else {\r
+ if (operation.transferWasRequested()) {\r
+ mContainerActivity.onFileStateChanged(); // this is not working; FileDownloader won't do NOTHING at all until this method finishes, so \r
+ // checking the service to see if the file is downloading results in FALSE\r
+ } else {\r
+ Toast msg = Toast.makeText(getActivity(), R.string.sync_file_nothing_to_do_msg, Toast.LENGTH_LONG); \r
+ msg.show();\r
+ if (mFile.isDown()) {\r
+ setButtonsForDown();\r
+ \r
+ } else {\r
+ setButtonsForRemote();\r
+ }\r
+ }\r
+ }\r
+ }\r
\r
}\r