disable + show info
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP &&
+ (PreferenceManager.instantPictureUploadEnabled(this) ||
+ PreferenceManager.instantPictureUploadEnabled(this))) {
+
+ // remove legacy shared preferences
+ SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
+ editor.remove("instant_uploading")
+ .remove("instant_video_uploading")
+ .remove("instant_upload_path")
+ .remove("instant_upload_path_use_subfolders")
+ .remove("instant_upload_on_wifi")
+ .remove("instant_upload_on_charging")
+ .remove("instant_video_upload_path")
+ .remove("instant_video_upload_path_use_subfolders")
+ .remove("instant_video_upload_on_wifi")
+ .remove("instant_video_uploading")
+ .remove("instant_video_upload_on_charging")
+ .remove("prefs_instant_behaviour").apply();
+
+ // show info pop-up
+ new AlertDialog.Builder(this, R.style.Theme_ownCloud_Dialog)
+ .setTitle(R.string.drawer_folder_sync)
+ .setMessage(R.string.folder_sync_new_info)
+ .setPositiveButton(R.string.drawer_open, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // show instant upload
+ Intent folderSyncIntent = new Intent(getApplicationContext(), FolderSyncActivity.class);
+ dialog.dismiss();
+ startActivity(folderSyncIntent);
+ }
+ })
+ .setNegativeButton(R.string.drawer_close, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ })
+ .setIcon(R.drawable.ic_cloud_upload)
+ .show();
+ }
}
@Override
diff --git a/src/com/owncloud/android/ui/activity/FolderSyncActivity.java b/src/com/owncloud/android/ui/activity/FolderSyncActivity.java
new file mode 100644
index 000000000000..9ea678a1ec10
--- /dev/null
+++ b/src/com/owncloud/android/ui/activity/FolderSyncActivity.java
@@ -0,0 +1,413 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 Andy Scherzinger
+ * Copyright (C) 2016 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see .
+ */
+
+package com.owncloud.android.ui.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.widget.GridLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.authentication.AccountUtils;
+import com.owncloud.android.datamodel.MediaFolder;
+import com.owncloud.android.datamodel.MediaProvider;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.datamodel.SyncedFolder;
+import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
+import com.owncloud.android.datamodel.SyncedFolderProvider;
+import com.owncloud.android.ui.adapter.FolderSyncAdapter;
+import com.owncloud.android.ui.decoration.MediaGridItemDecoration;
+import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment;
+import com.owncloud.android.ui.dialog.parcel.SyncedFolderParcelable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimerTask;
+
+import static com.owncloud.android.datamodel.SyncedFolderDisplayItem.UNPERSISTED_ID;
+
+/**
+ * Activity displaying all auto-synced folders and/or instant upload media folders.
+ */
+public class FolderSyncActivity extends FileActivity implements FolderSyncAdapter.ClickListener,
+ SyncedFolderPreferencesDialogFragment.OnSyncedFolderPreferenceListener {
+ private static final String TAG = FolderSyncActivity.class.getSimpleName();
+
+ private static final String SYNCED_FOLDER_PREFERENCES_DIALOG_TAG = "SYNCED_FOLDER_PREFERENCES_DIALOG";
+ public static final String PRIORITIZED_FOLDER = "Camera";
+
+ private RecyclerView mRecyclerView;
+ private FolderSyncAdapter mAdapter;
+ private LinearLayout mProgress;
+ private TextView mEmpty;
+ private SyncedFolderProvider mSyncedFolderProvider;
+ private List syncFolderItems;
+ private SyncedFolderPreferencesDialogFragment mSyncedFolderPreferencesDialogFragment;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.folder_sync_layout);
+
+ // setup toolbar
+ setupToolbar();
+
+ // setup drawer
+ setupDrawer(R.id.nav_folder_sync);
+ getSupportActionBar().setTitle(getString(R.string.drawer_folder_sync));
+
+ setupContent();
+ }
+
+ /**
+ * sets up the UI elements and loads all media/synced folders.
+ */
+ private void setupContent() {
+ mRecyclerView = (RecyclerView) findViewById(android.R.id.list);
+
+ mProgress = (LinearLayout) findViewById(android.R.id.progress);
+ mEmpty = (TextView) findViewById(android.R.id.empty);
+
+ final int gridWidth = getResources().getInteger(R.integer.media_grid_width);
+ mAdapter = new FolderSyncAdapter(this, gridWidth, this);
+ mSyncedFolderProvider = new SyncedFolderProvider(getContentResolver());
+
+ final GridLayoutManager lm = new GridLayoutManager(this, gridWidth);
+ mAdapter.setLayoutManager(lm);
+ int spacing = getResources().getDimensionPixelSize(R.dimen.media_grid_spacing);
+ mRecyclerView.addItemDecoration(new MediaGridItemDecoration(spacing));
+ mRecyclerView.setLayoutManager(lm);
+ mRecyclerView.setAdapter(mAdapter);
+
+ load(gridWidth * 2);
+ }
+
+ /**
+ * loads all media/synced folders, adds them to the recycler view adapter and shows the list.
+ *
+ * @param perFolderMediaItemLimit the amount of media items to be loaded/shown per media folder
+ */
+ private void load(final int perFolderMediaItemLimit) {
+ if (mAdapter.getItemCount() > 0) {
+ return;
+ }
+ setListShown(false);
+ final Handler mHandler = new Handler();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ final List mediaFolders = MediaProvider.getMediaFolders(getContentResolver(),
+ perFolderMediaItemLimit);
+ syncFolderItems = sortSyncedFolderItems(mergeFolderData(mSyncedFolderProvider.getSyncedFolders(),
+ mediaFolders));
+
+ mHandler.post(new TimerTask() {
+ @Override
+ public void run() {
+ mAdapter.setSyncFolderItems(syncFolderItems);
+ setListShown(true);
+ }
+ });
+ }
+ }).start();
+ }
+
+ /**
+ * merges two lists of {@link SyncedFolder} and {@link MediaFolder} items into one of SyncedFolderItems.
+ *
+ * @param syncedFolders the synced folders
+ * @param mediaFolders the media folders
+ * @return the merged list of SyncedFolderItems
+ */
+ @NonNull
+ private List mergeFolderData(List syncedFolders,
+ @NonNull List mediaFolders) {
+ Map syncedFoldersMap = createSyncedFoldersMap(syncedFolders);
+ List result = new ArrayList<>();
+
+ for (MediaFolder mediaFolder : mediaFolders) {
+ if (syncedFoldersMap.containsKey(mediaFolder.absolutePath)) {
+ SyncedFolder syncedFolder = syncedFoldersMap.get(mediaFolder.absolutePath);
+ result.add(createSyncedFolder(syncedFolder, mediaFolder));
+ } else {
+ result.add(createSyncedFolderFromMediaFolder(mediaFolder));
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Sorts list of {@link SyncedFolderDisplayItem}s.
+ *
+ * @param syncFolderItemList list of items to be sorted
+ * @return sorted list of items
+ */
+ public static List sortSyncedFolderItems(List
+ syncFolderItemList) {
+ Collections.sort(syncFolderItemList, new Comparator() {
+ public int compare(SyncedFolderDisplayItem f1, SyncedFolderDisplayItem f2) {
+ if (f1 == null && f2 == null) {
+ return 0;
+ } else if (f1 == null) {
+ return -1;
+ } else if (f2 == null) {
+ return 1;
+ } else if (f1.isEnabled() && f2.isEnabled()) {
+ return f1.getFolderName().toLowerCase().compareTo(f2.getFolderName().toLowerCase());
+ } else if (f1.isEnabled()) {
+ return -1;
+ } else if (f2.isEnabled()) {
+ return 1;
+ } else if (f1.getFolderName() == null && f2.getFolderName() == null) {
+ return 0;
+ } else if (f1.getFolderName() == null) {
+ return -1;
+ } else if (f2.getFolderName() == null) {
+ return 1;
+ } else if (PRIORITIZED_FOLDER.equals(f1.getFolderName())) {
+ return -1;
+ } else if (PRIORITIZED_FOLDER.equals(f2.getFolderName())) {
+ return 1;
+ } else {
+ return f1.getFolderName().toLowerCase().compareTo(f2.getFolderName().toLowerCase());
+ }
+ }
+ });
+
+ return syncFolderItemList;
+ }
+
+ /**
+ * creates a SyncedFolderDisplayItem merging a {@link SyncedFolder} and a {@link MediaFolder} object instance.
+ *
+ * @param syncedFolder the synced folder object
+ * @param mediaFolder the media folder object
+ * @return the created SyncedFolderDisplayItem
+ */
+ @NonNull
+ private SyncedFolderDisplayItem createSyncedFolder(@NonNull SyncedFolder syncedFolder, @NonNull MediaFolder mediaFolder) {
+ return new SyncedFolderDisplayItem(
+ syncedFolder.getId(),
+ syncedFolder.getLocalPath(),
+ syncedFolder.getRemotePath(),
+ syncedFolder.getWifiOnly(),
+ syncedFolder.getChargingOnly(),
+ syncedFolder.getSubfolderByDate(),
+ syncedFolder.getAccount(),
+ syncedFolder.getUploadAction(),
+ syncedFolder.isEnabled(),
+ mediaFolder.filePaths,
+ mediaFolder.folderName,
+ mediaFolder.numberOfFiles);
+ }
+
+ /**
+ * creates a {@link SyncedFolderDisplayItem} based on a {@link MediaFolder} object instance.
+ *
+ * @param mediaFolder the media folder object
+ * @return the created SyncedFolderDisplayItem
+ */
+ @NonNull
+ private SyncedFolderDisplayItem createSyncedFolderFromMediaFolder(@NonNull MediaFolder mediaFolder) {
+ return new SyncedFolderDisplayItem(
+ UNPERSISTED_ID,
+ mediaFolder.absolutePath,
+ getString(R.string.instant_upload_path) + "/" + mediaFolder.folderName,
+ true,
+ false,
+ false,
+ AccountUtils.getCurrentOwnCloudAccount(this).name,
+ 0,
+ false,
+ mediaFolder.filePaths,
+ mediaFolder.folderName,
+ mediaFolder.numberOfFiles);
+ }
+
+ /**
+ * creates a lookup map for a list of given {@link SyncedFolder}s with their local path as the key.
+ *
+ * @param syncFolders list of {@link SyncedFolder}s
+ * @return the lookup map for {@link SyncedFolder}s
+ */
+ @NonNull
+ private Map createSyncedFoldersMap(List syncFolders) {
+ Map result = new HashMap<>();
+ if (syncFolders != null) {
+ for (SyncedFolder syncFolder : syncFolders) {
+ result.put(syncFolder.getLocalPath(), syncFolder);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * show/hide recycler view list or the empty message / progress info.
+ *
+ * @param shown flag if list should be shown
+ */
+ private void setListShown(boolean shown) {
+ if (mRecyclerView != null) {
+ mRecyclerView.setVisibility(shown ? View.VISIBLE : View.GONE);
+ mProgress.setVisibility(shown ? View.GONE : View.VISIBLE);
+ mEmpty.setVisibility(shown && mAdapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ boolean result;
+ switch (item.getItemId()) {
+ case android.R.id.home: {
+ if (isDrawerOpen()) {
+ closeDrawer();
+ } else {
+ openDrawer();
+ }
+ }
+
+ default:
+ result = super.onOptionsItemSelected(item);
+ }
+ return result;
+ }
+
+ @Override
+ public void restart() {
+ Intent i = new Intent(this, FileDisplayActivity.class);
+ i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(i);
+ }
+
+ @Override
+ public void showFiles(boolean onDeviceOnly) {
+ MainApp.showOnlyFilesOnDevice(onDeviceOnly);
+ Intent fileDisplayActivity = new Intent(getApplicationContext(), FileDisplayActivity.class);
+ fileDisplayActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(fileDisplayActivity);
+ }
+
+ @Override
+ public void onSyncStatusToggleClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem) {
+ if (syncedFolderDisplayItem.getId() > UNPERSISTED_ID) {
+ mSyncedFolderProvider.updateFolderSyncEnabled(syncedFolderDisplayItem.getId(), syncedFolderDisplayItem.isEnabled());
+ } else {
+ mSyncedFolderProvider.storeFolderSync(syncedFolderDisplayItem);
+ }
+ }
+
+ @Override
+ public void onSyncFolderSettingsClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem) {
+ FragmentManager fm = getSupportFragmentManager();
+ FragmentTransaction ft = fm.beginTransaction();
+ ft.addToBackStack(null);
+
+ mSyncedFolderPreferencesDialogFragment = SyncedFolderPreferencesDialogFragment.newInstance(
+ syncedFolderDisplayItem, section);
+ mSyncedFolderPreferencesDialogFragment.show(ft, SYNCED_FOLDER_PREFERENCES_DIALOG_TAG);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == SyncedFolderPreferencesDialogFragment.REQUEST_CODE__SELECT_REMOTE_FOLDER
+ && resultCode == RESULT_OK && mSyncedFolderPreferencesDialogFragment != null) {
+ OCFile chosenFolder = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
+ mSyncedFolderPreferencesDialogFragment.setRemoteFolderSummary(chosenFolder.getRemotePath());
+
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+ @Override
+ public void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder) {
+ SyncedFolderDisplayItem item = syncFolderItems.get(syncedFolder.getSection());
+ boolean dirty = item.isEnabled() != syncedFolder.getEnabled();
+ item = updateSyncedFolderItem(item, syncedFolder.getLocalPath(), syncedFolder.getRemotePath(), syncedFolder
+ .getWifiOnly(), syncedFolder.getChargingOnly(), syncedFolder.getSubfolderByDate(), syncedFolder
+ .getUploadAction(), syncedFolder.getEnabled());
+
+ if (syncedFolder.getId() == UNPERSISTED_ID) {
+ // newly set up folder sync config
+ mSyncedFolderProvider.storeFolderSync(item);
+ } else {
+ // existing synced folder setup to be updated
+ mSyncedFolderProvider.updateSyncFolder(item);
+ }
+ mSyncedFolderPreferencesDialogFragment = null;
+
+ if(dirty) {
+ mAdapter.setSyncFolderItem(syncedFolder.getSection(), item);
+ }
+ }
+
+ @Override
+ public void onCancelSyncedFolderPreference() {
+ mSyncedFolderPreferencesDialogFragment = null;
+ }
+
+ /**
+ * update given synced folder with the given values.
+ *
+ * @param item the synced folder to be updated
+ * @param localPath the local path
+ * @param remotePath the remote path
+ * @param wifiOnly upload on wifi only
+ * @param chargingOnly upload on charging only
+ * @param subfolderByDate created sub folders
+ * @param uploadAction upload action
+ * @param enabled is sync enabled
+ * @return the updated item
+ */
+ private SyncedFolderDisplayItem updateSyncedFolderItem(SyncedFolderDisplayItem item,
+ String localPath,
+ String remotePath,
+ Boolean wifiOnly,
+ Boolean chargingOnly,
+ Boolean subfolderByDate,
+ Integer uploadAction,
+ Boolean enabled) {
+ item.setLocalPath(localPath);
+ item.setRemotePath(remotePath);
+ item.setWifiOnly(wifiOnly);
+ item.setChargingOnly(chargingOnly);
+ item.setSubfolderByDate(subfolderByDate);
+ item.setUploadAction(uploadAction);
+ item.setEnabled(enabled);
+ return item;
+ }
+}
diff --git a/src/com/owncloud/android/ui/activity/Preferences.java b/src/com/owncloud/android/ui/activity/Preferences.java
index 977eefe35baf..5274742238db 100644
--- a/src/com/owncloud/android/ui/activity/Preferences.java
+++ b/src/com/owncloud/android/ui/activity/Preferences.java
@@ -5,6 +5,7 @@
* @author David A. Velasco
* Copyright (C) 2011 Bartek Przybylski
* Copyright (C) 2016 ownCloud Inc.
+ * Copyright (C) 2016 Nextcloud
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
@@ -30,6 +31,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.preference.CheckBoxPreference;
@@ -69,8 +71,7 @@
/**
* An Activity that allows the user to change the application's settings.
*
- * It proxies the necessary calls via {@link android.support.v7.app.AppCompatDelegate} to be used
- * with AppCompat.
+ * It proxies the necessary calls via {@link android.support.v7.app.AppCompatDelegate} to be used with AppCompat.
*/
public class Preferences extends PreferenceActivity
implements StorageMigration.StorageMigrationProgressListener {
@@ -214,10 +215,10 @@ public boolean onPreferenceClick(Preference preference) {
preferenceCategory.removePreference(pCalendarContacts);
}
}
-
+
boolean helpEnabled = getResources().getBoolean(R.bool.help_enabled);
Preference pHelp = findPreference("help");
- if (pHelp != null ) {
+ if (pHelp != null) {
if (helpEnabled) {
pHelp.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
@@ -236,8 +237,8 @@ public boolean onPreferenceClick(Preference preference) {
}
}
- boolean recommendEnabled = getResources().getBoolean(R.bool.recommend_enabled);
- Preference pRecommend = findPreference("recommend");
+ boolean recommendEnabled = getResources().getBoolean(R.bool.recommend_enabled);
+ Preference pRecommend = findPreference("recommend");
if (pRecommend != null) {
if (recommendEnabled) {
pRecommend.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -269,7 +270,7 @@ public boolean onPreferenceClick(Preference preference) {
}
boolean feedbackEnabled = getResources().getBoolean(R.bool.feedback_enabled);
- Preference pFeedback = findPreference("feedback");
+ Preference pFeedback = findPreference("feedback");
if (pFeedback != null) {
if (feedbackEnabled) {
pFeedback.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -277,7 +278,7 @@ public boolean onPreferenceClick(Preference preference) {
public boolean onPreferenceClick(Preference preference) {
String feedbackMail = getString(R.string.mail_feedback);
String feedback = getText(R.string.prefs_feedback) + " - android v" + appVersion;
- Intent intent = new Intent(Intent.ACTION_SENDTO);
+ Intent intent = new Intent(Intent.ACTION_SENDTO);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_SUBJECT, feedback);
@@ -294,7 +295,7 @@ public boolean onPreferenceClick(Preference preference) {
}
boolean loggerEnabled = getResources().getBoolean(R.bool.logger_enabled) || BuildConfig.DEBUG;
- Preference pLogger = findPreference("logger");
+ Preference pLogger = findPreference("logger");
if (pLogger != null) {
if (loggerEnabled) {
pLogger.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -312,7 +313,7 @@ public boolean onPreferenceClick(Preference preference) {
}
boolean imprintEnabled = getResources().getBoolean(R.bool.imprint_enabled);
- Preference pImprint = findPreference("imprint");
+ Preference pImprint = findPreference("imprint");
if (pImprint != null) {
if (imprintEnabled) {
pImprint.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@@ -333,7 +334,7 @@ public boolean onPreferenceClick(Preference preference) {
}
}
- mPrefStoragePath = (ListPreference) findPreference(PreferenceKeys.STORAGE_PATH);
+ mPrefStoragePath = (ListPreference) findPreference(PreferenceKeys.STORAGE_PATH);
if (mPrefStoragePath != null) {
StoragePoint[] storageOptions = DataStorageProvider.getInstance().getAvailableStoragePoints();
String[] entries = new String[storageOptions.length];
@@ -353,22 +354,26 @@ public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
- StorageMigration storageMigration = new StorageMigration(Preferences.this, mStoragePath, newPath);
+ StorageMigration storageMigration = new StorageMigration(Preferences.this, mStoragePath, newPath);
- storageMigration.setStorageMigrationProgressListener(Preferences.this);
+ storageMigration.setStorageMigrationProgressListener(Preferences.this);
- storageMigration.migrate();
+ storageMigration.migrate();
- return false;
- }
- });
+ return false;
+ }
+ });
}
- mPrefInstantUploadPath = findPreference(PreferenceKeys.INSTANT_UPLOAD_PATH);
- if (mPrefInstantUploadPath != null) {
+ mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ // Instant upload via preferences on pre Android Lollipop
+ mPrefInstantUploadPath = findPreference("instant_upload_path");
+ if (mPrefInstantUploadPath != null) {
- mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ mPrefInstantUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (!mUploadPath.endsWith(OCFile.PATH_SEPARATOR)) {
@@ -380,33 +385,33 @@ public boolean onPreferenceClick(Preference preference) {
return true;
}
});
- }
+ }
mPrefInstantUploadCategory = (PreferenceCategory) findPreference("instant_uploading_category");
- mPrefInstantUploadUseSubfolders = findPreference("instant_upload_path_use_subfolders");
- mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi");
- mPrefInstantPictureUploadOnlyOnCharging = findPreference("instant_upload_on_charging");
- mPrefInstantUpload = findPreference("instant_uploading");
+ mPrefInstantUploadUseSubfolders = findPreference("instant_upload_path_use_subfolders");
+ mPrefInstantUploadPathWiFi = findPreference("instant_upload_on_wifi");
+ mPrefInstantPictureUploadOnlyOnCharging = findPreference("instant_upload_on_charging");
+ mPrefInstantUpload = findPreference("instant_uploading");
- toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
+ toggleInstantPictureOptions(((CheckBoxPreference) mPrefInstantUpload).isChecked());
- mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ mPrefInstantUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- toggleInstantPictureOptions((Boolean) newValue);
- toggleInstantUploadBehaviour(
- ((CheckBoxPreference)mPrefInstantVideoUpload).isChecked(),
- (Boolean) newValue);
- return true;
- }
- });
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ toggleInstantPictureOptions((Boolean) newValue);
+ toggleInstantUploadBehaviour(
+ ((CheckBoxPreference) mPrefInstantVideoUpload).isChecked(),
+ (Boolean) newValue);
+ return true;
+ }
+ });
- mPrefInstantVideoUploadPath = findPreference(PreferenceKeys.INSTANT_VIDEO_UPLOAD_PATH);
+ mPrefInstantVideoUploadPath = findPreference(PreferenceKeys.INSTANT_VIDEO_UPLOAD_PATH);
if (mPrefInstantVideoUploadPath != null){
- mPrefInstantVideoUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ mPrefInstantVideoUploadPath.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (!mUploadVideoPath.endsWith(OCFile.PATH_SEPARATOR)) {
@@ -419,42 +424,44 @@ public boolean onPreferenceClick(Preference preference) {
return true;
}
});
- }
+ }
- mPrefInstantVideoUploadUseSubfolders = findPreference("instant_video_upload_path_use_subfolders");
- mPrefInstantVideoUploadPathWiFi = findPreference("instant_video_upload_on_wifi");
- mPrefInstantVideoUpload = findPreference("instant_video_uploading");
- mPrefInstantVideoUploadOnlyOnCharging = findPreference("instant_video_upload_on_charging");
- toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked());
+ mPrefInstantVideoUploadUseSubfolders = findPreference("instant_video_upload_path_use_subfolders");
+ mPrefInstantVideoUploadPathWiFi = findPreference("instant_video_upload_on_wifi");
+ mPrefInstantVideoUpload = findPreference("instant_video_uploading");
+ mPrefInstantVideoUploadOnlyOnCharging = findPreference("instant_video_upload_on_charging");
+ toggleInstantVideoOptions(((CheckBoxPreference) mPrefInstantVideoUpload).isChecked());
+ mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ toggleInstantVideoOptions((Boolean) newValue);
+ toggleInstantUploadBehaviour(
+ (Boolean) newValue,
+ ((CheckBoxPreference) mPrefInstantUpload).isChecked());
+ return true;
+ }
+ });
- mPrefInstantVideoUpload.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ mPrefInstantUploadBehaviour = findPreference("prefs_instant_behaviour");
+ toggleInstantUploadBehaviour(
+ ((CheckBoxPreference) mPrefInstantVideoUpload).isChecked(),
+ ((CheckBoxPreference) mPrefInstantUpload).isChecked());
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- toggleInstantVideoOptions((Boolean) newValue);
- toggleInstantUploadBehaviour(
- (Boolean) newValue,
- ((CheckBoxPreference) mPrefInstantUpload).isChecked());
- return true;
- }
- });
-
- mPrefInstantUploadBehaviour = findPreference("prefs_instant_behaviour");
- toggleInstantUploadBehaviour(
- ((CheckBoxPreference)mPrefInstantVideoUpload).isChecked(),
- ((CheckBoxPreference)mPrefInstantUpload).isChecked());
+ loadInstantUploadPath();
+ loadInstantUploadVideoPath();
+ } else {
+ // Instant upload is handled via synced folders on Android Lollipop and up
+ getPreferenceScreen().removePreference(mPrefInstantUploadCategory);
+ }
/* About App */
- pAboutApp = findPreference("about_app");
- if (pAboutApp != null) {
- pAboutApp.setTitle(String.format(getString(R.string.about_android),
- getString(R.string.app_name)));
- pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
- }
+ pAboutApp = findPreference("about_app");
+ if (pAboutApp != null) {
+ pAboutApp.setTitle(String.format(getString(R.string.about_android), getString(R.string.app_name)));
+ pAboutApp.setSummary(String.format(getString(R.string.about_version), appVersion));
+ }
- loadInstantUploadPath();
- loadStoragePath();
- loadInstantUploadVideoPath();
+ loadStoragePath();
}
private void launchDavDroidLogin()
@@ -635,7 +642,8 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Toast.makeText(this, R.string.pass_code_removed, Toast.LENGTH_LONG).show();
}
} else if (requestCode == ACTION_REQUEST_CODE_DAVDROID_SETUP && resultCode == RESULT_OK) {
- Toast.makeText(this, R.string.prefs_calendar_contacts_sync_setup_successful, Toast.LENGTH_LONG).show(); }
+ Toast.makeText(this, R.string.prefs_calendar_contacts_sync_setup_successful, Toast.LENGTH_LONG).show();
+ }
}
public ActionBar getSupportActionBar() {
diff --git a/src/com/owncloud/android/ui/adapter/FolderSyncAdapter.java b/src/com/owncloud/android/ui/adapter/FolderSyncAdapter.java
new file mode 100644
index 000000000000..df6de99ca831
--- /dev/null
+++ b/src/com/owncloud/android/ui/adapter/FolderSyncAdapter.java
@@ -0,0 +1,187 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 Andy Scherzinger
+ * Copyright (C) 2016 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see .
+ */
+
+package com.owncloud.android.ui.adapter;
+
+import android.content.Context;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
+import com.owncloud.android.datamodel.ThumbnailsCacheManager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Adapter to display all auto-synced folders and/or instant upload media folders.
+ */
+public class FolderSyncAdapter extends SectionedRecyclerViewAdapter {
+
+ private static final String TAG = FolderSyncAdapter.class.getSimpleName();
+
+ private final Context mContext;
+ private final int mGridWidth;
+ private final int mGridTotal;
+ private final ClickListener mListener;
+ private final List mSyncFolderItems;
+
+ public FolderSyncAdapter(Context context, int gridWidth, ClickListener listener) {
+ mContext = context;
+ mGridWidth = gridWidth;
+ mGridTotal = gridWidth * 2;
+ mListener = listener;
+ mSyncFolderItems = new ArrayList<>();
+ }
+
+ public void setSyncFolderItems(List syncFolderItems) {
+ mSyncFolderItems.clear();
+ mSyncFolderItems.addAll(syncFolderItems);
+ notifyDataSetChanged();
+ }
+
+ public void setSyncFolderItem(int location, SyncedFolderDisplayItem syncFolderItem) {
+ mSyncFolderItems.set(location, syncFolderItem);
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public int getSectionCount() {
+ return mSyncFolderItems.size();
+ }
+
+ @Override
+ public int getItemCount(int section) {
+ return mSyncFolderItems.get(section).getFilePaths().size();
+ }
+
+ @Override
+ public void onBindHeaderViewHolder(final MainViewHolder holder, final int section) {
+ holder.title.setText(mSyncFolderItems.get(section).getFolderName());
+ holder.syncStatusButton.setVisibility(View.VISIBLE);
+ holder.syncStatusButton.setTag(section);
+ holder.syncStatusButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled());
+ setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
+ mListener.onSyncStatusToggleClick(section, mSyncFolderItems.get(section));
+ }
+ });
+ setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled());
+
+ holder.menuButton.setVisibility(View.VISIBLE);
+ holder.menuButton.setTag(section);
+ holder.menuButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mListener.onSyncFolderSettingsClick(section, mSyncFolderItems.get(section));
+ }
+ });
+ }
+
+ @Override
+ public void onBindViewHolder(MainViewHolder holder, int section, int relativePosition, int absolutePosition) {
+
+ File file = new File(mSyncFolderItems.get(section).getFilePaths().get(relativePosition));
+
+ ThumbnailsCacheManager.MediaThumbnailGenerationTask task =
+ new ThumbnailsCacheManager.MediaThumbnailGenerationTask(holder.image);
+
+ ThumbnailsCacheManager.AsyncMediaThumbnailDrawable asyncDrawable =
+ new ThumbnailsCacheManager.AsyncMediaThumbnailDrawable(
+ mContext.getResources(),
+ ThumbnailsCacheManager.mDefaultImg,
+ task
+ );
+ holder.image.setImageDrawable(asyncDrawable);
+
+ task.execute(file);
+
+ // set proper tag
+ holder.image.setTag(file.hashCode());
+
+ holder.itemView.setTag(relativePosition % mGridWidth);
+
+ if (mSyncFolderItems.get(section).getNumberOfFiles() > mGridTotal && relativePosition >= mGridTotal - 1) {
+ holder.counterValue.setText(Long.toString(mSyncFolderItems.get(section).getNumberOfFiles() - mGridTotal));
+ holder.counterBar.setVisibility(View.VISIBLE);
+ holder.thumbnailDarkener.setVisibility(View.VISIBLE);
+ } else {
+ holder.counterBar.setVisibility(View.GONE);
+ holder.thumbnailDarkener.setVisibility(View.GONE);
+ }
+
+ //holder.itemView.setTag(String.format(Locale.getDefault(), "%d:%d:%d", section, relativePos, absolutePos));
+ //holder.itemView.setOnClickListener(this);
+ }
+
+ @Override
+ public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View v = LayoutInflater.from(parent.getContext()).inflate(
+ viewType == VIEW_TYPE_HEADER ?
+ R.layout.folder_sync_item_header : R.layout.grid_sync_item, parent, false);
+ return new MainViewHolder(v);
+ }
+
+ public interface ClickListener {
+ void onSyncStatusToggleClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem);
+ void onSyncFolderSettingsClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem);
+ }
+
+ static class MainViewHolder extends RecyclerView.ViewHolder {
+ private final ImageView image;
+ private final TextView title;
+ private final ImageButton menuButton;
+ private final ImageButton syncStatusButton;
+ private final LinearLayout counterBar;
+ private final TextView counterValue;
+ private final ImageView thumbnailDarkener;
+
+ private MainViewHolder(View itemView) {
+ super(itemView);
+ image = (ImageView) itemView.findViewById(R.id.thumbnail);
+ title = (TextView) itemView.findViewById(R.id.title);
+ menuButton = (ImageButton) itemView.findViewById(R.id.settingsButton);
+ syncStatusButton = (ImageButton) itemView.findViewById(R.id.syncStatusButton);
+ counterBar = (LinearLayout) itemView.findViewById(R.id.counterLayout);
+ counterValue = (TextView) itemView.findViewById(R.id.counter);
+ thumbnailDarkener = (ImageView) itemView.findViewById(R.id.thumbnailDarkener);
+ }
+ }
+
+ private void setSyncButtonActiveIcon(ImageButton syncStatusButton, boolean enabled) {
+ if(enabled) {
+ syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_on);
+ } else {
+ syncStatusButton.setImageResource(R.drawable.ic_cloud_sync_off);
+ }
+ }
+}
diff --git a/src/com/owncloud/android/ui/decoration/MediaGridItemDecoration.java b/src/com/owncloud/android/ui/decoration/MediaGridItemDecoration.java
new file mode 100644
index 000000000000..de8bca3a1c19
--- /dev/null
+++ b/src/com/owncloud/android/ui/decoration/MediaGridItemDecoration.java
@@ -0,0 +1,44 @@
+/**
+ * Nextcloud Android client application
+ *
+ * Copyright (C) 2016 Andy Scherzinger
+ * Copyright (C) 2016 Nextcloud.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see .
+ */
+package com.owncloud.android.ui.decoration;
+
+import android.graphics.Rect;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.RecyclerView.ItemDecoration;
+import android.view.View;
+
+/**
+ * Decoration for media grid items.
+ */
+public class MediaGridItemDecoration extends ItemDecoration {
+ private int space;
+
+ public MediaGridItemDecoration(int space) {
+ this.space = space;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
+ outRect.right = space;
+ outRect.bottom = space;
+ outRect.left = space;
+ outRect.top = space;
+ }
+}
\ No newline at end of file
diff --git a/src/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java b/src/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java
new file mode 100644
index 000000000000..c453f718f112
--- /dev/null
+++ b/src/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.java
@@ -0,0 +1,294 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 Andy Scherzinger
+ * Copyright (C) 2016 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see .
+ */
+package com.owncloud.android.ui.dialog;
+
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v4.app.DialogFragment;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.widget.SwitchCompat;
+import android.text.style.StyleSpan;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.ui.activity.FolderPickerActivity;
+import com.owncloud.android.ui.dialog.parcel.SyncedFolderParcelable;
+import com.owncloud.android.utils.DisplayUtils;
+
+/**
+ * Dialog to show the preferences/configuration of a synced folder allowing the user to change the different parameters.
+ */
+public class SyncedFolderPreferencesDialogFragment extends DialogFragment {
+
+ private final static String TAG = SyncedFolderPreferencesDialogFragment.class.getSimpleName();
+ public static final String SYNCED_FOLDER_PARCELABLE = "SyncedFolderParcelable";
+ public static final int REQUEST_CODE__SELECT_REMOTE_FOLDER = 0;
+
+ private CharSequence[] mUploadBehaviorItemStrings;
+
+ protected View mView = null;
+ private SwitchCompat mEnabledSwitch;
+ private CheckBox mUploadOnWifiCheckbox;
+ private CheckBox mUploadOnChargingCheckbox;
+ private CheckBox mUploadUseSubfoldersCheckbox;
+ private TextView mUploadBehaviorSummary;
+ private TextView mLocalFolderPath;
+ private TextView mRemoteFolderSummary;
+
+ private SyncedFolderParcelable mSyncedFolder;
+
+ public static SyncedFolderPreferencesDialogFragment newInstance(SyncedFolderDisplayItem syncedFolder, int section) {
+ SyncedFolderPreferencesDialogFragment dialogFragment = new SyncedFolderPreferencesDialogFragment();
+
+ if (syncedFolder == null) {
+ throw new IllegalArgumentException("SyncedFolder is mandatory but NULL!");
+ }
+
+ Bundle args = new Bundle();
+ args.putParcelable(SYNCED_FOLDER_PARCELABLE, new SyncedFolderParcelable(syncedFolder, section));
+ dialogFragment.setArguments(args);
+ dialogFragment.setStyle(STYLE_NORMAL,R.style.Theme_ownCloud_Dialog);
+
+ return dialogFragment;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!(activity instanceof OnSyncedFolderPreferenceListener)) {
+ throw new IllegalArgumentException("The host activity must implement "
+ + OnSyncedFolderPreferenceListener.class.getCanonicalName());
+ }
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // keep the state of the fragment on configuration changes
+ setRetainInstance(true);
+
+ setCancelable(false);
+ mView = null;
+
+ mSyncedFolder = getArguments().getParcelable(SYNCED_FOLDER_PARCELABLE);
+ mUploadBehaviorItemStrings = getResources().getTextArray(R.array.pref_behaviour_entries);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ Log_OC.d(TAG, "onCreateView, savedInstanceState is " + savedInstanceState);
+
+ mView = inflater.inflate(R.layout.folder_sync_settings_layout, container, false);
+
+ setupDialogElements(mView);
+ setupListeners(mView);
+
+ return mView;
+ }
+
+ /**
+ * find all relevant UI elements and set their values.
+ *
+ * @param view the parent view
+ */
+ private void setupDialogElements(View view) {
+ // find/saves UI elements
+ mEnabledSwitch = (SwitchCompat) view.findViewById(R.id.sync_enabled);
+ mLocalFolderPath = (TextView) view.findViewById(R.id.folder_sync_settings_local_folder_path);
+
+ mRemoteFolderSummary = (TextView) view.findViewById(R.id.remote_folder_summary);
+
+ mUploadOnWifiCheckbox = (CheckBox) view.findViewById(R.id.setting_instant_upload_on_wifi_checkbox);
+ mUploadOnChargingCheckbox = (CheckBox) view.findViewById(R.id.setting_instant_upload_on_charging_checkbox);
+ mUploadUseSubfoldersCheckbox = (CheckBox) view.findViewById(R.id
+ .setting_instant_upload_path_use_subfolders_checkbox);
+
+ mUploadBehaviorSummary = (TextView) view.findViewById(R.id.setting_instant_behaviour_summary);
+
+ // Set values
+ setEnabled(mSyncedFolder.getEnabled());
+ mLocalFolderPath.setText(
+ DisplayUtils.createTextWithSpan(
+ String.format(
+ getString(R.string.folder_sync_preferences_folder_path),
+ mSyncedFolder.getLocalPath()),
+ mSyncedFolder.getFolderName(),
+ new StyleSpan(Typeface.BOLD)));
+
+ mRemoteFolderSummary.setText(mSyncedFolder.getRemotePath());
+
+ mUploadOnWifiCheckbox.setChecked(mSyncedFolder.getWifiOnly());
+ mUploadOnChargingCheckbox.setChecked(mSyncedFolder.getChargingOnly());
+ mUploadUseSubfoldersCheckbox.setChecked(mSyncedFolder.getSubfolderByDate());
+
+ mUploadBehaviorSummary.setText(mUploadBehaviorItemStrings[mSyncedFolder.getUploadActionInteger()]);
+ }
+
+ /**
+ * set correct icon/flag.
+ *
+ * @param enabled if enabled or disabled
+ */
+ private void setEnabled(boolean enabled) {
+ mSyncedFolder.setEnabled(enabled);
+ mEnabledSwitch.setChecked(enabled);
+ }
+
+ /**
+ * set (new) remote path on activity result of the folder picker activity. The result gets originally propagated
+ * to the underlying activity since the picker is an activity and the result can't get passed to the dialog
+ * fragment directly.
+ *
+ * @param path the remote path to be set
+ */
+ public void setRemoteFolderSummary(String path) {
+ mSyncedFolder.setRemotePath(path);
+ mRemoteFolderSummary.setText(path);
+ }
+
+ /**
+ * setup all listeners.
+ *
+ * @param view the parent view
+ */
+ private void setupListeners(View view) {
+ view.findViewById(R.id.save).setOnClickListener(new OnSyncedFolderSaveClickListener());
+ view.findViewById(R.id.cancel).setOnClickListener(new OnSyncedFolderCancelClickListener());
+
+ view.findViewById(R.id.setting_instant_upload_on_wifi_container).setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSyncedFolder.setWifiOnly(!mSyncedFolder.getWifiOnly());
+ mUploadOnWifiCheckbox.toggle();
+ }
+ });
+
+ view.findViewById(R.id.setting_instant_upload_on_charging_container).setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSyncedFolder.setChargingOnly(!mSyncedFolder.getChargingOnly());
+ mUploadOnChargingCheckbox.toggle();
+ }
+ });
+
+ view.findViewById(R.id.setting_instant_upload_path_use_subfolders_container).setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSyncedFolder.setSubfolderByDate(!mSyncedFolder.getSubfolderByDate());
+ mUploadUseSubfoldersCheckbox.toggle();
+ }
+ });
+
+ view.findViewById(R.id.remote_folder_container).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent action = new Intent(getActivity(), FolderPickerActivity.class);
+ action.putExtra(
+ FolderPickerActivity.EXTRA_ACTION, getResources().getText(R.string.choose_remote_folder));
+ getActivity().startActivityForResult(action, REQUEST_CODE__SELECT_REMOTE_FOLDER);
+ }
+ });
+
+ view.findViewById(R.id.sync_enabled).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setEnabled(!mSyncedFolder.getEnabled());
+ }
+ });
+
+ view.findViewById(R.id.setting_instant_behaviour_container).setOnClickListener(
+ new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setTitle(R.string.prefs_instant_behaviour_dialogTitle)
+ .setSingleChoiceItems(getResources().getTextArray(R.array.pref_behaviour_entries),
+ mSyncedFolder.getUploadActionInteger(),
+ new
+ DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ mSyncedFolder.setUploadAction(
+ getResources().getTextArray(
+ R.array.pref_behaviour_entryValues)[which].toString());
+ mUploadBehaviorSummary.setText(SyncedFolderPreferencesDialogFragment
+ .this.mUploadBehaviorItemStrings[which]);
+ dialog.dismiss();
+ }
+ });
+ builder.create().show();
+ }
+ });
+ }
+
+ @Override
+ @NonNull
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Dialog dialog = super.onCreateDialog(savedInstanceState);
+ dialog.setTitle(null);
+ return dialog;
+ }
+
+ @Override
+ public void onDestroyView() {
+ Log_OC.d(TAG, "destroy SyncedFolderPreferencesDialogFragment view");
+ if (getDialog() != null && getRetainInstance()) {
+ getDialog().setDismissMessage(null);
+ }
+ super.onDestroyView();
+ }
+
+ private class OnSyncedFolderSaveClickListener implements OnClickListener {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ ((OnSyncedFolderPreferenceListener) getActivity()).onSaveSyncedFolderPreference(mSyncedFolder);
+ }
+ }
+
+ private class OnSyncedFolderCancelClickListener implements OnClickListener {
+ @Override
+ public void onClick(View v) {
+ dismiss();
+ ((OnSyncedFolderPreferenceListener) getActivity()).onCancelSyncedFolderPreference();
+ }
+ }
+
+ public interface OnSyncedFolderPreferenceListener {
+ void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder);
+
+ void onCancelSyncedFolderPreference();
+ }
+}
diff --git a/src/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java b/src/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java
new file mode 100644
index 000000000000..f5d9f499ba57
--- /dev/null
+++ b/src/com/owncloud/android/ui/dialog/parcel/SyncedFolderParcelable.java
@@ -0,0 +1,219 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Andy Scherzinger
+ * Copyright (C) 2016 Andy Scherzinger
+ * Copyright (C) 2016 Nextcloud
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public
+ * License along with this program. If not, see .
+ */
+package com.owncloud.android.ui.dialog.parcel;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.owncloud.android.datamodel.SyncedFolderDisplayItem;
+import com.owncloud.android.files.services.FileUploader;
+
+/**
+ * Parcelable for {@link SyncedFolderDisplayItem} objects to transport them from/to dialog fragments.
+ */
+public class SyncedFolderParcelable implements Parcelable {
+ private String mFolderName;
+ private String mLocalPath;
+ private String mRemotePath;
+ private Boolean mWifiOnly = false;
+ private Boolean mChargingOnly = false;
+ private Boolean mEnabled = false;
+ private Boolean mSubfolderByDate = false;
+ private Integer mUploadAction;
+ private long mId;
+ private String mAccount;
+ private int mSection;
+
+ public SyncedFolderParcelable() {
+ }
+
+ public SyncedFolderParcelable(SyncedFolderDisplayItem syncedFolderDisplayItem, int section) {
+ mId = syncedFolderDisplayItem.getId();
+ mFolderName = syncedFolderDisplayItem.getFolderName();
+ mLocalPath = syncedFolderDisplayItem.getLocalPath();
+ mRemotePath = syncedFolderDisplayItem.getRemotePath();
+ mWifiOnly = syncedFolderDisplayItem.getWifiOnly();
+ mChargingOnly = syncedFolderDisplayItem.getChargingOnly();
+ mEnabled = syncedFolderDisplayItem.isEnabled();
+ mSubfolderByDate = syncedFolderDisplayItem.getSubfolderByDate();
+ mAccount = syncedFolderDisplayItem.getAccount();
+ mUploadAction = syncedFolderDisplayItem.getUploadAction();
+ mSection = section;
+ }
+
+ private SyncedFolderParcelable(Parcel read) {
+ mId = read.readLong();
+ mFolderName = read.readString();
+ mLocalPath = read.readString();
+ mRemotePath = read.readString();
+ mWifiOnly = read.readInt()!= 0;
+ mChargingOnly = read.readInt() != 0;
+ mEnabled = read.readInt() != 0;
+ mSubfolderByDate = read.readInt() != 0;
+ mAccount = read.readString();
+ mUploadAction = read.readInt();
+ mSection = read.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mId);
+ dest.writeString(mFolderName);
+ dest.writeString(mLocalPath);
+ dest.writeString(mRemotePath);
+ dest.writeInt(mWifiOnly ? 1 : 0);
+ dest.writeInt(mChargingOnly ? 1 : 0);
+ dest.writeInt(mEnabled ? 1 : 0);
+ dest.writeInt(mSubfolderByDate ? 1 : 0);
+ dest.writeString(mAccount);
+ dest.writeInt(mUploadAction);
+ dest.writeInt(mSection);
+ }
+
+ public static final Creator CREATOR =
+ new Creator() {
+
+ @Override
+ public SyncedFolderParcelable createFromParcel(Parcel source) {
+ return new SyncedFolderParcelable(source);
+ }
+
+ @Override
+ public SyncedFolderParcelable[] newArray(int size) {
+ return new SyncedFolderParcelable[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public String getFolderName() {
+ return mFolderName;
+ }
+
+ public void setFolderName(String mFolderName) {
+ this.mFolderName = mFolderName;
+ }
+
+ public String getLocalPath() {
+ return mLocalPath;
+ }
+
+ public void setLocalPath(String mLocalPath) {
+ this.mLocalPath = mLocalPath;
+ }
+
+ public String getRemotePath() {
+ return mRemotePath;
+ }
+
+ public void setRemotePath(String mRemotePath) {
+ this.mRemotePath = mRemotePath;
+ }
+
+ public Boolean getWifiOnly() {
+ return mWifiOnly;
+ }
+
+ public void setWifiOnly(Boolean mWifiOnly) {
+ this.mWifiOnly = mWifiOnly;
+ }
+
+ public Boolean getChargingOnly() {
+ return mChargingOnly;
+ }
+
+ public void setChargingOnly(Boolean mChargingOnly) {
+ this.mChargingOnly = mChargingOnly;
+ }
+
+ public Boolean getEnabled() {
+ return mEnabled;
+ }
+
+ public void setEnabled(boolean mEnabled) {
+ this.mEnabled = mEnabled;
+ }
+
+ public Boolean getSubfolderByDate() {
+ return mSubfolderByDate;
+ }
+
+ public void setSubfolderByDate(Boolean mSubfolderByDate) {
+ this.mSubfolderByDate = mSubfolderByDate;
+ }
+
+ public Integer getUploadAction() {
+ return mUploadAction;
+ }
+
+ public Integer getUploadActionInteger() {
+ switch (mUploadAction) {
+ case FileUploader.LOCAL_BEHAVIOUR_FORGET:
+ return 0;
+ case FileUploader.LOCAL_BEHAVIOUR_MOVE:
+ return 1;
+ case FileUploader.LOCAL_BEHAVIOUR_DELETE:
+ return 2;
+ }
+ return 0;
+ }
+
+ public void setUploadAction(String mUploadAction) {
+ switch (mUploadAction) {
+ case "LOCAL_BEHAVIOUR_FORGET":
+ this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_FORGET;
+ break;
+ case "LOCAL_BEHAVIOUR_MOVE":
+ this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_MOVE;
+ break;
+ case "LOCAL_BEHAVIOUR_DELETE":
+ this.mUploadAction = FileUploader.LOCAL_BEHAVIOUR_DELETE;
+ break;
+ }
+ }
+
+ public long getId() {
+ return mId;
+ }
+
+ public void setId(long mId) {
+ this.mId = mId;
+ }
+
+ public String getAccount() {
+ return mAccount;
+ }
+
+ public void setAccount(String mAccount) {
+ this.mAccount = mAccount;
+ }
+
+ public int getSection() {
+ return mSection;
+ }
+
+ public void setSection(int mSection) {
+ this.mSection = mSection;
+ }
+}
diff --git a/src/com/owncloud/android/utils/DisplayUtils.java b/src/com/owncloud/android/utils/DisplayUtils.java
index ec2ef5a82f63..508eef9168e5 100644
--- a/src/com/owncloud/android/utils/DisplayUtils.java
+++ b/src/com/owncloud/android/utils/DisplayUtils.java
@@ -38,7 +38,10 @@
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
import android.text.format.DateUtils;
+import android.text.style.StyleSpan;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.SeekBar;
@@ -68,9 +71,9 @@ public class DisplayUtils {
private static final String[] sizeSuffixes = { "B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
private static final int[] sizeScales = { 0, 0, 1, 1, 1, 2, 2, 2, 2 };
- public static final int RELATIVE_THRESHOLD_WARNING = 90;
- public static final int RELATIVE_THRESHOLD_CRITICAL = 95;
- public static final String MIME_TYPE_UNKNOWN = "Unknown type";
+ private static final int RELATIVE_THRESHOLD_WARNING = 90;
+ private static final int RELATIVE_THRESHOLD_CRITICAL = 95;
+ private static final String MIME_TYPE_UNKNOWN = "Unknown type";
private static Map mimeType2HumanReadable;
@@ -355,6 +358,21 @@ public static void colorStatusBar(FragmentActivity fragmentActivity, @ColorInt i
}
}
+ /**
+ * styling of given spanText within a given text.
+ *
+ * @param text the non styled complete text
+ * @param spanText the to be styled text
+ * @param style the style to be applied
+ */
+ public static SpannableStringBuilder createTextWithSpan(String text, String spanText, StyleSpan style) {
+ SpannableStringBuilder sb = new SpannableStringBuilder(text);
+ int start = text.lastIndexOf(spanText);
+ int end = start + spanText.length();
+ sb.setSpan(style, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
+ return sb;
+ }
+
/**
* Sets the color of the progressbar to {@code color} within the given toolbar.
*
diff --git a/src/com/owncloud/android/utils/FileStorageUtils.java b/src/com/owncloud/android/utils/FileStorageUtils.java
index c0f3a8f29adf..1eec561edd01 100644
--- a/src/com/owncloud/android/utils/FileStorageUtils.java
+++ b/src/com/owncloud/android/utils/FileStorageUtils.java
@@ -142,21 +142,17 @@ private static String getSubpathFromDate(long date) {
/**
* Returns the InstantUploadFilePath on the owncloud instance
*
- * @param context
* @param fileName
* @param dateTaken: Time in milliseconds since 1970 when the picture was taken.
* @return
*/
- public static String getInstantUploadFilePath(Context context, String fileName, long dateTaken) {
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
- String uploadPathdef = context.getString(R.string.instant_upload_path);
- String uploadPath = pref.getString("instant_upload_path", uploadPathdef);
+ public static String getInstantUploadFilePath(String remotePath, String fileName, long dateTaken,
+ Boolean subfolderByDate) {
String subPath = "";
- if (com.owncloud.android.db.PreferenceManager.instantPictureUploadPathUseSubfolders(context)) {
+ if (subfolderByDate) {
subPath = getSubpathFromDate(dateTaken);
}
- return uploadPath + OCFile.PATH_SEPARATOR + subPath
- + (fileName == null ? "" : fileName);
+ return remotePath + OCFile.PATH_SEPARATOR + subPath + (fileName == null ? "" : fileName);
}
/**
diff --git a/src/com/owncloud/android/utils/RecursiveFileObserver.java b/src/com/owncloud/android/utils/RecursiveFileObserver.java
index e85b30d18af6..b482882c43f6 100644
--- a/src/com/owncloud/android/utils/RecursiveFileObserver.java
+++ b/src/com/owncloud/android/utils/RecursiveFileObserver.java
@@ -20,13 +20,13 @@
package com.owncloud.android.utils;
+import android.os.FileObserver;
+
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
-import android.os.FileObserver;
-
public class RecursiveFileObserver extends FileObserver {
private final List mObservers = new ArrayList<>();
@@ -38,7 +38,7 @@ public RecursiveFileObserver(String path) {
this(path, ALL_EVENTS);
}
- RecursiveFileObserver(String path, int mask) {
+ public RecursiveFileObserver(String path, int mask) {
super(path, mask);
mPath = path;
mMask = mask;