diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 32e8b9c15b..ae7dd8c24b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -1953,9 +1953,6 @@ 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(); } public void loadFeaturedStickers(boolean emoji, boolean cache, boolean force) { @@ -2726,9 +2723,6 @@ public void loadStickers(int type, boolean cache, boolean force, boolean schedul })); } } - - // Na: [ExternalStickerCache] cache sticker sets - ExternalStickerCacheHelper.cacheStickers(); } private void putStickersToCache(int type, ArrayList stickers, int date, long hash) { @@ -2764,9 +2758,6 @@ private void putStickersToCache(int type, ArrayList sets) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java index 456b0abe74..66e20d4097 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java @@ -1166,9 +1166,6 @@ private void updateStickerTabs() { stickersTab.onPageScrolled(lastPosition, lastPosition); } checkPanels(); - - // Na: [ExternalStickerCache] cache sticker sets - ExternalStickerCacheHelper.cacheStickers(); } private void checkPanels() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 793ea1c487..00336cfc1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -231,6 +231,7 @@ import tw.nekomimi.nekogram.utils.ProxyUtil; import tw.nekomimi.nekogram.utils.UIUtil; import xyz.nextalone.nagram.NaConfig; +import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper; public class LaunchActivity extends BasePermissionsActivity implements INavigationLayout.INavigationLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate { public final static String EXTRA_FORCE_NOT_INTERNAL_APPS = "force_not_internal_apps"; @@ -1496,6 +1497,8 @@ private void checkCurrentAccount() { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatSwithcedToForum); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.storiesEnabledUpdate); + // Na: [ExternalStickerCache] remove observers + ExternalStickerCacheHelper.removeNotificationObservers(currentAccount); } currentAccount = UserConfig.selectedAccount; NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); @@ -1518,6 +1521,8 @@ private void checkCurrentAccount() { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.chatSwithcedToForum); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.storiesEnabledUpdate); + // Na: [ExternalStickerCache] add observers + ExternalStickerCacheHelper.addNotificationObservers(currentAccount); } private void checkLayout() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java index 2c53709343..3b53653f63 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -129,6 +129,8 @@ import tw.nekomimi.nekogram.utils.ShareUtil; import tw.nekomimi.nekogram.utils.StickersUtil; import tw.nekomimi.nekogram.utils.UIUtil; +import xyz.nextalone.nagram.NaConfig; +import xyz.nextalone.nagram.helper.ExternalStickerCacheHelper; public class StickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -1721,6 +1723,10 @@ protected void onRemoveButtonClick() { options.add(R.drawable.msg_reorder, LocaleController.getString("StickersReorder", R.string.StickersReorder), () -> processSelectionOption(4, stickerSet)); options.add(R.drawable.msg_share, LocaleController.getString("StickersShare", R.string.StickersShare), () -> processSelectionOption(2, stickerSet)); options.add(R.drawable.msg_delete, LocaleController.getString("StickersRemove", R.string.StickersRemove), true, () -> processSelectionOption(MENU_DELETE, stickerSet)); + if (!NaConfig.INSTANCE.getExternalStickerCache().String().isBlank()) { + options.add(R.drawable.menu_views_reposts, LocaleController.getString(R.string.ExternalStickerCacheRefresh), () -> ExternalStickerCacheHelper.refreshCacheFiles(stickerSet)); + options.add(R.drawable.msg_delete, LocaleController.getString(R.string.ExternalStickerCacheDelete), () -> ExternalStickerCacheHelper.deleteCacheFiles(stickerSet)); + } } options.setMinWidth(190); options.show(); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/ConfigCellText.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/ConfigCellText.java new file mode 100644 index 0000000000..efee40e38e --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/ConfigCellText.java @@ -0,0 +1,58 @@ +package tw.nekomimi.nekogram.config.cell; + +import androidx.recyclerview.widget.RecyclerView; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.Cells.TextSettingsCell; +import tw.nekomimi.nekogram.config.CellGroup; + +public class ConfigCellText extends AbstractConfigCell implements WithKey, WithOnClick { + private final String key; + private final String value; + private final Runnable onClick; + private boolean enabled = true; + private TextSettingsCell cell; + + public ConfigCellText(String key, String customValue, Runnable onClick) { + this.key = key; + this.value = (customValue == null) ? "" : customValue; + this.onClick = onClick; + } + + public ConfigCellText(String key, Runnable onClick) { + this(key, null, onClick); + } + + public int getType() { + return CellGroup.ITEM_TYPE_TEXT_SETTINGS_CELL; + } + + public String getKey() { + return key; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + if (this.cell != null) this.cell.setEnabled(this.enabled); + } + + public void onBindViewHolder(RecyclerView.ViewHolder holder) { + TextSettingsCell cell = (TextSettingsCell) holder.itemView; + this.cell = cell; + String title = LocaleController.getString(key); + cell.setTextAndValue(title, value, cellGroup.needSetDivider(this)); + cell.setEnabled(enabled); + } + + public void onClick() { + if (!enabled) return; + if (onClick != null) { + try { + onClick.run(); + } catch (Exception ignored) {} + } + } +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithKey.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithKey.java new file mode 100644 index 0000000000..b1350f10d9 --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithKey.java @@ -0,0 +1,5 @@ +package tw.nekomimi.nekogram.config.cell; + +public interface WithKey { + String getKey(); +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithOnClick.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithOnClick.java new file mode 100644 index 0000000000..cc3fda14ad --- /dev/null +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/config/cell/WithOnClick.java @@ -0,0 +1,5 @@ +package tw.nekomimi.nekogram.config.cell; + +public interface WithOnClick { + void onClick(); +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/BaseNekoXSettingsActivity.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/BaseNekoXSettingsActivity.java index e475e8357f..cc117130c7 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/BaseNekoXSettingsActivity.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/BaseNekoXSettingsActivity.java @@ -18,13 +18,7 @@ import tw.nekomimi.nekogram.config.CellGroup; import tw.nekomimi.nekogram.config.ConfigItem; -import tw.nekomimi.nekogram.config.cell.AbstractConfigCell; -import tw.nekomimi.nekogram.config.cell.ConfigCellAutoTextCheck; -import tw.nekomimi.nekogram.config.cell.ConfigCellCustom; -import tw.nekomimi.nekogram.config.cell.ConfigCellSelectBox; -import tw.nekomimi.nekogram.config.cell.ConfigCellTextCheck; -import tw.nekomimi.nekogram.config.cell.ConfigCellTextDetail; -import tw.nekomimi.nekogram.config.cell.ConfigCellTextInput; +import tw.nekomimi.nekogram.config.cell.*; public class BaseNekoXSettingsActivity extends BaseFragment { protected BlurredRecyclerView listView; @@ -79,7 +73,9 @@ protected ConfigItem getBindConfig(AbstractConfigCell row) { } protected String getRowKey(AbstractConfigCell row) { - if (row instanceof ConfigCellTextCheck) { + if (row instanceof WithKey) { + return ((WithKey) row).getKey(); + } else if (row instanceof ConfigCellTextCheck) { return ((ConfigCellTextCheck) row).getKey(); } else if (row instanceof ConfigCellSelectBox) { return ((ConfigCellSelectBox) row).getKey(); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java index 8fdafff6fa..40c66c75c6 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java @@ -11,7 +11,6 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; -import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.Toast; @@ -24,11 +23,9 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.R; -import org.telegram.messenger.SharedConfig; 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; @@ -41,7 +38,6 @@ import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BlurredRecyclerView; -import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.UndoView; @@ -49,7 +45,6 @@ import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; -import java.util.Locale; import kotlin.Unit; @@ -104,17 +99,30 @@ 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 divider1 = cellGroup.appendCell(new ConfigCellDivider()); + + private final AbstractConfigCell header3 = cellGroup.appendCell(new ConfigCellHeader(LocaleController.getString(R.string.ExternalStickerCache))); 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 final AbstractConfigCell externalStickerCacheAutoSyncRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getExternalStickerCacheAutoRefresh(), LocaleController.getString(R.string.ExternalStickerCacheAutoRefreshHint))); + private final AbstractConfigCell externalStickerCacheDirNameTypeRow = cellGroup.appendCell(new ConfigCellSelectBox(null, NaConfig.INSTANCE.getExternalStickerCacheDirNameType(), new String[]{ "Short name", "ID" }, null)); + private final AbstractConfigCell externalStickerCacheSyncAllRow = cellGroup.appendCell(new ConfigCellText("ExternalStickerCacheRefreshAll", ExternalStickerCacheHelper::syncAllCaches)); + private final AbstractConfigCell externalStickerCacheDeleteAllRow = cellGroup.appendCell(new ConfigCellText("ExternalStickerCacheDeleteAll", ExternalStickerCacheHelper::deleteAllCaches)); + private final AbstractConfigCell divider2 = 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 setExternalStickerCacheCellsEnabled(boolean enabled) { + ((ConfigCellText) externalStickerCacheSyncAllRow).setEnabled(enabled); + ((ConfigCellText) externalStickerCacheDeleteAllRow).setEnabled(enabled); + } + private void refreshExternalStickerStorageState() { ConfigCellAutoTextCheck cell = (ConfigCellAutoTextCheck) externalStickerCacheRow; + setExternalStickerCacheCellsEnabled(!cell.getBindConfig().String().isEmpty()); Context context = ApplicationLoader.applicationContext; ExternalStickerCacheHelper.checkUri(cell, context); } @@ -122,6 +130,7 @@ private void refreshExternalStickerStorageState() { private void onExternalStickerCacheButtonClick(boolean isChecked) { if (isChecked) { // clear config + setExternalStickerCacheCellsEnabled(false); ConfigCellAutoTextCheck cell = (ConfigCellAutoTextCheck) externalStickerCacheRow; cell.setSubtitle(null); NaConfig.INSTANCE.getExternalStickerCache().setConfigString(""); @@ -179,6 +188,8 @@ public void onItemClick(int id) { ((ConfigCellTextCheck) a).onClick((TextCheckCell) view); } else if (a instanceof ConfigCellSelectBox) { ((ConfigCellSelectBox) a).onClick(view); + } else if (a instanceof WithOnClick) { + ((WithOnClick) a).onClick(); } else if (a instanceof ConfigCellTextInput) { ((ConfigCellTextInput) a).onClick(); } else if (a instanceof ConfigCellAutoTextCheck) { diff --git a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/NaConfig.kt b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/NaConfig.kt index 30b2accfaf..7388aa6c84 100644 --- a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/NaConfig.kt +++ b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/NaConfig.kt @@ -488,6 +488,18 @@ object NaConfig { var externalStickerCacheUri: Uri? get() = externalStickerCache.String().let { if (it.isBlank()) return null else return Uri.parse(it) } set(value) = externalStickerCache.setConfigString(value.toString()) + val externalStickerCacheAutoRefresh = + addConfig( + "ExternalStickerCacheAutoRefresh", + ConfigItem.configTypeBool, + false + ) + val externalStickerCacheDirNameType = + addConfig( + "ExternalStickerCacheDirNameType", + ConfigItem.configTypeInt, + 0 + ) private fun addConfig( k: String, diff --git a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/ExternalStickerCacheHelper.kt b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/ExternalStickerCacheHelper.kt index 1fe6f1ce00..11e7942ea8 100644 --- a/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/ExternalStickerCacheHelper.kt +++ b/TMessagesProj/src/main/kotlin/xyz/nextalone/nagram/helper/ExternalStickerCacheHelper.kt @@ -11,6 +11,8 @@ import org.telegram.messenger.AndroidUtilities import org.telegram.messenger.ApplicationLoader import org.telegram.messenger.LocaleController import org.telegram.messenger.MediaDataController +import org.telegram.messenger.NotificationCenter +import org.telegram.messenger.NotificationCenter.NotificationCenterDelegate import org.telegram.messenger.R import org.telegram.messenger.UserConfig import org.telegram.tgnet.TLRPC.TL_messages_stickerSet @@ -26,31 +28,35 @@ object ExternalStickerCacheHelper { @JvmStatic fun checkUri(configCell: ConfigCellAutoTextCheck, context: Context) { - CoroutineScope(Dispatchers.IO).launch { + async { NaConfig.externalStickerCacheUri?.let { uri -> AndroidUtilities.runOnUIThread { configCell.setSubtitle("Loading...") } - val dir = DocumentFile.fromTreeUri(context, uri) - var subtitle: String - if (dir == null) { - subtitle = "Error: failed to access document" - } else { - if (dir.isDirectory) { - val testFile = dir.findFile("test") ?: dir.createFile("text/plain", "test") - if (testFile == null) { - subtitle = "Error: cannot create file" - } else { - if (testFile.canRead() && testFile.canWrite()) { - subtitle = "Currently using: ${dir.name}" + try { + val dir = DocumentFile.fromTreeUri(context, uri) + val subtitle: String + if (dir == null) { + subtitle = "Error: failed to access document" + } else { + if (dir.isDirectory) { + val nomedia = ".nomedia" + val testFile = dir.findFile(nomedia) ?: dir.createFile("", nomedia) + if (testFile == null) { + subtitle = "Error: cannot create $nomedia" } else { - subtitle = "Error: read/write is not supported" + if (testFile.canRead() && testFile.canWrite()) { + subtitle = "Currently using: ${dir.name}" + } else { + subtitle = "Error: read/write is not supported" + } } - if (!testFile.delete()) subtitle = "Error: cannot delete file" + } else { + subtitle = "Error: not a directory" } - } else { - subtitle = "Error: not a directory" } + AndroidUtilities.runOnUIThread { configCell.setSubtitle(subtitle) } + } catch (e: Exception) { + logException(e, "checking Uri") } - AndroidUtilities.runOnUIThread { configCell.setSubtitle(subtitle) } } } } @@ -59,18 +65,23 @@ object ExternalStickerCacheHelper { private var cacheAgain = false @JvmStatic - fun cacheStickers() { + fun cacheStickers(isAutoSync: Boolean = true) { + if (isAutoSync && !NaConfig.externalStickerCacheAutoRefresh.Bool()) return + if (NaConfig.externalStickerCache.String().isEmpty()) return if (caching) { cacheAgain = true return } - if (NaConfig.externalStickerCache.String().isEmpty()) return - CoroutineScope(Dispatchers.IO).launch { + cacheStickers0(isAutoSync) + } + + private fun cacheStickers0(isAutoSync: Boolean) { + async { caching = true val stickerSets = MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSets(MediaDataController.TYPE_IMAGE) val context = ApplicationLoader.applicationContext try { - val uri = NaConfig.externalStickerCacheUri ?: return@launch + val uri = NaConfig.externalStickerCacheUri ?: return@async val resolver = context.contentResolver DocumentFile.fromTreeUri(context, uri)?.let { dir -> logD("Caching ${stickerSets.size} sticker set(s)...") @@ -80,11 +91,10 @@ object ExternalStickerCacheHelper { forEach { it.name?.let { name -> map[name] = it } } map } - stickerSets.forEach { stickerSetObject -> - val stickerSet = stickerSetObject.set - val stickers = stickerSetObject.documents - val idString = stickerSet.id.toString() - (stickerSetDirMap[idString] ?: dir.createDirectory(idString))?.let { stickerSetDir -> + stickerSets.forEach { set -> + val stickers = set.documents + val setDirName = getStickerDirName(set) + (stickerSetDirMap[setDirName] ?: dir.createDirectory(setDirName))?.let { stickerSetDir -> if (stickerSetDir.isDirectory) { val stickerFileMap = stickerSetDir.listFiles().run { val map = mutableMapOf() @@ -127,6 +137,7 @@ object ExternalStickerCacheHelper { } } } + if (!isAutoSync) showToast(null) } } } catch (e: Exception) { @@ -135,7 +146,7 @@ object ExternalStickerCacheHelper { if (cacheAgain) { delay(30000) cacheAgain = false - cacheStickers() + cacheStickers0(true) } else { caching = false } @@ -144,23 +155,23 @@ object ExternalStickerCacheHelper { @JvmStatic fun refreshCacheFiles(set: TL_messages_stickerSet) { - CoroutineScope(Dispatchers.IO).launch { - val uri = NaConfig.externalStickerCacheUri ?: return@launch + async { + waitForSync() + val uri = NaConfig.externalStickerCacheUri ?: return@async val context = ApplicationLoader.applicationContext try { DocumentFile.fromTreeUri(context, uri)?.let { dir -> - val stickerSet = set.set - val idString = stickerSet.id.toString() - logD("Refreshing cache $idString...") - dir.findFile(idString)?.let { + val setDirName = getStickerDirName(set) + logD("Refreshing cache $setDirName...") + dir.findFile(setDirName)?.let { it.delete() logD("Deleting exist files...") while (true) { + if (dir.findFile(setDirName) == null) break delay(500) - if (dir.findFile(idString) == null) break } } - dir.createDirectory(idString)?.let { stickerSetDir -> + dir.createDirectory(setDirName)?.let { stickerSetDir -> val stickers = set.documents val resolver = context.contentResolver for (sticker in stickers) { @@ -196,14 +207,14 @@ object ExternalStickerCacheHelper { @JvmStatic fun deleteCacheFiles(set: TL_messages_stickerSet) { - CoroutineScope(Dispatchers.IO).launch { - val uri = NaConfig.externalStickerCacheUri ?: return@launch + async { + waitForSync() + val uri = NaConfig.externalStickerCacheUri ?: return@async val context = ApplicationLoader.applicationContext try { DocumentFile.fromTreeUri(context, uri)?.let { dir -> - val stickerSet = set.set - val idString = stickerSet.id.toString() - dir.findFile(idString)?.delete() + val setDirName = getStickerDirName(set) + dir.findFile(setDirName)?.delete() } showToast(null) } catch (e: Exception) { @@ -212,6 +223,56 @@ object ExternalStickerCacheHelper { } } + @JvmStatic + fun syncAllCaches() { + async { + if (caching) { + showToast(LocaleController.getString(R.string.ExternalStickerCacheSyncNotFinished)) + } else { + cacheStickers(false) + } + } + } + + @JvmStatic + fun deleteAllCaches() { + async { + waitForSync() + val uri = NaConfig.externalStickerCacheUri ?: return@async + val context = ApplicationLoader.applicationContext + try { + DocumentFile.fromTreeUri(context, uri)?.let { dir -> + dir.listFiles().forEach { if (it.isDirectory) it.delete() } + } + showToast(null) + } catch (e: Exception) { + logException(e, "deleting all caches") + } + } + } + + private val observer = NotificationCenterDelegate { _, _, _ -> cacheStickers(true) } + private val notificationIdList = listOf( + NotificationCenter.stickersDidLoad, + NotificationCenter.diceStickersDidLoad, + NotificationCenter.featuredStickersDidLoad, + NotificationCenter.stickersImportComplete, + ) + + @JvmStatic + fun addNotificationObservers(currentAccount: Int) { + NotificationCenter.getInstance(currentAccount).apply { + notificationIdList.forEach { addObserver(observer, it) } + } + } + + @JvmStatic + fun removeNotificationObservers(currentAccount: Int) { + NotificationCenter.getInstance(currentAccount).apply { + notificationIdList.forEach { removeObserver(observer, it) } + } + } + @JvmStatic private fun showToast(msg: String?) { var realMessage = msg @@ -225,6 +286,26 @@ object ExternalStickerCacheHelper { } } + private const val TYPE_USERNAME = 0 + private const val TYPE_ID = 1 + + private fun getStickerDirName(set: TL_messages_stickerSet): String = when (NaConfig.externalStickerCacheDirNameType.Int()) { + TYPE_USERNAME -> set.set.short_name + TYPE_ID -> set.set.id.toString() + else -> throw RuntimeException("Invalid dir name type") + } + + private suspend fun waitForSync() { + if (caching) { + showToast(LocaleController.getString(R.string.ExternalStickerCacheWaitSync)) + do delay(3000) while (caching) + } + } + + private fun async(scope: suspend CoroutineScope.() -> Unit) { + CoroutineScope(Dispatchers.IO).launch(block = scope) + } + private fun logException(e: Exception, s: String) { val exception = e.javaClass.canonicalName val message = e.message diff --git a/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml b/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml index 179f4336e4..3999bf5c5a 100644 --- a/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml +++ b/TMessagesProj/src/main/res/values-zh-rCN/strings_na.xml @@ -95,10 +95,17 @@ 禁用私聊的自定义背景 禁用频道的自定义背景 复制图片但是贴纸 - 在外部存储缓存贴纸文件 + 外部贴纸缓存 用于与其他应用共享贴纸包 (点击选择存储位置) 刷新外部缓存 删除外部缓存 + 正在等待缓存同步完成 + 缓存同步已经在运行了 + 自动同步 + 在有贴纸事件时自动同步所有缓存 + 同步所有缓存 + 删除所有缓存 + 目录命名方式 腾讯交互翻译 LibreTranslate diff --git a/TMessagesProj/src/main/res/values/strings_na.xml b/TMessagesProj/src/main/res/values/strings_na.xml index 179b0242f4..d799dc4a1a 100644 --- a/TMessagesProj/src/main/res/values/strings_na.xml +++ b/TMessagesProj/src/main/res/values/strings_na.xml @@ -102,6 +102,13 @@ For sharing sticker packs with other apps. Click to pick storage location. Refresh External Cache Delete External Cache + Waiting for cache sync to finish + Cache sync is already running + Automatic sync + Automatically sync all caches after receiving sticker events + Sync all caches + Delete all caches + Directory naming TranSmart Translator LibreTranslate