Thin the app's comments
The same pass the server had, on the Kotlin side: comments restating what the code says are gone, and the ones recording a measurement, a constraint or an incident are kept but cut to a few lines each. 6540 comment lines to 5674, and 920 lines off the app. Two doc comments had drifted onto the item above the one they describe -- `contextAfter`'s onto `sessionWorking` in Events.kt, and `UsageMonitor`'s equivalent on the server was fixed in the previous commit. Each is back on its own item, which is the only non-comment line this diff moves. The comments are reflowed to the column limit at their own indentation: several were written wide, and ktfmt re-wrapped them into lines holding a single orphan word. `/tmp` script, not kept -- ktfmt is idempotent over the result, which is the check. Left alone deliberately: this codebase's remaining comment density is high because the comments carry things the code cannot say -- what a null means, what a number was measured against, which bug a guard exists for. Of the 238 one-line doc comments in the app, five were pure restatement of the name and were removed; the rest each say something the signature does not. ktfmtFormat, compileDebugKotlin, lintDebug and testDebugUnitTest pass; cargo test (127), clippy --all-targets and fmt still clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
79682f03a7
commit
edc39c7371
68 files changed
+2077
-2997
No files matched your search
@@ -20,10 +20,8 @@ import kotlin.math.max
|
||||
* to be either thrown away or rejected -- which is what "sending an image is broken" was.
|
||||
*
|
||||
* Shrunk here rather than on the backend, so the bytes that never mattered are never sent: the
|
||||
* expensive part of this on a phone is the upload, not the decode. What the limit *is* comes from
|
||||
* the server, per session -- see `DriverKind::max_image_edge` -- because that is where a provider's
|
||||
* requirements are known, and a phone that carried its own copy of them would be a second place to
|
||||
* update when one changes.
|
||||
* expensive part on a phone is the upload, not the decode. What the limit *is* comes from the
|
||||
* server, per session, because that is where a provider's requirements are known.
|
||||
*/
|
||||
suspend fun uploadPickedImage(
|
||||
context: Context,
|
||||
@@ -53,17 +51,16 @@ suspend fun uploadPicked(
|
||||
if (mime != null && mime.startsWith("image/")) {
|
||||
return uploadPickedImage(context, settings, sessionId, uri, maxEdge)
|
||||
}
|
||||
// Opened before the request starts, so a provider that refuses says so here and not from
|
||||
// inside the connection; then streamed, since a trace or a log is bigger than this process
|
||||
// should hold at once.
|
||||
// Opened before the request starts, so a provider that refuses says so here and not from inside
|
||||
// the connection; then streamed, since a trace is bigger than this process should hold at once.
|
||||
val source = openSource(resolver, uri)
|
||||
val name = displayName(resolver, uri)
|
||||
return uploadAttachment(settings, sessionId, mime ?: "application/octet-stream", name) { out ->
|
||||
try {
|
||||
source.use { it.copyTo(out, COPY_BUFFER) }
|
||||
} catch (e: java.io.IOException) {
|
||||
// Either side of the copy can fail; the message names the file, which is the
|
||||
// part the reader can do something about.
|
||||
// Either side of the copy can fail; the message names the file, which is the part the
|
||||
// reader can do something about.
|
||||
throw ApiException("couldn't send $name: ${e.message}", cause = e)
|
||||
}
|
||||
}
|
||||
@@ -76,7 +73,7 @@ private const val COPY_BUFFER = 64 * 1024
|
||||
*
|
||||
* A share arrives with whatever access the other app granted, and a provider that refuses says so
|
||||
* with a `SecurityException`; a file gone between the pick and the read is an `IOException`. Both
|
||||
* are things the reader can act on, so neither is left to end the process.
|
||||
* are things the reader can act on.
|
||||
*/
|
||||
private fun openSource(resolver: ContentResolver, uri: Uri): java.io.InputStream =
|
||||
try {
|
||||
@@ -110,9 +107,9 @@ private fun displayName(resolver: ContentResolver, uri: Uri): String {
|
||||
/**
|
||||
* The bytes to upload and what they are, scaled down only if they need to be.
|
||||
*
|
||||
* An image already inside the limit is uploaded exactly as it came, rather than decoded and
|
||||
* re-encoded to the same size: a round trip through JPEG loses a little every time, and there is
|
||||
* nothing to gain from it. This is also the path a provider with no limit always takes.
|
||||
* An image already inside the limit is uploaded exactly as it came, rather than decoded and re-
|
||||
* encoded to the same size: a round trip through JPEG loses a little every time. This is also the
|
||||
* path a provider with no limit always takes.
|
||||
*/
|
||||
private fun readForUpload(context: Context, uri: Uri, maxEdge: Int?): Pair<ByteArray, String> {
|
||||
val resolver = context.contentResolver
|
||||
@@ -128,9 +125,9 @@ private fun readForUpload(context: Context, uri: Uri, maxEdge: Int?): Pair<ByteA
|
||||
// decision it has no business making.
|
||||
if (longest <= 0 || longest <= maxEdge) return original to mime
|
||||
|
||||
// Powers of two first, which is all the decoder can do, and then the exact scale. Decoding
|
||||
// the full twelve megapixels only to shrink it is how this runs out of memory on the images
|
||||
// it most needs to handle.
|
||||
// Powers of two first, which is all the decoder can do, and then the exact scale. Decoding the
|
||||
// full twelve megapixels only to shrink it is how this runs out of memory on the images it most
|
||||
// needs to handle.
|
||||
val decode =
|
||||
BitmapFactory.Options().apply {
|
||||
inSampleSize = Integer.highestOneBit(max(1, longest / maxEdge))
|
||||
@@ -141,9 +138,8 @@ private fun readForUpload(context: Context, uri: Uri, maxEdge: Int?): Pair<ByteA
|
||||
val matrix = Matrix()
|
||||
if (scale < 1f) matrix.postScale(scale, scale)
|
||||
// The camera writes which way up the picture is into EXIF rather than rotating the pixels, and
|
||||
// re-encoding drops the tag -- so a portrait photo would arrive at the model on its side, with
|
||||
// nothing anywhere saying so. Applied to the same matrix as the scale, so it costs no second
|
||||
// copy of the bitmap.
|
||||
// re-encoding drops the tag -- so a portrait photo would arrive at the model on its side.
|
||||
// Applied to the same matrix as the scale, so it costs no second copy of the bitmap.
|
||||
matrix.postRotate(exifRotation(original))
|
||||
val scaled = Bitmap.createBitmap(decoded, 0, 0, decoded.width, decoded.height, matrix, true)
|
||||
val out = ByteArrayOutputStream()
|
||||
@@ -166,8 +162,8 @@ private fun exifRotation(bytes: ByteArray): Float =
|
||||
else -> 0f
|
||||
}
|
||||
} catch (_: java.io.IOException) {
|
||||
// No EXIF, or none this can read. Upright is the assumption every
|
||||
// image without the tag is displayed under anyway.
|
||||
// No EXIF, or none this can read. Upright is the assumption every image without the tag is
|
||||
// displayed under anyway.
|
||||
0f
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user