Browse Source

Progress on magic

Mario Danic 8 years ago
parent
commit
0994140d55

+ 5 - 252
src/main/java/com/owncloud/android/ui/activity/ContactsPreferenceActivity.java

@@ -21,43 +21,27 @@
 
 package com.owncloud.android.ui.activity;
 
-import android.Manifest;
 import android.accounts.Account;
-import android.app.DatePickerDialog;
 import android.content.Context;
 import android.content.Intent;
-import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.design.widget.BottomNavigationView;
 import android.support.design.widget.Snackbar;
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentTransaction;
-import android.support.v7.widget.SwitchCompat;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.CompoundButton;
-import android.widget.DatePicker;
-import android.widget.TextView;
-import android.widget.Toast;
 
 import com.evernote.android.job.JobManager;
 import com.evernote.android.job.JobRequest;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
-import com.owncloud.android.db.PreferenceManager;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.services.ContactsBackupJob;
+import com.owncloud.android.ui.fragment.ContactsBackup.ContactsBackupFragment;
 import com.owncloud.android.ui.fragment.FileFragment;
-import com.owncloud.android.utils.DisplayUtils;
-import com.owncloud.android.utils.PermissionUtil;
 
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.Set;
-import java.util.Vector;
 
 /**
  * This activity shows all settings for contact backup/restore
@@ -69,9 +53,6 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
     public static final String PREFERENCE_CONTACTS_AUTOMATIC_BACKUP = "PREFERENCE_CONTACTS_AUTOMATIC_BACKUP";
     public static final String PREFERENCE_CONTACTS_LAST_BACKUP = "PREFERENCE_CONTACTS_LAST_BACKUP";
 
-    private SwitchCompat backupSwitch;
-    private SharedPreferences sharedPreferences;
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -84,41 +65,10 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
         // setup drawer
         setupDrawer(R.id.nav_contacts);
 
-        getSupportActionBar().setTitle(R.string.actionbar_contacts);
-        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
-        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
-
-        backupSwitch = (SwitchCompat) findViewById(R.id.contacts_automatic_backup);
-        backupSwitch.setChecked(sharedPreferences.getBoolean(PREFERENCE_CONTACTS_AUTOMATIC_BACKUP, false));
-
-        backupSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
-            @Override
-            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
-                if (isChecked &&
-                        checkAndAskForContactsReadPermission(PermissionUtil.PERMISSIONS_READ_CONTACTS_AUTOMATIC)) {
-                    // store value
-                    setAutomaticBackup(backupSwitch, true);
-
-                    // enable daily job
-                    startContactBackupJob(getAccount());
-                } else {
-                    setAutomaticBackup(backupSwitch, false);
-
-                    // cancel pending jobs
-                    cancelContactBackupJob(getBaseContext());
-                }
-            }
-        });
-
-        // display last backup
-        TextView lastBackup = (TextView) findViewById(R.id.contacts_last_backup_timestamp);
-        Long lastBackupTimestamp = sharedPreferences.getLong(PREFERENCE_CONTACTS_LAST_BACKUP, -1);
-
-        if (lastBackupTimestamp == -1) {
-            lastBackup.setText(R.string.contacts_preference_backup_never);
-        } else {
-            lastBackup.setText(DisplayUtils.getRelativeTimestamp(getBaseContext(), lastBackupTimestamp));
+        if (savedInstanceState == null) {
+            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+            transaction.add(R.id.frame_container, new ContactsBackupFragment());
+            transaction.commit();
         }
 
         BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.bottom_navigation_view);
@@ -129,183 +79,6 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
         }
     }
 
-    @Override
-    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
-        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-
-        if (requestCode == PermissionUtil.PERMISSIONS_READ_CONTACTS_AUTOMATIC) {
-            for (int index = 0; index < permissions.length; index++) {
-                if (Manifest.permission.READ_CONTACTS.equalsIgnoreCase(permissions[index])) {
-                    if (grantResults[index] >= 0) {
-                        setAutomaticBackup(backupSwitch, true);
-                    } else {
-                        setAutomaticBackup(backupSwitch, false);
-                    }
-
-                    break;
-                }
-            }
-        }
-
-        if (requestCode == PermissionUtil.PERMISSIONS_READ_CONTACTS_MANUALLY) {
-            for (int index = 0; index < permissions.length; index++) {
-                if (Manifest.permission.READ_CONTACTS.equalsIgnoreCase(permissions[index])) {
-                    if (grantResults[index] >= 0) {
-                        startContactsBackupJob();
-                    }
-
-                    break;
-                }
-            }
-        }
-    }
-
-    public void backupContacts(View v) {
-        if (checkAndAskForContactsReadPermission(PermissionUtil.PERMISSIONS_READ_CONTACTS_MANUALLY)) {
-            startContactsBackupJob();
-        }
-    }
-
-    private void startContactsBackupJob() {
-        PersistableBundleCompat bundle = new PersistableBundleCompat();
-        bundle.putString(ContactsBackupJob.ACCOUNT, getAccount().name);
-        bundle.putBoolean(ContactsBackupJob.FORCE, true);
-
-        new JobRequest.Builder(ContactsBackupJob.TAG)
-                .setExtras(bundle)
-                .setExecutionWindow(3_000L, 10_000L)
-                .setRequiresCharging(false)
-                .setPersisted(false)
-                .setUpdateCurrent(false)
-                .build()
-                .schedule();
-
-        Snackbar.make(findViewById(R.id.contacts_linear_layout), R.string.contacts_preferences_backup_scheduled,
-                Snackbar.LENGTH_LONG).show();
-    }
-
-    private void setAutomaticBackup(SwitchCompat backupSwitch, boolean bool) {
-        backupSwitch.setChecked(bool);
-        SharedPreferences.Editor editor = sharedPreferences.edit();
-        editor.putBoolean(PREFERENCE_CONTACTS_AUTOMATIC_BACKUP, bool);
-        editor.apply();
-    }
-
-    private boolean checkAndAskForContactsReadPermission(final int permission) {
-        // check permissions
-        if ((PermissionUtil.checkSelfPermission(this, Manifest.permission.READ_CONTACTS))) {
-            return true;
-        } else {
-            // Check if we should show an explanation
-            if (PermissionUtil.shouldShowRequestPermissionRationale(ContactsPreferenceActivity.this,
-                    android.Manifest.permission.READ_CONTACTS)) {
-                // Show explanation to the user and then request permission
-                Snackbar snackbar = Snackbar.make(findViewById(R.id.contacts_linear_layout), R.string.contacts_read_permission,
-                        Snackbar.LENGTH_INDEFINITE)
-                        .setAction(R.string.common_ok, new View.OnClickListener() {
-                            @Override
-                            public void onClick(View v) {
-                                PermissionUtil.requestReadContactPermission(ContactsPreferenceActivity.this, permission);
-                            }
-                        });
-
-                DisplayUtils.colorSnackbar(this, snackbar);
-
-                snackbar.show();
-
-                return false;
-            } else {
-                // No explanation needed, request the permission.
-                PermissionUtil.requestReadContactPermission(ContactsPreferenceActivity.this, permission);
-
-                return false;
-            }
-        }
-    }
-
-    public void openDate(View v) {
-        String backupFolderString = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
-        OCFile backupFolder = getStorageManager().getFileByPath(backupFolderString);
-
-        Vector<OCFile> backupFiles = getStorageManager().getFolderContent(backupFolder, false);
-
-        Collections.sort(backupFiles, new Comparator<OCFile>() {
-            @Override
-            public int compare(OCFile o1, OCFile o2) {
-                if (o1.getModificationTimestamp() == o2.getModificationTimestamp()) {
-                    return 0;
-                }
-
-                if (o1.getModificationTimestamp() > o2.getModificationTimestamp()) {
-                    return 1;
-                } else {
-                    return -1;
-                }
-            }
-        });
-
-        Calendar cal = Calendar.getInstance();
-        int year = cal.get(Calendar.YEAR);
-        int month = cal.get(Calendar.MONTH) + 1;
-        int day = cal.get(Calendar.DAY_OF_MONTH);
-
-        DatePickerDialog.OnDateSetListener dateSetListener = new DatePickerDialog.OnDateSetListener() {
-            @Override
-            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
-                String backupFolderString = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
-                OCFile backupFolder = getStorageManager().getFileByPath(backupFolderString);
-                Vector<OCFile> backupFiles = getStorageManager().getFolderContent(backupFolder, false);
-
-                // find file with modification with date and time between 00:00 and 23:59
-                // if more than one file exists, take oldest
-                Calendar date = Calendar.getInstance();
-                date.set(year, month, dayOfMonth);
-
-                // start
-                date.set(Calendar.HOUR, 0);
-                date.set(Calendar.MINUTE, 0);
-                date.set(Calendar.SECOND, 1);
-                date.set(Calendar.MILLISECOND, 0);
-                date.set(Calendar.AM_PM, Calendar.AM);
-                Long start = date.getTimeInMillis();
-
-                // end
-                date.set(Calendar.HOUR, 23);
-                date.set(Calendar.MINUTE, 59);
-                date.set(Calendar.SECOND, 59);
-                Long end = date.getTimeInMillis();
-
-                OCFile backupToRestore = null;
-
-                for (OCFile file : backupFiles) {
-                    if (start < file.getModificationTimestamp() && end > file.getModificationTimestamp()) {
-                        if (backupToRestore == null) {
-                            backupToRestore = file;
-                        } else if (backupToRestore.getModificationTimestamp() < file.getModificationTimestamp()) {
-                            backupToRestore = file;
-                        }
-                    }
-                }
-
-                if (backupToRestore != null) {
-                    Fragment contactListFragment = ContactListFragment.newInstance(backupToRestore, getAccount());
-
-                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
-                    transaction.replace(R.id.contacts_linear_layout, contactListFragment);
-                    transaction.commit();
-                } else {
-                    Toast.makeText(ContactsPreferenceActivity.this, R.string.contacts_preferences_no_file_found,
-                            Toast.LENGTH_SHORT).show();
-                }
-            }
-        };
-
-        DatePickerDialog datePickerDialog = new DatePickerDialog(this, dateSetListener, year, month, day);
-        datePickerDialog.getDatePicker().setMaxDate(backupFiles.lastElement().getModificationTimestamp());
-        datePickerDialog.getDatePicker().setMinDate(backupFiles.firstElement().getModificationTimestamp());
-
-        datePickerDialog.show();
-    }
 
     public static void startContactBackupJob(Account account) {
         Log_OC.d(TAG, "start daily contacts backup job");
@@ -335,26 +108,6 @@ public class ContactsPreferenceActivity extends FileActivity implements FileFrag
     }
 
 
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        boolean retval;
-        switch (item.getItemId()) {
-            case android.R.id.home:
-                if (isDrawerOpen()) {
-                    closeDrawer();
-                } else {
-                    openDrawer();
-                }
-                retval = true;
-                break;
-
-            default:
-                retval = super.onOptionsItemSelected(item);
-                break;
-        }
-        return retval;
-    }
-
     @Override
     public void showFiles(boolean onDeviceOnly) {
         super.showFiles(onDeviceOnly);

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

@@ -83,6 +83,7 @@ import com.owncloud.android.services.observer.FileObserverService;
 import com.owncloud.android.syncadapter.FileSyncAdapter;
 import com.owncloud.android.ui.dialog.SortingOrderDialogFragment;
 import com.owncloud.android.ui.events.TokenPushEvent;
+import com.owncloud.android.ui.fragment.ContactsBackup.ContactListFragment;
 import com.owncloud.android.ui.fragment.ExtendedListFragment;
 import com.owncloud.android.ui.fragment.FileDetailFragment;
 import com.owncloud.android.ui.fragment.FileFragment;

+ 38 - 9
src/main/java/com/owncloud/android/ui/activity/ContactListFragment.java → src/main/java/com/owncloud/android/ui/fragment/ContactsBackup/ContactListFragment.java

@@ -19,7 +19,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package com.owncloud.android.ui.activity;
+package com.owncloud.android.ui.fragment.ContactsBackup;
 
 import android.Manifest;
 import android.accounts.Account;
@@ -38,7 +38,7 @@ import android.support.v7.app.AlertDialog;
 import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
-import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
@@ -54,6 +54,7 @@ import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.services.ContactsImportJob;
 import com.owncloud.android.ui.TextDrawable;
+import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
 import com.owncloud.android.ui.fragment.FileFragment;
 import com.owncloud.android.utils.BitmapUtils;
 import com.owncloud.android.utils.PermissionUtil;
@@ -98,6 +99,11 @@ public class ContactListFragment extends FileFragment {
         View view = inflater.inflate(R.layout.contactlist_fragment, null);
         setHasOptionsMenu(true);
 
+        ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+        contactsPreferenceActivity.getSupportActionBar().setTitle(R.string.actionbar_contacts_restore);
+        contactsPreferenceActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        contactsPreferenceActivity.setDrawerIndicatorEnabled(false);
+
         ArrayList<VCard> vCards = new ArrayList<>();
         checkedVCards = new HashSet<>();
 
@@ -136,10 +142,10 @@ public class ContactListFragment extends FileFragment {
         ContactListAdapter.OnVCardClickListener vCardClickListener = new ContactListAdapter.OnVCardClickListener() {
             private void setRestoreButton() {
                 if (checkedVCards.size() > 0) {
-                    restoreContacts.setEnabled(true);
+                    restoreContacts.setVisibility(View.VISIBLE);
                     restoreContacts.setBackgroundColor(getResources().getColor(R.color.primary_button_background_color));
                 } else {
-                    restoreContacts.setEnabled(false);
+                    restoreContacts.setVisibility(View.GONE);
                     restoreContacts.setBackgroundColor(getResources().getColor(R.color.standard_grey));
                 }
             }
@@ -169,13 +175,36 @@ public class ContactListFragment extends FileFragment {
     }
 
     @Override
-    public void onPrepareOptionsMenu(Menu menu) {
-        menu.findItem(R.id.action_search).setVisible(false);
-        menu.findItem(R.id.action_sync_account).setVisible(false);
-        menu.findItem(R.id.action_sort).setVisible(false);
-        menu.findItem(R.id.action_switch_view).setVisible(false);
+    public void onDestroy() {
+        super.onDestroy();
+        ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+        contactsPreferenceActivity.setDrawerIndicatorEnabled(true);
+    }
+
+    public void onResume() {
+        super.onResume();
+        ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+        contactsPreferenceActivity.setDrawerIndicatorEnabled(false);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        boolean retval;
+        ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                contactsPreferenceActivity.onBackPressed();
+                retval = true;
+                break;
+            default:
+                retval = super.onOptionsItemSelected(item);
+                break;
+        }
+        return retval;
     }
 
+
     static class ContactItemViewHolder extends RecyclerView.ViewHolder {
         private ImageView badge;
         private CheckedTextView name;

+ 336 - 0
src/main/java/com/owncloud/android/ui/fragment/ContactsBackup/ContactsBackupFragment.java

@@ -0,0 +1,336 @@
+/**
+ * Nextcloud Android client application
+ *
+ * @author Mario Danic
+ * Copyright (C) 2017 Mario Danic
+ * Copyright (C) 2017 Nextcloud GmbH.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) 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 <http://www.gnu.org/licenses/>.
+ */
+package com.owncloud.android.ui.fragment.ContactsBackup;
+
+import android.Manifest;
+import android.app.DatePickerDialog;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.design.widget.Snackbar;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.widget.SwitchCompat;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CompoundButton;
+import android.widget.DatePicker;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.evernote.android.job.JobRequest;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
+import com.owncloud.android.R;
+import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.db.PreferenceManager;
+import com.owncloud.android.services.ContactsBackupJob;
+import com.owncloud.android.ui.activity.ContactsPreferenceActivity;
+import com.owncloud.android.ui.fragment.FileFragment;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.PermissionUtil;
+
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+
+import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.PREFERENCE_CONTACTS_AUTOMATIC_BACKUP;
+import static com.owncloud.android.ui.activity.ContactsPreferenceActivity.PREFERENCE_CONTACTS_LAST_BACKUP;
+
+public class ContactsBackupFragment extends FileFragment {
+    public static final String TAG = ContactsBackupFragment.class.getSimpleName();
+
+    private SharedPreferences sharedPreferences;
+
+    @BindView(R.id.contacts_automatic_backup)
+    SwitchCompat backupSwitch;
+
+    @Override
+    public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+
+        View view = inflater.inflate(R.layout.contacts_backup_fragment, null);
+        ButterKnife.bind(this, view);
+
+        setHasOptionsMenu(true);
+
+        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+        contactsPreferenceActivity.getSupportActionBar().setTitle(R.string.actionbar_contacts);
+        contactsPreferenceActivity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(contactsPreferenceActivity);
+
+        backupSwitch.setChecked(sharedPreferences.getBoolean(PREFERENCE_CONTACTS_AUTOMATIC_BACKUP, false));
+
+        backupSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                if (isChecked &&
+                        checkAndAskForContactsReadPermission(PermissionUtil.PERMISSIONS_READ_CONTACTS_AUTOMATIC)) {
+                    // store value
+                    setAutomaticBackup(backupSwitch, true);
+
+                    // enable daily job
+                    contactsPreferenceActivity.startContactBackupJob(contactsPreferenceActivity.getAccount());
+                } else {
+                    setAutomaticBackup(backupSwitch, false);
+
+                    // cancel pending jobs
+                    contactsPreferenceActivity.cancelContactBackupJob(contactsPreferenceActivity);
+                }
+            }
+        });
+
+        // display last backup
+        TextView lastBackup = (TextView) view.findViewById(R.id.contacts_last_backup_timestamp);
+        Long lastBackupTimestamp = sharedPreferences.getLong(PREFERENCE_CONTACTS_LAST_BACKUP, -1);
+
+        if (lastBackupTimestamp == -1) {
+            lastBackup.setText(R.string.contacts_preference_backup_never);
+        } else {
+            lastBackup.setText(DisplayUtils.getRelativeTimestamp(contactsPreferenceActivity, lastBackupTimestamp));
+        }
+
+        return view;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+        boolean retval;
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                if (contactsPreferenceActivity.isDrawerOpen()) {
+                    contactsPreferenceActivity.closeDrawer();
+                } else {
+                    contactsPreferenceActivity.openDrawer();
+                }
+                retval = true;
+                break;
+
+            default:
+                retval = super.onOptionsItemSelected(item);
+                break;
+        }
+        return retval;
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+        if (requestCode == PermissionUtil.PERMISSIONS_READ_CONTACTS_AUTOMATIC) {
+            for (int index = 0; index < permissions.length; index++) {
+                if (Manifest.permission.READ_CONTACTS.equalsIgnoreCase(permissions[index])) {
+                    if (grantResults[index] >= 0) {
+                        setAutomaticBackup(backupSwitch, true);
+                    } else {
+                        setAutomaticBackup(backupSwitch, false);
+                    }
+
+                    break;
+                }
+            }
+        }
+
+        if (requestCode == PermissionUtil.PERMISSIONS_READ_CONTACTS_MANUALLY) {
+            for (int index = 0; index < permissions.length; index++) {
+                if (Manifest.permission.READ_CONTACTS.equalsIgnoreCase(permissions[index])) {
+                    if (grantResults[index] >= 0) {
+                        startContactsBackupJob();
+                    }
+
+                    break;
+                }
+            }
+        }
+    }
+
+    @OnClick(R.id.contacts_backup_now)
+    public void backupContacts() {
+        if (checkAndAskForContactsReadPermission(PermissionUtil.PERMISSIONS_READ_CONTACTS_MANUALLY)) {
+            startContactsBackupJob();
+        }
+    }
+
+    private void startContactsBackupJob() {
+        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+        PersistableBundleCompat bundle = new PersistableBundleCompat();
+        bundle.putString(ContactsBackupJob.ACCOUNT, contactsPreferenceActivity.getAccount().name);
+        bundle.putBoolean(ContactsBackupJob.FORCE, true);
+
+        new JobRequest.Builder(ContactsBackupJob.TAG)
+                .setExtras(bundle)
+                .setExecutionWindow(3_000L, 10_000L)
+                .setRequiresCharging(false)
+                .setPersisted(false)
+                .setUpdateCurrent(false)
+                .build()
+                .schedule();
+
+        Snackbar.make(getView().findViewById(R.id.contacts_linear_layout), R.string.contacts_preferences_backup_scheduled,
+                Snackbar.LENGTH_LONG).show();
+    }
+
+    private void setAutomaticBackup(SwitchCompat backupSwitch, boolean bool) {
+        backupSwitch.setChecked(bool);
+        SharedPreferences.Editor editor = sharedPreferences.edit();
+        editor.putBoolean(PREFERENCE_CONTACTS_AUTOMATIC_BACKUP, bool);
+        editor.apply();
+    }
+
+    private boolean checkAndAskForContactsReadPermission(final int permission) {
+        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+        // check permissions
+        if ((PermissionUtil.checkSelfPermission(contactsPreferenceActivity, Manifest.permission.READ_CONTACTS))) {
+            return true;
+        } else {
+            // Check if we should show an explanation
+            if (PermissionUtil.shouldShowRequestPermissionRationale(contactsPreferenceActivity,
+                    android.Manifest.permission.READ_CONTACTS)) {
+                // Show explanation to the user and then request permission
+                Snackbar snackbar = Snackbar.make(getView().findViewById(R.id.contacts_linear_layout),
+                        R.string.contacts_read_permission,
+                        Snackbar.LENGTH_INDEFINITE)
+                        .setAction(R.string.common_ok, new View.OnClickListener() {
+                            @Override
+                            public void onClick(View v) {
+                                PermissionUtil.requestReadContactPermission(contactsPreferenceActivity, permission);
+                            }
+                        });
+
+                DisplayUtils.colorSnackbar(contactsPreferenceActivity, snackbar);
+
+                snackbar.show();
+
+                return false;
+            } else {
+                // No explanation needed, request the permission.
+                PermissionUtil.requestReadContactPermission(contactsPreferenceActivity, permission);
+
+                return false;
+            }
+        }
+    }
+
+    @OnClick(R.id.contacts_datepicker)
+    public void openDate() {
+        final ContactsPreferenceActivity contactsPreferenceActivity = (ContactsPreferenceActivity) getActivity();
+
+
+        String backupFolderString = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
+        OCFile backupFolder = contactsPreferenceActivity.getStorageManager().getFileByPath(backupFolderString);
+
+        Vector<OCFile> backupFiles = contactsPreferenceActivity.getStorageManager().getFolderContent(backupFolder,
+                false);
+
+        Collections.sort(backupFiles, new Comparator<OCFile>() {
+            @Override
+            public int compare(OCFile o1, OCFile o2) {
+                if (o1.getModificationTimestamp() == o2.getModificationTimestamp()) {
+                    return 0;
+                }
+
+                if (o1.getModificationTimestamp() > o2.getModificationTimestamp()) {
+                    return 1;
+                } else {
+                    return -1;
+                }
+            }
+        });
+
+        Calendar cal = Calendar.getInstance();
+        int year = cal.get(Calendar.YEAR);
+        int month = cal.get(Calendar.MONTH) + 1;
+        int day = cal.get(Calendar.DAY_OF_MONTH);
+
+        DatePickerDialog.OnDateSetListener dateSetListener = new DatePickerDialog.OnDateSetListener() {
+            @Override
+            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
+                String backupFolderString = getResources().getString(R.string.contacts_backup_folder) + OCFile.PATH_SEPARATOR;
+                OCFile backupFolder = contactsPreferenceActivity.getStorageManager().getFileByPath(backupFolderString);
+                Vector<OCFile> backupFiles = contactsPreferenceActivity.getStorageManager().getFolderContent(
+                        backupFolder, false);
+
+                // find file with modification with date and time between 00:00 and 23:59
+                // if more than one file exists, take oldest
+                Calendar date = Calendar.getInstance();
+                date.set(year, month, dayOfMonth);
+
+                // start
+                date.set(Calendar.HOUR, 0);
+                date.set(Calendar.MINUTE, 0);
+                date.set(Calendar.SECOND, 1);
+                date.set(Calendar.MILLISECOND, 0);
+                date.set(Calendar.AM_PM, Calendar.AM);
+                Long start = date.getTimeInMillis();
+
+                // end
+                date.set(Calendar.HOUR, 23);
+                date.set(Calendar.MINUTE, 59);
+                date.set(Calendar.SECOND, 59);
+                Long end = date.getTimeInMillis();
+
+                OCFile backupToRestore = null;
+
+                for (OCFile file : backupFiles) {
+                    if (start < file.getModificationTimestamp() && end > file.getModificationTimestamp()) {
+                        if (backupToRestore == null) {
+                            backupToRestore = file;
+                        } else if (backupToRestore.getModificationTimestamp() < file.getModificationTimestamp()) {
+                            backupToRestore = file;
+                        }
+                    }
+                }
+
+                if (backupToRestore != null) {
+                    Fragment contactListFragment = ContactListFragment.newInstance(backupToRestore,
+                            contactsPreferenceActivity.getAccount());
+
+                    FragmentTransaction transaction = contactsPreferenceActivity.getSupportFragmentManager().beginTransaction();
+                    transaction.replace(R.id.frame_container, contactListFragment);
+                    transaction.addToBackStack(null);
+                    transaction.commit();
+                } else {
+                    Toast.makeText(contactsPreferenceActivity, R.string.contacts_preferences_no_file_found,
+                            Toast.LENGTH_SHORT).show();
+                }
+            }
+        };
+
+        DatePickerDialog datePickerDialog = new DatePickerDialog(contactsPreferenceActivity,
+                dateSetListener, year, month, day);
+        datePickerDialog.getDatePicker().setMaxDate(backupFiles.lastElement().getModificationTimestamp());
+        datePickerDialog.getDatePicker().setMinDate(backupFiles.firstElement().getModificationTimestamp());
+
+        datePickerDialog.show();
+    }
+
+}

