From 866aa3260483e7db0082f8c03e9b924dbb5736b3 Mon Sep 17 00:00:00 2001 From: proninyaroslav Date: Thu, 3 Mar 2022 12:36:10 +0300 Subject: Add remove/rename folder dialog Signed-off-by: Yaroslav Pronin --- .../FolderOptionsDialogFragment.java | 235 +++++++++++++++++++++ .../owncloudnewsreader/NewsReaderListActivity.java | 13 ++ .../database/DatabaseConnectionOrm.java | 13 ++ .../luhmer/owncloudnewsreader/di/AppComponent.java | 2 + .../reader/nextcloud/NewsAPI.java | 6 + 5 files changed, 269 insertions(+) create mode 100644 News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/FolderOptionsDialogFragment.java (limited to 'News-Android-App/src/main/java/de/luhmer') diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/FolderOptionsDialogFragment.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/FolderOptionsDialogFragment.java new file mode 100644 index 00000000..26836daa --- /dev/null +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/FolderOptionsDialogFragment.java @@ -0,0 +1,235 @@ +package de.luhmer.owncloudnewsreader; + +import android.animation.AnimatorListenerAdapter; +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.Toast; + +import androidx.fragment.app.DialogFragment; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.inject.Inject; + +import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm; +import de.luhmer.owncloudnewsreader.database.model.Feed; +import de.luhmer.owncloudnewsreader.databinding.FragmentDialogFolderoptionsBinding; +import de.luhmer.owncloudnewsreader.di.ApiProvider; +import de.luhmer.owncloudnewsreader.reader.nextcloud.NewsAPI; +import io.reactivex.Completable; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.annotations.NonNull; +import io.reactivex.schedulers.Schedulers; + + +public class FolderOptionsDialogFragment extends DialogFragment { + + protected @Inject ApiProvider mApi; + + private long mFolderId; + private String mDialogTitle; + + private LinkedHashMap mMenuItems; + private NewsReaderListActivity parentActivity; + + protected FragmentDialogFolderoptionsBinding binding; + + + static FolderOptionsDialogFragment newInstance(long folderId, String dialogTitle) { + FolderOptionsDialogFragment f = new FolderOptionsDialogFragment(); + + Bundle args = new Bundle(); + args.putLong("folderid", folderId); + args.putString("title", dialogTitle); + + f.setArguments(args); + return f; + } + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ((NewsReaderApplication) requireActivity().getApplication()).getAppComponent().injectFragment(this); + + final Bundle args = requireArguments(); + mFolderId = args.getLong("folderid"); + mDialogTitle = args.getString("title"); + mMenuItems = new LinkedHashMap<>(); + + mMenuItems.put(getString(R.string.action_folder_rename), () -> showRenameFolderView(mFolderId, mDialogTitle)); + + mMenuItems.put(getString(R.string.action_folder_remove), () -> showRemoveFolderView(mFolderId)); + + setStyle(DialogFragment.STYLE_NO_TITLE, R.style.FloatingDialog); + } + + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + binding = FragmentDialogFolderoptionsBinding.inflate(inflater, container, false); + + binding.tvMenuTitle.setText(mDialogTitle); + + List menuItemsList = new ArrayList<>(mMenuItems.keySet()); + + final ArrayAdapter arrayAdapter = new ArrayAdapter<>( + getActivity(), + R.layout.fragment_dialog_listviewitem, + menuItemsList); + + binding.lvMenuList.setAdapter(arrayAdapter); + + binding.lvMenuList.setOnItemClickListener((adapterView, view, i, l) -> { + String key = arrayAdapter.getItem(i); + MenuAction mAction = mMenuItems.get(key); + mAction.execute(); + }); + return binding.getRoot(); + } + + + public void setActivity(Activity parentActivity) { + this.parentActivity = (NewsReaderListActivity)parentActivity; + } + + + public void showProgress(final boolean show) { + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + binding.renameFolderDialog.setVisibility(show ? View.GONE : View.VISIBLE); + binding.renameFolderDialog.setVisibility(show ? View.GONE : View.VISIBLE); + + binding.progressView.setVisibility(show ? View.VISIBLE : View.GONE); + binding.progressView.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + }); + } + + + private void showRenameFolderView(final long folderId, final String folderName) { + binding.renamefolderFoldername.setText(folderName); + binding.buttonRenameConfirm.setEnabled(false); + + binding.lvMenuList.setVisibility(View.GONE); + binding.renameFolderDialog.setVisibility(View.VISIBLE); + + binding.renamefolderFoldername.addTextChangedListener(new TextWatcher() { + @Override + public void afterTextChanged(Editable s) {} + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + binding.buttonRenameConfirm.setEnabled( + !s.toString().equals(folderName) && s.length() != 0); + } + }); + + binding.buttonRenameCancel.setOnClickListener(v -> dismiss()); + + binding.buttonRenameConfirm.setOnClickListener(v -> { + showProgress(true); + setCancelable(false); + getDialog().setCanceledOnTouchOutside(false); + + + Map paramMap = new LinkedHashMap<>(); + paramMap.put("name", binding.renamefolderFoldername.getText().toString()); + mApi.getNewsAPI().renameFolder(folderId, paramMap) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(() -> { + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getContext()); + dbConn.renameFolderById(folderId, binding.renamefolderFoldername.getText().toString()); + + parentActivity.getSlidingListFragment().reloadAdapter(); + parentActivity.startSync(); + dismiss(); + }, throwable -> { + Context context = getContext(); + if (context == null) { + return; + } + Toast.makeText(context.getApplicationContext(), getString(R.string.login_dialog_text_something_went_wrong) + " - " + throwable.getMessage(), Toast.LENGTH_LONG).show(); + dismiss(); + }); + }); + } + + + private void showRemoveFolderView(final long folderId) { + binding.lvMenuList.setVisibility(View.GONE); + binding.removeFolderDialog.setVisibility(View.VISIBLE); + + binding.buttonRemoveCancel.setOnClickListener(v -> dismiss()); + + binding.buttonRemoveConfirm.setOnClickListener(v -> { + showProgress(true); + setCancelable(false); + getDialog().setCanceledOnTouchOutside(false); + + NewsAPI newsApi = mApi.getNewsAPI(); + Observable deleteFeedsTask = newsApi.feeds() + .subscribeOn(Schedulers.newThread()) + .flatMap(feedList -> Observable.fromIterable(feedList) + .filter(feed -> folderId == feed.getFolderId()) + ) + .flatMap(feed -> newsApi.deleteFeed(feed.getId()) + .andThen(Observable.just(feed)) + ) + .observeOn(AndroidSchedulers.mainThread()) + .doOnNext(feed -> { + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getContext()); + dbConn.removeFeedById(feed.getId()); + + Long currentFeedId = parentActivity.getNewsReaderDetailFragment().getIdFeed(); + if(currentFeedId != null && currentFeedId == feed.getId()) { + parentActivity.switchToAllUnreadItemsFolder(); + } + }); + Completable.fromObservable(deleteFeedsTask) + .observeOn(Schedulers.newThread()) + .andThen(newsApi.deleteFolder(folderId)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(() -> { + DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(getContext()); + dbConn.removeFolderById(folderId); + + Long currentFolderId = parentActivity.getNewsReaderDetailFragment().getIdFolder(); + if(currentFolderId != null && currentFolderId == folderId) { + parentActivity.switchToAllUnreadItemsFolder(); + } + parentActivity.getSlidingListFragment().reloadAdapter(); + parentActivity.updateCurrentRssView(); + dismiss(); + }, throwable -> { + Context context = getContext(); + if (context == null) { + return; + } + Toast.makeText(context.getApplicationContext(), getString(R.string.login_dialog_text_something_went_wrong) + " - " + throwable.getMessage(), Toast.LENGTH_LONG).show(); + dismiss(); + }); + }); + } + + interface MenuAction { + void execute(); + } +} diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java index a3791ca4..96c393e0 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/NewsReaderListActivity.java @@ -619,6 +619,19 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements NewsReaderListDialogFragment fragment = NewsReaderListDialogFragment.newInstance(idFeed, titel, iconurl, feedurl); fragment.setActivity(this); fragment.show(ft, "news_reader_list_dialog"); + } else { + String label = dbConn.getFolderById(idFeed).getLabel(); + + FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); + Fragment prev = getSupportFragmentManager().findFragmentByTag("folder_options_dialog"); + if (prev != null) { + ft.remove(prev); + } + ft.addToBackStack(null); + + FolderOptionsDialogFragment fragment = FolderOptionsDialogFragment.newInstance(idFeed, label); + fragment.setActivity(this); + fragment.show(ft, "folder_options_dialog"); } } diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java index 0a92cb29..c05c85e8 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/database/DatabaseConnectionOrm.java @@ -475,6 +475,19 @@ public class DatabaseConnectionOrm { return daoSession.getRssItemDao().queryRawCreate(where_clause).listLazy(); } + /** + * Removes only the folder, without removing feeds inside the folder + */ + public void removeFolderById(final long folderId) { + daoSession.getFolderDao().deleteByKey(folderId); + } + + public void renameFolderById(long folderId, String newLabel) { + Folder folder = daoSession.getFolderDao().queryBuilder().where(FolderDao.Properties.Id.eq(folderId)).unique(); + folder.setLabel(newLabel); + daoSession.getFolderDao().update(folder); + } + /* public void markAllItemsAsReadForCurrentView() { diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/di/AppComponent.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/di/AppComponent.java index 5a071604..d7a2d8db 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/di/AppComponent.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/di/AppComponent.java @@ -3,6 +3,7 @@ package de.luhmer.owncloudnewsreader.di; import javax.inject.Singleton; import dagger.Component; +import de.luhmer.owncloudnewsreader.FolderOptionsDialogFragment; import de.luhmer.owncloudnewsreader.LoginDialogActivity; import de.luhmer.owncloudnewsreader.NewFeedActivity; import de.luhmer.owncloudnewsreader.NewsDetailActivity; @@ -39,6 +40,7 @@ public interface AppComponent { void injectFragment(SettingsFragment fragment); void injectFragment(NewsDetailFragment fragment); void injectFragment(NewsReaderDetailFragment fragment); + void injectFragment(FolderOptionsDialogFragment fragment); void injectService(SyncItemStateService service); void injectService(OwnCloudSyncAdapter ownCloudSyncAdapter); diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/NewsAPI.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/NewsAPI.java index 60de7ae2..9c3f1351 100644 --- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/NewsAPI.java +++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/reader/nextcloud/NewsAPI.java @@ -57,6 +57,9 @@ public interface NewsAPI { @PUT("feeds/{feedId}/rename") Completable renameFeed(@Path("feedId") long feedId, @Body Map paramMap); + @PUT("folders/{folderId}") + Completable renameFolder(@Path("folderId") long folderId, @Body Map paramMap); + @PUT("feeds/{feedId}/move") Completable moveFeed(@Path("feedId") long feedId, @Body Map folderIdMap); @@ -65,6 +68,9 @@ public interface NewsAPI { @DELETE("feeds/{feedId}") Completable deleteFeed(@Path("feedId") long feedId); + @DELETE("folders/{folderId}") + Completable deleteFolder(@Path("folderId") long folderId); + /** ITEMS **/ @GET("items") -- cgit v1.2.3