-
Notifications
You must be signed in to change notification settings - Fork 77
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
Changes from all commits
361b21f
2bee97e
5500352
a102cd6
4103863
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
|
||
|
@@ -160,6 +162,8 @@ public interface StickersAlertCustomButtonDelegate { | |
public boolean probablyEmojis; | ||
|
||
private int menu_archive = 4; | ||
private final int menuRefreshExternalCache = 100; | ||
private final int menuDeleteExternalCache = 101; | ||
|
||
private TLRPC.TL_messages_stickerSet stickerSet; | ||
private TLRPC.Document selectedSticker; | ||
|
@@ -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()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question (llm): The method call |
||
optionsButton.addSubItem(menuRefreshExternalCache, R.drawable.menu_views_reposts, LocaleController.getString(R.string.ExternalStickerCacheRefresh)); | ||
optionsButton.addSubItem(menuDeleteExternalCache, R.drawable.msg_delete, LocaleController.getString(R.string.ExternalStickerCacheDelete)); | ||
} | ||
|
||
optionsButton.setOnClickListener(v -> optionsButton.toggleSubMenu()); | ||
optionsButton.setDelegate(this::onSubItemClick); | ||
|
@@ -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 == menuRefreshExternalCache) { | ||
// Na: [ExternalStickerCache] force refresh cache files | ||
ExternalStickerCacheHelper.refreshCacheFiles(stickerSet); | ||
} else if (id == menuDeleteExternalCache) { | ||
// Na: [ExternalStickerCache] delete cache files | ||
ExternalStickerCacheHelper.deleteCacheFiles(stickerSet); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package tw.nekomimi.nekogram.config.cell; | ||
|
||
import androidx.recyclerview.widget.RecyclerView; | ||
|
||
import org.telegram.messenger.LocaleController; | ||
import org.telegram.ui.Cells.TextCheckCell; | ||
import tw.nekomimi.nekogram.config.CellGroup; | ||
import tw.nekomimi.nekogram.config.ConfigItem; | ||
|
||
import java.util.function.Consumer; | ||
|
||
public class ConfigCellAutoTextCheck extends AbstractConfigCell { | ||
private final ConfigItem bindConfig; | ||
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(ConfigItem bindConfig, String subtitleFallback, Consumer<Boolean> onClick) { | ||
this.bindConfig = bindConfig; | ||
this.title = LocaleController.getString(bindConfig.getKey()); | ||
this.subtitleFallback = subtitleFallback; | ||
this.onClick = onClick; | ||
} | ||
|
||
public int getType() { | ||
return CellGroup.ITEM_TYPE_TEXT_CHECK; | ||
} | ||
|
||
public String getKey() { | ||
return bindConfig == null ? null : bindConfig.getKey(); | ||
} | ||
|
||
public ConfigItem getBindConfig() { | ||
return bindConfig; | ||
} | ||
|
||
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 |
---|---|---|
|
@@ -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; | ||
|
@@ -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 { | ||
|
@@ -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( | ||
NaConfig.INSTANCE.getExternalStickerCache(), 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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(); | ||
|
@@ -133,6 +158,8 @@ public void onItemClick(int id) { | |
} | ||
}); | ||
|
||
refreshExternalStickerStorageState(); // Cell (externalStickerCacheRow): Refresh state | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (llm): Consider moving the call to |
||
|
||
listAdapter = new ListAdapter(context); | ||
|
||
fragmentView = new FrameLayout(context); | ||
|
@@ -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) { | ||
|
@@ -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); | ||
} | ||
}; | ||
|
||
|
@@ -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(); | ||
|
@@ -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); | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
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.