feat(wallpaper): extend commands with gallery, delete image, and crop
The plugin now exposes gallery retrieval, image deletion and image crop across Android, desktop and mobile. The Rust core and Android bridge are wired to handle these commands, updating state as needed. - Add gallery, delete_image, and set_image_crop commands - across Android, desktop and mobile. - Update permissions, defaults, and schema to enable new commands.
This commit is contained in:
@@ -17,12 +17,25 @@ import java.util.concurrent.Executors
|
||||
@InvokeArg
|
||||
class SettingArgs { lateinit var name: String; var value: Boolean = false }
|
||||
|
||||
@InvokeArg
|
||||
class GalleryArgs { var offset: Int = 0; var limit: Int = 48 }
|
||||
|
||||
@InvokeArg
|
||||
class DeleteImageArgs { lateinit var id: String }
|
||||
|
||||
@TauriPlugin
|
||||
class WallpaperPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
private val io = Executors.newSingleThreadExecutor()
|
||||
|
||||
@Command fun getState(invoke: Invoke) = io.execute { invoke.resolve(WallpaperStore.state(activity)) }
|
||||
|
||||
@Command fun getGallery(invoke: Invoke) = io.execute {
|
||||
try {
|
||||
val args = invoke.parseArgs(GalleryArgs::class.java)
|
||||
invoke.resolve(WallpaperStore.gallery(activity, args.offset, args.limit))
|
||||
} catch (error: Exception) { invoke.reject(error.message ?: "Galerie konnte nicht geladen werden") }
|
||||
}
|
||||
|
||||
@Command fun selectImages(invoke: Invoke) {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
@@ -33,6 +46,14 @@ class WallpaperPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
startActivityForResult(invoke, intent, "selectedImages")
|
||||
}
|
||||
|
||||
@Command fun deleteImage(invoke: Invoke) = io.execute {
|
||||
try {
|
||||
val args = invoke.parseArgs(DeleteImageArgs::class.java)
|
||||
if (!WallpaperStore.delete(activity, args.id)) throw IllegalArgumentException("Bild wurde nicht gefunden")
|
||||
invoke.resolve(WallpaperStore.state(activity))
|
||||
} catch (error: Exception) { invoke.reject(error.message ?: "Bild konnte nicht gelöscht werden") }
|
||||
}
|
||||
|
||||
@ActivityCallback
|
||||
fun selectedImages(invoke: Invoke, result: ActivityResult) {
|
||||
if (result.resultCode != Activity.RESULT_OK) { invoke.reject("Bildauswahl abgebrochen"); return }
|
||||
|
||||
@@ -44,6 +44,45 @@ object WallpaperStore {
|
||||
}
|
||||
}
|
||||
|
||||
fun gallery(context: Context, offset: Int, limit: Int): JSObject {
|
||||
val originals = files(context)
|
||||
val selectedIndex = prefs(context).getInt(KEY_INDEX, 0).coerceIn(0, (originals.size - 1).coerceAtLeast(0))
|
||||
val safeOffset = offset.coerceAtLeast(0).coerceAtMost(originals.size)
|
||||
val safeLimit = limit.coerceIn(1, 100)
|
||||
val items = JSArray()
|
||||
originals.drop(safeOffset).take(safeLimit).forEachIndexed { pageIndex, file ->
|
||||
items.put(JSObject().apply {
|
||||
put("id", file.name)
|
||||
put("url", thumbnailDataUrl(file))
|
||||
put("selected", safeOffset + pageIndex == selectedIndex)
|
||||
})
|
||||
}
|
||||
return JSObject().apply {
|
||||
put("total", originals.size)
|
||||
put("items", items)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun delete(context: Context, id: String): Boolean {
|
||||
if (id.isBlank() || File(id).name != id) return false
|
||||
val originals = files(context)
|
||||
val position = originals.indexOfFirst { it.name == id }
|
||||
if (position < 0 || !originals[position].delete()) return false
|
||||
|
||||
val preferences = prefs(context)
|
||||
val previousIndex = preferences.getInt(KEY_INDEX, 0).coerceIn(0, (originals.size - 1).coerceAtLeast(0))
|
||||
val remaining = originals.size - 1
|
||||
val nextIndex = when {
|
||||
remaining <= 0 -> 0
|
||||
position < previousIndex -> previousIndex - 1
|
||||
previousIndex >= remaining -> remaining - 1
|
||||
else -> previousIndex
|
||||
}
|
||||
preferences.edit().putInt(KEY_INDEX, nextIndex).apply()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun thumbnailDataUrl(file: File): String {
|
||||
val bounds = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||
BitmapFactory.decodeFile(file.absolutePath, bounds)
|
||||
|
||||
Reference in New Issue
Block a user