mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-22 01:40:07 +01:00
Add the ability to re-order sticker packs.
This commit is contained in:
@@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.MenuItem;
|
||||
@@ -12,6 +13,7 @@ import android.view.MenuItem;
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.ShareActivity;
|
||||
import org.thoughtcrime.securesms.logging.Log;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
|
||||
@@ -22,9 +24,8 @@ public final class StickerManagementActivity extends PassphraseRequiredActionBar
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicTheme();
|
||||
|
||||
private RecyclerView list;
|
||||
private StickerManagementAdapter adapter;
|
||||
|
||||
private RecyclerView list;
|
||||
private StickerManagementAdapter adapter;
|
||||
private StickerManagementViewModel viewModel;
|
||||
|
||||
public static Intent getIntent(@NonNull Context context) {
|
||||
@@ -96,6 +97,7 @@ public final class StickerManagementActivity extends PassphraseRequiredActionBar
|
||||
|
||||
list.setLayoutManager(new LinearLayoutManager(this));
|
||||
list.setAdapter(adapter);
|
||||
new ItemTouchHelper(new StickerManagementItemTouchHelper(new ItemTouchCallback())).attachToRecyclerView(list);
|
||||
}
|
||||
|
||||
private void initToolbar() {
|
||||
@@ -114,4 +116,21 @@ public final class StickerManagementActivity extends PassphraseRequiredActionBar
|
||||
adapter.setPackLists(packResult.getInstalledPacks(), packResult.getAvailablePacks(), packResult.getBlessedPacks());
|
||||
});
|
||||
}
|
||||
|
||||
private class ItemTouchCallback implements StickerManagementItemTouchHelper.Callback {
|
||||
@Override
|
||||
public boolean onMove(int start, int end) {
|
||||
return adapter.onMove(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMovable(int position) {
|
||||
return adapter.isMovable(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMoveCommitted() {
|
||||
viewModel.onOrderChanged(adapter.getInstalledPacksInOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.util.adapter.SectionedRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.util.adapter.StableIdGenerator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String, StickerManagementAdapter.StickerSection> {
|
||||
@@ -93,6 +94,30 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
|
||||
}
|
||||
}
|
||||
|
||||
boolean onMove(int start, int end) {
|
||||
StickerSection installed = sections.get(0);
|
||||
|
||||
if (!installed.isContent(start)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!installed.isContent(end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
installed.swap(start, end);
|
||||
notifyItemMoved(start, end);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isMovable(int position) {
|
||||
return sections.get(0).isContent(position);
|
||||
}
|
||||
|
||||
@NonNull List<StickerPackRecord> getInstalledPacksInOrder() {
|
||||
return sections.get(0).records;
|
||||
}
|
||||
|
||||
void setPackLists(@NonNull List<StickerPackRecord> installedPacks,
|
||||
@NonNull List<StickerPackRecord> availablePacks,
|
||||
@NonNull List<StickerPackRecord> blessedPacks)
|
||||
@@ -185,6 +210,21 @@ final class StickerManagementAdapter extends SectionedRecyclerViewAdapter<String
|
||||
((StickerViewHolder) viewHolder).bind(glideRequests, eventListener, records.get(localPosition - 1), localPosition == records.size());
|
||||
}
|
||||
}
|
||||
|
||||
void swap(int start, int end) {
|
||||
int localStart = getLocalPosition(start) - 1;
|
||||
int localEnd = getLocalPosition(end) - 1;
|
||||
|
||||
if (localStart < localEnd) {
|
||||
for (int i = localStart; i < localEnd; i++) {
|
||||
Collections.swap(records, i, i + 1);
|
||||
}
|
||||
} else {
|
||||
for (int i = localStart; i > localEnd; i--) {
|
||||
Collections.swap(records, i, i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class StickerViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.thoughtcrime.securesms.stickers;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class StickerManagementItemTouchHelper extends ItemTouchHelper.Callback {
|
||||
|
||||
private final Callback callback;
|
||||
|
||||
public StickerManagementItemTouchHelper(Callback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
if (callback.isMovable(viewHolder.getAdapterPosition())) {
|
||||
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
|
||||
return makeMovementFlags(dragFlags, 0);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
|
||||
return callback.onMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
|
||||
super.clearView(recyclerView, viewHolder);
|
||||
callback.onMoveCommitted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
/**
|
||||
* @return True if both the start and end positions are valid, and therefore the move will occur.
|
||||
*/
|
||||
boolean onMove(int start, int end);
|
||||
void onMoveCommitted();
|
||||
boolean isMovable(int position);
|
||||
}
|
||||
}
|
||||
@@ -100,6 +100,12 @@ final class StickerManagementRepository {
|
||||
});
|
||||
}
|
||||
|
||||
void setPackOrder(@NonNull List<StickerPackRecord> packsInOrder) {
|
||||
SignalExecutors.SERIAL.execute(() -> {
|
||||
stickerDatabase.updatePackOrder(packsInOrder);
|
||||
});
|
||||
}
|
||||
|
||||
static class PackResult {
|
||||
|
||||
private final List<StickerPackRecord> installedPacks;
|
||||
|
||||
@@ -10,8 +10,12 @@ import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders;
|
||||
import org.thoughtcrime.securesms.database.model.StickerPackRecord;
|
||||
import org.thoughtcrime.securesms.database.model.StickerRecord;
|
||||
import org.thoughtcrime.securesms.stickers.StickerManagementRepository.PackResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
final class StickerManagementViewModel extends ViewModel {
|
||||
|
||||
private final Application application;
|
||||
@@ -56,6 +60,10 @@ final class StickerManagementViewModel extends ViewModel {
|
||||
repository.installStickerPack(packId, packKey, false);
|
||||
}
|
||||
|
||||
void onOrderChanged(List<StickerPackRecord> packsInOrder) {
|
||||
repository.setPackOrder(packsInOrder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCleared() {
|
||||
application.getContentResolver().unregisterContentObserver(observer);
|
||||
|
||||
Reference in New Issue
Block a user