Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: external sticker cache #29

Merged
merged 5 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@

import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.ui.PinnedStickerHelper;
import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper;

@SuppressWarnings("unchecked")
public class MediaDataController extends BaseController {
Expand Down Expand Up @@ -1952,6 +1953,9 @@ public void addNewStickerSet(TLRPC.TL_messages_stickerSet set) {
loadHash[type] = calcStickersHash(stickerSets[type]);
getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);
loadStickers(type, false, true);

// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.cacheStickers();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (llm): Consider the impact of invoking cacheStickers method synchronously here. If this operation is I/O intensive or time-consuming, it might be beneficial to run it in a separate thread or use an asynchronous approach to avoid blocking the main thread.

}

public void loadFeaturedStickers(boolean emoji, boolean cache, boolean force) {
Expand Down Expand Up @@ -2722,6 +2726,9 @@ public void loadStickers(int type, boolean cache, boolean force, boolean schedul
}));
}
}

// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.cacheStickers();
}

private void putStickersToCache(int type, ArrayList<TLRPC.TL_messages_stickerSet> stickers, int date, long hash) {
Expand Down Expand Up @@ -2757,6 +2764,9 @@ private void putStickersToCache(int type, ArrayList<TLRPC.TL_messages_stickerSet
} catch (Exception e) {
FileLog.e(e);
}

// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.cacheStickers();
});
}

Expand Down Expand Up @@ -2940,6 +2950,8 @@ private void processLoadedStickers(int type, ArrayList<TLRPC.TL_messages_sticker
onFinish.run();
}
}
// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.onCacheStickers(type, res, ApplicationLoader.applicationContext);
omg-xtao marked this conversation as resolved.
Show resolved Hide resolved
} else if (!cache) {
AndroidUtilities.runOnUIThread(() -> loadDate[type] = date);
putStickersToCache(type, null, date, 0);
Expand Down Expand Up @@ -3115,6 +3127,9 @@ public void toggleStickerSet(Context context, TLObject stickerSetObject, int tog
}

getNotificationCenter().postNotificationName(NotificationCenter.stickersDidLoad, type, true);

// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.cacheStickers();
}

public void removeMultipleStickerSets(Context context, BaseFragment fragment, ArrayList<TLRPC.TL_messages_stickerSet> sets) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.telegram.ui.Cells.StickerEmojiCell;
import org.telegram.ui.Cells.StickerSetNameCell;
import org.telegram.ui.ContentPreviewViewer;
import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -1165,6 +1166,9 @@ private void updateStickerTabs() {
stickersTab.onPageScrolled(lastPosition, lastPosition);
}
checkPanels();

// Na: [ExternalStickerCache] cache sticker sets
ExternalStickerCacheHelper.cacheStickers();
}

private void checkPanels() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@

import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.utils.ProxyUtil;
import xyz.nextalone.nagram.NaConfig;
import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper;

