Add Android animation library browsing
This commit is contained in:
+31
-4
@@ -17,7 +17,7 @@ class FixtureActivity : ComponentActivity() {
|
||||
val controller = Controller(platform, scope)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent { QimiaoApp(controller, controller::scan, { ImageBitmap(64, 64) }) }
|
||||
setContent { QimiaoApp(controller, controller::scan, { marker -> platform.decodedMarkers += marker; ImageBitmap(64, 64) }) }
|
||||
}
|
||||
override fun onDestroy() { controller.disconnect(); scope.cancel(); super.onDestroy() }
|
||||
}
|
||||
@@ -28,8 +28,11 @@ class FixturePlatform : MobilePlatform {
|
||||
override val model = "模拟测试手机"
|
||||
private val saved = mutableMapOf<String, String>()
|
||||
val calls = mutableListOf<String>()
|
||||
val decodedMarkers = java.util.Collections.synchronizedSet(mutableSetOf<String>())
|
||||
var scanError = false
|
||||
var emptyLibrary = true
|
||||
var animatedLibrary = false
|
||||
override val libraryCache: LibraryCache = FixtureCache()
|
||||
override fun load(key: String) = saved[key]
|
||||
override fun save(key: String, value: String) { saved[key] = value }
|
||||
override fun scan(onDevice: (DiscoveredDevice) -> Unit, onError: (String) -> Unit) {
|
||||
@@ -59,7 +62,7 @@ private class FixtureLink(val platform: FixturePlatform) : DeviceLink {
|
||||
val method = request.getValue("method").jsonPrimitive.content
|
||||
platform.calls += method
|
||||
val result = when (method) {
|
||||
"session.open" -> """{"device_id":"00000000-0000-4000-8000-000000000001","device_name":"模拟小屏幕","short_id":"00000000","protocol_major":1,"capabilities":["status","frame","library","library_progressive","settings","wifi","wifi_scan"${if (platform.wifiEnabled) ",\"wifi_transport\"" else ""}]}"""
|
||||
"session.open" -> """{"device_id":"00000000-0000-4000-8000-000000000001","device_name":"模拟小屏幕","short_id":"00000000","protocol_major":1,"capabilities":["status","frame","library","library_progressive","library_animation","settings","wifi","wifi_scan"${if (platform.wifiEnabled) ",\"wifi_transport\"" else ""}]}"""
|
||||
"transport.offer" -> """{"device_id":"00000000-0000-4000-8000-000000000001","channel_id":"00000000000000000000000000000000"}"""
|
||||
"transport.close" -> """{"closed":true}"""
|
||||
"session.ping" -> """{"alive":true}"""
|
||||
@@ -68,8 +71,16 @@ private class FixtureLink(val platform: FixturePlatform) : DeviceLink {
|
||||
"settings.get" -> """{"revision":"fixture","values":{"brightness":40,"orientation":0,"prompt_delay_seconds":5}}"""
|
||||
"wifi.get" -> """{"revision":"fixture","saved":null,"active":{"connected":false}}"""
|
||||
"wifi.scan" -> """{"networks":[]}"""
|
||||
"library.summary" -> if (platform.emptyLibrary) """{"library_revision":"fixture-empty","item_count":0}""" else """{"library_revision":"fixture-full","item_count":1}"""
|
||||
"library.list" -> if (platform.emptyLibrary) """{"library_revision":"fixture-empty","items":[],"next_cursor":null}""" else """{"library_revision":"fixture-full","items":[{"id":"fixture","type":"template","name":"测试模板","revision":"fixture-1","playable":true}],"next_cursor":null}"""
|
||||
"library.summary" -> if (platform.emptyLibrary) """{"library_revision":"fixture-empty","item_count":0}""" else if (platform.animatedLibrary) """{"library_revision":"fixture-animation","item_count":1}""" else """{"library_revision":"fixture-full","item_count":1}"""
|
||||
"library.list" -> if (platform.emptyLibrary) """{"library_revision":"fixture-empty","items":[],"next_cursor":null}""" else if (platform.animatedLibrary) """{"library_revision":"fixture-animation","items":[{"id":"fixture","type":"animation","name":"测试动图","revision":"fixture-1","frame_count":2,"playable":true}],"next_cursor":null}""" else """{"library_revision":"fixture-full","items":[{"id":"fixture","type":"template","name":"测试模板","revision":"fixture-1","playable":true}],"next_cursor":null}"""
|
||||
"library.animation.info" -> """{"revision":"fixture-1","frame_count":2,"frames":[{"index":0,"duration_ms":80},{"index":1,"duration_ms":120}],"next_offset":null}"""
|
||||
"library.animation.chunk" -> {
|
||||
val params = request.getValue("params").jsonObject
|
||||
buildJsonObject {
|
||||
put("revision", "fixture-1"); put("tier", params.getValue("tier")); put("frame_index", params.getValue("frame_index"))
|
||||
put("offset", 0); put("total_bytes", 1); put("sha256", "fixture"); put("data_base64", "AA=="); put("next_offset", JsonNull)
|
||||
}.toString()
|
||||
}
|
||||
"content.default.get" -> """{"name":"测试默认"}"""
|
||||
"library.preview" -> """{"data_base64":"fixture-preview"}"""
|
||||
"library.thumbnail" -> """{"data_base64":"fixture-image"}"""
|
||||
@@ -112,3 +123,19 @@ class FixtureWifi : WifiPlatform {
|
||||
override fun close() { replies.close() }
|
||||
}
|
||||
}
|
||||
|
||||
private class FixtureCache : LibraryCache {
|
||||
private val images = mutableMapOf<String, String>()
|
||||
private val records = mutableMapOf<String, JsonObject>()
|
||||
var reads = 0
|
||||
override suspend fun loadCatalog(deviceId: String): CachedLibrary? = null
|
||||
override suspend fun saveCatalog(deviceId: String, catalog: CachedLibrary) {}
|
||||
override suspend fun readImage(deviceId: String, item: JsonObject, tier: String): String? { reads++; return images[tier] }
|
||||
override suspend fun writeImage(deviceId: String, item: JsonObject, tier: String, base64: String) { images[tier] = base64 }
|
||||
override suspend fun readRecord(deviceId: String, item: JsonObject, name: String) = records[name]
|
||||
override suspend fun writeRecord(deviceId: String, item: JsonObject, name: String, value: JsonObject) { records[name] = value }
|
||||
override suspend fun writeAnimationFrame(deviceId: String, item: JsonObject, tier: String, chunks: List<String>, sha256: String) { images[tier] = tier }
|
||||
override suspend fun retain(deviceId: String, items: List<JsonObject>) {}
|
||||
override suspend fun sizeBytes() = 0L
|
||||
override suspend fun clear() { images.clear(); records.clear() }
|
||||
}
|
||||
|
||||
+21
@@ -2,6 +2,7 @@ package org.qimiaoscreen.uitest
|
||||
|
||||
import androidx.compose.ui.test.*
|
||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||
import org.qimiaoscreen.core.thumbnailKey
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.Assert.*
|
||||
@@ -65,6 +66,26 @@ class IsolatedUiTest {
|
||||
assertTrue(ui.activity.platform.calls.indexOf("library.preview") < ui.activity.platform.calls.indexOf("library.thumbnail"))
|
||||
assertFalse(ui.activity.platform.calls.contains("content.play"))
|
||||
}
|
||||
@Test fun animationViewer() {
|
||||
ui.runOnIdle { ui.activity.platform.emptyLibrary = false; ui.activity.platform.animatedLibrary = true }
|
||||
connect(); click("显示内容")
|
||||
ui.waitUntil(10_000) { ui.activity.controller.state.value.animationClips.values.any { it.tier == "full" } }
|
||||
ui.waitUntil(5_000) { ui.activity.platform.decodedMarkers.containsAll(listOf("animation-full-0", "animation-full-1")) }
|
||||
val item = ui.activity.controller.state.value.library.single()
|
||||
ui.onNodeWithTag("library_image_" + thumbnailKey(item)).performScrollTo().performClick()
|
||||
ui.onNodeWithTag("image_viewer").assertExists()
|
||||
ui.waitUntil(5_000) { ui.activity.controller.state.value.viewerProgress == null }
|
||||
ui.onNodeWithTag("viewer_image").assertExists()
|
||||
ui.onNodeWithTag("viewer_close").performClick()
|
||||
ui.onNodeWithTag("image_viewer").assertDoesNotExist()
|
||||
ui.runOnIdle { ui.activity.controller.foreground(false) }
|
||||
assertFalse(ui.activity.controller.state.value.imagesForeground)
|
||||
ui.runOnIdle { ui.activity.controller.foreground(true) }
|
||||
ui.onNodeWithTag("frame_image").performScrollTo().performClick()
|
||||
ui.onNodeWithTag("image_viewer").assertExists()
|
||||
ui.onNodeWithTag("viewer_close").performClick()
|
||||
assertFalse(ui.activity.platform.calls.contains("content.play"))
|
||||
}
|
||||
@Test fun settings() {
|
||||
connect(); click("设备设置")
|
||||
ui.waitUntil(5_000) { ui.activity.controller.state.value.settings != null }
|
||||
|
||||
Reference in New Issue
Block a user