#655 Move notes to another account

This commit is contained in:
stefan-niedermann 2020-01-11 09:36:09 +01:00
parent 1fff7daf04
commit c6104b00e0
10 changed files with 250 additions and 7 deletions

View file

@ -16,16 +16,18 @@ import java.util.Calendar;
import java.util.Objects;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.android.fragment.AccountChooserDialogFragment;
import it.niedermann.owncloud.notes.android.fragment.BaseNoteFragment;
import it.niedermann.owncloud.notes.android.fragment.NoteEditFragment;
import it.niedermann.owncloud.notes.android.fragment.NotePreviewFragment;
import it.niedermann.owncloud.notes.model.Category;
import it.niedermann.owncloud.notes.model.CloudNote;
import it.niedermann.owncloud.notes.model.DBNote;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.util.ExceptionHandler;
import it.niedermann.owncloud.notes.util.NoteUtil;
public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragment.NoteFragmentListener {
public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragment.NoteFragmentListener, AccountChooserDialogFragment.AccountChooserListener {
private static final String TAG = EditNoteActivity.class.getSimpleName();
@ -227,4 +229,9 @@ public class EditNoteActivity extends AppCompatActivity implements BaseNoteFragm
finish();
}
}
@Override
public void onAccountChosen(LocalAccount account) {
fragment.moveNote(account);
}
}

View file

@ -0,0 +1,83 @@
package it.niedermann.owncloud.notes.android.fragment;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.LocalAccount;
public class AccountChooserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
@NonNull
private List<LocalAccount> localAccounts;
@NonNull
private AccountChooserDialogFragment.AccountChooserListener accountChooserListener;
@Nullable
private Context context;
AccountChooserAdapter(@NonNull List<LocalAccount> localAccounts, @NonNull AccountChooserDialogFragment.AccountChooserListener accountChooserListener, @Nullable Context context) {
super();
this.localAccounts = localAccounts;
this.accountChooserListener = accountChooserListener;
this.context = context;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_account_choose, parent, false);
return new AccountChooserViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
LocalAccount localAccount = localAccounts.get(position);
AccountChooserViewHolder accountChooserViewHolder = (AccountChooserViewHolder) holder;
accountChooserViewHolder.accountLayout.setOnClickListener((v) -> {
accountChooserListener.onAccountChosen(localAccount);
});
// if (context != null) {
// try {
//// ViewUtil.addAvatar(context, acHolder.avatar, SingleAccountHelper.getCurrentSingleSignOnAccount(context).url, ac.getUser().getUid(), R.drawable.ic_person_grey600_24dp);
// } catch (NextcloudFilesAppAccountNotFoundException | NoCurrentAccountSelectedException e) {
// e.printStackTrace();
// }
// }
accountChooserViewHolder.username.setText(localAccount.getUserName() + localAccount.getUrl());
}
@Override
public int getItemCount() {
return localAccounts.size();
}
static class AccountChooserViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.accountLayout)
RelativeLayout accountLayout;
@BindView(R.id.accountItemAvatar)
ImageView avatar;
@BindView(R.id.accountItemLabel)
TextView username;
private AccountChooserViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}

View file

@ -0,0 +1,80 @@
package it.niedermann.owncloud.notes.android.fragment;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import java.util.Objects;
import butterknife.BindView;
import butterknife.ButterKnife;
import it.niedermann.owncloud.notes.R;
import it.niedermann.owncloud.notes.model.LocalAccount;
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
public class AccountChooserDialogFragment extends DialogFragment {
private AccountChooserListener accountChooserListener;
@BindView(R.id.accounts_list)
RecyclerView accountRecyclerView;
/**
* Use newInstance()-Method
*/
public AccountChooserDialogFragment() {
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof AccountChooserListener) {
this.accountChooserListener = (AccountChooserListener) context;
} else {
throw new ClassCastException("Caller must implement " + AccountChooserListener.class.getCanonicalName());
}
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
View view = Objects.requireNonNull(getActivity()).getLayoutInflater().inflate(R.layout.choose_account, null);
ButterKnife.bind(this, view);
NoteSQLiteOpenHelper db = NoteSQLiteOpenHelper.getInstance(getActivity());
List<LocalAccount> accountsList = db.getAccounts();
RecyclerView.Adapter adapter = new AccountChooserAdapter(accountsList, accountChooserListener, getActivity());
accountRecyclerView.setAdapter(adapter);
return new AlertDialog.Builder(getActivity(), R.style.ncAlertDialog)
.setView(view)
.setTitle(R.string.simple_move)
.setNegativeButton(android.R.string.cancel, null)
.create();
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Objects.requireNonNull(Objects.requireNonNull(getDialog()).getWindow()).setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
return super.onCreateView(inflater, container, savedInstanceState);
}
public static AccountChooserDialogFragment newInstance() {
return new AccountChooserDialogFragment();
}
public interface AccountChooserListener {
void onAccountChosen(LocalAccount account);
}
}

