mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Add java-side prefix filtering for ContentUri directory listing
This commit is contained in:
@@ -39,7 +39,7 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) {
|
||||
|
||||
openContentUri = env->GetStaticMethodID(localClass, "openContentUri", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;)I");
|
||||
_dbg_assert_(openContentUri);
|
||||
listContentUriDir = env->GetStaticMethodID(localClass, "listContentUriDir", "(Landroid/app/Activity;Ljava/lang/String;)[Ljava/lang/String;");
|
||||
listContentUriDir = env->GetStaticMethodID(localClass, "listContentUriDir", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;");
|
||||
_dbg_assert_(listContentUriDir);
|
||||
contentUriCreateDirectory = env->GetStaticMethodID(localClass, "contentUriCreateDirectory", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;)I");
|
||||
_dbg_assert_(contentUriCreateDirectory);
|
||||
@@ -265,7 +265,8 @@ std::vector<File::FileInfo> Android_ListContentUri(const std::string &uri, const
|
||||
double start = time_now_d();
|
||||
|
||||
jstring param = env->NewStringUTF(uri.c_str());
|
||||
jobject retval = env->CallStaticObjectMethod(g_classContentUri, listContentUriDir, g_nativeActivity, param);
|
||||
jstring filenamePrefix = prefix.empty() ? nullptr : env->NewStringUTF(prefix.c_str());
|
||||
jobject retval = env->CallStaticObjectMethod(g_classContentUri, listContentUriDir, g_nativeActivity, param, filenamePrefix);
|
||||
|
||||
jobjectArray fileList = (jobjectArray)retval;
|
||||
std::vector<File::FileInfo> items;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Common/System/System.h"
|
||||
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/DirListing.h"
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Common/StringUtils.h"
|
||||
@@ -68,7 +69,9 @@ static const char * const LOAD_UNDO_NAME = "load_undo.ppst";
|
||||
|
||||
namespace SaveState {
|
||||
|
||||
// Used for "confirm exit if you haven't saved in a while"
|
||||
double g_lastSaveTime = -1.0;
|
||||
|
||||
static bool needsProcess = false;
|
||||
static bool needsRestart = false;
|
||||
static std::mutex mutex;
|
||||
|
||||
+3
-1
@@ -41,6 +41,8 @@ namespace SaveState {
|
||||
// Cycle through the 5 savestate slots
|
||||
void PrevSlot();
|
||||
void NextSlot();
|
||||
|
||||
// Run the various actions directly.
|
||||
void SaveSlot(const Path &gameFilename, int slot, Callback callback);
|
||||
void LoadSlot(const Path &gameFilename, int slot, Callback callback);
|
||||
bool UndoSaveSlot(const Path &gameFilename, int slot);
|
||||
@@ -55,6 +57,7 @@ namespace SaveState {
|
||||
bool HasUndoLoad(const Path &gameFilename);
|
||||
bool HasScreenshotInSlot(const Path &gameFilename, int slot);
|
||||
|
||||
// Just returns the current slot from config.
|
||||
int GetCurrentSlot();
|
||||
|
||||
// Returns -1 if there's no oldest/newest slot.
|
||||
@@ -62,7 +65,6 @@ namespace SaveState {
|
||||
int GetOldestSlot(const Path &gameFilename);
|
||||
|
||||
std::string GetSlotDateAsString(const Path &gameFilename, int slot);
|
||||
std::string GenerateFullDiscId(const Path &gameFilename);
|
||||
Path GenerateSaveSlotFilename(const Path &gameFilename, int slot, const char *extension);
|
||||
|
||||
std::string GetTitle(const Path &filename);
|
||||
|
||||
@@ -19,6 +19,7 @@ import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ContentUri {
|
||||
@@ -65,7 +66,7 @@ public class ContentUri {
|
||||
DocumentsContract.Document.COLUMN_LAST_MODIFIED
|
||||
};
|
||||
|
||||
private static String cursorToString(Cursor c) {
|
||||
private static String cursorToString(Cursor c, String prefixLowercase) {
|
||||
final int flags = c.getInt(2);
|
||||
// Filter out any virtual or partial nonsense.
|
||||
// There's a bunch of potentially-interesting flags here btw,
|
||||
@@ -74,9 +75,16 @@ public class ContentUri {
|
||||
if ((flags & (DocumentsContract.Document.FLAG_PARTIAL | DocumentsContract.Document.FLAG_VIRTUAL_DOCUMENT)) != 0) {
|
||||
return null;
|
||||
}
|
||||
final String documentName = c.getString(0);
|
||||
if (prefixLowercase != null && !prefixLowercase.isEmpty()) {
|
||||
// Filter by prefix, case insensitive.
|
||||
if (!documentName.toLowerCase(Locale.ROOT).startsWith(prefixLowercase)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
final String mimeType = c.getString(3);
|
||||
final boolean isDirectory = mimeType.equals(DocumentsContract.Document.MIME_TYPE_DIR);
|
||||
final String documentName = c.getString(0);
|
||||
final long size = isDirectory ? 0 : c.getLong(1);
|
||||
final long lastModified = c.getLong(4);
|
||||
|
||||
@@ -160,7 +168,7 @@ public class ContentUri {
|
||||
// uestions/42186820/documentfile-is-very-slow
|
||||
@Keep
|
||||
@SuppressWarnings("unused")
|
||||
public static String[] listContentUriDir(Activity activity, String uriString) {
|
||||
public static String[] listContentUriDir(Activity activity, String uriString, String prefix) {
|
||||
try {
|
||||
Uri uri = Uri.parse(uriString);
|
||||
final ContentResolver resolver = activity.getContentResolver();
|
||||
@@ -176,12 +184,16 @@ public class ContentUri {
|
||||
DocumentsContract.Document.COLUMN_LAST_MODIFIED // index 4
|
||||
};
|
||||
|
||||
if (prefix != null) {
|
||||
prefix = prefix.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
try (Cursor c = resolver.query(childrenUri, projection, null, null, null)) {
|
||||
if (c == null) {
|
||||
return new String[]{"X"};
|
||||
}
|
||||
while (c.moveToNext()) {
|
||||
String str = cursorToString(c);
|
||||
String str = cursorToString(c, prefix);
|
||||
if (str != null) {
|
||||
listing.add(str);
|
||||
}
|
||||
@@ -354,7 +366,7 @@ public class ContentUri {
|
||||
|
||||
try (Cursor c = activity.getContentResolver().query(Uri.parse(fileName), projection, null, null, null)) {
|
||||
if (c != null && c.moveToFirst()) {
|
||||
return cursorToString(c);
|
||||
return cursorToString(c, null);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user