public class StickersAlert extends BottomSheet implements NotificationCenter.NotificationCenterDelegate {

Expand Down Expand Up @@ -160,6 +162,8 @@ public interface StickersAlertCustomButtonDelegate {
public boolean probablyEmojis;

private int menu_archive = 4;
private int menu_refreshExternalCache = 5;
private int menu_deleteExternalCache = 6;

private TLRPC.TL_messages_stickerSet stickerSet;
private TLRPC.Document selectedSticker;
Expand Down Expand Up @@ -865,6 +869,10 @@ public void requestLayout() {
optionsButton.addSubItem(2, R.drawable.msg_link, LocaleController.getString("CopyLink", R.string.CopyLink));
optionsButton.addSubItem(3, R.drawable.msg_qrcode, LocaleController.getString("ShareQRCode", R.string.ShareQRCode));
optionsButton.addSubItem(menu_archive, R.drawable.msg_archive, LocaleController.getString("Archive", R.string.Archive));
if (!NaConfig.INSTANCE.getExternalStickerCache().String().isBlank()) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (llm): The method call String() on getExternalStickerCache() seems unusual. Verify that String() is the correct method to call for checking if the external sticker cache configuration is not blank.

optionsButton.addSubItem(menu_refreshExternalCache, R.drawable.menu_views_reposts, LocaleController.getString(R.string.ExternalStickerCacheRefresh));
optionsButton.addSubItem(menu_deleteExternalCache, R.drawable.msg_delete, LocaleController.getString(R.string.ExternalStickerCacheDelete));
}

optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu());
optionsButton.setDelegate(this::onSubItemClick);
Expand Down Expand Up @@ -1092,6 +1100,12 @@ protected void onSend(LongSparseArray<TLRPC.Dialog> dids, int count, TLRPC.TL_fo
} else if (id == menu_archive) {
dismiss();
MediaDataController.getInstance(currentAccount).toggleStickerSet(parentActivity, stickerSet, 1, parentFragment, false, true);
} else if (id == menu_refreshExternalCache) {
// Na: [ExternalStickerCache] force refresh cache files
ExternalStickerCacheHelper.refreshCacheFiles(stickerSet);
} else if (id == menu_deleteExternalCache) {
// Na: [ExternalStickerCache] delete cache files
ExternalStickerCacheHelper.deleteCacheFiles(stickerSet);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package tw.nekomimi.nekogram.config.cell;

import androidx.recyclerview.widget.RecyclerView;
import org.telegram.ui.Cells.TextCheckCell;
import tw.nekomimi.nekogram.config.CellGroup;

import java.util.function.Consumer;

public class ConfigCellAutoTextCheck extends AbstractConfigCell {
private final Consumer<Boolean> onClick;
private final String title;
private String subtitle = null;
private final String subtitleFallback;
private boolean enabled = true;
public TextCheckCell cell;

public ConfigCellAutoTextCheck(String title, String subtitleFallback, Consumer<Boolean> onClick) {
this.title = title;
this.subtitleFallback = subtitleFallback;
this.onClick = onClick;
}

public ConfigCellAutoTextCheck(String title, Consumer<Boolean> onClick) {
this(title, null, onClick);
}

public int getType() {
return CellGroup.ITEM_TYPE_TEXT_CHECK;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
if (this.cell != null)
this.cell.setEnabled(this.enabled);
}

public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
boolean checked = true;
if (subtitle == null || subtitle.isBlank()) {
subtitle = subtitleFallback;
checked = false;
}
if (cell != null) {
if (subtitle == null) {
cell.setTextAndCheck(title, checked, cellGroup.needSetDivider(this));
} else {
cell.setTextAndValueAndCheck(title, subtitle, checked, true, cellGroup.needSetDivider(this));
}
}
}

public void onBindViewHolder(RecyclerView.ViewHolder holder) {
TextCheckCell cell = (TextCheckCell) holder.itemView;
this.cell = cell;
setSubtitle(subtitle);
cell.setEnabled(enabled, null);
}

public void onClick() {
if (enabled) {
if (onClick != null) onClick.accept(cell.isChecked());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.EmptyCell;
Expand Down Expand Up @@ -60,6 +61,7 @@
import tw.nekomimi.nekogram.config.cell.AbstractConfigCell;
import tw.nekomimi.nekogram.config.cell.*;
import xyz.nextalone.nagram.NaConfig;
import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper;

@SuppressLint("RtlHardcoded")
public class NekoExperimentalSettingsActivity extends BaseNekoXSettingsActivity {
Expand Down Expand Up @@ -102,10 +104,33 @@ public class NekoExperimentalSettingsActivity extends BaseNekoXSettingsActivity
private final AbstractConfigCell customArtworkApiRow = cellGroup.appendCell(new ConfigCellTextInput(null, NaConfig.INSTANCE.getCustomArtworkApi(), "", null));
private final AbstractConfigCell fakeHighPerformanceDeviceRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getFakeHighPerformanceDevice()));
private final AbstractConfigCell disableEmojiDrawLimitRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getDisableEmojiDrawLimit()));
private final AbstractConfigCell externalStickerCacheRow = cellGroup.appendCell(new ConfigCellAutoTextCheck(
LocaleController.getString(R.string.ExternalStickerCache), LocaleController.getString(R.string.ExternalStickerCacheHint), this::onExternalStickerCacheButtonClick));
private final AbstractConfigCell divider1 = cellGroup.appendCell(new ConfigCellDivider());

private UndoView tooltip;

private static final int INTENT_PICK_CUSTOM_EMOJI_PACK = 114;
private static final int INTENT_PICK_EXTERNAL_STICKER_DIRECTORY = 514;

private void refreshExternalStickerStorageState() {
ConfigCellAutoTextCheck cell = (ConfigCellAutoTextCheck) externalStickerCacheRow;
Context context = ApplicationLoader.applicationContext;
ExternalStickerCacheHelper.checkUri(cell, context);
}

private void onExternalStickerCacheButtonClick(boolean isChecked) {
if (isChecked) {
// clear config
ConfigCellAutoTextCheck cell = (ConfigCellAutoTextCheck) externalStickerCacheRow;
cell.setSubtitle(null);
NaConfig.INSTANCE.getExternalStickerCache().setConfigString("");
} else {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, INTENT_PICK_EXTERNAL_STICKER_DIRECTORY);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (llm): It's good practice to handle the potential ActivityNotFoundException that might be thrown if no app can handle the ACTION_OPEN_DOCUMENT_TREE intent.

}
}