+ 3 - 4
src/main/res/layout/contactlist_fragment.xml

@@ -21,6 +21,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
+              android:animateLayoutChanges="true"
               android:orientation="vertical">
 
     <android.support.v7.widget.RecyclerView
@@ -34,10 +35,8 @@
         android:id="@+id/contactlist_restore_selected"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_margin="@dimen/standard_margin"
-        android:enabled="false"
         android:text="@string/contaclist_restore_selected"
-        android:background="@color/standard_grey"
-        android:theme="@style/Button.Primary"/>
+        android:theme="@style/Button.Primary"
+        android:visibility="gone"/>
 
 </LinearLayout>

+ 88 - 0
src/main/res/layout/contacts_backup_fragment.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+            android:id="@+id/contacts_linear_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/contacts_header_backup"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/standard_margin"
+            android:layout_marginRight="@dimen/standard_margin"
+            android:layout_marginTop="@dimen/standard_margin"
+            android:text="@string/contacts_header_backup"
+            android:textColor="@color/primary"
+            android:textStyle="bold"/>
+
+        <android.support.v7.widget.SwitchCompat
+            android:id="@+id/contacts_automatic_backup"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="@dimen/standard_margin"
+            android:text="@string/contacts_automatic_backup"
+            android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/contacts_last_backup"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="@dimen/standard_margin"
+                android:layout_weight="1"
+                android:text="@string/contacts_last_backup"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:textColor="@color/black"/>
+
+            <TextView
+                android:id="@+id/contacts_last_backup_timestamp"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_margin="@dimen/standard_margin"
+                android:layout_weight="1"
+                android:gravity="right"
+                android:text="@string/contacts_preference_backup_never"
+                android:textAppearance="?android:attr/textAppearanceMedium"/>
+        </LinearLayout>
+
+        <android.support.v7.widget.AppCompatButton
+            android:id="@+id/contacts_backup_now"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="@dimen/standard_margin"
+            android:onClick="backupContacts"
+            android:text="@string/contacts_backup_button"
+            android:theme="@style/Button.Primary"/>
+
+        <TextView
+            android:id="@+id/contacts_header_restore"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="@dimen/standard_margin"
+            android:layout_marginRight="@dimen/standard_margin"
+            android:layout_marginTop="@dimen/standard_margin"
+            android:text="@string/contacts_header_restore"
+            android:textColor="@color/primary"
+            android:textStyle="bold"/>
+
+        <android.support.v7.widget.AppCompatButton
+            android:id="@+id/contacts_datepicker"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="@dimen/standard_margin"
+            android:onClick="openDate"
+            android:text="@string/contacts_preference_choose_date"
+            android:theme="@style/Button.Primary"/>
+
+    </LinearLayout>
+
+</ScrollView>

