Split typed SSD client into per-file fragments
ober
c41ef257fc3983961a5f92693f149fc59fe2d6e0
new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/AndroidApi.ss @@ -0,0 +1,15 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/AndroidApi.kt" + (typed-library (com sfb ssdreview) (export sdkAtLeast sdkBefore) + (type Int32) + (def (sdkAtLeast (sdk : Int32) (api : Int32)) + : + Bool + (>= sdk api)) + (def (sdkBefore (sdk : Int32) (api : Int32)) + : + Bool + (< sdk api)))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/AndroidBitmap.ss @@ -0,0 +1,74 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/AndroidBitmap.kt" + (kotlin-imports (android graphics Bitmap)) + (typed-library (com sfb ssdreview) + (export bitmapPixelWidth bitmapPixelHeight bitmapHasPixels + bitmapReadyForNativeDetection + bitmapNotReadyForNativeDetection bitmapPixels + bitmapWindowPixels bitmapToRgba) + (type Bitmap) (type Int32) (type IntArray) (type Bytes) + (extern + (bitmapWidth (bitmap : Bitmap)) + : + Int32 + (kotlin-member-get width)) + (extern + (bitmapHeight (bitmap : Bitmap)) + : + Int32 + (kotlin-member-get height)) + (extern + (bitmapGetPixels (bitmap : Bitmap) (pixels : IntArray) (offset : Int32) + (stride : Int32) (x : Int32) (y : Int32) (width : Int32) + (height : Int32)) + : + Unit + (kotlin-member-call getPixels)) + (def (bitmapPixelWidth (bitmap : Bitmap)) + : + Int32 + (bitmapWidth bitmap)) + (def (bitmapPixelHeight (bitmap : Bitmap)) + : + Int32 + (bitmapHeight bitmap)) + (def (bitmapHasPixels (bitmap : Bitmap)) + : + Bool + (and (> (bitmapPixelWidth bitmap) (int32 0)) + (> (bitmapPixelHeight bitmap) (int32 0)))) + (def (bitmapReadyForNativeDetection + (loaded : Bool) + (bitmap : Bitmap)) + : + Bool + (and loaded (bitmapHasPixels bitmap))) + (def (bitmapNotReadyForNativeDetection + (loaded : Bool) + (bitmap : Bitmap)) + : + Bool + (not (bitmapReadyForNativeDetection loaded bitmap))) + (def (bitmapWindowPixels (bitmap : Bitmap) (x : Int32) + (y : Int32) (width : Int32) (height : Int32)) + : + IntArray + (let ([pixels (int-array-build + (* width height) + (index (int32 0)))]) + (begin + (bitmapGetPixels bitmap pixels (int32 0) width x y + width height) + pixels))) + (def (bitmapPixels (bitmap : Bitmap)) + : + IntArray + (bitmapWindowPixels bitmap (int32 0) (int32 0) + (bitmapPixelWidth bitmap) (bitmapPixelHeight bitmap))) + (def (bitmapToRgba (bitmap : Bitmap)) + : + Bytes + (pixelsToRgba (bitmapPixels bitmap))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/AppendNote.ss @@ -0,0 +1,16 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/AppendNote.kt" + (typed-library + (com sfb ssdreview) + (export appendNote) + (def (appendNote (existing : String) (note : String)) + : + String + (if (string-blank? existing) + note + (string-append + existing + (string-append "; " note)))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BoxType.ss @@ -0,0 +1,57 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BoxType.kt" + (typed-library (com sfb ssdreview) + (export make-BoxType BoxType? BoxType-id BoxType-name + box-type-display boxTypeDisplays boxTypeById + boxTypeDisplayById addNullableBoxType) + (type Int) (type Int32) + (record BoxType ((id : String) (name : String))) + (def (box-type-display (box : BoxType)) + : + String + (string-append + (string-append (BoxType-id box) " ") + (BoxType-name box))) + (def (boxTypeDisplays (items : (List BoxType))) + : + (MutableList String) + (for/fold + ((out (mutable-list-empty String))) + ((i (in-range (int32 0) (list-size items)))) + (begin + (mutable-list-add! + out + (box-type-display (list-ref items i))) + out))) + (def (boxTypeById (items : (List BoxType)) (id : String)) + : + (Nullable BoxType) + (for/fold + ((found (nullable-none BoxType))) + ((i (in-range (int32 0) (list-size items)))) + (if (nullable-null? found) + (let ([box (list-ref items i)]) + (if (equal? (BoxType-id box) id) + (nullable-some box) + found)) + found))) + (def (boxTypeDisplayById + (items : (List BoxType)) + (id : String)) + : + String + (let ([box (boxTypeById items id)]) + (if (nullable-null? box) + id + (box-type-display (nullable-get box))))) + (def (addNullableBoxType + (items : (MutableList BoxType)) + (box : (Nullable BoxType))) + : + Unit + (if (nullable-null? box) + (begin) + (mutable-list-add! items (nullable-get box)))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BoxTypeAndroid.ss @@ -0,0 +1,80 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BoxTypeAndroid.kt" + (kotlin-imports + (android content Context) + (android content res AssetManager) + (java io InputStream)) + (typed-library (com sfb ssdreview) + (export boxTypeRawIsWeapon resolvedBoxTypeNameOr + resolvedBoxTypeIdOr boxTypesLoadAndroid + boxTypesResolveAndroid boxTypesDisplayAndroid) + (type Context) (type AssetManager) (type InputStream) + (extern + (contextAssets (context : Context)) + : + AssetManager + (kotlin-member-get assets)) + (extern + (assetManagerOpen (assets : AssetManager) (name : String)) + : + InputStream + (kotlin-member-call open)) + (extern + (boxTypeInputStreamClose (input : InputStream)) + : + Unit + (kotlin-member-call close)) + (def (boxTypesCsvText (context : Context)) + : + String + (let ([input (assetManagerOpen + (contextAssets context) + "box_types.csv")]) + (let ([text (utf8->string + (readBoundedBytes input (int 262144)))]) + (begin (boxTypeInputStreamClose input) text)))) + (def (boxTypesLoadAndroid (context : Context)) + : + (List BoxType) + (boxTypesFromCsvText (boxTypesCsvText context))) + (def (boxTypesResolveAndroid + (context : Context) + (raw : String)) + : + (Nullable BoxType) + (resolveBoxType (boxTypesLoadAndroid context) raw)) + (def (boxTypesDisplayAndroid + (context : Context) + (id : String)) + : + String + (boxTypeDisplayById (boxTypesLoadAndroid context) id)) + (def (resolvedBoxTypeNameOr + (boxType : (Nullable BoxType)) + (fallback : String)) + : + String + (if (nullable-null? boxType) + fallback + (BoxType-name (nullable-get boxType)))) + (def (resolvedBoxTypeIdOr + (boxType : (Nullable BoxType)) + (fallback : String)) + : + String + (if (nullable-null? boxType) + fallback + (BoxType-id (nullable-get boxType)))) + (def (boxTypeRawIsWeapon (context : Context) (raw : String)) + : + Bool + (let ([text (string-trim raw)]) + (if (string-blank? text) + #f + (boxTypeIsWeapon + (resolvedBoxTypeNameOr + (boxTypesResolveAndroid context text) + text))))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BoxTypeCsv.ss @@ -0,0 +1,39 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BoxTypeCsv.kt" + (typed-library (com sfb ssdreview) + (export parseBoxTypeCsvLine boxTypesFromCsvText) + (extern + (boxTypeCsvStringLines (text : String)) + : + (List String) + (kotlin-member-call lines)) + (def (parseBoxTypeCsvLine (line : String)) + : + (Nullable BoxType) + (if (not (string-matches-regex? line "^[^,]+,.+$")) + (nullable-none BoxType) + (let ([id (string-trim + (string-substring-before line ","))] + [name (string-trim + (string-replace-regex + line + "^[^,]*," + ""))]) + (if (or (string-blank? id) (string-blank? name)) + (nullable-none BoxType) + (nullable-some (make-BoxType id name)))))) + (def (boxTypesFromCsvText (text : String)) + : + (MutableList BoxType) + (let ([lines (boxTypeCsvStringLines text)]) + (for/fold + ((items (mutable-list-empty BoxType))) + ((i (in-range (int32 1) (list-size lines)))) + (begin + (addNullableBoxType + items + (parseBoxTypeCsvLine (list-ref lines i))) + items)))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BoxTypeLabelAndroid.ss @@ -0,0 +1,87 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BoxTypeLabelAndroid.kt" + (kotlin-imports (android content Context)) + (typed-library (com sfb ssdreview) + (export + defaultLabelForBoxTypeAndroid + resolvedLabelForBoxTypeAndroid + shouldReplaceLabelForBoxTypeAndroid + shouldKeepLabelForBoxTypeAndroid) + (type Context) + (extern + (boxTypesResolve (context : Context) (raw : String)) + : + (Nullable BoxType) + (kotlin-call boxTypesResolveAndroid)) + (def (nullableBoxTypeName (boxType : (Nullable BoxType))) + : + (Nullable String) + (if (nullable-null? boxType) + (nullable-none String) + (nullable-some (BoxType-name (nullable-get boxType))))) + (def (nullableBoxTypeDisplay (boxType : (Nullable BoxType))) + : + (Nullable String) + (if (nullable-null? boxType) + (nullable-none String) + (nullable-some + (box-type-display (nullable-get boxType))))) + (def (boxTypeLabelMatchesAndroid + (context : Context) + (label : String) + (boxType : String)) + : + Bool + (let ([resolved (boxTypesResolve context boxType)]) + (boxTypeLabelMatches + label + boxType + (nullableBoxTypeName resolved) + (nullableBoxTypeDisplay resolved)))) + (def (defaultLabelForBoxTypeAndroid + (context : Context) + (boxType : String)) + : + String + (defaultBoxTypeLabel + boxType + (nullableBoxTypeName (boxTypesResolve context boxType)))) + (def (resolvedLabelForBoxTypeAndroid + (context : Context) + (label : String) + (boxType : String) + (previousBoxType : String)) + : + String + (resolvedBoxTypeLabel + label + (defaultLabelForBoxTypeAndroid context boxType) + (boxTypeLabelMatchesAndroid + context + (string-trim label) + previousBoxType))) + (def (shouldReplaceLabelForBoxTypeAndroid + (context : Context) + (label : String) + (previousBoxType : String)) + : + Bool + (shouldReplaceBoxTypeLabel + label + (boxTypeLabelMatchesAndroid + context + (string-trim label) + previousBoxType))) + (def (shouldKeepLabelForBoxTypeAndroid + (context : Context) + (label : String) + (previousBoxType : String)) + : + Bool + (not (shouldReplaceLabelForBoxTypeAndroid + context + label + previousBoxType))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BoxTypeResolve.ss @@ -0,0 +1,125 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BoxTypeResolve.kt" + (typed-library (com sfb ssdreview) (export resolveBoxType boxTypeIsWeapon) + (type Int32) + (record + BoxTypeMatch + ((count : Int32) (found : (Nullable BoxType)))) + (def (boxTypeCompact (value : String)) + : + String + (string-filter-letter-or-digit (string-lowercase value))) + (def (boxTypeNonWeaponTerm? (normalized : String)) + : + Bool + (string-matches-regex? + normalized + ".*(charge|degradation|fighterbox|hangar|hit|internalweaponbay|link|mechlink|rail|round|stabilizer|targetaccentuator|targetacquisitiongear|targetacquisitionguide).*")) + (def (boxTypeWeaponTerm? (normalized : String)) + : + Bool + (string-matches-regex? + normalized + ".*(add|antiproton|atomicmissile|axiontorpedo|bioelectricbolt|bombthrower|bosondrill|cannon|clusterbomb|deathboltrack|disruptor|drone|energyhowitzer|esg|fireball|fusion|gausscannon|hellbore|hellgun|hypercannon|hyperdrone|implosionbolt|implosiontorpedo|ioncannon|ionpulsecannon|kineticcannon|kineticwave|laser|massdriver|megaphaser|missile|mine|morter|mortar|neutronbeam|neutrongun|novacannon|optionmount|particlebeam|particlecannon|phaser|photon|plasma|positronlancet|ppd|prospectingcannon|proton|pulsecannon|pulseemitter|quantumcannon|railgun|rocket|sfg|shortrangecannon|sonicpulser|spaceauger|stingtorpedo|subspacerocket|tachyonbeam|tachyongun|tachyonmissile|torp|torpedo|trh|trl|webbreaker|webcaster|websnare).*")) + (def (boxTypeIsWeapon (raw : String)) + : + Bool + (let ([normalized (boxTypeCompact raw)]) + (if (string-blank? normalized) + #f + (if (boxTypeNonWeaponTerm? normalized) + #f + (boxTypeWeaponTerm? normalized))))) + (def (boxTypeExactMatch + (box : BoxType) + (text : String) + (lowered : String) + (normalized : String)) + : + Bool + (or (equal? (BoxType-id box) text) + (or (equal? + (string-lowercase (box-type-display box)) + lowered) + (or (equal? + (string-lowercase (BoxType-name box)) + lowered) + (equal? + (boxTypeCompact (BoxType-name box)) + normalized))))) + (def (boxTypePartialMatch + (box : BoxType) + (lowered : String) + (normalized : String)) + : + Bool + (or (string-contains? + (string-lowercase (box-type-display box)) + lowered) + (string-contains? + (boxTypeCompact (BoxType-name box)) + normalized))) + (def (findExactBoxType + (items : (List BoxType)) + (text : String) + (lowered : String) + (normalized : String)) + : + (Nullable BoxType) + (for/fold + ((found (nullable-none BoxType))) + ((i (in-range (int32 0) (list-size items)))) + (if (nullable-null? found) + (let ([box (list-ref items i)]) + (if (boxTypeExactMatch box text lowered normalized) + (nullable-some box) + found)) + found))) + (def (findPartialBoxTypes + (items : (List BoxType)) + (lowered : String) + (normalized : String)) + : + BoxTypeMatch + (for/fold + ((match (make-BoxTypeMatch + (int32 0) + (nullable-none BoxType)))) + ((i (in-range (int32 0) (list-size items)))) + (let ([box (list-ref items i)]) + (if (boxTypePartialMatch box lowered normalized) + (make-BoxTypeMatch + (+ (BoxTypeMatch-count match) (int32 1)) + (nullable-some box)) + match)))) + (def (singleBoxTypeMatch (match : BoxTypeMatch)) + : + (Nullable BoxType) + (if (= (BoxTypeMatch-count match) (int32 1)) + (BoxTypeMatch-found match) + (nullable-none BoxType))) + (def (resolveBoxType + (items : (List BoxType)) + (raw : String)) + : + (Nullable BoxType) + (let ([text (string-trim raw)]) + (if (string-blank? text) + (nullable-none BoxType) + (let ([normalized (boxTypeCompact text)] + [lowered (string-lowercase text)]) + (let ([exact (findExactBoxType + items + text + lowered + normalized)]) + (if (nullable-null? exact) + (singleBoxTypeMatch + (findPartialBoxTypes + items + lowered + normalized)) + exact)))))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/ButtonKind.ss @@ -0,0 +1,41 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/ButtonKind.kt" + (typed-library (com sfb ssdreview) (export ButtonKind) (type Int32) + (type Float32) + (enum ButtonKind + ((backgroundColor : Int32) + (foregroundColor : Int32) + (textSp : Float32) + (heightDp : Int32)) + (PRIMARY + (reviewPrimaryColor) + (reviewWhiteColor) + (float32 18.0) + (int32 56)) + (ACCENT + (reviewAccentColor) + (reviewWhiteColor) + (float32 18.0) + (int32 56)) + (MODE + (reviewModeColor) + (reviewDarkTextColor) + (float32 17.0) + (int32 54)) + (NAV (reviewNavColor) + (reviewWhiteColor) + (float32 17.0) + (int32 52)) + (NEUTRAL + (reviewNeutralColor) + (reviewDarkTextColor) + (float32 15.0) + (int32 48)) + (DANGER + (reviewDangerColor) + (reviewWhiteColor) + (float32 16.0) + (int32 50))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/BytesHex.ss @@ -0,0 +1,12 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/BytesHex.kt" + (typed-library + (com sfb ssdreview) + (export bytesToLowerHex) + (def (bytesToLowerHex (bytes : Bytes)) + : + String + (bytes->lower-hex bytes)))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/ClientCrash.ss @@ -0,0 +1,37 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/ClientCrash.kt" + (kotlin-imports + (java lang Thread) + (java lang Thread UncaughtExceptionHandler)) + (typed-library (com sfb ssdreview) (export finishUncaughtException) + (type Int32) (type Thread) (type Throwable) + (type UncaughtExceptionHandler) + (extern + (systemExit (code : Int32)) + : + Unit + (kotlin-call java lang System exit)) + (extern + (handlerUncaughtException + (handler : UncaughtExceptionHandler) + (crashingThread : Thread) + (error : Throwable)) + : + Unit + (kotlin-member-call uncaughtException)) + (def (finishUncaughtException + (handler : (Nullable UncaughtExceptionHandler)) + (crashingThread : Thread) + (error : Throwable) + (exitCode : Int32)) + : + Unit + (if (nullable-null? handler) + (systemExit exitCode) + (handlerUncaughtException + (nullable-get handler) + crashingThread + error))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/ClientCrashInstall.ss @@ -0,0 +1,155 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/ClientCrashInstall.kt" + (kotlin-imports + (java lang Runnable) + (java lang Thread) + (java lang Thread UncaughtExceptionHandler) + (org json JSONObject)) + (typed-library (com sfb ssdreview) + (export mainActivityInstallClientCrashLoggerHandler) + (type Int) (type Int32) (type Exception) (type Runnable) + (type Thread) (type Throwable) + (type UncaughtExceptionHandler) (type JSONObject) + (type MainActivity) + (extern + (threadDefaultUncaughtExceptionHandlerRaw) + : + (Nullable UncaughtExceptionHandler) + (kotlin-call Thread getDefaultUncaughtExceptionHandler)) + (extern + (threadSetDefaultUncaughtExceptionHandlerRaw + (handler : UncaughtExceptionHandler)) + : + Unit + (kotlin-call Thread setDefaultUncaughtExceptionHandler)) + (extern + (makeCrashThread (runnable : Runnable)) + : + Thread + (kotlin-call Thread)) + (extern + (threadStartCrashRaw (thread : Thread)) + : + Unit + (kotlin-member-call start)) + (extern + (threadJoinCrashRaw (thread : Thread) (timeoutMillis : Int)) + : + Unit + (kotlin-member-call join)) + (extern + (threadNameRaw (thread : Thread)) + : + String + (kotlin-member-get name)) + (extern + (mainActivityCrashLogPayloadRaw + (activity : MainActivity) + (event : String) + (fields : JSONObject)) + : + JSONObject + (kotlin-call mainActivityClientLogPayloadRaw)) + (extern + (sendClientLogBlockingRawForCrash + (payload : JSONObject) + (readTimeoutMillis : Int32)) + : + Unit + (kotlin-call sendClientLogBlocking)) + (extern + (mainActivityThrowableLogRaw (error : Throwable)) + : + JSONObject + (kotlin-call throwableLogJsonForThrowable)) + (def (startCrashSenderThread + (activity : MainActivity) + (payload : JSONObject) + (readTimeoutMillis : Int32)) + : + Thread + (let ([sender (makeCrashThread + (object + Runnable + (override + (run) + : + Unit + (mainActivityCrashSendClientLogRaw + activity + payload + readTimeoutMillis))))]) + (begin (threadStartCrashRaw sender) sender))) + (def (mainActivityCrashSendClientLogRaw + (activity : MainActivity) + (payload : JSONObject) + (readTimeoutMillis : Int32)) + : + Unit + (sendClientLogBlockingRawForCrash + payload + readTimeoutMillis)) + (def (crashPayloadFor + (activity : MainActivity) + (crashingThread : Thread) + (throwable : Throwable)) + : + JSONObject + (try (mainActivityCrashLogPayloadRaw + activity + "ssd-uncaught-exception" + (clientLogCrashFields + (nullableTextOrEmpty + (nullable-some (threadNameRaw crashingThread))) + (mainActivityThrowableLogRaw throwable))) + (catch + (error : Exception) + (clientLogFallbackPayload + "ssd-uncaught-exception")))) + (def (sendCrashPayloadBlocking + (activity : MainActivity) + (payload : JSONObject) + (readTimeoutMillis : Int32) + (joinTimeoutMillis : Int)) + : + Unit + (try (let ([sender (startCrashSenderThread + activity + payload + readTimeoutMillis)]) + (threadJoinCrashRaw sender joinTimeoutMillis)) + (catch (error : Exception) (begin)))) + (def (mainActivityInstallClientCrashLoggerHandler + (activity : MainActivity) + (readTimeoutMillis : Int32) + (joinTimeoutMillis : Int)) + : + Unit + (let ([previous (threadDefaultUncaughtExceptionHandlerRaw)]) + (threadSetDefaultUncaughtExceptionHandlerRaw + (object + UncaughtExceptionHandler + (override + (uncaughtException + (crashingThread : Thread) + (throwable : Throwable)) + : + Unit + (let ([payload (crashPayloadFor + activity + crashingThread + throwable)]) + (begin + (sendCrashPayloadBlocking + activity + payload + readTimeoutMillis + joinTimeoutMillis) + (finishUncaughtException + previous + crashingThread + throwable + (int32 2))))))))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/ClientLogJson.ss @@ -0,0 +1,143 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/ClientLogJson.kt" + (kotlin-imports (org json JSONObject)) + (typed-library (com sfb ssdreview) + (export clientLogPayloadJson clientLogCrashFields + clientLogFallbackPayload appLogPackageInfo appLogVersionInfo + androidPackageVersionCode deviceLogInfoJson throwableLogJson + statusLogFields truncateClientLogStack) + (type JSONObject) (type Int) (type Int32) (type String) + (def (clientLogPdfJson + (pdfName : String) + (page : Int32) + (pageCount : Int32)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-string! out "name" pdfName) + (json-object-put-int32! out "page" page) + (json-object-put-int32! out "pages" pageCount) + out))) + (def (clientLogPayloadJson (event : String) (uptimeMs : Int) (threadName : String) + (app : JSONObject) (device : JSONObject) + (pdfName : String) (page : Int32) (pageCount : Int32) + (selectedGroupId : String) (fields : JSONObject)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-int32! out "schema" (int32 1)) + (json-object-put-string! out "event" event) + (json-object-put-int! + out + "client-time-ms" + (system-current-time-millis)) + (json-object-put-int! out "uptime-ms" uptimeMs) + (json-object-put-string! out "thread" threadName) + (json-object-put-json-object! out "app" app) + (json-object-put-json-object! out "device" device) + (json-object-put-json-object! + out + "pdf" + (clientLogPdfJson pdfName page pageCount)) + (json-object-put-string! + out + "selected-group" + selectedGroupId) + (json-object-put-json-object! out "fields" fields) + out))) + (def (clientLogCrashFields + (threadName : String) + (error : JSONObject)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-string! + out + "crashing-thread" + threadName) + (json-object-put-json-object! out "error" error) + out))) + (def (clientLogFallbackPayload (event : String)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin (json-object-put-string! out "event" event) out))) + (def (appLogPackageInfo (packageName : String)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-string! out "package" packageName) + out))) + (def (appLogVersionInfo + (packageName : String) + (versionName : String) + (versionCode : Int)) + : + JSONObject + (let ([out (appLogPackageInfo packageName)]) + (begin + (json-object-put-string! + out + "version-name" + versionName) + (json-object-put-int! out "version-code" versionCode) + out))) + (def (androidPackageVersionCode + (sdk : Int32) + (apiP : Int32) + (longVersionCode : Int) + (legacyVersionCode : Int)) + : + Int + (if (>= sdk apiP) longVersionCode legacyVersionCode)) + (def (deviceLogInfoJson + (sdk : Int32) + (release : String) + (manufacturer : String) + (model : String)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-int32! out "sdk" sdk) + (json-object-put-string! out "release" release) + (json-object-put-string! + out + "manufacturer" + manufacturer) + (json-object-put-string! out "model" model) + out))) + (def (throwableLogJson + (className : String) + (message : String) + (stack : String)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-string! out "class" className) + (json-object-put-string! out "message" message) + (json-object-put-string! out "stack" stack) + out))) + (def (truncateClientLogStack (stack : String)) + : + String + (if (<= (string-length stack) 12000) + stack + (string-append + (string-take stack (int32 12000)) + "...[truncated]"))) + (def (statusLogFields (text : String)) + : + JSONObject + (let ([out (json-object-empty)]) + (begin + (json-object-put-string! out "status" text) + out))))))) new file mode 100644 --- /dev/null +++ b/templates/ssd-review-parts/ClientLogTransport.ss @@ -0,0 +1,201 @@ +(import (jerboa prelude)) + +(def fragment + '((typed-kotlin-file + "com/sfb/ssdreview/ClientLogTransport.kt" + (kotlin-imports (java io InputStream) (java io OutputStream) (java net URL) + (java net URLConnection) (javax net ssl HttpsURLConnection) + (org json JSONObject)) + (typed-library (com sfb ssdreview) + (export sendClientLogBlocking) (type Exception) + (type HttpsURLConnection) (type InputStream) (type Int) + (type Int32) (type JSONObject) (type OutputStream) + (type URL) (type URLConnection) + (extern + (clientLogEndpointValue) + : + String + (kotlin-value CLIENT_LOG_ENDPOINT)) + (extern + (clientLogConnectTimeoutMillisValue) + : + Int32 + (kotlin-value CLIENT_LOG_CONNECT_TIMEOUT_MS)) + (extern + (clientLogUrl (value : String)) + : + URL + (kotlin-call URL)) + (extern + (clientLogOpenConnection (url : URL)) + : + URLConnection + (kotlin-member-call openConnection)) + (extern + (clientLogHttpsConnection (connection : URLConnection)) + : + HttpsURLConnection + (kotlin-cast HttpsURLConnection)) + (extern + (clientLogJsonToString (payload : JSONObject)) + : + String + (kotlin-member-call toString)) + (extern + (clientLogConnectionRequestMethodSet + (connection : HttpsURLConnection) + (method : String)) + : + Unit + (kotlin-member-set requestMethod)) + (extern + (clientLogConnectionConnectTimeoutSet + (connection : HttpsURLConnection) + (timeoutMillis : Int32)) + : + Unit + (kotlin-member-set connectTimeout)) + (extern + (clientLogConnectionReadTimeoutSet + (connection : HttpsURLConnection) + (timeoutMillis : Int32)) + : + Unit + (kotlin-member-set readTimeout)) + (extern + (clientLogConnectionDoOutputSet + (connection : HttpsURLConnection) + (enabled : Bool)) + : + Unit + (kotlin-member-set doOutput)) + (extern + (clientLogConnectionSetRequestProperty + (connection : HttpsURLConnection) + (name : String) + (value : String)) + : + Unit + (kotlin-member-call setRequestProperty)) + (extern + (clientLogConnectionSetFixedLengthStreamingMode + (connection : HttpsURLConnection) + (length : Int)) + : + Unit + (kotlin-member-call setFixedLengthStreamingMode)) + (extern + (clientLogConnectionOutputStream + (connection : HttpsURLConnection)) + :