Skip to content

Commit 8f7601e

Browse files
author
ying
committed
Ship remaining ClipDock updates
1 parent 057d64b commit 8f7601e

178 files changed

Lines changed: 47518 additions & 1141 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/build-release-artifacts.yml‎

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ jobs:
163163
name: ClipDock-${{ needs.metadata.outputs.version }}-macos
164164
path: |
165165
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/macos/ClipDock-${{ needs.metadata.outputs.version }}-*.dmg
166-
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/macos/SHA256SUMS
167166
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/macos/ClipDock-release-manifest.txt
168167
if-no-files-found: error
169168
retention-days: 30
@@ -265,7 +264,7 @@ jobs:
265264
artifact_root="$PWD/${{ needs.metadata.outputs.artifact_path }}/android"
266265
267266
mkdir -p "$artifact_root"
268-
rm -f "$artifact_root"/*.apk "$artifact_root"/*.aab "$artifact_root"/SHA256SUMS "$artifact_root"/ClipDock-Android-release-manifest.txt
267+
rm -f "$artifact_root"/*.apk "$artifact_root"/*.aab "$artifact_root"/ClipDock-Android-release-manifest.txt
269268
270269
apk_sources=()
271270
while IFS= read -r artifact; do
@@ -278,20 +277,10 @@ jobs:
278277
fi
279278
280279
apk_path="$artifact_root/ClipDock-$version-$build-android-release-signed.apk"
281-
checksums_path="$artifact_root/SHA256SUMS"
282280
manifest_path="$artifact_root/ClipDock-Android-release-manifest.txt"
283281
284282
cp "${apk_sources[0]}" "$apk_path"
285283
286-
: > "$checksums_path"
287-
for artifact in "$apk_path"; do
288-
if command -v sha256sum >/dev/null 2>&1; then
289-
(cd "$artifact_root" && sha256sum "$(basename "$artifact")") >> "$checksums_path"
290-
else
291-
(cd "$artifact_root" && shasum -a 256 "$(basename "$artifact")") >> "$checksums_path"
292-
fi
293-
done
294-
295284
{
296285
printf 'name=ClipDock\n'
297286
printf 'platform=android\n'
@@ -308,7 +297,8 @@ jobs:
308297
with:
309298
name: ClipDock-${{ needs.metadata.outputs.version }}-android
310299
path: |
311-
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/android/*
300+
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/android/*.apk
301+
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/android/ClipDock-Android-release-manifest.txt
312302
if-no-files-found: error
313303
retention-days: 30
314304

@@ -337,9 +327,6 @@ jobs:
337327
- artifact_label: windows-x86_64
338328
runner: windows-2025
339329
target: x86_64-pc-windows-msvc
340-
- artifact_label: windows-arm64
341-
runner: windows-11-arm
342-
target: aarch64-pc-windows-msvc
343330

344331
steps:
345332
- name: Checkout
@@ -374,7 +361,9 @@ jobs:
374361
with:
375362
name: ClipDock-Server-${{ needs.metadata.outputs.version }}-${{ matrix.artifact_label }}
376363
path: |
377-
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/server/${{ matrix.artifact_label }}/*
364+
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/server/${{ matrix.artifact_label }}/*.tar.gz
365+
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/server/${{ matrix.artifact_label }}/*.zip
366+
.codex/artifacts/release/${{ needs.metadata.outputs.version }}/server/${{ matrix.artifact_label }}/*.manifest.txt
378367
if-no-files-found: error
379368
retention-days: 30
380369

@@ -461,4 +450,3 @@ jobs:
461450
release-artifacts/**/*.dmg
462451
release-artifacts/**/*.tar.gz
463452
release-artifacts/**/*.zip
464-
release-artifacts/**/*.sha256

