Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ec098f98 authored by 2bllw8's avatar 2bllw8 Committed by Michael W
Browse files

Recorder: Add delete selected list items

Change-Id: Iac36d4d2acef8ab526ab65a1b9b92205e75f32b3
parent cf7e9812
Loading
Loading
Loading
Loading
+60 −7
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package org.lineageos.recorder;

import android.net.Uri;
import android.os.Bundle;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -34,8 +35,9 @@ import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import org.lineageos.recorder.list.ListActionModeCallback;
import org.lineageos.recorder.list.RecordingData;
import org.lineageos.recorder.list.RecordingItemCallbacks;
import org.lineageos.recorder.list.RecordingListCallbacks;
import org.lineageos.recorder.list.RecordingsAdapter;
import org.lineageos.recorder.utils.LastRecordHelper;
import org.lineageos.recorder.utils.MediaProviderHelper;
@@ -44,15 +46,18 @@ import org.lineageos.recorder.utils.Utils;
import java.util.ArrayList;
import java.util.List;

public class ListActivity extends AppCompatActivity implements RecordingItemCallbacks {
public class ListActivity extends AppCompatActivity implements RecordingListCallbacks {
    private static final String TYPE_AUDIO = "audio/*";

    private RecordingsAdapter mAdapter;

    private Toolbar mToolbar;
    private RecyclerView mListView;
    private ProgressBar mProgressBar;
    private TextView mEmptyText;

    private ActionMode mActionMode;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
@@ -60,12 +65,12 @@ public class ListActivity extends AppCompatActivity implements RecordingItemCall
        setContentView(R.layout.activity_list);

        final CoordinatorLayout coordinatorLayout = findViewById(R.id.coordinator);
        final Toolbar toolbar = findViewById(R.id.toolbar);
        mToolbar = findViewById(R.id.toolbar);
        mListView = findViewById(R.id.list_view);
        mProgressBar = findViewById(R.id.list_loading);
        mEmptyText = findViewById(R.id.list_empty);

        setSupportActionBar(toolbar);
        setSupportActionBar(mToolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayShowHomeEnabled(true);
@@ -79,6 +84,7 @@ public class ListActivity extends AppCompatActivity implements RecordingItemCall
                super.onItemRangeRemoved(positionStart, itemCount);
                if (mAdapter.getItemCount() == 0) {
                    changeEmptyView(true);
                    endSelectionMode();
                }
            }

@@ -142,14 +148,16 @@ public class ListActivity extends AppCompatActivity implements RecordingItemCall

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem item = menu.findItem(R.id.action_delete_all);
        item.setEnabled(mAdapter.getItemCount() > 0);
        MenuItem deleteAllItem = menu.findItem(R.id.action_delete_all);
        boolean hasItems = mAdapter.getItemCount() > 0;
        deleteAllItem.setEnabled(hasItems);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.action_delete_all) {
        int id = item.getItemId();
        if (id == R.id.action_delete_all) {
            deleteAllRecordings();
            return true;
        } else {
@@ -157,6 +165,31 @@ public class ListActivity extends AppCompatActivity implements RecordingItemCall
        }
    }

    @Override
    public void startSelectionMode() {
        // Clear previous (should do nothing), but be sure
        endSelectionMode();
        // Start action mode
        mActionMode = mToolbar.startActionMode(new ListActionModeCallback(
                this::deleteSelectedRecordings));
        mAdapter.enterSelectionMode();
    }

    @Override
    public void endSelectionMode() {
        if (mActionMode != null) {
            mActionMode.finish();
            mActionMode = null;
        }
        mAdapter.exitSelectionMode();
    }

    @Override
    public void onActionModeFinished(@NonNull ActionMode mode) {
        super.onActionModeFinished(mode);
        endSelectionMode();
    }