@Override
public boolean onFragmentCreate() {
super.onFragmentCreate();
Expand Down Expand Up @@ -133,6 +158,8 @@ public void onItemClick(int id) {
}
});

refreshExternalStickerStorageState(); // Cell (externalStickerCacheRow): Refresh state
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (llm): Consider moving the call to refreshExternalStickerStorageState to a more appropriate lifecycle method if onFragmentCreate is not the best place to refresh the state, ensuring that the state is refreshed at the correct time.


listAdapter = new ListAdapter(context);

fragmentView = new FrameLayout(context);
Expand All @@ -154,6 +181,8 @@ public void onItemClick(int id) {
((ConfigCellSelectBox) a).onClick(view);
} else if (a instanceof ConfigCellTextInput) {
((ConfigCellTextInput) a).onClick();
} else if (a instanceof ConfigCellAutoTextCheck) {
((ConfigCellAutoTextCheck) a).onClick();
} else if (a instanceof ConfigCellTextDetail) {
RecyclerListView.OnItemClickListener o = ((ConfigCellTextDetail) a).onItemClickListener;
if (o != null) {
Expand Down Expand Up @@ -251,7 +280,7 @@ public void onItemClick(int id) {
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/zip");
Activity act = getParentActivity();
act.startActivityFromChild(act, intent, 114);
act.startActivityFromChild(act, intent, INTENT_PICK_CUSTOM_EMOJI_PACK);
}
};

Expand All @@ -266,7 +295,7 @@ public void onItemClick(int id) {

@Override
public void onActivityResultFragment(int requestCode, int resultCode, Intent data) {
if (requestCode == 114 && resultCode == Activity.RESULT_OK) {
if (requestCode == INTENT_PICK_CUSTOM_EMOJI_PACK && resultCode == Activity.RESULT_OK) {
try {
// copy emoji zip
Uri uri = data.getData();
Expand Down Expand Up @@ -299,6 +328,15 @@ public void onActivityResultFragment(int requestCode, int resultCode, Intent dat
}
tooltip.showWithAction(0, UndoView.ACTION_NEED_RESATRT, null, null);
// listAdapter.notifyItemChanged(cellGroup.rows.indexOf(useCustomEmojiRow));
} else if (requestCode == INTENT_PICK_EXTERNAL_STICKER_DIRECTORY && resultCode == Activity.RESULT_OK) {
Uri uri = data.getData();
// reserve permissions
int takeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
ApplicationLoader.applicationContext.getContentResolver().takePersistableUriPermission(uri, takeFlags);
// save config
NaConfig.INSTANCE.setExternalStickerCacheUri(uri);
refreshExternalStickerStorageState();
tooltip.showWithAction(0, UndoView.ACTION_NEED_RESATRT, null, null);
}
}

Expand Down
10 changes: 10 additions & 0 deletions TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/NaConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package xyz.nextalone.nagram

import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.util.Base64
import org.telegram.messenger.ApplicationLoader
import org.telegram.messenger.LocaleController
Expand Down Expand Up @@ -478,6 +479,15 @@ object NaConfig {
ConfigItem.configTypeBool,
false
)
val externalStickerCache =
addConfig(
"ExternalStickerCache",
ConfigItem.configTypeString,
""
)
var externalStickerCacheUri: Uri?
get() = externalStickerCache.String().let { if (it.isBlank()) return null else return Uri.parse(it) }
set(value) = externalStickerCache.setConfigString(value.toString())

private fun addConfig(
k: String,
Expand Down
Loading