‎Android/app/build.gradle.kts‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,12 @@ dependencies {
146146
implementation(libs.androidx.core.ktx)
147147
implementation(libs.androidx.lifecycle.runtime.ktx)
148148
implementation(libs.androidx.work.runtime.ktx)
149+
implementation(libs.androidx.webkit)
149150
implementation(libs.androidx.activity.compose)
150151
implementation(libs.kotlinx.serialization.json)
151152
implementation(libs.okhttp)
152153
implementation(libs.commons.codec)
154+
implementation(libs.jsoup)
153155

154156
// Arch Components
155157
implementation(libs.androidx.lifecycle.runtime.compose)
@@ -262,6 +264,16 @@ tasks.named("preBuild") {
262264
dependsOn(copyRustJniTasks)
263265
}
264266

267+
tasks.register<Exec>("validateMobileV4WebAssets") {
268+
workingDir = rootProject.projectDir
269+
commandLine(
270+
"python3",
271+
"scripts/mobile_v4_validate_web_source.py",
272+
"--design",
273+
"../.codex/artifacts/mobile-design-reference/clipdock-mobile-complete-design-v4.html",
274+
)
275+
}
276+
265277
val validateReleaseSigning =
266278
tasks.register<ValidateReleaseSigningTask>("validateReleaseSigning") {
267279
signingConfigured.set(releaseSigningConfigured)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.apkdv.clipdock
2+
3+
import android.content.Context
4+
import android.graphics.BitmapFactory
5+
import android.net.Uri
6+
import androidx.test.core.app.ApplicationProvider
7+
import androidx.test.ext.junit.runners.AndroidJUnit4
8+
import androidx.test.platform.app.InstrumentationRegistry
9+
import com.apkdv.clipdock.data.ClipItemType
10+
import com.apkdv.clipdock.data.PayloadState
11+
import com.apkdv.clipdock.data.RemoteAssetActionResult
12+
import java.util.concurrent.TimeUnit
13+
import junit.framework.TestCase.assertNotNull
14+
import junit.framework.TestCase.assertTrue
15+
import kotlinx.coroutines.delay
16+
import kotlinx.coroutines.runBlocking
17+
import org.junit.Assume.assumeTrue
18+
import org.junit.Test
19+
import org.junit.runner.RunWith
20+
21+
@RunWith(AndroidJUnit4::class)
22+
class AndroidDownloadRemoteImageInstrumentedTest {
23+
@Test
24+
fun downloadsRemoteImageToLocalCache() = runBlocking {
25+
val contentHash = InstrumentationRegistry.getArguments().getString("contentHash").orEmpty()
26+
assumeTrue("Remote image download E2E requires contentHash.", contentHash.isNotBlank())
27+
28+
val app = ApplicationProvider.getApplicationContext<ClipDockApplication>()
29+
val repository = app.repository
30+
repository.setP2pEnabled(true)
31+
repository.setWifiOnly(false)
32+
33+
val item =
34+
waitFor("remote image item") {
35+
repository.syncNow().firstOrNull { candidate ->
36+
candidate.type == ClipItemType.Image &&
37+
candidate.contentHash.removePrefix("blake3:") == contentHash.removePrefix("blake3:")
38+
}
39+
}
40+
assertNotNull(item.thumbnailUri)
41+
assertNotNull(item.assetId)
42+
43+
val downloaded =
44+
if (item.payloadState == PayloadState.Ready) {
45+
item
46+
} else {
47+
val result = repository.downloadToCache(item, timeoutMillis = 30_000)
48+
assertTrue(result is RemoteAssetActionResult.Cached)
49+
(result as RemoteAssetActionResult.Cached).item
50+
}
51+
assertTrue(downloaded.payloadState == PayloadState.Ready)
52+
assertNotNull(downloaded.localUri)
53+
val bytes = readContentUri(app, downloaded.localUri!!)
54+
assertTrue(bytes.size >= 8)
55+
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
56+
assertNotNull(bitmap)
57+
assertTrue(bitmap.width > 0)
58+
assertTrue(bitmap.height > 0)
59+
}
60+
61+
private suspend fun <T : Any> waitFor(label: String, block: suspend () -> T?): T {
62+
val deadline = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(45)
63+
while (System.currentTimeMillis() < deadline) {
64+
block()?.let { return it }
65+
delay(500)
66+
}
67+
throw AssertionError("Timed out waiting for $label")
68+
}
69+
70+
private fun readContentUri(context: Context, uri: String): ByteArray =
71+
context.contentResolver.openInputStream(Uri.parse(uri))?.use { it.readBytes() }
72+
?: throw AssertionError("Cannot open downloaded URI: $uri")
73+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.apkdv.clipdock
2+
3+
import android.content.Intent
4+
import android.provider.Settings
5+
import androidx.test.core.app.ApplicationProvider
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import com.apkdv.clipdock.overlay.FloatingOverlayService
8+
import junit.framework.TestCase.assertNotNull
9+
import junit.framework.TestCase.assertTrue
10+
import kotlinx.coroutines.delay
11+
import kotlinx.coroutines.runBlocking
12+
import org.junit.Test
13+
import org.junit.runner.RunWith
14+
15+
@RunWith(AndroidJUnit4::class)
16+
class FloatingOverlayInstrumentedTest {
17+
@Test
18+
fun overlayPermissionAndServiceStartAreAvailable() {
19+
runBlocking {
20+
val app = ApplicationProvider.getApplicationContext<ClipDockApplication>()
21+
assertTrue("SYSTEM_ALERT_WINDOW must be allowed before this smoke test.", Settings.canDrawOverlays(app))
22+
app.repository.setOverlayEnabled(true)
23+
assertTrue("Overlay preference should be enabled for the floating-ball smoke test.", app.repository.state.value.overlayEnabled)
24+
25+
val component = app.startService(Intent(app, FloatingOverlayService::class.java))
26+
assertNotNull(component)
27+
delay(1_000)
28+
app.stopService(Intent(app, FloatingOverlayService::class.java))
29+
}
30+
}
31+
}

‎Android/app/src/androidTest/java/com/apkdv/clipdock/HistoryDetailSheetInstrumentedTest.kt‎

Lines changed: 0 additions & 130 deletions
This file was deleted.

0 commit comments

Comments
 (0)