    private void loadRecordings() {
        MediaProviderHelper.requestMyRecordings(getContentResolver(), list -> {
            mProgressBar.setVisibility(View.GONE);
@@ -169,6 +202,26 @@ public class ListActivity extends AppCompatActivity implements RecordingItemCall
        mListView.setVisibility(isEmpty ? View.GONE : View.VISIBLE);
    }

    private void deleteSelectedRecordings() {
        final List<RecordingData> selectedItems = mAdapter.getSelected();
        if (selectedItems.isEmpty()) {
            return;
        }

        new AlertDialog.Builder(this)
                .setTitle(R.string.delete_selected_title)
                .setMessage(getString(R.string.delete_selected_message))
                .setPositiveButton(R.string.delete, (dialog, which) -> {
                    selectedItems.forEach(item -> {
                        MediaProviderHelper.remove(this, item.getUri());
                        mAdapter.onDelete(item);
                    });
                    Utils.cancelShareNotification(this);
                })
                .setNegativeButton(R.string.cancel, null)
                .show();
    }

    private void deleteAllRecordings() {
        final List<RecordingData> items = mAdapter.getData();
        if (items.isEmpty()) {
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.lineageos.recorder.list;

import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import androidx.annotation.NonNull;

import org.lineageos.recorder.R;

public class ListActionModeCallback implements ActionMode.Callback {

    @NonNull
    private final Runnable mDeleteSelected;

    public ListActionModeCallback(@NonNull Runnable deleteSelected) {
        mDeleteSelected = deleteSelected;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        final MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.menu_list_action_mode, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        if (item.getItemId() == R.id.action_delete_selected) {
            mDeleteSelected.run();
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
    }
}
+29 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.lineageos.recorder.list;

import androidx.annotation.IntDef;

@IntDef(value = {
        ListItemStatus.DEFAULT,
        ListItemStatus.UNCHECKED,
        ListItemStatus.CHECKED,
})
public @interface ListItemStatus {
    int DEFAULT = 0;
    int UNCHECKED = 1;
    int CHECKED = 2;
}
+20 −9
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ public class RecordingItemViewHolder extends RecyclerView.ViewHolder {
    private static final String SUMMARY_FORMAT = "%s - %02d:%02d";

    private final SimpleDateFormat mDateFormat;
    private final ImageView mIconView;
    private final TextView mTitleView;
    private final TextView mSummaryView;
    @NonNull
@@ -52,21 +53,15 @@ public class RecordingItemViewHolder extends RecyclerView.ViewHolder {
        mCallbacks = callbacks;

        mDateFormat = dateFormat;
        mIconView = itemView.findViewById(R.id.item_play);
        mTitleView = itemView.findViewById(R.id.item_title);
        mSummaryView = itemView.findViewById(R.id.item_date);
        final ImageView playView = itemView.findViewById(R.id.item_play);
        final ImageView menuView = itemView.findViewById(R.id.item_menu);

        playView.setOnClickListener(v -> mCallbacks.onPlay(mUri));
        menuView.setOnClickListener(this::showPopupMenu);
        itemView.setOnClickListener(v -> mCallbacks.onPlay(mUri));
        itemView.setOnLongClickListener(v -> {
            showPopupMenu(menuView);
            return true;
        });
    }

    public void setData(@NonNull RecordingData data) {
    public void setData(@NonNull RecordingData data,
                        @ListItemStatus int selection) {
        mUri = data.getUri();
        mTitleView.setText(data.getTitle());
        long seconds = data.getDuration() / 1000;
@@ -74,6 +69,22 @@ public class RecordingItemViewHolder extends RecyclerView.ViewHolder {
        seconds -= (minutes * 60);
        mSummaryView.setText(String.format(Locale.getDefault(), SUMMARY_FORMAT,
                mDateFormat.format(data.getDate()), minutes, seconds));

        switch (selection) {
            case ListItemStatus.DEFAULT:
                mIconView.setImageResource(R.drawable.ic_play_circle_outline);
                break;
            case ListItemStatus.UNCHECKED:
                mIconView.setImageResource(R.drawable.ic_list_unchecked);
                break;
            case ListItemStatus.CHECKED:
                mIconView.setImageResource(R.drawable.ic_list_checked);
                break;
        }
    }

    public Uri getUri() {
        return mUri;
    }

    @SuppressLint("RestrictedApi")
+21 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.lineageos.recorder.list;

public interface RecordingListCallbacks extends RecordingItemCallbacks {
    void startSelectionMode();
    void endSelectionMode();
}
Loading