View file

@ -96,13 +96,13 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
long id = getArguments().getLong(PARAM_NOTE_ID);
if (id > 0) {
long accountId = getArguments().getLong(PARAM_ACCOUNT_ID);
if(accountId > 0) {
if (accountId > 0) {
/* Switch account if account id has been provided */
this.localAccount = db.getAccount(accountId);
SingleAccountHelper.setCurrentAccount(getActivity().getApplicationContext(), localAccount.getAccountName());
try {
db.getNoteServerSyncHelper().updateAccount();
} catch(NextcloudFilesAppAccountNotFoundException e) {
} catch (NextcloudFilesAppAccountNotFoundException e) {
e.printStackTrace();
}
}
@ -271,6 +271,9 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
case R.id.menu_category:
showCategorySelector();
return true;
case R.id.menu_move:
AccountChooserDialogFragment.newInstance().show(getFragmentManager(), BaseNoteFragment.class.getCanonicalName());
return true;
case R.id.menu_share:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
@ -332,7 +335,7 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
*/
protected void saveNote(@Nullable ICallback callback) {
Log.d(TAG, "saveData()");
if(note != null) {
if (note != null) {
String newContent = getContent();
if (note.getContent().equals(newContent)) {
Log.v(TAG, "... not saving, since nothing has changed");
@ -388,6 +391,11 @@ public abstract class BaseNoteFragment extends Fragment implements CategoryDialo
listener.onNoteUpdated(note);
}
public void moveNote(LocalAccount account) {
db.moveNoteToAnotherAccount(note.getAccountId(), note, account.getId());
listener.close();
}
public interface NoteFragmentListener {
void close();

View file

@ -340,6 +340,15 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
return db.insert(table_notes, null, values);
}
public void moveNoteToAnotherAccount(long oldAccountId, DBNote note, long newAccountId) {
// Add new note
addNoteAndSync(newAccountId, new CloudNote(0, note.getModified(), note.getTitle(), note.getContent(), note.isFavorite(), note.getCategory(), null));
deleteNoteAndSync(note.getId());
notifyNotesChanged();
getNoteServerSyncHelper().scheduleSync(true);
}
/**
* Get a single Note by ID
*

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/accounts_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="0dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_account_choose" />

View file

@ -0,0 +1,32 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/accountLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:padding="16dp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/accountItemAvatar"
android:layout_width="44dp"
android:layout_height="44dp"
android:padding="10dp"
android:scaleType="center"
android:focusable="false"
app:srcCompat="@drawable/ic_account_circle_grey_24dp"
android:contentDescription="@null" />
<TextView
android:id="@+id/accountItemLabel"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:ellipsize="middle"
android:singleLine="true"
android:textColor="@color/fg_default"
android:textAppearance="@style/NavigationItem"
tools:hint="Username"/>
</LinearLayout>

View file

@ -29,16 +29,22 @@
android:title="@string/menu_share"
app:showAsAction="never"
app:actionProviderClass="androidx.appcompat.widget.ShareActionProvider" />
<item
android:id="@+id/menu_move"
android:icon="@drawable/ic_send_white_24dp"
android:orderInCategory="120"
android:title="@string/simple_move"
app:showAsAction="never" />
<item
android:id="@+id/menu_cancel"
android:icon="@drawable/ic_clear_white_24dp"
android:orderInCategory="120"
android:title="@string/simple_cancel"
android:orderInCategory="130"
android:title="@android:string/cancel"
app:showAsAction="never" />
<item
android:id="@+id/menu_delete"
android:icon="@drawable/ic_delete_white_24dp"
android:orderInCategory="130"
android:orderInCategory="140"
android:title="@string/menu_delete"
app:showAsAction="never" />

View file

@ -138,6 +138,7 @@
<string name="no_notes_yet_description">Press + button to create a new note</string>
<string name="could_not_load_preview_two_digit_numbered_list">Could not load preview. Please check whether there is a two-digit numbered list item without content.</string>
<string name="simple_more">More</string>
<string name="simple_move">Move</string>
<!-- Array: note modes -->
<string-array name="noteMode_entries">