+ 5 - 70
src/main/res/layout/contacts_preference.xml

@@ -28,7 +28,7 @@
 
     <!-- The main content view -->
     <RelativeLayout
-        android:id="@+id/contacts_linear_layout"
+        android:id="@+id/contacts_layout"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical">
@@ -45,77 +45,12 @@
 
         <TextView
             android:id="@+id/contacts_header_backup"
+        <FrameLayout
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/standard_margin"
-            android:layout_marginRight="@dimen/standard_margin"
-            android:layout_marginTop="@dimen/standard_margin"
-            android:text="@string/contacts_header_backup"
-            android:textColor="@color/primary"
-            android:textStyle="bold"/>
-
-        <android.support.v7.widget.SwitchCompat
-            android:id="@+id/contacts_automatic_backup"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_margin="@dimen/standard_margin"
-            android:text="@string/contacts_automatic_backup"
-            android:textAppearance="?android:attr/textAppearanceMedium"/>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <TextView
-                android:id="@+id/contacts_last_backup"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_margin="@dimen/standard_margin"
-                android:layout_weight="1"
-                android:text="@string/contacts_last_backup"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:textColor="@color/black"/>
-
-            <TextView
-                android:id="@+id/contacts_last_backup_timestamp"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_margin="@dimen/standard_margin"
-                android:layout_weight="1"
-                android:gravity="right"
-                android:text="@string/contacts_preference_backup_never"
-                android:textAppearance="?android:attr/textAppearanceMedium"/>
-        </LinearLayout>
-
-        <android.support.v7.widget.AppCompatButton
-            android:id="@+id/contacts_backup_now"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_margin="@dimen/standard_margin"
-            android:onClick="backupContacts"
-            android:text="@string/contacts_backup_button"
-            android:theme="@style/Button.Primary"/>
-
-        <TextView
-            android:id="@+id/contacts_header_restore"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="@dimen/standard_margin"
-            android:layout_marginRight="@dimen/standard_margin"
-            android:layout_marginTop="@dimen/standard_margin"
-            android:text="@string/contacts_header_restore"
-            android:textColor="@color/primary"
-            android:textStyle="bold"/>
+            android:layout_height="match_parent"
+            android:id="@+id/frame_container">
 
-        <android.support.v7.widget.AppCompatButton
-            android:id="@+id/contacts_datepacker"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_margin="@dimen/standard_margin"
-            android:onClick="openDate"
-            android:text="@string/contacts_preference_choose_date"
-            android:theme="@style/Button.Primary"/>
+        </FrameLayout>
 
         </LinearLayout>
 

+ 2 - 1
src/main/res/values/strings.xml

@@ -633,7 +633,8 @@
     <string name="prefs_category_about">About</string>
 
     <string name="actionbar_contacts">Backup contacts</string>
-    <string name="contacts_backup_button">Now</string>
+    <string name="actionbar_contacts_restore">Restore contacts</string>
+    <string name="contacts_backup_button">Backup now</string>
     <string name="contacts_restore_button">Restore last backup</string>
     <string name="contacts_header_restore">Restore</string>
     <string name="contacts_header_backup">Backup</string>