From 6cf0e927b7f8441dd7a77d91ff7e3761d6ed32f5 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Thu, 30 Apr 2026 17:36:05 -0400 Subject: [PATCH 01/16] jsi perf test --- plans/jsi-perf.md | 101 ++++ .../react-native-kb/android/CMakeLists.txt | 22 +- .../react-native-kb/android/build.gradle | 14 +- .../cpp/react-native-kb-experiments.h | 27 + .../react-native-kb/cpp/react-native-kb.cpp | 487 ++++++++++++++++-- .../react-native-kb/cpp/react-native-kb.h | 46 ++ .../react-native-kb/react-native-kb.podspec | 11 +- shared/globals.d.ts | 30 ++ 8 files changed, 697 insertions(+), 41 deletions(-) create mode 100644 plans/jsi-perf.md create mode 100644 rnmodules/react-native-kb/cpp/react-native-kb-experiments.h diff --git a/plans/jsi-perf.md b/plans/jsi-perf.md new file mode 100644 index 000000000000..bf3b0e637410 --- /dev/null +++ b/plans/jsi-perf.md @@ -0,0 +1,101 @@ +# JSI Performance Evaluation Plan + +## Summary + +Keybase is on RN 0.83.4 with New Architecture and Hermes enabled. RN's public TurboModule Codegen surface still does not document ArrayBuffer or typed-array parameters, but RN's C++ JSI API exposes MutableBuffer, ArrayBuffer, direct buffer data access, NativeState, and runtime data. The evaluation should focus on our pure C++ JSI bridge in react-native-kb, not on moving the RPC pipe to normal TurboModule methods. + +## Progress + +- [x] Added build-time experiment switches so baseline and prototype bridge implementations can be built separately. +- [x] Added an optional outbound Uint8Array fast path controlled by `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH`. +- [x] Added benchmark-only measurement hooks controlled by `KB_JSI_PERF`. +- [x] Added inbound binary prototypes controlled by `KB_JSI_INBOUND_BINARY_MODE`. +- [ ] Run the benchmark-only workflow on a machine with installed JS/native toolchains. + +## Evaluation Targets + +- Benchmark current bridge costs in react-native-kb: rpcOnGo, rpcOnJs, msgpack encode/decode, object/map walking, string conversion, binary payload handling, JNI/ObjC copies, and batching. +- Prototype, in benchmark-only code, creating inbound binary values via jsi::MutableBuffer + Runtime::createArrayBuffer instead of constructing Uint8Array(size) and copying into its buffer. +- Test whether JS can safely accept ArrayBuffer directly for msgpack binary fields; if not, measure new Uint8Array(arrayBuffer) wrapping versus the current constructor path. +- Evaluate typed-array detection in convertJSIToMP: avoid getPropertyNames() before checking ArrayBuffer/typed-array-like objects when payloads contain binary data. +- Evaluate NativeState only for JS-visible stateful native objects; current hot RPC function does not need it, and the existing teardown HostObject is not a hot path. +- Evaluate runtime/engine compatibility explicitly against Hermes current, Hermes V1, and JSC fallback assumptions before adopting any ArrayBuffer-backed fast path. + +## API Policy + +- Preserve the existing JS contract: global.rpcOnGo(message) and global.rpcOnJs(objs, count). +- Do not migrate this RPC pipe to normal TurboModule methods unless benchmarks show a clear win; Codegen's documented type surface is currently weaker for arbitrary msgpack/binary payloads. +- Any binary representation change must be behavior-compatible with existing RPC consumers, especially code expecting Uint8Array rather than ArrayBuffer. + +## Test Plan + +- Add native round-trip tests or a standalone benchmark harness for nulls, booleans, integers, floats, strings, maps, arrays, empty objects, ArrayBuffer, Uint8Array, and large binary blobs. +- Measure before/after on representative RPC shapes: small method calls, nested maps, chat/message payloads, and binary-heavy payloads. +- Use RN 0.83 Web Performance APIs / DevTools Performance panel for JS-side timing where useful. +- Do not run yarn, npm, yarn lint, or yarn tsc on this machine because node_modules is absent. + +## Run / Evaluation Notes + +- Keep all measurements benchmark-only until the current bridge baseline is captured and compared against any ArrayBuffer-backed prototype. +- This machine cannot run the JS validation or benchmark workflow because `node_modules` is absent; do not run `yarn`, `npm`, `yarn lint`, `yarn tsc`, or other node-based tooling here. +- Local work on this machine is limited to code/document inspection and source updates. Run the benchmark harness, RN build, and validation on a machine with dependencies installed. +- The remaining unchecked item is the actual run/result capture step on a runnable environment. + +## Experiment Matrix + +Default build behavior is the baseline: + +- `KB_JSI_INBOUND_BINARY_MODE=0`: current inbound BIN behavior, `Uint8Array(size)` plus copy into its buffer. +- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=0`: current outbound typed-array detection order, using `getPropertyNames()` before the broad shape probe. +- `KB_JSI_PERF=0`: no benchmark globals or counters. + +Prototype builds: + +- `KB_JSI_INBOUND_BINARY_MODE=1`: inbound BIN becomes a direct `ArrayBuffer` backed by `jsi::MutableBuffer`. This is expected to change JS-visible behavior and must not ship without consumer validation. +- `KB_JSI_INBOUND_BINARY_MODE=2`: inbound BIN uses `jsi::MutableBuffer` + `createArrayBuffer`, then wraps with `new Uint8Array(arrayBuffer)` to preserve the expected JS `Uint8Array` shape. +- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=1`: outbound encode checks `instanceof Uint8Array` before property enumeration and keeps the old broad shape probe as fallback. +- `KB_JSI_PERF=1`: installs `global.kbJSIExperimentConfig` and `global.kbJSIPerf`. + +Android build knobs are CMake/Gradle properties: + +- `Kb_JSI_INBOUND_BINARY_MODE=0|1|2` +- `Kb_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=OFF|ON` +- `Kb_JSI_PERF=OFF|ON` + +iOS build knobs are environment variables consumed by the podspec: + +- `KB_JSI_INBOUND_BINARY_MODE=0|1|2` +- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=0|1` +- `KB_JSI_PERF=0|1` + +Benchmark globals when `KB_JSI_PERF=1`: + +- `global.kbJSIExperimentConfig`: confirms which experiment was compiled into the app. +- `global.kbJSIPerf.stats()`: returns counters for `rpcOnGo`, encode, frame copy, native write, inbound unpack, JSI conversion, and `rpcOnJs` call time. +- `global.kbJSIPerf.reset()`: clears counters. +- `global.kbJSIPerf.makeBinary(size, mode)`: returns benchmark binary values for `uint8Array`, `arrayBuffer`, or `wrappedUint8Array`. +- `global.kbJSIPerf.roundTrip(value, iterations, mode)`: msgpack-encodes and decodes a value in native code; decode mode is `uint8Array`, `arrayBuffer`, or `wrappedUint8Array`. + +Validation shape: + +- Build baseline with `KB_JSI_PERF=1`, all other experiment knobs at defaults, and capture `kbJSIPerf.stats()` during normal app RPC traffic. +- Build each prototype separately and compare behavior with the same RPC flows. +- For binary behavior, compare `roundTrip` results with values covering nulls, booleans, integers, floats, strings, maps, arrays, empty objects, `ArrayBuffer`, `Uint8Array`, sliced `Uint8Array`, and large binary blobs. + +Example JS console checks in a `KB_JSI_PERF=1` build: + +- `global.kbJSIExperimentConfig` +- `const bin = global.kbJSIPerf.makeBinary(1024, 'uint8Array')` +- `global.kbJSIPerf.roundTrip({bin, nested: [bin]}, 1000, 'uint8Array').value.bin instanceof Uint8Array` +- `global.kbJSIPerf.roundTrip({bin}, 1000, 'arrayBuffer').value.bin instanceof ArrayBuffer` +- `global.kbJSIPerf.roundTrip({bin}, 1000, 'wrappedUint8Array').value.bin instanceof Uint8Array` +- `global.kbJSIPerf.stats()` + +## Sources + +- React Native New Architecture docs: https://reactnative.dev/architecture/landing-page +- RN 0.83 Native Modules docs: https://reactnative.dev/docs/0.83/turbo-native-modules-introduction +- RN Codegen typings appendix: https://reactnative.dev/docs/appendix +- RN 0.83.4 JSI header: https://raw.githubusercontent.com/facebook/react-native/v0.83.4/packages/react-native/ReactCommon/jsi/jsi/jsi.h +- RN 0.83 release notes: https://reactnative.dev/blog/2025/12/10/react-native-0.83 +- Margelo JSI performance post: https://blog.margelo.com/make-jsi-run-faster diff --git a/rnmodules/react-native-kb/android/CMakeLists.txt b/rnmodules/react-native-kb/android/CMakeLists.txt index 92cacd494863..5a552f9d491a 100644 --- a/rnmodules/react-native-kb/android/CMakeLists.txt +++ b/rnmodules/react-native-kb/android/CMakeLists.txt @@ -4,6 +4,16 @@ cmake_minimum_required(VERSION 3.4.1) set (CMAKE_VERBOSE_MAKEFILE ON) set (CMAKE_CXX_STANDARD 20) set (NODE_MODULES_DIR "${CMAKE_SOURCE_DIR}/../..") +set (KB_JSI_INBOUND_BINARY_MODE "0" CACHE STRING "0=current Uint8Array, 1=MutableBuffer ArrayBuffer, 2=MutableBuffer wrapped Uint8Array") +set_property(CACHE KB_JSI_INBOUND_BINARY_MODE PROPERTY STRINGS "0" "1" "2") +option(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH "Check Uint8Array before object property enumeration" OFF) +option(KB_JSI_PERF "Install benchmark-only JSI performance hooks" OFF) + +if(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH) + set(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE 1) +else() + set(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE 0) +endif() add_library(cpp SHARED @@ -26,7 +36,17 @@ set_target_properties( POSITION_INDEPENDENT_CODE ON ) -add_definitions(-DMSGPACK_NO_BOOST) +target_compile_definitions( + cpp + PRIVATE + MSGPACK_NO_BOOST + KB_JSI_INBOUND_BINARY_MODE=${KB_JSI_INBOUND_BINARY_MODE} + KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=${KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE} +) + +if(KB_JSI_PERF) + target_compile_definitions(cpp PRIVATE KB_JSI_PERF=1) +endif() find_package(ReactAndroid REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) diff --git a/rnmodules/react-native-kb/android/build.gradle b/rnmodules/react-native-kb/android/build.gradle index 727944b90e8c..d4af7389c7dd 100644 --- a/rnmodules/react-native-kb/android/build.gradle +++ b/rnmodules/react-native-kb/android/build.gradle @@ -35,11 +35,20 @@ def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Kb_" + name]).toInteger() } +def getKbExperimentOrDefault(name, defaultValue) { + def key = "Kb_" + name + return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.findProperty(key) ?: defaultValue) +} + def reactNativeArchitectures() { def value = project.getProperties().get('reactNativeArchitectures') return value ? value.split(',') : ['armeabi-v7a', 'x86', 'x86_64', 'arm64-v8a'] } +def kbJsiInboundBinaryMode = getKbExperimentOrDefault("JSI_INBOUND_BINARY_MODE", "0") +def kbJsiOutboundTypedArrayFastpath = getKbExperimentOrDefault("JSI_OUTBOUND_TYPED_ARRAY_FASTPATH", "OFF") +def kbJsiPerf = getKbExperimentOrDefault("JSI_PERF", "OFF") + android { ndkVersion getExtOrDefault("ndkVersion") compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") @@ -54,7 +63,10 @@ android { externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" - arguments '-DANDROID_STL=c++_shared' + arguments '-DANDROID_STL=c++_shared', + "-DKB_JSI_INBOUND_BINARY_MODE=${kbJsiInboundBinaryMode}", + "-DKB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=${kbJsiOutboundTypedArrayFastpath}", + "-DKB_JSI_PERF=${kbJsiPerf}" abiFilters(*reactNativeArchitectures()) } } diff --git a/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h b/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h new file mode 100644 index 000000000000..e3e50cd8d8e8 --- /dev/null +++ b/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h @@ -0,0 +1,27 @@ +#pragma once + +#ifndef KB_JSI_INBOUND_BINARY_MODE +#define KB_JSI_INBOUND_BINARY_MODE 0 +#endif + +#ifndef KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH +#define KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH 0 +#endif + +#ifndef KB_JSI_PERF +#define KB_JSI_PERF 0 +#endif + +#if KB_JSI_INBOUND_BINARY_MODE < 0 || KB_JSI_INBOUND_BINARY_MODE > 2 +#error "KB_JSI_INBOUND_BINARY_MODE must be 0, 1, or 2" +#endif + +#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 0 && \ + KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 1 +#error "KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH must be 0 or 1" +#endif + +#if KB_JSI_PERF || KB_JSI_INBOUND_BINARY_MODE != 0 || \ + KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 0 +#define KB_JSI_EXPERIMENTS_ENABLED 1 +#endif diff --git a/rnmodules/react-native-kb/cpp/react-native-kb.cpp b/rnmodules/react-native-kb/cpp/react-native-kb.cpp index ef1be84eead8..da16e5f6248b 100644 --- a/rnmodules/react-native-kb/cpp/react-native-kb.cpp +++ b/rnmodules/react-native-kb/cpp/react-native-kb.cpp @@ -1,6 +1,8 @@ #include "react-native-kb.h" +#include #include #include +#include #include "msgpack-safe.hpp" #include @@ -14,6 +16,33 @@ struct KBBridge::MsgpackState { msgpack::sbuffer sendBuf; }; +class KBMutableBuffer final : public MutableBuffer { +public: + explicit KBMutableBuffer(size_t size) : bytes_(size) {} + size_t size() const override { return bytes_.size(); } + uint8_t *data() override { return bytes_.data(); } + +private: + std::vector bytes_; +}; + +#if KB_JSI_PERF +using KBPerfClock = std::chrono::steady_clock; + +static uint64_t perfNanosSince(KBPerfClock::time_point start) { + return static_cast( + std::chrono::duration_cast( + KBPerfClock::now() - start) + .count()); +} + +static void fillPerfBytes(uint8_t *data, size_t size) { + for (size_t i = 0; i < size; ++i) { + data[i] = static_cast(i & 0xff); + } +} +#endif + KBBridge::KBBridge() = default; KBBridge::~KBBridge() = default; @@ -37,6 +66,43 @@ void KBBridge::resetCaches(Runtime &runtime) { } } +Function &KBBridge::uint8ArrayCtor(Runtime &runtime) { + resetCaches(runtime); + if (!cachedUint8ArrayCtor_) { + auto ctor = runtime.global().getPropertyAsFunction(runtime, "Uint8Array"); + cachedUint8ArrayCtor_ = std::make_unique(std::move(ctor)); + } + return *cachedUint8ArrayCtor_; +} + +Value KBBridge::binaryFromBytes(Runtime &runtime, const char *ptr, size_t size, + BinaryMode mode) { + if (mode == BinaryMode::uint8ArrayCtor) { + Value uint8Array = uint8ArrayCtor(runtime).callAsConstructor( + runtime, static_cast(size)); + Object uint8ArrayObj = uint8Array.asObject(runtime); + ArrayBuffer buffer = uint8ArrayObj.getProperty(runtime, "buffer") + .asObject(runtime) + .getArrayBuffer(runtime); + if (size > 0) { + std::memcpy(buffer.data(runtime), ptr, size); + } + return uint8Array; + } + + auto mutableBuffer = std::make_shared(size); + if (size > 0) { + std::memcpy(mutableBuffer->data(), ptr, size); + } + ArrayBuffer arrayBuffer(runtime, mutableBuffer); + if (mode == BinaryMode::mutableArrayBuffer) { + return arrayBuffer; + } + + Value arrayBufferArg(std::move(arrayBuffer)); + return uint8ArrayCtor(runtime).callAsConstructor(runtime, &arrayBufferArg, 1); +} + static std::string mpToString(msgpack::object &o) { switch (o.type) { case msgpack::type::STR: @@ -96,23 +162,15 @@ Value KBBridge::convertMPToJSI(Runtime &runtime, void *mpObj) { } case msgpack::type::BIN: { auto ptr = o.via.bin.ptr; - int size = o.via.bin.size; - - resetCaches(runtime); - if (!cachedUint8ArrayCtor_) { - auto ctor = - runtime.global().getPropertyAsFunction(runtime, "Uint8Array"); - cachedUint8ArrayCtor_ = std::make_unique(std::move(ctor)); - } - - Value uint8Array = - cachedUint8ArrayCtor_->callAsConstructor(runtime, size); - Object uint8ArrayObj = uint8Array.asObject(runtime); - ArrayBuffer buffer = uint8ArrayObj.getProperty(runtime, "buffer") - .asObject(runtime) - .getArrayBuffer(runtime); - std::memcpy(buffer.data(runtime), ptr, size); - return uint8Array; + auto size = o.via.bin.size; +#if KB_JSI_INBOUND_BINARY_MODE == 1 + return binaryFromBytes(runtime, ptr, size, BinaryMode::mutableArrayBuffer); +#elif KB_JSI_INBOUND_BINARY_MODE == 2 + return binaryFromBytes(runtime, ptr, size, + BinaryMode::mutableWrappedUint8Array); +#else + return binaryFromBytes(runtime, ptr, size, BinaryMode::uint8ArrayCtor); +#endif } case msgpack::type::ARRAY: { auto size = o.via.array.size; @@ -154,11 +212,32 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, pk.pack(str); } else if (value.isObject()) { auto obj = value.getObject(runtime); + auto packArrayBufferBytesUnchecked = [&](ArrayBuffer &arrayBuf, + size_t offset, size_t length) { + pk.pack_bin(static_cast(length)); + pk.pack_bin_body( + reinterpret_cast(arrayBuf.data(runtime)) + offset, + static_cast(length)); + }; + auto packArrayBufferBytes = [&](ArrayBuffer &arrayBuf, size_t offset, + size_t length) { + auto bufferSize = arrayBuf.size(runtime); + if (offset > bufferSize || length > bufferSize - offset || + length > std::numeric_limits::max()) { + throw std::runtime_error("ArrayBuffer view is out of range"); + } + pk.pack_bin(static_cast(length)); + pk.pack_bin_body( + reinterpret_cast(arrayBuf.data(runtime)) + offset, + static_cast(length)); + }; if (obj.isArrayBuffer(runtime)) { auto buf = obj.getArrayBuffer(runtime); - pk.pack_bin(static_cast(buf.size(runtime))); - pk.pack_bin_body(reinterpret_cast(buf.data(runtime)), - static_cast(buf.size(runtime))); +#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH + packArrayBufferBytes(buf, 0, buf.size(runtime)); +#else + packArrayBufferBytesUnchecked(buf, 0, buf.size(runtime)); +#endif } else if (obj.isArray(runtime)) { auto arr = obj.getArray(runtime); auto len = arr.size(runtime); @@ -167,12 +246,12 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, convertJSIToMP(runtime, arr.getValueAtIndex(runtime, i), &pk); } } else { - auto names = obj.getPropertyNames(runtime); - auto len = names.size(runtime); - - // Probe for TypedArray (Uint8Array). Extracted as a lambda so it - // can be called from two sites without duplicating the logic. - auto tryPackTypedArray = [&]() -> bool { + auto tryPackTypedArray = [&](bool requireUint8Array, + bool validateView) -> bool { + if (requireUint8Array && + !obj.instanceOf(runtime, uint8ArrayCtor(runtime))) { + return false; + } auto byteLengthProp = obj.getProperty(runtime, "byteLength"); if (!byteLengthProp.isNumber()) return false; auto bufferProp = obj.getProperty(runtime, "buffer"); @@ -181,20 +260,39 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, if (!bufferObj.isArrayBuffer(runtime)) return false; auto arrayBuf = bufferObj.getArrayBuffer(runtime); auto byteOffset = obj.getProperty(runtime, "byteOffset"); - size_t offset = byteOffset.isNumber() - ? static_cast(byteOffset.getNumber()) - : 0; - size_t length = static_cast(byteLengthProp.getNumber()); - pk.pack_bin(static_cast(length)); - pk.pack_bin_body( - reinterpret_cast(arrayBuf.data(runtime)) + offset, - static_cast(length)); + auto byteLengthNum = byteLengthProp.getNumber(); + auto byteOffsetNum = + byteOffset.isNumber() ? byteOffset.getNumber() : 0; + if (validateView) { + if (!std::isfinite(byteOffsetNum) || + !std::isfinite(byteLengthNum) || byteOffsetNum < 0 || + byteLengthNum < 0 || byteOffsetNum != std::floor(byteOffsetNum) || + byteLengthNum != std::floor(byteLengthNum)) { + return false; + } + auto offset = static_cast(byteOffsetNum); + auto length = static_cast(byteLengthNum); + packArrayBufferBytes(arrayBuf, offset, length); + } else { + auto offset = static_cast(byteOffsetNum); + auto length = static_cast(byteLengthNum); + packArrayBufferBytesUnchecked(arrayBuf, offset, length); + } return true; }; +#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH + if (tryPackTypedArray(true, true)) { + return; + } +#endif + + auto names = obj.getPropertyNames(runtime); + auto len = names.size(runtime); + // Empty object: could be {} or empty TypedArray — must probe if (len == 0) { - if (tryPackTypedArray()) return; + if (tryPackTypedArray(false, false)) return; pk.pack_map(0); return; } @@ -206,7 +304,7 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, auto firstName = names.getValueAtIndex(runtime, 0).getString(runtime); auto firstStr = firstName.utf8(runtime); if (!firstStr.empty() && firstStr[0] >= '0' && firstStr[0] <= '9') { - if (tryPackTypedArray()) return; + if (tryPackTypedArray(false, false)) return; } // Regular object — encode as MAP @@ -223,11 +321,275 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, } } +#ifdef KB_JSI_EXPERIMENTS_ENABLED +void KBBridge::installExperimentBindings(Runtime &runtime) { + Object config(runtime); + config.setProperty(runtime, "inboundBinaryMode", + static_cast(KB_JSI_INBOUND_BINARY_MODE)); + config.setProperty(runtime, "outboundTypedArrayFastPath", + static_cast(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH)); +#if KB_JSI_PERF + config.setProperty(runtime, "perf", true); +#else + config.setProperty(runtime, "perf", false); +#endif + + const char *inboundBinaryModeName = "uint8ArrayCtor"; +#if KB_JSI_INBOUND_BINARY_MODE == 1 + inboundBinaryModeName = "mutableArrayBuffer"; +#elif KB_JSI_INBOUND_BINARY_MODE == 2 + inboundBinaryModeName = "mutableWrappedUint8Array"; +#endif + config.setProperty(runtime, "inboundBinaryModeName", + String::createFromUtf8(runtime, inboundBinaryModeName)); + runtime.global().setProperty(runtime, "kbJSIExperimentConfig", + std::move(config)); +} +#endif + +#if KB_JSI_PERF +void KBBridge::resetPerfCounters() { + perf_.rpcOnGoCalls.store(0); + perf_.rpcOnGoBytes.store(0); + perf_.encodeNs.store(0); + perf_.frameNs.store(0); + perf_.writeToGoNs.store(0); + perf_.onDataCalls.store(0); + perf_.onDataBytes.store(0); + perf_.inboundMessages.store(0); + perf_.unpackNs.store(0); + perf_.convertMPToJSINs.store(0); + perf_.rpcOnJsCalls.store(0); + perf_.rpcOnJsNs.store(0); +} + +Value KBBridge::perfStats(Runtime &runtime) { + Object stats(runtime); + stats.setProperty(runtime, "rpcOnGoCalls", + static_cast(perf_.rpcOnGoCalls.load())); + stats.setProperty(runtime, "rpcOnGoBytes", + static_cast(perf_.rpcOnGoBytes.load())); + stats.setProperty(runtime, "encodeNs", + static_cast(perf_.encodeNs.load())); + stats.setProperty(runtime, "frameNs", + static_cast(perf_.frameNs.load())); + stats.setProperty(runtime, "writeToGoNs", + static_cast(perf_.writeToGoNs.load())); + stats.setProperty(runtime, "onDataCalls", + static_cast(perf_.onDataCalls.load())); + stats.setProperty(runtime, "onDataBytes", + static_cast(perf_.onDataBytes.load())); + stats.setProperty(runtime, "inboundMessages", + static_cast(perf_.inboundMessages.load())); + stats.setProperty(runtime, "unpackNs", + static_cast(perf_.unpackNs.load())); + stats.setProperty(runtime, "convertMPToJSINs", + static_cast(perf_.convertMPToJSINs.load())); + stats.setProperty(runtime, "rpcOnJsCalls", + static_cast(perf_.rpcOnJsCalls.load())); + stats.setProperty(runtime, "rpcOnJsNs", + static_cast(perf_.rpcOnJsNs.load())); + stats.setProperty(runtime, "runtime", + String::createFromUtf8(runtime, runtime.description())); + return stats; +} + +Value KBBridge::convertMPToJSIPerf(Runtime &runtime, void *mpObj, + BinaryMode mode) { + auto &o = *static_cast(mpObj); + switch (o.type) { + case msgpack::type::STR: + return jsi::String::createFromUtf8( + runtime, reinterpret_cast(o.via.str.ptr), + o.via.str.size); + case msgpack::type::POSITIVE_INTEGER: + return jsi::Value(o.as()); + case msgpack::type::NEGATIVE_INTEGER: + return jsi::Value(o.as()); + case msgpack::type::FLOAT32: + return jsi::Value(o.as()); + case msgpack::type::FLOAT64: + return jsi::Value(o.as()); + case msgpack::type::BOOLEAN: + return jsi::Value(o.as()); + case msgpack::type::NIL: + return jsi::Value::null(); + case msgpack::type::EXT: + return jsi::Value::undefined(); + case msgpack::type::MAP: { + jsi::Object obj = jsi::Object(runtime); + auto *p = o.via.map.ptr; + auto *const pend = o.via.map.ptr + o.via.map.size; + for (; p < pend; ++p) { + auto val = convertMPToJSIPerf(runtime, &p->val, mode); + auto &k = p->key; + if (k.type == msgpack::type::STR) { + obj.setProperty( + runtime, + jsi::PropNameID::forUtf8( + runtime, reinterpret_cast(k.via.str.ptr), + k.via.str.size), + val); + } else { + auto keyStr = mpToString(k); + obj.setProperty(runtime, jsi::PropNameID::forUtf8(runtime, keyStr), + val); + } + } + return obj; + } + case msgpack::type::BIN: + return binaryFromBytes(runtime, o.via.bin.ptr, o.via.bin.size, mode); + case msgpack::type::ARRAY: { + auto size = o.via.array.size; + jsi::Array arr(runtime, size); + for (uint32_t i = 0; i < size; ++i) { + arr.setValueAtIndex( + runtime, i, convertMPToJSIPerf(runtime, &o.via.array.ptr[i], mode)); + } + return arr; + } + default: + return jsi::Value::undefined(); + } +} + +Value KBBridge::perfMakeBinary(Runtime &runtime, const Value *arguments, + size_t count) { + auto size = count > 0 && arguments[0].isNumber() + ? static_cast(arguments[0].getNumber()) + : 1024; + if (size > std::numeric_limits::max()) { + throw std::runtime_error("kbJSIPerf.makeBinary size is too large"); + } + + auto mode = BinaryMode::uint8ArrayCtor; + if (count > 1 && arguments[1].isString()) { + auto modeName = arguments[1].getString(runtime).utf8(runtime); + if (modeName == "arrayBuffer") { + mode = BinaryMode::mutableArrayBuffer; + } else if (modeName == "wrappedUint8Array") { + mode = BinaryMode::mutableWrappedUint8Array; + } + } + + auto bytes = std::make_shared(size); + fillPerfBytes(bytes->data(), size); + return binaryFromBytes(runtime, reinterpret_cast(bytes->data()), + size, mode); +} + +Value KBBridge::perfRoundTrip(Runtime &runtime, const Value *arguments, + size_t count) { + if (count == 0) { + throw std::runtime_error("kbJSIPerf.roundTrip needs a value"); + } + + auto iterations = count > 1 && arguments[1].isNumber() + ? static_cast(arguments[1].getNumber()) + : 100; + if (iterations == 0) { + iterations = 1; + } + + auto mode = BinaryMode::uint8ArrayCtor; + const char *modeName = "uint8Array"; + if (count > 2 && arguments[2].isString()) { + auto modeArg = arguments[2].getString(runtime).utf8(runtime); + if (modeArg == "arrayBuffer") { + mode = BinaryMode::mutableArrayBuffer; + modeName = "arrayBuffer"; + } else if (modeArg == "wrappedUint8Array") { + mode = BinaryMode::mutableWrappedUint8Array; + modeName = "wrappedUint8Array"; + } + } + + msgpack::sbuffer encoded; + auto encodeStart = KBPerfClock::now(); + for (size_t i = 0; i < iterations; ++i) { + encoded.clear(); + msgpack::packer pk(&encoded); + convertJSIToMP(runtime, arguments[0], &pk); + } + auto encodeNs = perfNanosSince(encodeStart); + + std::string encodedBytes(encoded.data(), encoded.size()); + Value lastValue = Value::undefined(); + auto decodeStart = KBPerfClock::now(); + for (size_t i = 0; i < iterations; ++i) { + auto unpacked = + msgpack::unpack(encodedBytes.data(), encodedBytes.size()); + msgpack::object obj(unpacked.get()); + lastValue = convertMPToJSIPerf(runtime, &obj, mode); + } + auto decodeNs = perfNanosSince(decodeStart); + + Object result(runtime); + result.setProperty(runtime, "iterations", static_cast(iterations)); + result.setProperty(runtime, "bytes", static_cast(encodedBytes.size())); + result.setProperty(runtime, "encodeNs", static_cast(encodeNs)); + result.setProperty(runtime, "decodeNs", static_cast(decodeNs)); + result.setProperty(runtime, "mode", String::createFromUtf8(runtime, modeName)); + result.setProperty(runtime, "value", std::move(lastValue)); + return result; +} + +void KBBridge::installPerfBindings(Runtime &runtime) { + Object perf(runtime); + perf.setProperty( + runtime, "stats", + Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "stats"), 0, + [self = shared_from_this()](Runtime &runtime, const Value &, + const Value *, size_t) -> Value { + return self->perfStats(runtime); + })); + perf.setProperty( + runtime, "reset", + Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "reset"), 0, + [self = shared_from_this()](Runtime &, const Value &, const Value *, + size_t) -> Value { + self->resetPerfCounters(); + return Value(true); + })); + perf.setProperty( + runtime, "roundTrip", + Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "roundTrip"), 3, + [self = shared_from_this()](Runtime &runtime, const Value &, + const Value *arguments, + size_t count) -> Value { + return self->perfRoundTrip(runtime, arguments, count); + })); + perf.setProperty( + runtime, "makeBinary", + Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "makeBinary"), 2, + [self = shared_from_this()](Runtime &runtime, const Value &, + const Value *arguments, + size_t count) -> Value { + return self->perfMakeBinary(runtime, arguments, count); + })); + runtime.global().setProperty(runtime, "kbJSIPerf", std::move(perf)); +} +#endif + void KBBridge::packAndSend(Runtime &runtime, const Value &value) { mp_->sendBuf.clear(); msgpack::packer pk(&mp_->sendBuf); +#if KB_JSI_PERF + auto encodeStart = KBPerfClock::now(); +#endif convertJSIToMP(runtime, value, &pk); +#if KB_JSI_PERF + perf_.encodeNs.fetch_add(perfNanosSince(encodeStart)); +#endif +#if KB_JSI_PERF + auto frameStart = KBPerfClock::now(); +#endif // Encode frame header (msgpack uint32 length prefix) on the stack. // 0xce = msgpack uint32 format tag, followed by 4 big-endian bytes. auto contentSize = static_cast(mp_->sendBuf.size()); @@ -243,8 +605,17 @@ void KBBridge::packAndSend(Runtime &runtime, const Value &value) { combinedBuf_.resize(headerLen + mp_->sendBuf.size()); std::memcpy(combinedBuf_.data(), frameHeader, headerLen); std::memcpy(combinedBuf_.data() + headerLen, mp_->sendBuf.data(), mp_->sendBuf.size()); +#if KB_JSI_PERF + perf_.frameNs.fetch_add(perfNanosSince(frameStart)); + perf_.rpcOnGoCalls.fetch_add(1); + perf_.rpcOnGoBytes.fetch_add(combinedBuf_.size()); + auto writeStart = KBPerfClock::now(); +#endif writeToGo_(combinedBuf_.data(), combinedBuf_.size()); +#if KB_JSI_PERF + perf_.writeToGoNs.fetch_add(perfNanosSince(writeStart)); +#endif } void KBBridge::install( @@ -275,6 +646,13 @@ void KBBridge::install( runtime.global().setProperty(runtime, "rpcOnGo", std::move(rpcOnGo)); +#ifdef KB_JSI_EXPERIMENTS_ENABLED + installExperimentBindings(runtime); +#endif +#if KB_JSI_PERF + installPerfBindings(runtime); +#endif + // HostObject that calls teardown when the JS runtime is destroyed class KBTearDownSimple : public jsi::HostObject { public: @@ -312,6 +690,9 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { try { auto values = std::make_shared>(); +#if KB_JSI_PERF + auto unpackStart = KBPerfClock::now(); +#endif mp_->unpacker.reserve_buffer(size); std::copy(data, data + size, mp_->unpacker.buffer()); mp_->unpacker.buffer_consumed(size); @@ -328,6 +709,12 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { break; } } +#if KB_JSI_PERF + perf_.onDataCalls.fetch_add(1); + perf_.onDataBytes.fetch_add(static_cast(size)); + perf_.unpackNs.fetch_add(perfNanosSince(unpackStart)); + perf_.inboundMessages.fetch_add(values->size()); +#endif if (values->empty()) { return; @@ -356,15 +743,32 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { } if (values->size() == 1) { +#if KB_JSI_PERF + auto convertStart = KBPerfClock::now(); +#endif // Single message: pass directly (no array wrapper) msgpack::object obj((*values)[0].get()); Value value = self->convertMPToJSI(runtime, &obj); +#if KB_JSI_PERF + self->perf_.convertMPToJSINs.fetch_add( + perfNanosSince(convertStart)); +#endif if (self->isTornDown_.load()) { return; } +#if KB_JSI_PERF + auto callStart = KBPerfClock::now(); +#endif self->cachedRpcOnJs_->call(runtime, std::move(value), jsi::Value(1)); +#if KB_JSI_PERF + self->perf_.rpcOnJsCalls.fetch_add(1); + self->perf_.rpcOnJsNs.fetch_add(perfNanosSince(callStart)); +#endif } else { +#if KB_JSI_PERF + auto convertStart = KBPerfClock::now(); +#endif // Multiple messages: batch into array, pass count jsi::Array arr(runtime, values->size()); for (size_t i = 0; i < values->size(); ++i) { @@ -372,12 +776,23 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { arr.setValueAtIndex(runtime, i, self->convertMPToJSI(runtime, &obj)); } +#if KB_JSI_PERF + self->perf_.convertMPToJSINs.fetch_add( + perfNanosSince(convertStart)); +#endif if (self->isTornDown_.load()) { return; } +#if KB_JSI_PERF + auto callStart = KBPerfClock::now(); +#endif self->cachedRpcOnJs_->call( runtime, std::move(arr), jsi::Value(static_cast(values->size()))); +#if KB_JSI_PERF + self->perf_.rpcOnJsCalls.fetch_add(1); + self->perf_.rpcOnJsNs.fetch_add(perfNanosSince(callStart)); +#endif } } catch (const std::exception &e) { if (self->onError_) { diff --git a/rnmodules/react-native-kb/cpp/react-native-kb.h b/rnmodules/react-native-kb/cpp/react-native-kb.h index 8fc5521fd93f..f09c6bd4f09e 100644 --- a/rnmodules/react-native-kb/cpp/react-native-kb.h +++ b/rnmodules/react-native-kb/cpp/react-native-kb.h @@ -5,6 +5,7 @@ // include with #undef/#pragma push/pop to handle the conflict safely. #pragma once #include +#include "react-native-kb-experiments.h" #include #include #include @@ -50,13 +51,58 @@ class KBBridge : public std::enable_shared_from_this { std::function writeToGo_; std::vector combinedBuf_; + enum class BinaryMode { + uint8ArrayCtor, + mutableArrayBuffer, + mutableWrappedUint8Array, + }; + void resetCaches(facebook::jsi::Runtime &runtime); + facebook::jsi::Function &uint8ArrayCtor(facebook::jsi::Runtime &runtime); + facebook::jsi::Value binaryFromBytes(facebook::jsi::Runtime &runtime, + const char *ptr, size_t size, + BinaryMode mode); facebook::jsi::Value convertMPToJSI(facebook::jsi::Runtime &runtime, void *mpObj); void convertJSIToMP(facebook::jsi::Runtime &runtime, const facebook::jsi::Value &value, void *packer); void packAndSend(facebook::jsi::Runtime &runtime, const facebook::jsi::Value &value); + +#ifdef KB_JSI_EXPERIMENTS_ENABLED + void installExperimentBindings(facebook::jsi::Runtime &runtime); +#endif + +#if KB_JSI_PERF + struct PerfCounters { + std::atomic rpcOnGoCalls{0}; + std::atomic rpcOnGoBytes{0}; + std::atomic encodeNs{0}; + std::atomic frameNs{0}; + std::atomic writeToGoNs{0}; + std::atomic onDataCalls{0}; + std::atomic onDataBytes{0}; + std::atomic inboundMessages{0}; + std::atomic unpackNs{0}; + std::atomic convertMPToJSINs{0}; + std::atomic rpcOnJsCalls{0}; + std::atomic rpcOnJsNs{0}; + }; + + PerfCounters perf_; + + void installPerfBindings(facebook::jsi::Runtime &runtime); + void resetPerfCounters(); + facebook::jsi::Value perfStats(facebook::jsi::Runtime &runtime); + facebook::jsi::Value perfRoundTrip(facebook::jsi::Runtime &runtime, + const facebook::jsi::Value *arguments, + size_t count); + facebook::jsi::Value perfMakeBinary(facebook::jsi::Runtime &runtime, + const facebook::jsi::Value *arguments, + size_t count); + facebook::jsi::Value convertMPToJSIPerf(facebook::jsi::Runtime &runtime, + void *mpObj, BinaryMode mode); +#endif }; } // namespace kb diff --git a/rnmodules/react-native-kb/react-native-kb.podspec b/rnmodules/react-native-kb/react-native-kb.podspec index 5091221340d4..60c9b37f9164 100644 --- a/rnmodules/react-native-kb/react-native-kb.podspec +++ b/rnmodules/react-native-kb/react-native-kb.podspec @@ -2,6 +2,11 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' +kb_jsi_inbound_binary_mode = ENV.fetch("KB_JSI_INBOUND_BINARY_MODE", "0") +kb_jsi_outbound_typed_array_fastpath = ENV.fetch("KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH", "0") +kb_jsi_perf = ENV["KB_JSI_PERF"] == "1" ? " -DKB_JSI_PERF=1" : "" +kb_jsi_experiment_flags = " -DKB_JSI_INBOUND_BINARY_MODE=#{kb_jsi_inbound_binary_mode} -DKB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=#{kb_jsi_outbound_typed_array_fastpath}#{kb_jsi_perf}" +kb_cpp_flags = "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1#{kb_jsi_experiment_flags}" Pod::Spec.new do |s| s.name = "react-native-kb" @@ -27,7 +32,7 @@ Pod::Spec.new do |s| if respond_to?(:install_modules_dependencies, true) s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" $(PODS_ROOT)/../../node_modules/msgpack-cxx-7.0.0/include $(PODS_ROOT)/../keybasego.xcframework/ios-arm64/Keybasego.framework/Headers \"$(PODS_CONFIGURATION_BUILD_DIR)/KBCommon\"", - "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1", + "OTHER_CPLUSPLUSFLAGS" => kb_cpp_flags, "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } install_modules_dependencies(s) @@ -39,7 +44,7 @@ Pod::Spec.new do |s| s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" $(PODS_ROOT)/../../node_modules/msgpack-cxx-7.0.0/include $(PODS_ROOT)/../keybasego.xcframework/ios-arm64/Keybasego.framework/Headers \"$(PODS_CONFIGURATION_BUILD_DIR)/KBCommon\"", - "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1", + "OTHER_CPLUSPLUSFLAGS" => kb_cpp_flags, "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } s.dependency "React-Codegen" @@ -50,7 +55,7 @@ Pod::Spec.new do |s| else s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" $(PODS_ROOT)/../../node_modules/msgpack-cxx-7.0.0/include $(PODS_ROOT)/../keybasego.xcframework/ios-arm64/Keybasego.framework/Headers \"$(PODS_CONFIGURATION_BUILD_DIR)/KBCommon\"", - "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1", + "OTHER_CPLUSPLUSFLAGS" => kb_cpp_flags, "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" } end diff --git a/shared/globals.d.ts b/shared/globals.d.ts index b42d214a7992..5cc51c18a800 100644 --- a/shared/globals.d.ts +++ b/shared/globals.d.ts @@ -40,6 +40,36 @@ declare global { var __PROFILE__: boolean var rpcOnGo: undefined | ((msg: unknown) => void) var rpcOnJs: undefined | ((objs: unknown, count: number) => void) + var kbJSIExperimentConfig: + | undefined + | { + inboundBinaryMode: number + inboundBinaryModeName: string + outboundTypedArrayFastPath: boolean + perf: boolean + } + var kbJSIPerf: + | undefined + | { + makeBinary: ( + size?: number, + mode?: 'uint8Array' | 'arrayBuffer' | 'wrappedUint8Array' + ) => unknown + reset: () => boolean + roundTrip: ( + value: unknown, + iterations?: number, + mode?: 'uint8Array' | 'arrayBuffer' | 'wrappedUint8Array' + ) => { + bytes: number + decodeNs: number + encodeNs: number + iterations: number + mode: string + value: unknown + } + stats: () => Record + } // RN var __turboModuleProxy: unknown } From 550892b0dc20a8d110631b2782a829d4b9a23120 Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Mon, 4 May 2026 10:47:00 -0400 Subject: [PATCH 02/16] WIP --- plans/jsi-perf.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/plans/jsi-perf.md b/plans/jsi-perf.md index f82ba377d2ad..cdf9ab3e7575 100644 --- a/plans/jsi-perf.md +++ b/plans/jsi-perf.md @@ -29,9 +29,7 @@ Keybase is on RN 0.83.4 with New Architecture and Hermes enabled. RN's public Tu ## Run / Evaluation Notes - Keep all measurements benchmark-only until the current bridge baseline is captured and compared against any ArrayBuffer-backed prototype. -- This machine cannot run the JS validation or benchmark workflow because `node_modules` is absent; do not run `yarn`, `npm`, `yarn lint`, `yarn tsc`, or other node-based tooling here. - Local work on this machine is limited to code/document inspection and source updates. Run the benchmark harness, RN build, and validation on a machine with dependencies installed. -- The remaining unchecked item is the actual run/result capture step on a runnable environment. ## Experiment Matrix From 977761a4d4eed5a605b771ef4a7a6c419d5a1677 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 11:16:30 -0400 Subject: [PATCH 03/16] WIP --- rnmodules/react-native-kb/cpp/react-native-kb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rnmodules/react-native-kb/cpp/react-native-kb.cpp b/rnmodules/react-native-kb/cpp/react-native-kb.cpp index da16e5f6248b..234c0b9865bd 100644 --- a/rnmodules/react-native-kb/cpp/react-native-kb.cpp +++ b/rnmodules/react-native-kb/cpp/react-native-kb.cpp @@ -100,7 +100,8 @@ Value KBBridge::binaryFromBytes(Runtime &runtime, const char *ptr, size_t size, } Value arrayBufferArg(std::move(arrayBuffer)); - return uint8ArrayCtor(runtime).callAsConstructor(runtime, &arrayBufferArg, 1); + return uint8ArrayCtor(runtime).callAsConstructor(runtime, + std::move(arrayBufferArg)); } static std::string mpToString(msgpack::object &o) { From c4577e6e24ad15f4e42dfac0fc2b0eff9770aabc Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 11:20:29 -0400 Subject: [PATCH 04/16] WIP --- shared/desktop/yarn-helper/index.mts | 67 ++++++++++++++++++++++++++++ shared/package.json | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/shared/desktop/yarn-helper/index.mts b/shared/desktop/yarn-helper/index.mts index ee64f95aae3a..5f82302428fc 100644 --- a/shared/desktop/yarn-helper/index.mts +++ b/shared/desktop/yarn-helper/index.mts @@ -42,6 +42,7 @@ const commands: {[key: string]: Command} = { postinstall: { code: () => { fixModules() + syncLocalRNModules() checkFSEvents() clearTSCache() clearAndroidBuild() @@ -51,6 +52,12 @@ const commands: {[key: string]: Command} = { }, help: '', }, + 'sync-local-rnmodules': { + code: () => { + syncLocalRNModules() + }, + help: 'Sync local file:../rnmodules dependencies into node_modules', + }, test: { code: () => { const update = process.argv[3] === '-u' @@ -95,6 +102,66 @@ function fixModules() { } catch {} } +const syncLocalRNModules = () => { + const sharedRoot = path.resolve(__dirname, '..', '..') + const repoRoot = path.resolve(sharedRoot, '..') + const rnmodulesRoot = path.join(repoRoot, 'rnmodules') + const nodeModulesRoot = path.join(sharedRoot, 'node_modules') + + if (!fs.existsSync(nodeModulesRoot)) { + return + } + + const packageJSONPath = path.join(sharedRoot, 'package.json') + const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf8')) as { + dependencies?: Record + devDependencies?: Record + optionalDependencies?: Record + } + const deps = { + ...packageJSON.dependencies, + ...packageJSON.devDependencies, + ...packageJSON.optionalDependencies, + } + + for (const [name, spec] of Object.entries(deps)) { + if (!spec.startsWith('file:../rnmodules/')) { + continue + } + + const source = path.resolve(sharedRoot, spec.slice('file:'.length)) + const relToRNModules = path.relative(rnmodulesRoot, source) + if (relToRNModules.startsWith('..') || path.isAbsolute(relToRNModules)) { + continue + } + + if (!fs.existsSync(source)) { + throw new Error(`Local RN module source is missing for ${name}: ${source}`) + } + + const dest = path.join(nodeModulesRoot, name) + console.log(`Syncing ${name} from ${path.relative(sharedRoot, source)} to node_modules`) + rimrafSync(dest) + fs.mkdirSync(path.dirname(dest), {recursive: true}) + fs.cpSync(source, dest, { + filter: src => { + const rel = path.relative(source, src) + return !( + rel === 'node_modules' || + rel.startsWith(`node_modules${path.sep}`) || + rel === '.git' || + rel.startsWith(`.git${path.sep}`) || + rel === 'android/build' || + rel.startsWith(`android${path.sep}build${path.sep}`) || + rel === 'ios/build' || + rel.startsWith(`ios${path.sep}build${path.sep}`) + ) + }, + recursive: true, + }) + } +} + function exec(command: string, env?: object, options?: object) { console.log( execSync(command, { diff --git a/shared/package.json b/shared/package.json index dab71df0d6b8..91bd160e6adc 100644 --- a/shared/package.json +++ b/shared/package.json @@ -63,7 +63,7 @@ "android-log-clear": "adb logcat -b all -c", "clean-and-install": "rm -rf node_modules ; yarn pod-clean ; yarn modules ; yarn pod-install", "coverage": "rm -rf coverage-ts; npx typescript-coverage-report", - "sync-kb-modules": "rm -rf node_modules/react-native-kb ; yarn --check-files", + "sync-kb-modules": "yarn run _helper sync-local-rnmodules", "maestro-test": "MAESTRO_CLI_NO_ANALYTICS=1 ./perf/run-maestro.sh", "maestro-test-perf-inbox": "MAESTRO_CLI_NO_ANALYTICS=1 ./perf/run-maestro.sh --flow performance/perf-inbox-scroll.yaml", "maestro-test-perf-teams": "MAESTRO_CLI_NO_ANALYTICS=1 ./perf/run-maestro.sh --flow performance/perf-teams-scroll.yaml", From b2c1b7504f6e4e9a776373e29302bb55249f72ec Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Mon, 4 May 2026 11:20:38 -0400 Subject: [PATCH 05/16] WIP --- shared/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/ios/Podfile.lock b/shared/ios/Podfile.lock index b7dd7ffe8896..64861e1f9eb0 100644 --- a/shared/ios/Podfile.lock +++ b/shared/ios/Podfile.lock @@ -3678,7 +3678,7 @@ SPEC CHECKSUMS: React-logger: 993e4b9793768764e0fdd379ad1d6582f7905463 React-Mapbuffer: 0b0d3c3074187e72d8a6e8cacce120cb24581565 React-microtasksnativemodule: 175741856a8f6a31e20b973cb784db023256b259 - react-native-kb: 47269c30b862f82a1556f88cc6f00dbee91a9a98 + react-native-kb: 47693256b04fde39236635d95a3e9d506ef1e101 react-native-keyboard-controller: 1caa8b8c3fc43060344286f17d17cbf649e7e598 react-native-netinfo: 9fad4eedfec9840a10e73ac4591ea1158523309b react-native-safe-area-context: eda63a662750758c1fdd7e719c9f1026c8d161cb From a1d6b25cece4fba0dc5ad971f180fd3c1c409494 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 12:33:46 -0400 Subject: [PATCH 06/16] WIP --- plans/jsi-perf.md | 91 ---- .../react-native-kb/android/CMakeLists.txt | 16 - .../react-native-kb/android/build.gradle | 14 +- .../cpp/react-native-kb-experiments.h | 27 -- .../react-native-kb/cpp/react-native-kb.cpp | 401 +----------------- .../react-native-kb/cpp/react-native-kb.h | 45 +- .../react-native-kb/react-native-kb.podspec | 6 +- shared/globals.d.ts | 30 -- 8 files changed, 18 insertions(+), 612 deletions(-) delete mode 100644 plans/jsi-perf.md delete mode 100644 rnmodules/react-native-kb/cpp/react-native-kb-experiments.h diff --git a/plans/jsi-perf.md b/plans/jsi-perf.md deleted file mode 100644 index cdf9ab3e7575..000000000000 --- a/plans/jsi-perf.md +++ /dev/null @@ -1,91 +0,0 @@ -# JSI Performance Evaluation Plan - -## Summary - -Keybase is on RN 0.83.4 with New Architecture and Hermes enabled. RN's public TurboModule Codegen surface still does not document ArrayBuffer or typed-array parameters, but RN's C++ JSI API exposes MutableBuffer, ArrayBuffer, direct buffer data access, NativeState, and runtime data. The evaluation should focus on our pure C++ JSI bridge in react-native-kb, not on moving the RPC pipe to normal TurboModule methods. - -## Evaluation Targets - -- Benchmark current bridge costs in react-native-kb: rpcOnGo, rpcOnJs, msgpack encode/decode, object/map walking, string conversion, binary payload handling, JNI/ObjC copies, and batching. -- Prototype, in benchmark-only code, creating inbound binary values via jsi::MutableBuffer + Runtime::createArrayBuffer instead of constructing Uint8Array(size) and copying into its buffer. -- Test whether JS can safely accept ArrayBuffer directly for msgpack binary fields; if not, measure new Uint8Array(arrayBuffer) wrapping versus the current constructor path. -- Evaluate typed-array detection in convertJSIToMP: avoid getPropertyNames() before checking ArrayBuffer/typed-array-like objects when payloads contain binary data. -- Evaluate NativeState only for JS-visible stateful native objects; current hot RPC function does not need it, and the existing teardown HostObject is not a hot path. -- Evaluate runtime/engine compatibility explicitly against Hermes current, Hermes V1, and JSC fallback assumptions before adopting any ArrayBuffer-backed fast path. - -## API Policy - -- Preserve the existing JS contract: global.rpcOnGo(message) and global.rpcOnJs(objs, count). -- Do not migrate this RPC pipe to normal TurboModule methods unless benchmarks show a clear win; Codegen's documented type surface is currently weaker for arbitrary msgpack/binary payloads. -- Any binary representation change must be behavior-compatible with existing RPC consumers, especially code expecting Uint8Array rather than ArrayBuffer. - -## Test Plan - -- Add native round-trip tests or a standalone benchmark harness for nulls, booleans, integers, floats, strings, maps, arrays, empty objects, ArrayBuffer, Uint8Array, and large binary blobs. -- Measure before/after on representative RPC shapes: small method calls, nested maps, chat/message payloads, and binary-heavy payloads. -- Use RN 0.83 Web Performance APIs / DevTools Performance panel for JS-side timing where useful. -- Do not run yarn, npm, yarn lint, or yarn tsc on this machine because node_modules is absent. - -## Run / Evaluation Notes - -- Keep all measurements benchmark-only until the current bridge baseline is captured and compared against any ArrayBuffer-backed prototype. -- Local work on this machine is limited to code/document inspection and source updates. Run the benchmark harness, RN build, and validation on a machine with dependencies installed. - -## Experiment Matrix - -Default build behavior is the baseline: - -- `KB_JSI_INBOUND_BINARY_MODE=0`: current inbound BIN behavior, `Uint8Array(size)` plus copy into its buffer. -- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=0`: current outbound typed-array detection order, using `getPropertyNames()` before the broad shape probe. -- `KB_JSI_PERF=0`: no benchmark globals or counters. - -Prototype builds: - -- `KB_JSI_INBOUND_BINARY_MODE=1`: inbound BIN becomes a direct `ArrayBuffer` backed by `jsi::MutableBuffer`. This is expected to change JS-visible behavior and must not ship without consumer validation. -- `KB_JSI_INBOUND_BINARY_MODE=2`: inbound BIN uses `jsi::MutableBuffer` + `createArrayBuffer`, then wraps with `new Uint8Array(arrayBuffer)` to preserve the expected JS `Uint8Array` shape. -- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=1`: outbound encode checks `instanceof Uint8Array` before property enumeration and keeps the old broad shape probe as fallback. -- `KB_JSI_PERF=1`: installs `global.kbJSIExperimentConfig` and `global.kbJSIPerf`. - -Android build knobs are CMake/Gradle properties: - -- `Kb_JSI_INBOUND_BINARY_MODE=0|1|2` -- `Kb_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=OFF|ON` -- `Kb_JSI_PERF=OFF|ON` - -iOS build knobs are environment variables consumed by the podspec: - -- `KB_JSI_INBOUND_BINARY_MODE=0|1|2` -- `KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=0|1` -- `KB_JSI_PERF=0|1` - -Benchmark globals when `KB_JSI_PERF=1`: - -- `global.kbJSIExperimentConfig`: confirms which experiment was compiled into the app. -- `global.kbJSIPerf.stats()`: returns counters for `rpcOnGo`, encode, frame copy, native write, inbound unpack, JSI conversion, and `rpcOnJs` call time. -- `global.kbJSIPerf.reset()`: clears counters. -- `global.kbJSIPerf.makeBinary(size, mode)`: returns benchmark binary values for `uint8Array`, `arrayBuffer`, or `wrappedUint8Array`. -- `global.kbJSIPerf.roundTrip(value, iterations, mode)`: msgpack-encodes and decodes a value in native code; decode mode is `uint8Array`, `arrayBuffer`, or `wrappedUint8Array`. - -Validation shape: - -- Build baseline with `KB_JSI_PERF=1`, all other experiment knobs at defaults, and capture `kbJSIPerf.stats()` during normal app RPC traffic. -- Build each prototype separately and compare behavior with the same RPC flows. -- For binary behavior, compare `roundTrip` results with values covering nulls, booleans, integers, floats, strings, maps, arrays, empty objects, `ArrayBuffer`, `Uint8Array`, sliced `Uint8Array`, and large binary blobs. - -Example JS console checks in a `KB_JSI_PERF=1` build: - -- `global.kbJSIExperimentConfig` -- `const bin = global.kbJSIPerf.makeBinary(1024, 'uint8Array')` -- `global.kbJSIPerf.roundTrip({bin, nested: [bin]}, 1000, 'uint8Array').value.bin instanceof Uint8Array` -- `global.kbJSIPerf.roundTrip({bin}, 1000, 'arrayBuffer').value.bin instanceof ArrayBuffer` -- `global.kbJSIPerf.roundTrip({bin}, 1000, 'wrappedUint8Array').value.bin instanceof Uint8Array` -- `global.kbJSIPerf.stats()` - -## Sources - -- React Native New Architecture docs: https://reactnative.dev/architecture/landing-page -- RN 0.83 Native Modules docs: https://reactnative.dev/docs/0.83/turbo-native-modules-introduction -- RN Codegen typings appendix: https://reactnative.dev/docs/appendix -- RN 0.83.4 JSI header: https://raw.githubusercontent.com/facebook/react-native/v0.83.4/packages/react-native/ReactCommon/jsi/jsi/jsi.h -- RN 0.83 release notes: https://reactnative.dev/blog/2025/12/10/react-native-0.83 -- Margelo JSI performance post: https://blog.margelo.com/make-jsi-run-faster diff --git a/rnmodules/react-native-kb/android/CMakeLists.txt b/rnmodules/react-native-kb/android/CMakeLists.txt index 5a552f9d491a..30091fd94228 100644 --- a/rnmodules/react-native-kb/android/CMakeLists.txt +++ b/rnmodules/react-native-kb/android/CMakeLists.txt @@ -4,16 +4,6 @@ cmake_minimum_required(VERSION 3.4.1) set (CMAKE_VERBOSE_MAKEFILE ON) set (CMAKE_CXX_STANDARD 20) set (NODE_MODULES_DIR "${CMAKE_SOURCE_DIR}/../..") -set (KB_JSI_INBOUND_BINARY_MODE "0" CACHE STRING "0=current Uint8Array, 1=MutableBuffer ArrayBuffer, 2=MutableBuffer wrapped Uint8Array") -set_property(CACHE KB_JSI_INBOUND_BINARY_MODE PROPERTY STRINGS "0" "1" "2") -option(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH "Check Uint8Array before object property enumeration" OFF) -option(KB_JSI_PERF "Install benchmark-only JSI performance hooks" OFF) - -if(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH) - set(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE 1) -else() - set(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE 0) -endif() add_library(cpp SHARED @@ -40,14 +30,8 @@ target_compile_definitions( cpp PRIVATE MSGPACK_NO_BOOST - KB_JSI_INBOUND_BINARY_MODE=${KB_JSI_INBOUND_BINARY_MODE} - KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=${KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH_VALUE} ) -if(KB_JSI_PERF) - target_compile_definitions(cpp PRIVATE KB_JSI_PERF=1) -endif() - find_package(ReactAndroid REQUIRED CONFIG) find_package(fbjni REQUIRED CONFIG) find_library(LOG_LIB log) diff --git a/rnmodules/react-native-kb/android/build.gradle b/rnmodules/react-native-kb/android/build.gradle index d4af7389c7dd..727944b90e8c 100644 --- a/rnmodules/react-native-kb/android/build.gradle +++ b/rnmodules/react-native-kb/android/build.gradle @@ -35,20 +35,11 @@ def getExtOrIntegerDefault(name) { return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Kb_" + name]).toInteger() } -def getKbExperimentOrDefault(name, defaultValue) { - def key = "Kb_" + name - return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.findProperty(key) ?: defaultValue) -} - def reactNativeArchitectures() { def value = project.getProperties().get('reactNativeArchitectures') return value ? value.split(',') : ['armeabi-v7a', 'x86', 'x86_64', 'arm64-v8a'] } -def kbJsiInboundBinaryMode = getKbExperimentOrDefault("JSI_INBOUND_BINARY_MODE", "0") -def kbJsiOutboundTypedArrayFastpath = getKbExperimentOrDefault("JSI_OUTBOUND_TYPED_ARRAY_FASTPATH", "OFF") -def kbJsiPerf = getKbExperimentOrDefault("JSI_PERF", "OFF") - android { ndkVersion getExtOrDefault("ndkVersion") compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") @@ -63,10 +54,7 @@ android { externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" - arguments '-DANDROID_STL=c++_shared', - "-DKB_JSI_INBOUND_BINARY_MODE=${kbJsiInboundBinaryMode}", - "-DKB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=${kbJsiOutboundTypedArrayFastpath}", - "-DKB_JSI_PERF=${kbJsiPerf}" + arguments '-DANDROID_STL=c++_shared' abiFilters(*reactNativeArchitectures()) } } diff --git a/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h b/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h deleted file mode 100644 index e3e50cd8d8e8..000000000000 --- a/rnmodules/react-native-kb/cpp/react-native-kb-experiments.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#ifndef KB_JSI_INBOUND_BINARY_MODE -#define KB_JSI_INBOUND_BINARY_MODE 0 -#endif - -#ifndef KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH -#define KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH 0 -#endif - -#ifndef KB_JSI_PERF -#define KB_JSI_PERF 0 -#endif - -#if KB_JSI_INBOUND_BINARY_MODE < 0 || KB_JSI_INBOUND_BINARY_MODE > 2 -#error "KB_JSI_INBOUND_BINARY_MODE must be 0, 1, or 2" -#endif - -#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 0 && \ - KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 1 -#error "KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH must be 0 or 1" -#endif - -#if KB_JSI_PERF || KB_JSI_INBOUND_BINARY_MODE != 0 || \ - KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH != 0 -#define KB_JSI_EXPERIMENTS_ENABLED 1 -#endif diff --git a/rnmodules/react-native-kb/cpp/react-native-kb.cpp b/rnmodules/react-native-kb/cpp/react-native-kb.cpp index 234c0b9865bd..7be06ad373ed 100644 --- a/rnmodules/react-native-kb/cpp/react-native-kb.cpp +++ b/rnmodules/react-native-kb/cpp/react-native-kb.cpp @@ -1,5 +1,4 @@ #include "react-native-kb.h" -#include #include #include #include @@ -16,33 +15,6 @@ struct KBBridge::MsgpackState { msgpack::sbuffer sendBuf; }; -class KBMutableBuffer final : public MutableBuffer { -public: - explicit KBMutableBuffer(size_t size) : bytes_(size) {} - size_t size() const override { return bytes_.size(); } - uint8_t *data() override { return bytes_.data(); } - -private: - std::vector bytes_; -}; - -#if KB_JSI_PERF -using KBPerfClock = std::chrono::steady_clock; - -static uint64_t perfNanosSince(KBPerfClock::time_point start) { - return static_cast( - std::chrono::duration_cast( - KBPerfClock::now() - start) - .count()); -} - -static void fillPerfBytes(uint8_t *data, size_t size) { - for (size_t i = 0; i < size; ++i) { - data[i] = static_cast(i & 0xff); - } -} -#endif - KBBridge::KBBridge() = default; KBBridge::~KBBridge() = default; @@ -75,33 +47,18 @@ Function &KBBridge::uint8ArrayCtor(Runtime &runtime) { return *cachedUint8ArrayCtor_; } -Value KBBridge::binaryFromBytes(Runtime &runtime, const char *ptr, size_t size, - BinaryMode mode) { - if (mode == BinaryMode::uint8ArrayCtor) { - Value uint8Array = uint8ArrayCtor(runtime).callAsConstructor( - runtime, static_cast(size)); - Object uint8ArrayObj = uint8Array.asObject(runtime); - ArrayBuffer buffer = uint8ArrayObj.getProperty(runtime, "buffer") - .asObject(runtime) - .getArrayBuffer(runtime); - if (size > 0) { - std::memcpy(buffer.data(runtime), ptr, size); - } - return uint8Array; - } - - auto mutableBuffer = std::make_shared(size); +Value KBBridge::binaryFromBytes(Runtime &runtime, const char *ptr, + size_t size) { + Value uint8Array = uint8ArrayCtor(runtime).callAsConstructor( + runtime, static_cast(size)); + Object uint8ArrayObj = uint8Array.asObject(runtime); + ArrayBuffer buffer = uint8ArrayObj.getProperty(runtime, "buffer") + .asObject(runtime) + .getArrayBuffer(runtime); if (size > 0) { - std::memcpy(mutableBuffer->data(), ptr, size); - } - ArrayBuffer arrayBuffer(runtime, mutableBuffer); - if (mode == BinaryMode::mutableArrayBuffer) { - return arrayBuffer; + std::memcpy(buffer.data(runtime), ptr, size); } - - Value arrayBufferArg(std::move(arrayBuffer)); - return uint8ArrayCtor(runtime).callAsConstructor(runtime, - std::move(arrayBufferArg)); + return uint8Array; } static std::string mpToString(msgpack::object &o) { @@ -164,14 +121,7 @@ Value KBBridge::convertMPToJSI(Runtime &runtime, void *mpObj) { case msgpack::type::BIN: { auto ptr = o.via.bin.ptr; auto size = o.via.bin.size; -#if KB_JSI_INBOUND_BINARY_MODE == 1 - return binaryFromBytes(runtime, ptr, size, BinaryMode::mutableArrayBuffer); -#elif KB_JSI_INBOUND_BINARY_MODE == 2 - return binaryFromBytes(runtime, ptr, size, - BinaryMode::mutableWrappedUint8Array); -#else - return binaryFromBytes(runtime, ptr, size, BinaryMode::uint8ArrayCtor); -#endif + return binaryFromBytes(runtime, ptr, size); } case msgpack::type::ARRAY: { auto size = o.via.array.size; @@ -234,11 +184,7 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, }; if (obj.isArrayBuffer(runtime)) { auto buf = obj.getArrayBuffer(runtime); -#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH packArrayBufferBytes(buf, 0, buf.size(runtime)); -#else - packArrayBufferBytesUnchecked(buf, 0, buf.size(runtime)); -#endif } else if (obj.isArray(runtime)) { auto arr = obj.getArray(runtime); auto len = arr.size(runtime); @@ -267,7 +213,8 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, if (validateView) { if (!std::isfinite(byteOffsetNum) || !std::isfinite(byteLengthNum) || byteOffsetNum < 0 || - byteLengthNum < 0 || byteOffsetNum != std::floor(byteOffsetNum) || + byteLengthNum < 0 || + byteOffsetNum != std::floor(byteOffsetNum) || byteLengthNum != std::floor(byteLengthNum)) { return false; } @@ -282,11 +229,11 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, return true; }; -#if KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH + // Uint8Array is common for RPC binary payloads; check it before + // enumerating indexed properties. if (tryPackTypedArray(true, true)) { return; } -#endif auto names = obj.getPropertyNames(runtime); auto len = names.size(runtime); @@ -322,275 +269,11 @@ void KBBridge::convertJSIToMP(Runtime &runtime, const Value &value, } } -#ifdef KB_JSI_EXPERIMENTS_ENABLED -void KBBridge::installExperimentBindings(Runtime &runtime) { - Object config(runtime); - config.setProperty(runtime, "inboundBinaryMode", - static_cast(KB_JSI_INBOUND_BINARY_MODE)); - config.setProperty(runtime, "outboundTypedArrayFastPath", - static_cast(KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH)); -#if KB_JSI_PERF - config.setProperty(runtime, "perf", true); -#else - config.setProperty(runtime, "perf", false); -#endif - - const char *inboundBinaryModeName = "uint8ArrayCtor"; -#if KB_JSI_INBOUND_BINARY_MODE == 1 - inboundBinaryModeName = "mutableArrayBuffer"; -#elif KB_JSI_INBOUND_BINARY_MODE == 2 - inboundBinaryModeName = "mutableWrappedUint8Array"; -#endif - config.setProperty(runtime, "inboundBinaryModeName", - String::createFromUtf8(runtime, inboundBinaryModeName)); - runtime.global().setProperty(runtime, "kbJSIExperimentConfig", - std::move(config)); -} -#endif - -#if KB_JSI_PERF -void KBBridge::resetPerfCounters() { - perf_.rpcOnGoCalls.store(0); - perf_.rpcOnGoBytes.store(0); - perf_.encodeNs.store(0); - perf_.frameNs.store(0); - perf_.writeToGoNs.store(0); - perf_.onDataCalls.store(0); - perf_.onDataBytes.store(0); - perf_.inboundMessages.store(0); - perf_.unpackNs.store(0); - perf_.convertMPToJSINs.store(0); - perf_.rpcOnJsCalls.store(0); - perf_.rpcOnJsNs.store(0); -} - -Value KBBridge::perfStats(Runtime &runtime) { - Object stats(runtime); - stats.setProperty(runtime, "rpcOnGoCalls", - static_cast(perf_.rpcOnGoCalls.load())); - stats.setProperty(runtime, "rpcOnGoBytes", - static_cast(perf_.rpcOnGoBytes.load())); - stats.setProperty(runtime, "encodeNs", - static_cast(perf_.encodeNs.load())); - stats.setProperty(runtime, "frameNs", - static_cast(perf_.frameNs.load())); - stats.setProperty(runtime, "writeToGoNs", - static_cast(perf_.writeToGoNs.load())); - stats.setProperty(runtime, "onDataCalls", - static_cast(perf_.onDataCalls.load())); - stats.setProperty(runtime, "onDataBytes", - static_cast(perf_.onDataBytes.load())); - stats.setProperty(runtime, "inboundMessages", - static_cast(perf_.inboundMessages.load())); - stats.setProperty(runtime, "unpackNs", - static_cast(perf_.unpackNs.load())); - stats.setProperty(runtime, "convertMPToJSINs", - static_cast(perf_.convertMPToJSINs.load())); - stats.setProperty(runtime, "rpcOnJsCalls", - static_cast(perf_.rpcOnJsCalls.load())); - stats.setProperty(runtime, "rpcOnJsNs", - static_cast(perf_.rpcOnJsNs.load())); - stats.setProperty(runtime, "runtime", - String::createFromUtf8(runtime, runtime.description())); - return stats; -} - -Value KBBridge::convertMPToJSIPerf(Runtime &runtime, void *mpObj, - BinaryMode mode) { - auto &o = *static_cast(mpObj); - switch (o.type) { - case msgpack::type::STR: - return jsi::String::createFromUtf8( - runtime, reinterpret_cast(o.via.str.ptr), - o.via.str.size); - case msgpack::type::POSITIVE_INTEGER: - return jsi::Value(o.as()); - case msgpack::type::NEGATIVE_INTEGER: - return jsi::Value(o.as()); - case msgpack::type::FLOAT32: - return jsi::Value(o.as()); - case msgpack::type::FLOAT64: - return jsi::Value(o.as()); - case msgpack::type::BOOLEAN: - return jsi::Value(o.as()); - case msgpack::type::NIL: - return jsi::Value::null(); - case msgpack::type::EXT: - return jsi::Value::undefined(); - case msgpack::type::MAP: { - jsi::Object obj = jsi::Object(runtime); - auto *p = o.via.map.ptr; - auto *const pend = o.via.map.ptr + o.via.map.size; - for (; p < pend; ++p) { - auto val = convertMPToJSIPerf(runtime, &p->val, mode); - auto &k = p->key; - if (k.type == msgpack::type::STR) { - obj.setProperty( - runtime, - jsi::PropNameID::forUtf8( - runtime, reinterpret_cast(k.via.str.ptr), - k.via.str.size), - val); - } else { - auto keyStr = mpToString(k); - obj.setProperty(runtime, jsi::PropNameID::forUtf8(runtime, keyStr), - val); - } - } - return obj; - } - case msgpack::type::BIN: - return binaryFromBytes(runtime, o.via.bin.ptr, o.via.bin.size, mode); - case msgpack::type::ARRAY: { - auto size = o.via.array.size; - jsi::Array arr(runtime, size); - for (uint32_t i = 0; i < size; ++i) { - arr.setValueAtIndex( - runtime, i, convertMPToJSIPerf(runtime, &o.via.array.ptr[i], mode)); - } - return arr; - } - default: - return jsi::Value::undefined(); - } -} - -Value KBBridge::perfMakeBinary(Runtime &runtime, const Value *arguments, - size_t count) { - auto size = count > 0 && arguments[0].isNumber() - ? static_cast(arguments[0].getNumber()) - : 1024; - if (size > std::numeric_limits::max()) { - throw std::runtime_error("kbJSIPerf.makeBinary size is too large"); - } - - auto mode = BinaryMode::uint8ArrayCtor; - if (count > 1 && arguments[1].isString()) { - auto modeName = arguments[1].getString(runtime).utf8(runtime); - if (modeName == "arrayBuffer") { - mode = BinaryMode::mutableArrayBuffer; - } else if (modeName == "wrappedUint8Array") { - mode = BinaryMode::mutableWrappedUint8Array; - } - } - - auto bytes = std::make_shared(size); - fillPerfBytes(bytes->data(), size); - return binaryFromBytes(runtime, reinterpret_cast(bytes->data()), - size, mode); -} - -Value KBBridge::perfRoundTrip(Runtime &runtime, const Value *arguments, - size_t count) { - if (count == 0) { - throw std::runtime_error("kbJSIPerf.roundTrip needs a value"); - } - - auto iterations = count > 1 && arguments[1].isNumber() - ? static_cast(arguments[1].getNumber()) - : 100; - if (iterations == 0) { - iterations = 1; - } - - auto mode = BinaryMode::uint8ArrayCtor; - const char *modeName = "uint8Array"; - if (count > 2 && arguments[2].isString()) { - auto modeArg = arguments[2].getString(runtime).utf8(runtime); - if (modeArg == "arrayBuffer") { - mode = BinaryMode::mutableArrayBuffer; - modeName = "arrayBuffer"; - } else if (modeArg == "wrappedUint8Array") { - mode = BinaryMode::mutableWrappedUint8Array; - modeName = "wrappedUint8Array"; - } - } - - msgpack::sbuffer encoded; - auto encodeStart = KBPerfClock::now(); - for (size_t i = 0; i < iterations; ++i) { - encoded.clear(); - msgpack::packer pk(&encoded); - convertJSIToMP(runtime, arguments[0], &pk); - } - auto encodeNs = perfNanosSince(encodeStart); - - std::string encodedBytes(encoded.data(), encoded.size()); - Value lastValue = Value::undefined(); - auto decodeStart = KBPerfClock::now(); - for (size_t i = 0; i < iterations; ++i) { - auto unpacked = - msgpack::unpack(encodedBytes.data(), encodedBytes.size()); - msgpack::object obj(unpacked.get()); - lastValue = convertMPToJSIPerf(runtime, &obj, mode); - } - auto decodeNs = perfNanosSince(decodeStart); - - Object result(runtime); - result.setProperty(runtime, "iterations", static_cast(iterations)); - result.setProperty(runtime, "bytes", static_cast(encodedBytes.size())); - result.setProperty(runtime, "encodeNs", static_cast(encodeNs)); - result.setProperty(runtime, "decodeNs", static_cast(decodeNs)); - result.setProperty(runtime, "mode", String::createFromUtf8(runtime, modeName)); - result.setProperty(runtime, "value", std::move(lastValue)); - return result; -} - -void KBBridge::installPerfBindings(Runtime &runtime) { - Object perf(runtime); - perf.setProperty( - runtime, "stats", - Function::createFromHostFunction( - runtime, PropNameID::forAscii(runtime, "stats"), 0, - [self = shared_from_this()](Runtime &runtime, const Value &, - const Value *, size_t) -> Value { - return self->perfStats(runtime); - })); - perf.setProperty( - runtime, "reset", - Function::createFromHostFunction( - runtime, PropNameID::forAscii(runtime, "reset"), 0, - [self = shared_from_this()](Runtime &, const Value &, const Value *, - size_t) -> Value { - self->resetPerfCounters(); - return Value(true); - })); - perf.setProperty( - runtime, "roundTrip", - Function::createFromHostFunction( - runtime, PropNameID::forAscii(runtime, "roundTrip"), 3, - [self = shared_from_this()](Runtime &runtime, const Value &, - const Value *arguments, - size_t count) -> Value { - return self->perfRoundTrip(runtime, arguments, count); - })); - perf.setProperty( - runtime, "makeBinary", - Function::createFromHostFunction( - runtime, PropNameID::forAscii(runtime, "makeBinary"), 2, - [self = shared_from_this()](Runtime &runtime, const Value &, - const Value *arguments, - size_t count) -> Value { - return self->perfMakeBinary(runtime, arguments, count); - })); - runtime.global().setProperty(runtime, "kbJSIPerf", std::move(perf)); -} -#endif - void KBBridge::packAndSend(Runtime &runtime, const Value &value) { mp_->sendBuf.clear(); msgpack::packer pk(&mp_->sendBuf); -#if KB_JSI_PERF - auto encodeStart = KBPerfClock::now(); -#endif convertJSIToMP(runtime, value, &pk); -#if KB_JSI_PERF - perf_.encodeNs.fetch_add(perfNanosSince(encodeStart)); -#endif -#if KB_JSI_PERF - auto frameStart = KBPerfClock::now(); -#endif // Encode frame header (msgpack uint32 length prefix) on the stack. // 0xce = msgpack uint32 format tag, followed by 4 big-endian bytes. auto contentSize = static_cast(mp_->sendBuf.size()); @@ -606,17 +289,8 @@ void KBBridge::packAndSend(Runtime &runtime, const Value &value) { combinedBuf_.resize(headerLen + mp_->sendBuf.size()); std::memcpy(combinedBuf_.data(), frameHeader, headerLen); std::memcpy(combinedBuf_.data() + headerLen, mp_->sendBuf.data(), mp_->sendBuf.size()); -#if KB_JSI_PERF - perf_.frameNs.fetch_add(perfNanosSince(frameStart)); - perf_.rpcOnGoCalls.fetch_add(1); - perf_.rpcOnGoBytes.fetch_add(combinedBuf_.size()); - auto writeStart = KBPerfClock::now(); -#endif writeToGo_(combinedBuf_.data(), combinedBuf_.size()); -#if KB_JSI_PERF - perf_.writeToGoNs.fetch_add(perfNanosSince(writeStart)); -#endif } void KBBridge::install( @@ -647,13 +321,6 @@ void KBBridge::install( runtime.global().setProperty(runtime, "rpcOnGo", std::move(rpcOnGo)); -#ifdef KB_JSI_EXPERIMENTS_ENABLED - installExperimentBindings(runtime); -#endif -#if KB_JSI_PERF - installPerfBindings(runtime); -#endif - // HostObject that calls teardown when the JS runtime is destroyed class KBTearDownSimple : public jsi::HostObject { public: @@ -691,9 +358,6 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { try { auto values = std::make_shared>(); -#if KB_JSI_PERF - auto unpackStart = KBPerfClock::now(); -#endif mp_->unpacker.reserve_buffer(size); std::copy(data, data + size, mp_->unpacker.buffer()); mp_->unpacker.buffer_consumed(size); @@ -710,13 +374,6 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { break; } } -#if KB_JSI_PERF - perf_.onDataCalls.fetch_add(1); - perf_.onDataBytes.fetch_add(static_cast(size)); - perf_.unpackNs.fetch_add(perfNanosSince(unpackStart)); - perf_.inboundMessages.fetch_add(values->size()); -#endif - if (values->empty()) { return; } @@ -744,32 +401,15 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { } if (values->size() == 1) { -#if KB_JSI_PERF - auto convertStart = KBPerfClock::now(); -#endif // Single message: pass directly (no array wrapper) msgpack::object obj((*values)[0].get()); Value value = self->convertMPToJSI(runtime, &obj); -#if KB_JSI_PERF - self->perf_.convertMPToJSINs.fetch_add( - perfNanosSince(convertStart)); -#endif if (self->isTornDown_.load()) { return; } -#if KB_JSI_PERF - auto callStart = KBPerfClock::now(); -#endif self->cachedRpcOnJs_->call(runtime, std::move(value), jsi::Value(1)); -#if KB_JSI_PERF - self->perf_.rpcOnJsCalls.fetch_add(1); - self->perf_.rpcOnJsNs.fetch_add(perfNanosSince(callStart)); -#endif } else { -#if KB_JSI_PERF - auto convertStart = KBPerfClock::now(); -#endif // Multiple messages: batch into array, pass count jsi::Array arr(runtime, values->size()); for (size_t i = 0; i < values->size(); ++i) { @@ -777,23 +417,12 @@ void KBBridge::onDataFromGo(uint8_t *data, int size) { arr.setValueAtIndex(runtime, i, self->convertMPToJSI(runtime, &obj)); } -#if KB_JSI_PERF - self->perf_.convertMPToJSINs.fetch_add( - perfNanosSince(convertStart)); -#endif if (self->isTornDown_.load()) { return; } -#if KB_JSI_PERF - auto callStart = KBPerfClock::now(); -#endif self->cachedRpcOnJs_->call( runtime, std::move(arr), jsi::Value(static_cast(values->size()))); -#if KB_JSI_PERF - self->perf_.rpcOnJsCalls.fetch_add(1); - self->perf_.rpcOnJsNs.fetch_add(perfNanosSince(callStart)); -#endif } } catch (const std::exception &e) { if (self->onError_) { diff --git a/rnmodules/react-native-kb/cpp/react-native-kb.h b/rnmodules/react-native-kb/cpp/react-native-kb.h index f09c6bd4f09e..4ca49b66d639 100644 --- a/rnmodules/react-native-kb/cpp/react-native-kb.h +++ b/rnmodules/react-native-kb/cpp/react-native-kb.h @@ -5,7 +5,6 @@ // include with #undef/#pragma push/pop to handle the conflict safely. #pragma once #include -#include "react-native-kb-experiments.h" #include #include #include @@ -51,58 +50,16 @@ class KBBridge : public std::enable_shared_from_this { std::function writeToGo_; std::vector combinedBuf_; - enum class BinaryMode { - uint8ArrayCtor, - mutableArrayBuffer, - mutableWrappedUint8Array, - }; - void resetCaches(facebook::jsi::Runtime &runtime); facebook::jsi::Function &uint8ArrayCtor(facebook::jsi::Runtime &runtime); facebook::jsi::Value binaryFromBytes(facebook::jsi::Runtime &runtime, - const char *ptr, size_t size, - BinaryMode mode); + const char *ptr, size_t size); facebook::jsi::Value convertMPToJSI(facebook::jsi::Runtime &runtime, void *mpObj); void convertJSIToMP(facebook::jsi::Runtime &runtime, const facebook::jsi::Value &value, void *packer); void packAndSend(facebook::jsi::Runtime &runtime, const facebook::jsi::Value &value); - -#ifdef KB_JSI_EXPERIMENTS_ENABLED - void installExperimentBindings(facebook::jsi::Runtime &runtime); -#endif - -#if KB_JSI_PERF - struct PerfCounters { - std::atomic rpcOnGoCalls{0}; - std::atomic rpcOnGoBytes{0}; - std::atomic encodeNs{0}; - std::atomic frameNs{0}; - std::atomic writeToGoNs{0}; - std::atomic onDataCalls{0}; - std::atomic onDataBytes{0}; - std::atomic inboundMessages{0}; - std::atomic unpackNs{0}; - std::atomic convertMPToJSINs{0}; - std::atomic rpcOnJsCalls{0}; - std::atomic rpcOnJsNs{0}; - }; - - PerfCounters perf_; - - void installPerfBindings(facebook::jsi::Runtime &runtime); - void resetPerfCounters(); - facebook::jsi::Value perfStats(facebook::jsi::Runtime &runtime); - facebook::jsi::Value perfRoundTrip(facebook::jsi::Runtime &runtime, - const facebook::jsi::Value *arguments, - size_t count); - facebook::jsi::Value perfMakeBinary(facebook::jsi::Runtime &runtime, - const facebook::jsi::Value *arguments, - size_t count); - facebook::jsi::Value convertMPToJSIPerf(facebook::jsi::Runtime &runtime, - void *mpObj, BinaryMode mode); -#endif }; } // namespace kb diff --git a/rnmodules/react-native-kb/react-native-kb.podspec b/rnmodules/react-native-kb/react-native-kb.podspec index 60c9b37f9164..1ec4a7782d1e 100644 --- a/rnmodules/react-native-kb/react-native-kb.podspec +++ b/rnmodules/react-native-kb/react-native-kb.podspec @@ -2,11 +2,7 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -kb_jsi_inbound_binary_mode = ENV.fetch("KB_JSI_INBOUND_BINARY_MODE", "0") -kb_jsi_outbound_typed_array_fastpath = ENV.fetch("KB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH", "0") -kb_jsi_perf = ENV["KB_JSI_PERF"] == "1" ? " -DKB_JSI_PERF=1" : "" -kb_jsi_experiment_flags = " -DKB_JSI_INBOUND_BINARY_MODE=#{kb_jsi_inbound_binary_mode} -DKB_JSI_OUTBOUND_TYPED_ARRAY_FASTPATH=#{kb_jsi_outbound_typed_array_fastpath}#{kb_jsi_perf}" -kb_cpp_flags = "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1#{kb_jsi_experiment_flags}" +kb_cpp_flags = "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -DMSGPACK_NO_BOOST=1" Pod::Spec.new do |s| s.name = "react-native-kb" diff --git a/shared/globals.d.ts b/shared/globals.d.ts index 6c6033c92d19..e8a16291bf2a 100644 --- a/shared/globals.d.ts +++ b/shared/globals.d.ts @@ -39,36 +39,6 @@ declare global { var __PROFILE__: boolean var rpcOnGo: undefined | ((msg: unknown) => void) var rpcOnJs: undefined | ((objs: unknown, count: number) => void) - var kbJSIExperimentConfig: - | undefined - | { - inboundBinaryMode: number - inboundBinaryModeName: string - outboundTypedArrayFastPath: boolean - perf: boolean - } - var kbJSIPerf: - | undefined - | { - makeBinary: ( - size?: number, - mode?: 'uint8Array' | 'arrayBuffer' | 'wrappedUint8Array' - ) => unknown - reset: () => boolean - roundTrip: ( - value: unknown, - iterations?: number, - mode?: 'uint8Array' | 'arrayBuffer' | 'wrappedUint8Array' - ) => { - bytes: number - decodeNs: number - encodeNs: number - iterations: number - mode: string - value: unknown - } - stats: () => Record - } // RN var __turboModuleProxy: unknown } From 436e8e697ebf04b5ad054fac33bcc1e9fc949304 Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Mon, 4 May 2026 12:37:06 -0400 Subject: [PATCH 07/16] WIP --- shared/ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/ios/Podfile.lock b/shared/ios/Podfile.lock index 64861e1f9eb0..b7dd7ffe8896 100644 --- a/shared/ios/Podfile.lock +++ b/shared/ios/Podfile.lock @@ -3678,7 +3678,7 @@ SPEC CHECKSUMS: React-logger: 993e4b9793768764e0fdd379ad1d6582f7905463 React-Mapbuffer: 0b0d3c3074187e72d8a6e8cacce120cb24581565 React-microtasksnativemodule: 175741856a8f6a31e20b973cb784db023256b259 - react-native-kb: 47693256b04fde39236635d95a3e9d506ef1e101 + react-native-kb: 47269c30b862f82a1556f88cc6f00dbee91a9a98 react-native-keyboard-controller: 1caa8b8c3fc43060344286f17d17cbf649e7e598 react-native-netinfo: 9fad4eedfec9840a10e73ac4591ea1158523309b react-native-safe-area-context: eda63a662750758c1fdd7e719c9f1026c8d161cb From 38f943551928968804dbbab04dac73199608c399 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 12:38:19 -0400 Subject: [PATCH 08/16] WIP --- shared/stores/tests/config.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/stores/tests/config.test.ts b/shared/stores/tests/config.test.ts index 2bafad76faae..4130ba253f39 100644 --- a/shared/stores/tests/config.test.ts +++ b/shared/stores/tests/config.test.ts @@ -118,7 +118,7 @@ test('onEngineIncoming owns audit errors and badge state', () => { test('custom resetState preserves the fields config intentionally carries across resets', () => { const {dispatch} = useConfigState.getState() - dispatch.setAccounts([{hasStoredSecret: true, username: 'alice'}]) + dispatch.setAccounts([{hasStoredSecret: true, uid: 'alice-uid', username: 'alice'}]) dispatch.setDefaultUsername('alice') useConfigState.setState({ globalError: new Error('transient'), @@ -128,7 +128,7 @@ test('custom resetState preserves the fields config intentionally carries across dispatch.resetState() const state = useConfigState.getState() - expect(state.configuredAccounts).toEqual([{hasStoredSecret: true, username: 'alice'}]) + expect(state.configuredAccounts).toEqual([{hasStoredSecret: true, uid: 'alice-uid', username: 'alice'}]) expect(state.defaultUsername).toBe('alice') expect(state.userSwitching).toBe(true) expect(state.globalError).toBeUndefined() From 2b1a45b144047477a07b37c57407a055dc0a0df5 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 12:51:32 -0400 Subject: [PATCH 09/16] WIP --- shared/chat/conversation/data-hooks.tsx | 2 +- shared/chat/conversation/thread-context.tsx | 4 +- shared/chat/inbox/engine.tsx | 10 ++-- shared/chat/inbox/metadata.test.tsx | 51 +++++++++++++++++++++ shared/chat/inbox/metadata.tsx | 32 +++++++++---- 5 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 shared/chat/inbox/metadata.test.tsx diff --git a/shared/chat/conversation/data-hooks.tsx b/shared/chat/conversation/data-hooks.tsx index 61a41f439ccf..1de090cc4848 100644 --- a/shared/chat/conversation/data-hooks.tsx +++ b/shared/chat/conversation/data-hooks.tsx @@ -24,7 +24,7 @@ const emptyMessages: ReadonlyArray = [] const reloadConversationMetadata = (conversationIDKey: T.Chat.ConversationIDKey) => { if (T.Chat.isValidConversationIDKey(conversationIDKey)) { - unboxRows([conversationIDKey], true) + unboxRows([conversationIDKey]) } } diff --git a/shared/chat/conversation/thread-context.tsx b/shared/chat/conversation/thread-context.tsx index 394f894c8d4e..cc0f13dc5691 100644 --- a/shared/chat/conversation/thread-context.tsx +++ b/shared/chat/conversation/thread-context.tsx @@ -1973,7 +1973,6 @@ export const useConversationThreadMessageActions = () => { export const useConversationThreadSelectedConversation = () => { const conversationIDKey = useConversationThreadID() - const isMetaGood = useConversationThreadSelector(s => s.meta.conversationIDKey === conversationIDKey) const loadMoreMessages = useConversationThreadLoadMoreMessages() const participantInfo = useConversationThreadSelector(s => s.participants) @@ -1981,8 +1980,7 @@ export const useConversationThreadSelectedConversation = () => { const {skipThreadLoad, ...loadStatusOptions} = options ?? {} clearChatTimeCache() - const force = !isMetaGood || participantInfo.all.length === 0 - unboxRows([conversationIDKey], force) + unboxRows([conversationIDKey]) const username = useCurrentUserState.getState().username const otherParticipants = Meta.getRowParticipants(participantInfo, username || '') diff --git a/shared/chat/inbox/engine.tsx b/shared/chat/inbox/engine.tsx index 1f2810d12a81..3185097fdf98 100644 --- a/shared/chat/inbox/engine.tsx +++ b/shared/chat/inbox/engine.tsx @@ -12,6 +12,7 @@ import {useShellState} from '@/stores/shell' import {useUsersState} from '@/stores/users' import {updateInboxRowTyping} from '@/stores/inbox-rows' import { + forceUnboxRowsForService, getInboxConversationMeta, metaReceivedError, metasReceived, @@ -57,7 +58,7 @@ const onChatThreadsStale = (updates: ThreadStaleUpdates) => { logger.info( `onChatThreadsStale: dispatching thread reload actions for ${conversationIDKeys.length} convs of type ${key}` ) - unboxRows(conversationIDKeys, true) + forceUnboxRowsForService(conversationIDKeys) }) } @@ -144,7 +145,7 @@ const onNewChatActivity = (activity: NewChatActivity): ConvoEngineIncomingResult return handledConvoEngineIncoming({inboxUIItem}) } case T.RPCChat.ChatActivityType.membersUpdate: - unboxRows([T.Chat.conversationIDToKey(activity.membersUpdate.convID)], true) + forceUnboxRowsForService([T.Chat.conversationIDToKey(activity.membersUpdate.convID)]) return handledConvoEngineIncoming() case T.RPCChat.ChatActivityType.setAppNotificationSettings: { const {setAppNotificationSettings} = activity @@ -228,9 +229,8 @@ export const handleConvoEngineIncoming = (action: EngineGen.Actions): ConvoEngin onChatThreadsStale(action.payload.params.updates) return handledConvoEngineIncoming() case 'chat.1.NotifyChat.ChatSubteamRename': - unboxRows( - (action.payload.params.convs ?? []).map(c => T.Chat.stringToConversationIDKey(c.convID)), - true + forceUnboxRowsForService( + (action.payload.params.convs ?? []).map(c => T.Chat.stringToConversationIDKey(c.convID)) ) return handledConvoEngineIncoming() case 'chat.1.NotifyChat.ChatTLFFinalize': diff --git a/shared/chat/inbox/metadata.test.tsx b/shared/chat/inbox/metadata.test.tsx new file mode 100644 index 000000000000..014796bac89b --- /dev/null +++ b/shared/chat/inbox/metadata.test.tsx @@ -0,0 +1,51 @@ +/// +import * as T from '@/constants/types' +import {resetAllStores} from '@/util/zustand' +import {useConfigState} from '@/stores/config' +import {forceUnboxRowsForService} from './metadata' + +const convID = T.Chat.conversationIDToKey(new Uint8Array([1, 2, 3, 4])) + +const flushPromises = async () => { + for (let i = 0; i < 5; i++) { + await Promise.resolve() + } +} + +beforeEach(() => { + useConfigState.setState({loggedIn: true}) +}) + +afterEach(() => { + jest.restoreAllMocks() + resetAllStores() +}) + +test('forceUnboxRowsForService deduplicates requests while an unbox is in flight', async () => { + const resolvers = new Array<() => void>() + jest.spyOn(T.RPCChat, 'localRequestInboxUnboxRpcPromise').mockImplementation( + () => + new Promise(resolve => { + resolvers.push(() => { + resolve(undefined) + }) + }) + ) + + forceUnboxRowsForService([convID]) + forceUnboxRowsForService([convID]) + await flushPromises() + + expect(T.RPCChat.localRequestInboxUnboxRpcPromise).toHaveBeenCalledTimes(1) + + resolvers[0]?.() + await flushPromises() + + forceUnboxRowsForService([convID]) + await flushPromises() + + expect(T.RPCChat.localRequestInboxUnboxRpcPromise).toHaveBeenCalledTimes(2) + + resolvers[1]?.() + await flushPromises() +}) diff --git a/shared/chat/inbox/metadata.tsx b/shared/chat/inbox/metadata.tsx index 86988e60db27..a81e36c10ac3 100644 --- a/shared/chat/inbox/metadata.tsx +++ b/shared/chat/inbox/metadata.tsx @@ -260,7 +260,7 @@ export const onChatRouteChanged = ( return } if (wasChat && wasID && T.Chat.isValidConversationIDKey(wasID)) { - unboxRows([wasID], true) + unboxRows([wasID]) } } @@ -298,6 +298,8 @@ const untrustedConversationIDKeys = (ids: ReadonlyArray() + type ConvoMetaQueueState = T.Immutable<{ generation: number inFlight: boolean @@ -340,6 +342,7 @@ const useConvoMetaQueueState = Z.createZustand('convo-meta- get().dispatch.queueMetaHandle() }, resetState: () => { + inFlightUnboxRows.clear() set(s => { s.generation += 1 s.inFlight = false @@ -405,7 +408,7 @@ async function runMetaQueueWorker(generation: number) { } } -export const unboxRows = (ids: ReadonlyArray, force?: boolean) => { +const requestInboxUnboxRows = (ids: ReadonlyArray, force: boolean) => { const f = async () => { if (!useConfigState.getState().loggedIn) { return @@ -414,7 +417,10 @@ export const unboxRows = (ids: ReadonlyArray, force?: const conversationIDKeys = ids.reduce>((arr, id) => { if (id && T.Chat.isValidConversationIDKey(id)) { const trustedState = trustedStateForConversation(id) - if (force || (trustedState !== 'requesting' && trustedState !== 'trusted')) { + if ( + !inFlightUnboxRows.has(id) && + (force || (trustedState !== 'requesting' && trustedState !== 'trusted')) + ) { arr.push(id) } } @@ -424,6 +430,7 @@ export const unboxRows = (ids: ReadonlyArray, force?: if (!conversationIDKeys.length) { return } + conversationIDKeys.forEach(id => inFlightUnboxRows.add(id)) setInboxRowTrustedState(conversationIDKeys, 'requesting') logger.info( `unboxRows: unboxing len: ${conversationIDKeys.length} convs: ${conversationIDKeys.join(',')}` @@ -436,11 +443,21 @@ export const unboxRows = (ids: ReadonlyArray, force?: if (error instanceof RPCError) { logger.info(`unboxRows: failed ${error.desc}`) } + } finally { + conversationIDKeys.forEach(id => inFlightUnboxRows.delete(id)) } } ignorePromise(f()) } +export const unboxRows = (ids: ReadonlyArray) => { + requestInboxUnboxRows(ids, false) +} + +export const forceUnboxRowsForService = (ids: ReadonlyArray) => { + requestInboxUnboxRows(ids, true) +} + export const queueMetaHandle = () => { useConvoMetaQueueState.getState().dispatch.queueMetaHandle() } @@ -471,7 +488,7 @@ export const ensureWidgetMetas = ( if (missing.length === 0) { return } - unboxRows(missing, true) + unboxRows(missing) } export const ensureInboxSearchMetas = (ids: ReadonlyArray) => { @@ -482,7 +499,7 @@ export const ensureInboxSearchMetas = (ids: ReadonlyArray 0) { - unboxRows(missing, true) + unboxRows(missing) } } @@ -554,11 +571,10 @@ export const onChatInboxSynced = async ( metasReceived(metas, removals) } - unboxRows( + forceUnboxRowsForService( items .filter(item => item.shouldUnbox) - .map(item => T.Chat.stringToConversationIDKey(item.conv.convID)), - true + .map(item => T.Chat.stringToConversationIDKey(item.conv.convID)) ) return } From 05b9495bf7622cf31f689846e481ff7fe199cc9d Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Mon, 4 May 2026 12:52:36 -0400 Subject: [PATCH 10/16] WIP --- shared/chat/inbox/metadata.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/chat/inbox/metadata.test.tsx b/shared/chat/inbox/metadata.test.tsx index 014796bac89b..818aa9e38174 100644 --- a/shared/chat/inbox/metadata.test.tsx +++ b/shared/chat/inbox/metadata.test.tsx @@ -24,7 +24,7 @@ afterEach(() => { test('forceUnboxRowsForService deduplicates requests while an unbox is in flight', async () => { const resolvers = new Array<() => void>() jest.spyOn(T.RPCChat, 'localRequestInboxUnboxRpcPromise').mockImplementation( - () => + async () => new Promise(resolve => { resolvers.push(() => { resolve(undefined) From a8b619ff463affe24f3364a96b1e81b446c85958 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 13:00:08 -0400 Subject: [PATCH 11/16] WIP --- shared/chat/inbox/engine.test.tsx | 28 ++++++++++++++++++++++++++++ shared/chat/inbox/engine.tsx | 9 +++++++-- shared/chat/inbox/metadata.test.tsx | 7 ++----- shared/chat/inbox/metadata.tsx | 21 +++++++++++++++++---- 4 files changed, 54 insertions(+), 11 deletions(-) diff --git a/shared/chat/inbox/engine.test.tsx b/shared/chat/inbox/engine.test.tsx index 98a2e0e7e637..b78349808c77 100644 --- a/shared/chat/inbox/engine.test.tsx +++ b/shared/chat/inbox/engine.test.tsx @@ -3,6 +3,7 @@ import * as T from '@/constants/types' import {resetAllStores} from '@/util/zustand' import {handleConvoEngineIncoming} from './engine' import {getInboxConversationMeta, getInboxConversationParticipants, syncBadgeState} from './metadata' +import {useConfigState} from '@/stores/config' import { syncInboxRowBadgeState, syncInboxRowsFromParticipantMap, @@ -265,6 +266,33 @@ test('global message activity routing preserves returned global data', () => { expect(reactionResult.userReacjis).toEqual(userReacjis) }) +test('read message activity without attached inbox item refreshes service-owned metadata', () => { + useConfigState.setState({loggedIn: true}) + const unbox = jest.spyOn(T.RPCChat, 'localRequestInboxUnboxRpcPromise').mockResolvedValue(undefined) + + expect( + handleConvoEngineIncoming({ + payload: { + params: { + activity: { + activityType: T.RPCChat.ChatActivityType.readMessage, + readMessage: { + conv: null, + convID: T.Chat.keyToConversationID(convID), + msgID: T.Chat.messageIDToNumber(msgID), + }, + }, + }, + }, + type: 'chat.1.NotifyChat.NewChatActivity', + } as never).handled + ).toBe(true) + + expect(unbox).toHaveBeenCalledWith({ + convIDs: [T.Chat.keyToConversationID(convID)], + }) +}) + test('global failed message and transfer routing is handled without mounted thread state', () => { expect( handleConvoEngineIncoming({ diff --git a/shared/chat/inbox/engine.tsx b/shared/chat/inbox/engine.tsx index 3185097fdf98..b8911f5a129e 100644 --- a/shared/chat/inbox/engine.tsx +++ b/shared/chat/inbox/engine.tsx @@ -116,8 +116,13 @@ const onNewChatActivity = (activity: NewChatActivity): ConvoEngineIncomingResult } case T.RPCChat.ChatActivityType.setStatus: return handledConvoEngineIncoming({inboxUIItem: activity.setStatus.conv ?? undefined}) - case T.RPCChat.ChatActivityType.readMessage: - return handledConvoEngineIncoming({inboxUIItem: activity.readMessage.conv ?? undefined}) + case T.RPCChat.ChatActivityType.readMessage: { + const {readMessage} = activity + if (!readMessage.conv) { + forceUnboxRowsForService([T.Chat.conversationIDToKey(readMessage.convID)]) + } + return handledConvoEngineIncoming({inboxUIItem: readMessage.conv ?? undefined}) + } case T.RPCChat.ChatActivityType.newConversation: return handledConvoEngineIncoming({inboxUIItem: activity.newConversation.conv ?? undefined}) case T.RPCChat.ChatActivityType.failedMessage: { diff --git a/shared/chat/inbox/metadata.test.tsx b/shared/chat/inbox/metadata.test.tsx index 818aa9e38174..ca6b87ddfd0d 100644 --- a/shared/chat/inbox/metadata.test.tsx +++ b/shared/chat/inbox/metadata.test.tsx @@ -21,10 +21,10 @@ afterEach(() => { resetAllStores() }) -test('forceUnboxRowsForService deduplicates requests while an unbox is in flight', async () => { +test('forceUnboxRowsForService reruns once for requests made while an unbox is in flight', async () => { const resolvers = new Array<() => void>() jest.spyOn(T.RPCChat, 'localRequestInboxUnboxRpcPromise').mockImplementation( - async () => + () => new Promise(resolve => { resolvers.push(() => { resolve(undefined) @@ -41,9 +41,6 @@ test('forceUnboxRowsForService deduplicates requests while an unbox is in flight resolvers[0]?.() await flushPromises() - forceUnboxRowsForService([convID]) - await flushPromises() - expect(T.RPCChat.localRequestInboxUnboxRpcPromise).toHaveBeenCalledTimes(2) resolvers[1]?.() diff --git a/shared/chat/inbox/metadata.tsx b/shared/chat/inbox/metadata.tsx index a81e36c10ac3..feb73f05c957 100644 --- a/shared/chat/inbox/metadata.tsx +++ b/shared/chat/inbox/metadata.tsx @@ -299,6 +299,7 @@ const untrustedConversationIDKeys = (ids: ReadonlyArray() +const pendingForcedUnboxRows = new Set() type ConvoMetaQueueState = T.Immutable<{ generation: number @@ -343,6 +344,7 @@ const useConvoMetaQueueState = Z.createZustand('convo-meta- }, resetState: () => { inFlightUnboxRows.clear() + pendingForcedUnboxRows.clear() set(s => { s.generation += 1 s.inFlight = false @@ -417,10 +419,11 @@ const requestInboxUnboxRows = (ids: ReadonlyArray, for const conversationIDKeys = ids.reduce>((arr, id) => { if (id && T.Chat.isValidConversationIDKey(id)) { const trustedState = trustedStateForConversation(id) - if ( - !inFlightUnboxRows.has(id) && - (force || (trustedState !== 'requesting' && trustedState !== 'trusted')) - ) { + if (inFlightUnboxRows.has(id)) { + if (force) { + pendingForcedUnboxRows.add(id) + } + } else if (force || (trustedState !== 'requesting' && trustedState !== 'trusted')) { arr.push(id) } } @@ -445,6 +448,16 @@ const requestInboxUnboxRows = (ids: ReadonlyArray, for } } finally { conversationIDKeys.forEach(id => inFlightUnboxRows.delete(id)) + const rerunIDs = conversationIDKeys.filter(id => { + const shouldRerun = pendingForcedUnboxRows.has(id) + if (shouldRerun) { + pendingForcedUnboxRows.delete(id) + } + return shouldRerun + }) + if (rerunIDs.length > 0) { + requestInboxUnboxRows(rerunIDs, true) + } } } ignorePromise(f()) From 0131ad244fd8a3e0b1c7ffaed2846b58062d2dcb Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 13:09:07 -0400 Subject: [PATCH 12/16] WIP --- .../conversation/list-area/index.native.tsx | 23 +++++++++---------- shared/chat/inbox/metadata.test.tsx | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/shared/chat/conversation/list-area/index.native.tsx b/shared/chat/conversation/list-area/index.native.tsx index 70f81140a25c..43d3ca4d98ee 100644 --- a/shared/chat/conversation/list-area/index.native.tsx +++ b/shared/chat/conversation/list-area/index.native.tsx @@ -31,10 +31,6 @@ import {useThreadLoadStatusOptionsGetter} from '../thread-load-status-context' const List = /*usingFlashList ? FlashList :*/ FlatList const noOrdinals: ReadonlyArray = [] -// We load the first thread automatically so in order to mark it read -// we send an action on the first mount once -let markedInitiallyLoaded = false - export const DEBUGDump = () => {} const useInvertedMessageOrdinals = (messageOrdinals?: ReadonlyArray) => { @@ -183,20 +179,23 @@ const ConversationList = function ConversationList() { return undefined }, [centeredOrdinalOrNone, scrollToCentered]) - React.useEffect(() => { - if (!markedInitiallyLoaded) { - markedInitiallyLoaded = true - markInitiallyLoadedThreadAsRead() - } - }, [markInitiallyLoadedThreadAsRead]) - - const prevLoadedRef = React.useRef(loaded) + const prevLoadedRef = React.useRef(false) + const markedLoadedThreadRef = React.useRef(false) + React.useLayoutEffect(() => { + prevLoadedRef.current = false + markedLoadedThreadRef.current = false + }, [conversationIDKey]) React.useLayoutEffect(() => { const justLoaded = loaded && !prevLoadedRef.current prevLoadedRef.current = loaded if (!justLoaded) return + if (!markedLoadedThreadRef.current) { + markedLoadedThreadRef.current = true + markInitiallyLoadedThreadAsRead() + } + if (centeredOrdinalOrNone > 0) { scrollToCentered() setTimeout(() => { diff --git a/shared/chat/inbox/metadata.test.tsx b/shared/chat/inbox/metadata.test.tsx index ca6b87ddfd0d..cbde2fbfde72 100644 --- a/shared/chat/inbox/metadata.test.tsx +++ b/shared/chat/inbox/metadata.test.tsx @@ -24,7 +24,7 @@ afterEach(() => { test('forceUnboxRowsForService reruns once for requests made while an unbox is in flight', async () => { const resolvers = new Array<() => void>() jest.spyOn(T.RPCChat, 'localRequestInboxUnboxRpcPromise').mockImplementation( - () => + async () => new Promise(resolve => { resolvers.push(() => { resolve(undefined) From 4d015a412ace9930b3276f77cc734684db43aec3 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 13:10:03 -0400 Subject: [PATCH 13/16] WIP --- shared/chat/conversation/list-area/index.native.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/shared/chat/conversation/list-area/index.native.tsx b/shared/chat/conversation/list-area/index.native.tsx index 43d3ca4d98ee..b5d574e0b11f 100644 --- a/shared/chat/conversation/list-area/index.native.tsx +++ b/shared/chat/conversation/list-area/index.native.tsx @@ -207,7 +207,14 @@ const ConversationList = function ConversationList() { scrollToBottom() }, 100) } - }, [loaded, centeredOrdinalOrNone, scrollToBottom, scrollToCentered, numOrdinals]) + }, [ + centeredOrdinalOrNone, + loaded, + markInitiallyLoadedThreadAsRead, + numOrdinals, + scrollToBottom, + scrollToCentered, + ]) // useChatDebugDump( // 'listArea', From 3049f1df0aae2c3aca51f7f14a625e1b78d1f363 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 13:13:24 -0400 Subject: [PATCH 14/16] WIP --- shared/chat/conversation/list-area/hooks.tsx | 11 +---------- shared/chat/conversation/list-area/index.desktop.tsx | 2 +- shared/chat/conversation/list-area/index.native.tsx | 2 +- shared/chat/conversation/thread-context.tsx | 5 ++++- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/shared/chat/conversation/list-area/hooks.tsx b/shared/chat/conversation/list-area/hooks.tsx index c320b12e72d2..5b6f064cbf99 100644 --- a/shared/chat/conversation/list-area/hooks.tsx +++ b/shared/chat/conversation/list-area/hooks.tsx @@ -1,24 +1,15 @@ import * as C from '@/constants' -import * as Chat from '@/constants/chat' import JumpToRecent from './jump-to-recent' -import type * as T from '@/constants/types' import {useConversationCenter} from '../center-context' import { useConversationThreadMarkThreadAsRead, useConversationThreadSelector, useConversationThreadToggleSearch, } from '../thread-context' -import logger from '@/logger' -export const useActions = (p: {conversationIDKey: T.Chat.ConversationIDKey}) => { - const {conversationIDKey} = p +export const useActions = () => { const markThreadAsRead = useConversationThreadMarkThreadAsRead() const markInitiallyLoadedThreadAsRead = () => { - const selected = Chat.getSelectedConversation() - if (selected !== conversationIDKey) { - logger.info('mark intially as read bail on not looking at this thread anymore?') - return - } markThreadAsRead() } diff --git a/shared/chat/conversation/list-area/index.desktop.tsx b/shared/chat/conversation/list-area/index.desktop.tsx index 409698f74e4f..8a4a932d5a54 100644 --- a/shared/chat/conversation/list-area/index.desktop.tsx +++ b/shared/chat/conversation/list-area/index.desktop.tsx @@ -64,7 +64,7 @@ const useScrolling = (p: { const loadOlderMessages = React.useCallback((numOrdinals: number) => { loadOlderMessagesDueToScroll(numOrdinals, getThreadLoadStatusOptions()) }, [loadOlderMessagesDueToScroll, getThreadLoadStatusOptions]) - const {markInitiallyLoadedThreadAsRead} = Hooks.useActions({conversationIDKey}) + const {markInitiallyLoadedThreadAsRead} = Hooks.useActions() // pixels away from top/bottom to load/be locked const listEdgeSlopBottom = 10 const listEdgeSlopTop = 1000 diff --git a/shared/chat/conversation/list-area/index.native.tsx b/shared/chat/conversation/list-area/index.native.tsx index b5d574e0b11f..e47df471047e 100644 --- a/shared/chat/conversation/list-area/index.native.tsx +++ b/shared/chat/conversation/list-area/index.native.tsx @@ -123,7 +123,7 @@ const ConversationList = function ConversationList() { const messageOrdinals = useInvertedMessageOrdinals(listData.messageOrdinals) const listRef = React.useRef |*/ FlatList | null>(null) - const {markInitiallyLoadedThreadAsRead} = Hooks.useActions({conversationIDKey}) + const {markInitiallyLoadedThreadAsRead} = Hooks.useActions() const keyExtractor = (ordinal: ItemType) => { return String(ordinal) } diff --git a/shared/chat/conversation/thread-context.tsx b/shared/chat/conversation/thread-context.tsx index cc0f13dc5691..5f446145c29c 100644 --- a/shared/chat/conversation/thread-context.tsx +++ b/shared/chat/conversation/thread-context.tsx @@ -30,6 +30,7 @@ import {useShellState} from '@/stores/shell' import {produce, type Draft} from 'immer' import {useStore} from 'zustand' import {createStore, type StoreApi} from 'zustand/vanilla' +import {useIsFocused} from '@react-navigation/core' import { addMessagesToThreadState, applyOptimisticReactionsToMessage, @@ -903,6 +904,8 @@ const ConversationThreadProviderInner = (p: ConversationThreadProviderProps) => const {children, id} = p const [threadStore] = React.useState(() => makeThreadStore(id)) const active = useShellState(s => s.active) + const appFocused = useShellState(s => s.appFocused) + const routeFocused = useIsFocused() const previousActiveRef = React.useRef(active) const activeMarkReadEnabledRef = React.useRef(false) const markReadBlockedRef = React.useRef(false) @@ -936,7 +939,7 @@ const ConversationThreadProviderInner = (p: ConversationThreadProviderProps) => logger.info('mark read bail on blocked thread load') return } - if (!Common.isUserActivelyLookingAtThisThread(id)) { + if (!appFocused || !active || !routeFocused) { logger.info('mark read bail on not looking at this thread') return } From f5dd7aff8022f7a555c4e6ec3d410cec4e102382 Mon Sep 17 00:00:00 2001 From: Chris Nojima Date: Mon, 4 May 2026 13:15:28 -0400 Subject: [PATCH 15/16] WIP --- shared/chat/conversation/list-area/index.desktop.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/shared/chat/conversation/list-area/index.desktop.tsx b/shared/chat/conversation/list-area/index.desktop.tsx index 8a4a932d5a54..23fe3b263b3c 100644 --- a/shared/chat/conversation/list-area/index.desktop.tsx +++ b/shared/chat/conversation/list-area/index.desktop.tsx @@ -44,7 +44,6 @@ const useScrolling = (p: { setListRef: (r: HTMLDivElement | null) => void centeredOrdinal: T.Chat.Ordinal | undefined }) => { - const conversationIDKey = useConversationThreadID() const {listRef, setListRef: _setListRef, containsLatestMessage} = p const containsLatestMessageRef = React.useRef(containsLatestMessage) React.useEffect(() => { From b5fe604a2ff7932c65e12ab83d861cbf0aee9f2b Mon Sep 17 00:00:00 2001 From: chrisnojima Date: Mon, 4 May 2026 13:21:07 -0400 Subject: [PATCH 16/16] WIP --- go/protocol/chat1/blocking.go | 3 ++- go/protocol/chat1/chat_ui.go | 3 ++- go/protocol/chat1/commands.go | 1 + go/protocol/chat1/common.go | 1 + go/protocol/chat1/emoji.go | 1 + go/protocol/chat1/local.go | 3 ++- go/protocol/chat1/notify.go | 3 ++- go/protocol/chat1/remote.go | 3 ++- go/protocol/chat1/unfurl.go | 1 + go/protocol/gregor1/auth.go | 3 ++- go/protocol/gregor1/auth_internal.go | 3 ++- go/protocol/gregor1/auth_update.go | 3 ++- go/protocol/gregor1/incoming.go | 3 ++- go/protocol/gregor1/outgoing.go | 3 ++- go/protocol/gregor1/remind.go | 3 ++- go/protocol/kbgitkbfs1/disk_block_cache.go | 3 ++- go/protocol/keybase1/account.go | 3 ++- go/protocol/keybase1/airdrop.go | 3 ++- go/protocol/keybase1/apiserver.go | 3 ++- go/protocol/keybase1/appstate.go | 3 ++- go/protocol/keybase1/audit.go | 3 ++- go/protocol/keybase1/avatars.go | 3 ++- go/protocol/keybase1/backend_common.go | 1 + go/protocol/keybase1/badger.go | 3 ++- go/protocol/keybase1/block.go | 3 ++- go/protocol/keybase1/bot.go | 3 ++- go/protocol/keybase1/btc.go | 3 ++- go/protocol/keybase1/common.go | 1 + go/protocol/keybase1/config.go | 3 ++- go/protocol/keybase1/constants.go | 1 + go/protocol/keybase1/contacts.go | 3 ++- go/protocol/keybase1/crypto.go | 3 ++- go/protocol/keybase1/cryptocurrency.go | 3 ++- go/protocol/keybase1/ctl.go | 3 ++- go/protocol/keybase1/debugging.go | 3 ++- go/protocol/keybase1/delegate_ui_ctl.go | 3 ++- go/protocol/keybase1/device.go | 3 ++- go/protocol/keybase1/emails.go | 3 ++- go/protocol/keybase1/ephemeral.go | 1 + go/protocol/keybase1/favorite.go | 3 ++- go/protocol/keybase1/featured_bot.go | 3 ++- go/protocol/keybase1/fs.go | 3 ++- go/protocol/keybase1/git.go | 3 ++- go/protocol/keybase1/gpg_ui.go | 3 ++- go/protocol/keybase1/gregor.go | 3 ++- go/protocol/keybase1/gregor_ui.go | 3 ++- go/protocol/keybase1/home.go | 3 ++- go/protocol/keybase1/home_ui.go | 3 ++- go/protocol/keybase1/identify.go | 3 ++- go/protocol/keybase1/identify3.go | 3 ++- go/protocol/keybase1/identify3_ui.go | 3 ++- go/protocol/keybase1/identify_common.go | 1 + go/protocol/keybase1/identify_ui.go | 3 ++- go/protocol/keybase1/implicit_team_migration.go | 3 ++- go/protocol/keybase1/incoming-share.go | 3 ++- go/protocol/keybase1/install.go | 3 ++- go/protocol/keybase1/invite_friends.go | 3 ++- go/protocol/keybase1/kbfs.go | 3 ++- go/protocol/keybase1/kbfs_common.go | 1 + go/protocol/keybase1/kbfs_git.go | 3 ++- go/protocol/keybase1/kbfsmount.go | 3 ++- go/protocol/keybase1/kex2provisionee.go | 3 ++- go/protocol/keybase1/kex2provisionee2.go | 3 ++- go/protocol/keybase1/kex2provisioner.go | 3 ++- go/protocol/keybase1/kvstore.go | 3 ++- go/protocol/keybase1/log.go | 3 ++- go/protocol/keybase1/log_ui.go | 3 ++- go/protocol/keybase1/login.go | 3 ++- go/protocol/keybase1/login_ui.go | 3 ++- go/protocol/keybase1/logsend.go | 3 ++- go/protocol/keybase1/merkle.go | 3 ++- go/protocol/keybase1/metadata.go | 3 ++- go/protocol/keybase1/metadata_update.go | 3 ++- go/protocol/keybase1/network_stats.go | 1 + go/protocol/keybase1/notify_app.go | 3 ++- go/protocol/keybase1/notify_audit.go | 3 ++- go/protocol/keybase1/notify_badges.go | 3 ++- go/protocol/keybase1/notify_can_user_perform.go | 3 ++- go/protocol/keybase1/notify_ctl.go | 3 ++- go/protocol/keybase1/notify_device_clone.go | 3 ++- go/protocol/keybase1/notify_email.go | 3 ++- go/protocol/keybase1/notify_ephemeral.go | 3 ++- go/protocol/keybase1/notify_favorites.go | 3 ++- go/protocol/keybase1/notify_featuredbots.go | 3 ++- go/protocol/keybase1/notify_fs.go | 3 ++- go/protocol/keybase1/notify_fs_request.go | 3 ++- go/protocol/keybase1/notify_invite_friends.go | 3 ++- go/protocol/keybase1/notify_keyfamily.go | 3 ++- go/protocol/keybase1/notify_paperkey.go | 3 ++- go/protocol/keybase1/notify_pgp.go | 3 ++- go/protocol/keybase1/notify_phone.go | 3 ++- go/protocol/keybase1/notify_runtimestats.go | 3 ++- go/protocol/keybase1/notify_saltpack.go | 3 ++- go/protocol/keybase1/notify_service.go | 3 ++- go/protocol/keybase1/notify_session.go | 3 ++- go/protocol/keybase1/notify_simple_fs.go | 3 ++- go/protocol/keybase1/notify_team.go | 3 ++- go/protocol/keybase1/notify_teambot.go | 3 ++- go/protocol/keybase1/notify_tracking.go | 3 ++- go/protocol/keybase1/notify_users.go | 3 ++- go/protocol/keybase1/os.go | 1 + go/protocol/keybase1/paperprovision.go | 3 ++- go/protocol/keybase1/passphrase_common.go | 1 + go/protocol/keybase1/pgp.go | 3 ++- go/protocol/keybase1/pgp_ui.go | 3 ++- go/protocol/keybase1/phone_numbers.go | 3 ++- go/protocol/keybase1/pprof.go | 3 ++- go/protocol/keybase1/process.go | 1 + go/protocol/keybase1/prove.go | 3 ++- go/protocol/keybase1/prove_common.go | 1 + go/protocol/keybase1/prove_ui.go | 3 ++- go/protocol/keybase1/provision_ui.go | 3 ++- go/protocol/keybase1/quota.go | 3 ++- go/protocol/keybase1/reachability.go | 3 ++- go/protocol/keybase1/rekey.go | 3 ++- go/protocol/keybase1/rekey_ui.go | 3 ++- go/protocol/keybase1/reset.go | 1 + go/protocol/keybase1/revoke.go | 3 ++- go/protocol/keybase1/saltpack.go | 3 ++- go/protocol/keybase1/saltpack_ui.go | 3 ++- go/protocol/keybase1/scanproofs.go | 3 ++- go/protocol/keybase1/secret_ui.go | 3 ++- go/protocol/keybase1/secretkeys.go | 3 ++- go/protocol/keybase1/selfprovision.go | 3 ++- go/protocol/keybase1/session.go | 3 ++- go/protocol/keybase1/signup.go | 3 ++- go/protocol/keybase1/sigs.go | 3 ++- go/protocol/keybase1/simple_fs.go | 3 ++- go/protocol/keybase1/stream_ui.go | 3 ++- go/protocol/keybase1/teams.go | 3 ++- go/protocol/keybase1/teams_ui.go | 3 ++- go/protocol/keybase1/teamsearch.go | 3 ++- go/protocol/keybase1/test.go | 3 ++- go/protocol/keybase1/tlf.go | 3 ++- go/protocol/keybase1/tlf_keys.go | 3 ++- go/protocol/keybase1/track.go | 3 ++- go/protocol/keybase1/ui.go | 3 ++- go/protocol/keybase1/upk.go | 1 + go/protocol/keybase1/user.go | 3 ++- go/protocol/keybase1/usersearch.go | 3 ++- go/protocol/keybase1/wot.go | 3 ++- go/protocol/stellar1/bundle.go | 1 + go/protocol/stellar1/common.go | 1 + go/protocol/stellar1/local.go | 3 ++- go/protocol/stellar1/notify.go | 3 ++- go/protocol/stellar1/remote.go | 3 ++- go/protocol/stellar1/ui.go | 3 ++- 147 files changed, 275 insertions(+), 128 deletions(-) diff --git a/go/protocol/chat1/blocking.go b/go/protocol/chat1/blocking.go index a3089766af1e..aa9e8ef94e8b 100644 --- a/go/protocol/chat1/blocking.go +++ b/go/protocol/chat1/blocking.go @@ -5,9 +5,10 @@ package chat1 import ( "context" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type BlockConversationsArg struct { diff --git a/go/protocol/chat1/chat_ui.go b/go/protocol/chat1/chat_ui.go index c42d991ae124..c1931f2ec8ff 100644 --- a/go/protocol/chat1/chat_ui.go +++ b/go/protocol/chat1/chat_ui.go @@ -7,11 +7,12 @@ import ( "context" "errors" "fmt" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" keybase1 "github.com/keybase/client/go/protocol/keybase1" stellar1 "github.com/keybase/client/go/protocol/stellar1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type UIPagination struct { diff --git a/go/protocol/chat1/commands.go b/go/protocol/chat1/commands.go index 191345d1238c..31f26b835ef7 100644 --- a/go/protocol/chat1/commands.go +++ b/go/protocol/chat1/commands.go @@ -6,6 +6,7 @@ package chat1 import ( "errors" "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/chat1/common.go b/go/protocol/chat1/common.go index 4165070d94bc..54a11c6a00c5 100644 --- a/go/protocol/chat1/common.go +++ b/go/protocol/chat1/common.go @@ -6,6 +6,7 @@ package chat1 import ( "errors" "fmt" + gregor1 "github.com/keybase/client/go/protocol/gregor1" keybase1 "github.com/keybase/client/go/protocol/keybase1" stellar1 "github.com/keybase/client/go/protocol/stellar1" diff --git a/go/protocol/chat1/emoji.go b/go/protocol/chat1/emoji.go index dd3bbea25b00..3119464a3f26 100644 --- a/go/protocol/chat1/emoji.go +++ b/go/protocol/chat1/emoji.go @@ -6,6 +6,7 @@ package chat1 import ( "errors" "fmt" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/chat1/local.go b/go/protocol/chat1/local.go index 325b42fc04d1..81a70ac10faf 100644 --- a/go/protocol/chat1/local.go +++ b/go/protocol/chat1/local.go @@ -7,11 +7,12 @@ import ( "context" "errors" "fmt" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" keybase1 "github.com/keybase/client/go/protocol/keybase1" stellar1 "github.com/keybase/client/go/protocol/stellar1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type VersionKind string diff --git a/go/protocol/chat1/notify.go b/go/protocol/chat1/notify.go index 8d5938203bbf..4d0beb306391 100644 --- a/go/protocol/chat1/notify.go +++ b/go/protocol/chat1/notify.go @@ -7,9 +7,10 @@ import ( "context" "errors" "fmt" + "time" + keybase1 "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type ChatActivitySource int diff --git a/go/protocol/chat1/remote.go b/go/protocol/chat1/remote.go index 09fa48ad9da3..d4659e34c643 100644 --- a/go/protocol/chat1/remote.go +++ b/go/protocol/chat1/remote.go @@ -7,10 +7,11 @@ import ( "context" "errors" "fmt" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" keybase1 "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type MessageBoxed struct { diff --git a/go/protocol/chat1/unfurl.go b/go/protocol/chat1/unfurl.go index 2b855c72ff67..dc6cbfc26045 100644 --- a/go/protocol/chat1/unfurl.go +++ b/go/protocol/chat1/unfurl.go @@ -6,6 +6,7 @@ package chat1 import ( "errors" "fmt" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/gregor1/auth.go b/go/protocol/gregor1/auth.go index 11b651dff36f..276e3de05eba 100644 --- a/go/protocol/gregor1/auth.go +++ b/go/protocol/gregor1/auth.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type AuthResult struct { diff --git a/go/protocol/gregor1/auth_internal.go b/go/protocol/gregor1/auth_internal.go index 64f00b07707b..e540efaafdc9 100644 --- a/go/protocol/gregor1/auth_internal.go +++ b/go/protocol/gregor1/auth_internal.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CreateGregorSuperUserSessionTokenArg struct { diff --git a/go/protocol/gregor1/auth_update.go b/go/protocol/gregor1/auth_update.go index 46f008d6655c..0b424f339da8 100644 --- a/go/protocol/gregor1/auth_update.go +++ b/go/protocol/gregor1/auth_update.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RevokeSessionIDsArg struct { diff --git a/go/protocol/gregor1/incoming.go b/go/protocol/gregor1/incoming.go index eeb7e12d990c..1c3962b92630 100644 --- a/go/protocol/gregor1/incoming.go +++ b/go/protocol/gregor1/incoming.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SyncResult struct { diff --git a/go/protocol/gregor1/outgoing.go b/go/protocol/gregor1/outgoing.go index fb9f0df681f3..0351291ac898 100644 --- a/go/protocol/gregor1/outgoing.go +++ b/go/protocol/gregor1/outgoing.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type BroadcastMessageArg struct { diff --git a/go/protocol/gregor1/remind.go b/go/protocol/gregor1/remind.go index 6d35e4d6032c..ce27da1c4d50 100644 --- a/go/protocol/gregor1/remind.go +++ b/go/protocol/gregor1/remind.go @@ -5,8 +5,9 @@ package gregor1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type GetRemindersArg struct { diff --git a/go/protocol/kbgitkbfs1/disk_block_cache.go b/go/protocol/kbgitkbfs1/disk_block_cache.go index 755e42deb95e..728d7d4875cb 100644 --- a/go/protocol/kbgitkbfs1/disk_block_cache.go +++ b/go/protocol/kbgitkbfs1/disk_block_cache.go @@ -6,8 +6,9 @@ package kbgitkbfs1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PrefetchStatus int diff --git a/go/protocol/keybase1/account.go b/go/protocol/keybase1/account.go index d617da84a7ab..8ed636389762 100644 --- a/go/protocol/keybase1/account.go +++ b/go/protocol/keybase1/account.go @@ -5,9 +5,10 @@ package keybase1 import ( "context" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type HasServerKeysRes struct { diff --git a/go/protocol/keybase1/airdrop.go b/go/protocol/keybase1/airdrop.go index 79e35f738d38..8d8952d6fc7c 100644 --- a/go/protocol/keybase1/airdrop.go +++ b/go/protocol/keybase1/airdrop.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type AirdropDetails struct { diff --git a/go/protocol/keybase1/apiserver.go b/go/protocol/keybase1/apiserver.go index 9e3a3ed55ce4..2ad6a7680414 100644 --- a/go/protocol/keybase1/apiserver.go +++ b/go/protocol/keybase1/apiserver.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type APIRes struct { diff --git a/go/protocol/keybase1/appstate.go b/go/protocol/keybase1/appstate.go index d1e705035b5d..9850958b713e 100644 --- a/go/protocol/keybase1/appstate.go +++ b/go/protocol/keybase1/appstate.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type MobileAppState int diff --git a/go/protocol/keybase1/audit.go b/go/protocol/keybase1/audit.go index 3af82c5ed91e..95e39d81c738 100644 --- a/go/protocol/keybase1/audit.go +++ b/go/protocol/keybase1/audit.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type BoxAuditAttemptResult int diff --git a/go/protocol/keybase1/avatars.go b/go/protocol/keybase1/avatars.go index c4b07ab714cf..ebbb537dfc31 100644 --- a/go/protocol/keybase1/avatars.go +++ b/go/protocol/keybase1/avatars.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type AvatarUrl string diff --git a/go/protocol/keybase1/backend_common.go b/go/protocol/keybase1/backend_common.go index fe5bbe41f883..1d8eda7000ee 100644 --- a/go/protocol/keybase1/backend_common.go +++ b/go/protocol/keybase1/backend_common.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/badger.go b/go/protocol/keybase1/badger.go index 7d199d5a0fdf..2e66791dd0d1 100644 --- a/go/protocol/keybase1/badger.go +++ b/go/protocol/keybase1/badger.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type GetBadgeStateArg struct { diff --git a/go/protocol/keybase1/block.go b/go/protocol/keybase1/block.go index 4e2084937460..73300513c973 100644 --- a/go/protocol/keybase1/block.go +++ b/go/protocol/keybase1/block.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type BlockStatus int diff --git a/go/protocol/keybase1/bot.go b/go/protocol/keybase1/bot.go index d910b1d18ecf..0603ec6bb239 100644 --- a/go/protocol/keybase1/bot.go +++ b/go/protocol/keybase1/bot.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type BotToken string diff --git a/go/protocol/keybase1/btc.go b/go/protocol/keybase1/btc.go index 2a89c066af10..f54ceba73d69 100644 --- a/go/protocol/keybase1/btc.go +++ b/go/protocol/keybase1/btc.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RegisterBTCArg struct { diff --git a/go/protocol/keybase1/common.go b/go/protocol/keybase1/common.go index 66ff60d1a898..755c4030df44 100644 --- a/go/protocol/keybase1/common.go +++ b/go/protocol/keybase1/common.go @@ -6,6 +6,7 @@ package keybase1 import ( "errors" "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/config.go b/go/protocol/keybase1/config.go index 39aacdbed04c..093d5a2eaa99 100644 --- a/go/protocol/keybase1/config.go +++ b/go/protocol/keybase1/config.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CurrentStatus struct { diff --git a/go/protocol/keybase1/constants.go b/go/protocol/keybase1/constants.go index d98fbb9f22a0..d91be85ae977 100644 --- a/go/protocol/keybase1/constants.go +++ b/go/protocol/keybase1/constants.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/contacts.go b/go/protocol/keybase1/contacts.go index 14d1078dc6c0..d88e674f04eb 100644 --- a/go/protocol/keybase1/contacts.go +++ b/go/protocol/keybase1/contacts.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ContactComponent struct { diff --git a/go/protocol/keybase1/crypto.go b/go/protocol/keybase1/crypto.go index b0d3df2b7fb6..17f722c7ec66 100644 --- a/go/protocol/keybase1/crypto.go +++ b/go/protocol/keybase1/crypto.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ED25519PublicKey [32]byte diff --git a/go/protocol/keybase1/cryptocurrency.go b/go/protocol/keybase1/cryptocurrency.go index 49b4a0ed56ae..bfc07f89174d 100644 --- a/go/protocol/keybase1/cryptocurrency.go +++ b/go/protocol/keybase1/cryptocurrency.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RegisterAddressRes struct { diff --git a/go/protocol/keybase1/ctl.go b/go/protocol/keybase1/ctl.go index 24fd11a29dc0..f1a6c5314249 100644 --- a/go/protocol/keybase1/ctl.go +++ b/go/protocol/keybase1/ctl.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ExitCode int diff --git a/go/protocol/keybase1/debugging.go b/go/protocol/keybase1/debugging.go index da3a8fd3597e..67305efc48de 100644 --- a/go/protocol/keybase1/debugging.go +++ b/go/protocol/keybase1/debugging.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FirstStepResult struct { diff --git a/go/protocol/keybase1/delegate_ui_ctl.go b/go/protocol/keybase1/delegate_ui_ctl.go index 30a43896d20f..8828bd019302 100644 --- a/go/protocol/keybase1/delegate_ui_ctl.go +++ b/go/protocol/keybase1/delegate_ui_ctl.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RegisterIdentifyUIArg struct { diff --git a/go/protocol/keybase1/device.go b/go/protocol/keybase1/device.go index 81acc2f8d441..243af1ced599 100644 --- a/go/protocol/keybase1/device.go +++ b/go/protocol/keybase1/device.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type DeviceDetail struct { diff --git a/go/protocol/keybase1/emails.go b/go/protocol/keybase1/emails.go index 479450592436..90dac217fda5 100644 --- a/go/protocol/keybase1/emails.go +++ b/go/protocol/keybase1/emails.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type EmailLookupResult struct { diff --git a/go/protocol/keybase1/ephemeral.go b/go/protocol/keybase1/ephemeral.go index 1a0b7fd1a285..c2c191a761be 100644 --- a/go/protocol/keybase1/ephemeral.go +++ b/go/protocol/keybase1/ephemeral.go @@ -6,6 +6,7 @@ package keybase1 import ( "errors" "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/favorite.go b/go/protocol/keybase1/favorite.go index de2f27428870..de26b7c7f4bb 100644 --- a/go/protocol/keybase1/favorite.go +++ b/go/protocol/keybase1/favorite.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FolderType int diff --git a/go/protocol/keybase1/featured_bot.go b/go/protocol/keybase1/featured_bot.go index c02b8e0054f0..10567685ec32 100644 --- a/go/protocol/keybase1/featured_bot.go +++ b/go/protocol/keybase1/featured_bot.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FeaturedBot struct { diff --git a/go/protocol/keybase1/fs.go b/go/protocol/keybase1/fs.go index 01950a3254e5..36124b49d0e9 100644 --- a/go/protocol/keybase1/fs.go +++ b/go/protocol/keybase1/fs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type File struct { diff --git a/go/protocol/keybase1/git.go b/go/protocol/keybase1/git.go index 1107f78183d6..35bc58146296 100644 --- a/go/protocol/keybase1/git.go +++ b/go/protocol/keybase1/git.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type EncryptedGitMetadata struct { diff --git a/go/protocol/keybase1/gpg_ui.go b/go/protocol/keybase1/gpg_ui.go index f811d26d977a..fae04cf48678 100644 --- a/go/protocol/keybase1/gpg_ui.go +++ b/go/protocol/keybase1/gpg_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SelectKeyRes struct { diff --git a/go/protocol/keybase1/gregor.go b/go/protocol/keybase1/gregor.go index e1145aa6ebb2..cdab70aacad0 100644 --- a/go/protocol/keybase1/gregor.go +++ b/go/protocol/keybase1/gregor.go @@ -5,9 +5,10 @@ package keybase1 import ( "context" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type GetStateArg struct { diff --git a/go/protocol/keybase1/gregor_ui.go b/go/protocol/keybase1/gregor_ui.go index 1b3cdb2185b7..a8fb91d5e675 100644 --- a/go/protocol/keybase1/gregor_ui.go +++ b/go/protocol/keybase1/gregor_ui.go @@ -6,9 +6,10 @@ package keybase1 import ( "context" "fmt" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type PushReason int diff --git a/go/protocol/keybase1/home.go b/go/protocol/keybase1/home.go index bec28f83d44a..6a2c8889e8da 100644 --- a/go/protocol/keybase1/home.go +++ b/go/protocol/keybase1/home.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type HomeScreenItemID string diff --git a/go/protocol/keybase1/home_ui.go b/go/protocol/keybase1/home_ui.go index be01cc77defa..9bf41511b006 100644 --- a/go/protocol/keybase1/home_ui.go +++ b/go/protocol/keybase1/home_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type HomeUIRefreshArg struct { diff --git a/go/protocol/keybase1/identify.go b/go/protocol/keybase1/identify.go index e55b67704c3f..a8acd1414a0f 100644 --- a/go/protocol/keybase1/identify.go +++ b/go/protocol/keybase1/identify.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type IdentifyProofBreak struct { diff --git a/go/protocol/keybase1/identify3.go b/go/protocol/keybase1/identify3.go index 052a60ff04a6..a0df690e5c39 100644 --- a/go/protocol/keybase1/identify3.go +++ b/go/protocol/keybase1/identify3.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Identify3Arg struct { diff --git a/go/protocol/keybase1/identify3_ui.go b/go/protocol/keybase1/identify3_ui.go index fad28349afc6..16f91197f794 100644 --- a/go/protocol/keybase1/identify3_ui.go +++ b/go/protocol/keybase1/identify3_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Identify3RowState int diff --git a/go/protocol/keybase1/identify_common.go b/go/protocol/keybase1/identify_common.go index f98bdbdac823..e5a6e22da1b8 100644 --- a/go/protocol/keybase1/identify_common.go +++ b/go/protocol/keybase1/identify_common.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/identify_ui.go b/go/protocol/keybase1/identify_ui.go index f99413b91780..4beecf994981 100644 --- a/go/protocol/keybase1/identify_ui.go +++ b/go/protocol/keybase1/identify_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ProofResult struct { diff --git a/go/protocol/keybase1/implicit_team_migration.go b/go/protocol/keybase1/implicit_team_migration.go index 904fa6612079..ab1ad029c032 100644 --- a/go/protocol/keybase1/implicit_team_migration.go +++ b/go/protocol/keybase1/implicit_team_migration.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type StartMigrationArg struct { diff --git a/go/protocol/keybase1/incoming-share.go b/go/protocol/keybase1/incoming-share.go index 1ff93254dbe0..2b416c44a749 100644 --- a/go/protocol/keybase1/incoming-share.go +++ b/go/protocol/keybase1/incoming-share.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type IncomingShareType int diff --git a/go/protocol/keybase1/install.go b/go/protocol/keybase1/install.go index 3fb502393dfc..75d7682854f7 100644 --- a/go/protocol/keybase1/install.go +++ b/go/protocol/keybase1/install.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) // Install status describes state of install for a component or service. diff --git a/go/protocol/keybase1/invite_friends.go b/go/protocol/keybase1/invite_friends.go index 8522cf1b87c9..7aaa20f76971 100644 --- a/go/protocol/keybase1/invite_friends.go +++ b/go/protocol/keybase1/invite_friends.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type InviteCounts struct { diff --git a/go/protocol/keybase1/kbfs.go b/go/protocol/keybase1/kbfs.go index 85a8d6378e55..1196166a56e9 100644 --- a/go/protocol/keybase1/kbfs.go +++ b/go/protocol/keybase1/kbfs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type KBFSTeamSettings struct { diff --git a/go/protocol/keybase1/kbfs_common.go b/go/protocol/keybase1/kbfs_common.go index 5c23180df469..a7be81ae669f 100644 --- a/go/protocol/keybase1/kbfs_common.go +++ b/go/protocol/keybase1/kbfs_common.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/kbfs_git.go b/go/protocol/keybase1/kbfs_git.go index 47c1085caa3a..fa6a690cb2a3 100644 --- a/go/protocol/keybase1/kbfs_git.go +++ b/go/protocol/keybase1/kbfs_git.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type GcOptions struct { diff --git a/go/protocol/keybase1/kbfsmount.go b/go/protocol/keybase1/kbfsmount.go index b9043f47b82d..5c8f4eab314c 100644 --- a/go/protocol/keybase1/kbfsmount.go +++ b/go/protocol/keybase1/kbfsmount.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type GetCurrentMountDirArg struct { diff --git a/go/protocol/keybase1/kex2provisionee.go b/go/protocol/keybase1/kex2provisionee.go index 2c7a2dd63479..4f7f8f4c3499 100644 --- a/go/protocol/keybase1/kex2provisionee.go +++ b/go/protocol/keybase1/kex2provisionee.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PassphraseStream struct { diff --git a/go/protocol/keybase1/kex2provisionee2.go b/go/protocol/keybase1/kex2provisionee2.go index 392ce4bebd8b..0a40c192f846 100644 --- a/go/protocol/keybase1/kex2provisionee2.go +++ b/go/protocol/keybase1/kex2provisionee2.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Hello2Res struct { diff --git a/go/protocol/keybase1/kex2provisioner.go b/go/protocol/keybase1/kex2provisioner.go index f7a6f3b964db..5a21ea26f49a 100644 --- a/go/protocol/keybase1/kex2provisioner.go +++ b/go/protocol/keybase1/kex2provisioner.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type KexStartArg struct { diff --git a/go/protocol/keybase1/kvstore.go b/go/protocol/keybase1/kvstore.go index 023baab78be3..d42c2a5929a9 100644 --- a/go/protocol/keybase1/kvstore.go +++ b/go/protocol/keybase1/kvstore.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type KVGetResult struct { diff --git a/go/protocol/keybase1/log.go b/go/protocol/keybase1/log.go index 41489a41852d..20d867256259 100644 --- a/go/protocol/keybase1/log.go +++ b/go/protocol/keybase1/log.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RegisterLoggerArg struct { diff --git a/go/protocol/keybase1/log_ui.go b/go/protocol/keybase1/log_ui.go index 2e1663872fbe..752e56caca7e 100644 --- a/go/protocol/keybase1/log_ui.go +++ b/go/protocol/keybase1/log_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type LogArg struct { diff --git a/go/protocol/keybase1/login.go b/go/protocol/keybase1/login.go index b9e4470016d2..a73fca4efa2b 100644 --- a/go/protocol/keybase1/login.go +++ b/go/protocol/keybase1/login.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ConfiguredAccount struct { diff --git a/go/protocol/keybase1/login_ui.go b/go/protocol/keybase1/login_ui.go index b7131433a453..9a45baf93a9b 100644 --- a/go/protocol/keybase1/login_ui.go +++ b/go/protocol/keybase1/login_ui.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ResetPromptType int diff --git a/go/protocol/keybase1/logsend.go b/go/protocol/keybase1/logsend.go index 4d2634269170..ceeb3363bb81 100644 --- a/go/protocol/keybase1/logsend.go +++ b/go/protocol/keybase1/logsend.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PrepareLogsendArg struct { diff --git a/go/protocol/keybase1/merkle.go b/go/protocol/keybase1/merkle.go index 505ecfb2c6dd..6f39f5d586e2 100644 --- a/go/protocol/keybase1/merkle.go +++ b/go/protocol/keybase1/merkle.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type MerkleRootAndTime struct { diff --git a/go/protocol/keybase1/metadata.go b/go/protocol/keybase1/metadata.go index 22372f8bb9c2..aa4f9e8aa314 100644 --- a/go/protocol/keybase1/metadata.go +++ b/go/protocol/keybase1/metadata.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type KeyHalf struct { diff --git a/go/protocol/keybase1/metadata_update.go b/go/protocol/keybase1/metadata_update.go index 5e3128a499a0..ecb0a0860172 100644 --- a/go/protocol/keybase1/metadata_update.go +++ b/go/protocol/keybase1/metadata_update.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RekeyRequest struct { diff --git a/go/protocol/keybase1/network_stats.go b/go/protocol/keybase1/network_stats.go index 708049e75b3a..671df9ee9cdc 100644 --- a/go/protocol/keybase1/network_stats.go +++ b/go/protocol/keybase1/network_stats.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/notify_app.go b/go/protocol/keybase1/notify_app.go index c8b4149ad767..19120a54d2d3 100644 --- a/go/protocol/keybase1/notify_app.go +++ b/go/protocol/keybase1/notify_app.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ExitArg struct { diff --git a/go/protocol/keybase1/notify_audit.go b/go/protocol/keybase1/notify_audit.go index 0ed98370023d..a9b442158256 100644 --- a/go/protocol/keybase1/notify_audit.go +++ b/go/protocol/keybase1/notify_audit.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RootAuditErrorArg struct { diff --git a/go/protocol/keybase1/notify_badges.go b/go/protocol/keybase1/notify_badges.go index 392919631232..9aa931d6cd66 100644 --- a/go/protocol/keybase1/notify_badges.go +++ b/go/protocol/keybase1/notify_badges.go @@ -5,9 +5,10 @@ package keybase1 import ( "context" + "time" + gregor1 "github.com/keybase/client/go/protocol/gregor1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type ChatConversationID []byte diff --git a/go/protocol/keybase1/notify_can_user_perform.go b/go/protocol/keybase1/notify_can_user_perform.go index a804f908b5cd..c3bfd684e00c 100644 --- a/go/protocol/keybase1/notify_can_user_perform.go +++ b/go/protocol/keybase1/notify_can_user_perform.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CanUserPerformChangedArg struct { diff --git a/go/protocol/keybase1/notify_ctl.go b/go/protocol/keybase1/notify_ctl.go index e0ca0ad30676..e451a7e4b8fa 100644 --- a/go/protocol/keybase1/notify_ctl.go +++ b/go/protocol/keybase1/notify_ctl.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type NotificationChannels struct { diff --git a/go/protocol/keybase1/notify_device_clone.go b/go/protocol/keybase1/notify_device_clone.go index e87f332033fb..08b1e245590e 100644 --- a/go/protocol/keybase1/notify_device_clone.go +++ b/go/protocol/keybase1/notify_device_clone.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type DeviceCloneCountChangedArg struct { diff --git a/go/protocol/keybase1/notify_email.go b/go/protocol/keybase1/notify_email.go index e191537b0db5..5103d1bc0782 100644 --- a/go/protocol/keybase1/notify_email.go +++ b/go/protocol/keybase1/notify_email.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type EmailAddressVerifiedArg struct { diff --git a/go/protocol/keybase1/notify_ephemeral.go b/go/protocol/keybase1/notify_ephemeral.go index 4c4d4956efa0..d6c5e7cb67f4 100644 --- a/go/protocol/keybase1/notify_ephemeral.go +++ b/go/protocol/keybase1/notify_ephemeral.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type NewTeamEkArg struct { diff --git a/go/protocol/keybase1/notify_favorites.go b/go/protocol/keybase1/notify_favorites.go index f51381630162..b9fe7b2de443 100644 --- a/go/protocol/keybase1/notify_favorites.go +++ b/go/protocol/keybase1/notify_favorites.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FavoritesChangedArg struct { diff --git a/go/protocol/keybase1/notify_featuredbots.go b/go/protocol/keybase1/notify_featuredbots.go index 5ee58155deba..b21baad854aa 100644 --- a/go/protocol/keybase1/notify_featuredbots.go +++ b/go/protocol/keybase1/notify_featuredbots.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FeaturedBotsUpdateArg struct { diff --git a/go/protocol/keybase1/notify_fs.go b/go/protocol/keybase1/notify_fs.go index f468353035dc..051d8ae1c122 100644 --- a/go/protocol/keybase1/notify_fs.go +++ b/go/protocol/keybase1/notify_fs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FSActivityArg struct { diff --git a/go/protocol/keybase1/notify_fs_request.go b/go/protocol/keybase1/notify_fs_request.go index 18929f599e0c..d7b2d67f924e 100644 --- a/go/protocol/keybase1/notify_fs_request.go +++ b/go/protocol/keybase1/notify_fs_request.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type FSEditListRequestArg struct { diff --git a/go/protocol/keybase1/notify_invite_friends.go b/go/protocol/keybase1/notify_invite_friends.go index 0f44240bba3a..d4c1ba01e50a 100644 --- a/go/protocol/keybase1/notify_invite_friends.go +++ b/go/protocol/keybase1/notify_invite_friends.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type UpdateInviteCountsArg struct { diff --git a/go/protocol/keybase1/notify_keyfamily.go b/go/protocol/keybase1/notify_keyfamily.go index dd11f3d46760..430c39faf882 100644 --- a/go/protocol/keybase1/notify_keyfamily.go +++ b/go/protocol/keybase1/notify_keyfamily.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type KeyfamilyChangedArg struct { diff --git a/go/protocol/keybase1/notify_paperkey.go b/go/protocol/keybase1/notify_paperkey.go index d0cd63cbd37a..95435da068fd 100644 --- a/go/protocol/keybase1/notify_paperkey.go +++ b/go/protocol/keybase1/notify_paperkey.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PaperKeyCachedArg struct { diff --git a/go/protocol/keybase1/notify_pgp.go b/go/protocol/keybase1/notify_pgp.go index 57009e12522f..f6ab0b415a81 100644 --- a/go/protocol/keybase1/notify_pgp.go +++ b/go/protocol/keybase1/notify_pgp.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PGPKeyInSecretStoreFileArg struct { diff --git a/go/protocol/keybase1/notify_phone.go b/go/protocol/keybase1/notify_phone.go index 8e7d877fed3a..286934902424 100644 --- a/go/protocol/keybase1/notify_phone.go +++ b/go/protocol/keybase1/notify_phone.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PhoneNumbersChangedArg struct { diff --git a/go/protocol/keybase1/notify_runtimestats.go b/go/protocol/keybase1/notify_runtimestats.go index e60bb8944cc1..bb9202819c62 100644 --- a/go/protocol/keybase1/notify_runtimestats.go +++ b/go/protocol/keybase1/notify_runtimestats.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type StatsSeverityLevel int diff --git a/go/protocol/keybase1/notify_saltpack.go b/go/protocol/keybase1/notify_saltpack.go index d3c0ce65a41b..c500cbcf67bb 100644 --- a/go/protocol/keybase1/notify_saltpack.go +++ b/go/protocol/keybase1/notify_saltpack.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SaltpackOperationType int diff --git a/go/protocol/keybase1/notify_service.go b/go/protocol/keybase1/notify_service.go index 30ac43bee1fa..c9eb27588491 100644 --- a/go/protocol/keybase1/notify_service.go +++ b/go/protocol/keybase1/notify_service.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type HttpSrvInfo struct { diff --git a/go/protocol/keybase1/notify_session.go b/go/protocol/keybase1/notify_session.go index e6baa4f9df0a..0aca0ca39fcc 100644 --- a/go/protocol/keybase1/notify_session.go +++ b/go/protocol/keybase1/notify_session.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type LoggedOutArg struct { diff --git a/go/protocol/keybase1/notify_simple_fs.go b/go/protocol/keybase1/notify_simple_fs.go index dee283c01245..19741d59bb30 100644 --- a/go/protocol/keybase1/notify_simple_fs.go +++ b/go/protocol/keybase1/notify_simple_fs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SimpleFSArchiveStatusChangedArg struct { diff --git a/go/protocol/keybase1/notify_team.go b/go/protocol/keybase1/notify_team.go index 3a5ab774a2be..5ef25aef0436 100644 --- a/go/protocol/keybase1/notify_team.go +++ b/go/protocol/keybase1/notify_team.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TeamChangeSet struct { diff --git a/go/protocol/keybase1/notify_teambot.go b/go/protocol/keybase1/notify_teambot.go index dac1d92a3e91..4207fc8cc101 100644 --- a/go/protocol/keybase1/notify_teambot.go +++ b/go/protocol/keybase1/notify_teambot.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type NewTeambotKeyArg struct { diff --git a/go/protocol/keybase1/notify_tracking.go b/go/protocol/keybase1/notify_tracking.go index e27807739f8b..da95f0b506e8 100644 --- a/go/protocol/keybase1/notify_tracking.go +++ b/go/protocol/keybase1/notify_tracking.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TrackingChangedArg struct { diff --git a/go/protocol/keybase1/notify_users.go b/go/protocol/keybase1/notify_users.go index 09931b9193d3..4bf5e2f6783a 100644 --- a/go/protocol/keybase1/notify_users.go +++ b/go/protocol/keybase1/notify_users.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type UserChangedArg struct { diff --git a/go/protocol/keybase1/os.go b/go/protocol/keybase1/os.go index 6dc431731926..614286b887a1 100644 --- a/go/protocol/keybase1/os.go +++ b/go/protocol/keybase1/os.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/paperprovision.go b/go/protocol/keybase1/paperprovision.go index a4d1a73a63ec..9964a77018f0 100644 --- a/go/protocol/keybase1/paperprovision.go +++ b/go/protocol/keybase1/paperprovision.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PaperProvisionArg struct { diff --git a/go/protocol/keybase1/passphrase_common.go b/go/protocol/keybase1/passphrase_common.go index 03a806727915..8edf32733e0b 100644 --- a/go/protocol/keybase1/passphrase_common.go +++ b/go/protocol/keybase1/passphrase_common.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/pgp.go b/go/protocol/keybase1/pgp.go index ce9841c26522..b682093a41f1 100644 --- a/go/protocol/keybase1/pgp.go +++ b/go/protocol/keybase1/pgp.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SignMode int diff --git a/go/protocol/keybase1/pgp_ui.go b/go/protocol/keybase1/pgp_ui.go index 9e8d6750ff42..0b6f0c13bf74 100644 --- a/go/protocol/keybase1/pgp_ui.go +++ b/go/protocol/keybase1/pgp_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type OutputPGPWarningArg struct { diff --git a/go/protocol/keybase1/phone_numbers.go b/go/protocol/keybase1/phone_numbers.go index b3fc451a9f8e..9a4760dbaed2 100644 --- a/go/protocol/keybase1/phone_numbers.go +++ b/go/protocol/keybase1/phone_numbers.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) // Phone number support for TOFU chats. diff --git a/go/protocol/keybase1/pprof.go b/go/protocol/keybase1/pprof.go index 5fea4745cff2..bf3490e6d40a 100644 --- a/go/protocol/keybase1/pprof.go +++ b/go/protocol/keybase1/pprof.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ProcessorProfileArg struct { diff --git a/go/protocol/keybase1/process.go b/go/protocol/keybase1/process.go index fdd9ccf1fa7f..1b6b8a4a4a14 100644 --- a/go/protocol/keybase1/process.go +++ b/go/protocol/keybase1/process.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/prove.go b/go/protocol/keybase1/prove.go index dd468736f53c..fc220b2644f5 100644 --- a/go/protocol/keybase1/prove.go +++ b/go/protocol/keybase1/prove.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CheckProofStatus struct { diff --git a/go/protocol/keybase1/prove_common.go b/go/protocol/keybase1/prove_common.go index 9dbea68458bd..56ea542e584e 100644 --- a/go/protocol/keybase1/prove_common.go +++ b/go/protocol/keybase1/prove_common.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/prove_ui.go b/go/protocol/keybase1/prove_ui.go index 6d93d9cdebaf..c4847d4571a5 100644 --- a/go/protocol/keybase1/prove_ui.go +++ b/go/protocol/keybase1/prove_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PromptOverwriteType int diff --git a/go/protocol/keybase1/provision_ui.go b/go/protocol/keybase1/provision_ui.go index f3b60534515e..2d225edb8817 100644 --- a/go/protocol/keybase1/provision_ui.go +++ b/go/protocol/keybase1/provision_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ProvisionMethod int diff --git a/go/protocol/keybase1/quota.go b/go/protocol/keybase1/quota.go index 7f47014ce7ed..9b61f72a4c9d 100644 --- a/go/protocol/keybase1/quota.go +++ b/go/protocol/keybase1/quota.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type VerifySessionRes struct { diff --git a/go/protocol/keybase1/reachability.go b/go/protocol/keybase1/reachability.go index 024ff7a088a3..23383632d468 100644 --- a/go/protocol/keybase1/reachability.go +++ b/go/protocol/keybase1/reachability.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Reachable int diff --git a/go/protocol/keybase1/rekey.go b/go/protocol/keybase1/rekey.go index ac94b772bf0a..c9bb01feacf3 100644 --- a/go/protocol/keybase1/rekey.go +++ b/go/protocol/keybase1/rekey.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TLF struct { diff --git a/go/protocol/keybase1/rekey_ui.go b/go/protocol/keybase1/rekey_ui.go index 223d46e7af65..3650486b3a31 100644 --- a/go/protocol/keybase1/rekey_ui.go +++ b/go/protocol/keybase1/rekey_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RekeyEventType int diff --git a/go/protocol/keybase1/reset.go b/go/protocol/keybase1/reset.go index bc0b446cbe4b..ea3491332a4d 100644 --- a/go/protocol/keybase1/reset.go +++ b/go/protocol/keybase1/reset.go @@ -5,6 +5,7 @@ package keybase1 import ( "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/revoke.go b/go/protocol/keybase1/revoke.go index ce0af69118c1..01cd22bc8e72 100644 --- a/go/protocol/keybase1/revoke.go +++ b/go/protocol/keybase1/revoke.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type RevokeKeyArg struct { diff --git a/go/protocol/keybase1/saltpack.go b/go/protocol/keybase1/saltpack.go index 2e297164e79b..35e3cbedd216 100644 --- a/go/protocol/keybase1/saltpack.go +++ b/go/protocol/keybase1/saltpack.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type AuthenticityType int diff --git a/go/protocol/keybase1/saltpack_ui.go b/go/protocol/keybase1/saltpack_ui.go index 1f417f826fe5..2a7fb7375318 100644 --- a/go/protocol/keybase1/saltpack_ui.go +++ b/go/protocol/keybase1/saltpack_ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SaltpackSenderType int diff --git a/go/protocol/keybase1/scanproofs.go b/go/protocol/keybase1/scanproofs.go index 0c77baca1251..8abf491fa341 100644 --- a/go/protocol/keybase1/scanproofs.go +++ b/go/protocol/keybase1/scanproofs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ScanProofsArg struct { diff --git a/go/protocol/keybase1/secret_ui.go b/go/protocol/keybase1/secret_ui.go index ff4a9c064fbf..f329dbc3b115 100644 --- a/go/protocol/keybase1/secret_ui.go +++ b/go/protocol/keybase1/secret_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SecretEntryArg struct { diff --git a/go/protocol/keybase1/secretkeys.go b/go/protocol/keybase1/secretkeys.go index bfc40db61a71..55b1fdc80942 100644 --- a/go/protocol/keybase1/secretkeys.go +++ b/go/protocol/keybase1/secretkeys.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type NaclSigningKeyPublic [32]byte diff --git a/go/protocol/keybase1/selfprovision.go b/go/protocol/keybase1/selfprovision.go index 3fd22b9c93f6..5d59da7843a7 100644 --- a/go/protocol/keybase1/selfprovision.go +++ b/go/protocol/keybase1/selfprovision.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SelfProvisionArg struct { diff --git a/go/protocol/keybase1/session.go b/go/protocol/keybase1/session.go index 2c3e4fbb5db8..0e98140d7c8a 100644 --- a/go/protocol/keybase1/session.go +++ b/go/protocol/keybase1/session.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Session struct { diff --git a/go/protocol/keybase1/signup.go b/go/protocol/keybase1/signup.go index 65d3e0690cc7..b91aaf8ed4e5 100644 --- a/go/protocol/keybase1/signup.go +++ b/go/protocol/keybase1/signup.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type SignupRes struct { diff --git a/go/protocol/keybase1/sigs.go b/go/protocol/keybase1/sigs.go index ed71ebd9f7fd..2d25302cf707 100644 --- a/go/protocol/keybase1/sigs.go +++ b/go/protocol/keybase1/sigs.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type Sig struct { diff --git a/go/protocol/keybase1/simple_fs.go b/go/protocol/keybase1/simple_fs.go index 23006eeead5b..255eab3569d1 100644 --- a/go/protocol/keybase1/simple_fs.go +++ b/go/protocol/keybase1/simple_fs.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type OpID [16]byte diff --git a/go/protocol/keybase1/stream_ui.go b/go/protocol/keybase1/stream_ui.go index 6f7e84641b4e..232be1c31114 100644 --- a/go/protocol/keybase1/stream_ui.go +++ b/go/protocol/keybase1/stream_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CloseArg struct { diff --git a/go/protocol/keybase1/teams.go b/go/protocol/keybase1/teams.go index 3cabda0c8c5e..e41a3e578bc1 100644 --- a/go/protocol/keybase1/teams.go +++ b/go/protocol/keybase1/teams.go @@ -7,8 +7,9 @@ import ( "context" "errors" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TeamRole int diff --git a/go/protocol/keybase1/teams_ui.go b/go/protocol/keybase1/teams_ui.go index 8a29316aecc1..897d5a35e7b1 100644 --- a/go/protocol/keybase1/teams_ui.go +++ b/go/protocol/keybase1/teams_ui.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type ConfirmRootTeamDeleteArg struct { diff --git a/go/protocol/keybase1/teamsearch.go b/go/protocol/keybase1/teamsearch.go index 9393e42e94ad..0f61bc314883 100644 --- a/go/protocol/keybase1/teamsearch.go +++ b/go/protocol/keybase1/teamsearch.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TeamSearchItem struct { diff --git a/go/protocol/keybase1/test.go b/go/protocol/keybase1/test.go index 9401f06c5bab..fdb6a4a54785 100644 --- a/go/protocol/keybase1/test.go +++ b/go/protocol/keybase1/test.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) // Result from calling test(..). diff --git a/go/protocol/keybase1/tlf.go b/go/protocol/keybase1/tlf.go index e13c6fd7b094..f974708e3273 100644 --- a/go/protocol/keybase1/tlf.go +++ b/go/protocol/keybase1/tlf.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type CryptKeysArg struct { diff --git a/go/protocol/keybase1/tlf_keys.go b/go/protocol/keybase1/tlf_keys.go index ee5b60f8110e..f3140b2c2428 100644 --- a/go/protocol/keybase1/tlf_keys.go +++ b/go/protocol/keybase1/tlf_keys.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TLFIdentifyBehavior int diff --git a/go/protocol/keybase1/track.go b/go/protocol/keybase1/track.go index 918e89346389..2eae2812a3c0 100644 --- a/go/protocol/keybase1/track.go +++ b/go/protocol/keybase1/track.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TrackArg struct { diff --git a/go/protocol/keybase1/ui.go b/go/protocol/keybase1/ui.go index 82fd8b359bd7..1ade9e30a73b 100644 --- a/go/protocol/keybase1/ui.go +++ b/go/protocol/keybase1/ui.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PromptDefault int diff --git a/go/protocol/keybase1/upk.go b/go/protocol/keybase1/upk.go index a8d9f55d4095..45c85e9c1b85 100644 --- a/go/protocol/keybase1/upk.go +++ b/go/protocol/keybase1/upk.go @@ -6,6 +6,7 @@ package keybase1 import ( "errors" "fmt" + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/keybase1/user.go b/go/protocol/keybase1/user.go index fce11d86abcc..0866221f645f 100644 --- a/go/protocol/keybase1/user.go +++ b/go/protocol/keybase1/user.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type TrackProof struct { diff --git a/go/protocol/keybase1/usersearch.go b/go/protocol/keybase1/usersearch.go index d85b13fbdb88..88102f487a63 100644 --- a/go/protocol/keybase1/usersearch.go +++ b/go/protocol/keybase1/usersearch.go @@ -5,8 +5,9 @@ package keybase1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type APIUserServiceID string diff --git a/go/protocol/keybase1/wot.go b/go/protocol/keybase1/wot.go index 269fc9c4bf05..99cc76051158 100644 --- a/go/protocol/keybase1/wot.go +++ b/go/protocol/keybase1/wot.go @@ -6,8 +6,9 @@ package keybase1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type UsernameVerificationType string diff --git a/go/protocol/stellar1/bundle.go b/go/protocol/stellar1/bundle.go index c27c47d72767..1fe6bdea04f8 100644 --- a/go/protocol/stellar1/bundle.go +++ b/go/protocol/stellar1/bundle.go @@ -6,6 +6,7 @@ package stellar1 import ( "errors" "fmt" + keybase1 "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/stellar1/common.go b/go/protocol/stellar1/common.go index 981c210011d1..99ee1565d65b 100644 --- a/go/protocol/stellar1/common.go +++ b/go/protocol/stellar1/common.go @@ -5,6 +5,7 @@ package stellar1 import ( "fmt" + keybase1 "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" ) diff --git a/go/protocol/stellar1/local.go b/go/protocol/stellar1/local.go index 6a2b7eb97ef1..6fc9d8090ec0 100644 --- a/go/protocol/stellar1/local.go +++ b/go/protocol/stellar1/local.go @@ -6,8 +6,9 @@ package stellar1 import ( "context" "fmt" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type WalletAccountLocal struct { diff --git a/go/protocol/stellar1/notify.go b/go/protocol/stellar1/notify.go index 575540316f95..6ccb3db4d6d7 100644 --- a/go/protocol/stellar1/notify.go +++ b/go/protocol/stellar1/notify.go @@ -5,8 +5,9 @@ package stellar1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type PaymentNotificationArg struct { diff --git a/go/protocol/stellar1/remote.go b/go/protocol/stellar1/remote.go index 465118243950..184c3307419b 100644 --- a/go/protocol/stellar1/remote.go +++ b/go/protocol/stellar1/remote.go @@ -7,9 +7,10 @@ import ( "context" "errors" "fmt" + "time" + keybase1 "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" - "time" ) type ChatConversationID string diff --git a/go/protocol/stellar1/ui.go b/go/protocol/stellar1/ui.go index f8140f3b8842..798d4d15f70c 100644 --- a/go/protocol/stellar1/ui.go +++ b/go/protocol/stellar1/ui.go @@ -5,8 +5,9 @@ package stellar1 import ( "context" - "github.com/keybase/go-framed-msgpack-rpc/rpc" "time" + + "github.com/keybase/go-framed-msgpack-rpc/rpc" ) type UIPaymentReviewed struct {