Skip to content

Document AI/LLM, ChatView, speech, and ML Kit cn1libs from PR #5035#5057

Merged
liannacasper merged 5 commits into
masterfrom
docs/ai-and-speech
May 28, 2026
Merged

Document AI/LLM, ChatView, speech, and ML Kit cn1libs from PR #5035#5057
liannacasper merged 5 commits into
masterfrom
docs/ai-and-speech

Conversation

@shai-almog
Copy link
Copy Markdown
Collaborator

Summary

  • Add a new "AI, Chat UI, and Speech" chapter to the developer guide that documents the surface PR Add com.codename1.ai package, ChatView, Speech/TTS, and build-time AI dependency injection #5035 added: com.codename1.ai (LlmClient, ChatRequest, streaming SSE, tool calls, embeddings, image generation, conversation persistence, retries, simulator Ollama redirect), com.codename1.components.ChatView, SpeechRecognizer / TextToSpeech, the non-prompting SecureStorage overloads, and the cn1-ai-mlkit-{barcode,docscan,face} cn1libs. Includes an SVG mockup of the ChatView surface.
  • Add references/ai-and-speech.md to the bundled initializr authoring skill (so Claude Code inside any generated project inherits the new APIs), index it from SKILL.md, and add it to GeneratorModelMatrixTest for regression.
  • Extend docs/developer-guide/languagetool-accept.txt with the AI proper nouns (Ollama, [Ll]lama, [Vv]LLM, [Aa]nthropic, SAPI, espeak) that the en_US dictionary doesn't recognise.

Test plan

  • asciidoctor --failure-level WARN docs/developer-guide/developer-guide.asciidoc is clean (only the pre-existing INFO: possible invalid reference: lines remain)
  • vale --config docs/developer-guide/.vale.ini --minAlertLevel=suggestion docs/developer-guide/Ai-And-Speech.asciidoc -> 0 errors / 0 warnings / 0 suggestions
  • ruby scripts/developer-guide/check_paragraph_capitalization.rb docs/developer-guide/developer-guide.asciidoc passes
  • python3 scripts/developer-guide/find_unused_images.py docs/developer-guide -> "No unused images found." (the new img/chat-view-mockup.svg is referenced from the new chapter)
  • Developer-guide-docs CI workflow green (vale, asciidoctor lint, paragraph capitalization, unused images, LanguageTool, HTML + PDF builds)
  • Website-docs CI workflow green (bundles the initializr skill, which now includes the new reference)

🤖 Generated with Claude Code

PR #5035 introduced com.codename1.ai (LlmClient, ChatRequest, streaming
SSE, tool calls, embeddings, image generation, conversation persistence,
retries, simulator Ollama redirect), the com.codename1.components.ChatView
component, com.codename1.media.SpeechRecognizer / TextToSpeech, the
non-prompting SecureStorage overloads, and the cn1-ai-mlkit-{barcode,
docscan,face} cn1libs. The PR shipped the framework code but left both
the developer guide and the initializr authoring skill silent on every
new API.

Adds a new "AI, Chat UI, and Speech" chapter to the developer guide:
provider factories, streaming, tool calling, structured output, multi-
modal messages, embeddings, image generation, conversation store, prompt
templates, retry policy, simulator redirect, SecureStorage key handling,
ChatView wiring and theming UIIDs, SpeechRecognizer / TextToSpeech, the
three ML Kit cn1libs, and a capture-photo -> describe -> speak example.
Includes an SVG mockup of the ChatView surface.

Adds references/ai-and-speech.md to the bundled initializr authoring
skill, indexed from SKILL.md and exercised from
GeneratorModelMatrixTest, so Claude Code (and any agent that respects
the skills convention) inside a generated project picks up the new
APIs automatically.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Cloudflare Preview

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

Developer Guide build artifacts are available for download from this workflow run:

Developer Guide quality checks:

  • AsciiDoc linter: No issues found (report)
  • Vale: No alerts found (report)
  • Paragraph capitalization: No paragraph capitalization issues (report)
  • LanguageTool: No grammar matches (report)
  • Image references: No unused images detected (report)

shai-almog and others added 2 commits May 28, 2026 04:12
Local reproduction with language-tool-python==2.9.4 (the CI-pinned
version) flagged three matches in Ai-And-Speech.asciidoc:

- PCT_SINGULAR_NOUN_PLURAL_VERB_AGREEMENT on "the simulator, the cloud
  build, and your CI pipeline route everything" -- the rule wanted
  the singular-vs-plural agreement reworded. Rephrased to ":
  the simulator, the cloud builder, and your CI pipeline all run
  the same code."
- MORFOLOGIK_RULE_EN_US on "thread-safe mutators" -- the en_US
  dictionary doesn't recognise "mutators". Spelled the methods out
  ("addMessage, appendToLastMessage, and setTypingIndicatorVisible").
- MORFOLOGIK_RULE_EN_US on "SAPI on Windows" -- the flagged span was
  the two-word phrase, so the accept-list entry for "SAPI" alone did
  not match it. Wrapped SAPI in a code span so the HTML extractor
  replaces it with the inline placeholder before LanguageTool sees
  the surrounding prose.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first revision shipped a hand-authored SVG sketch of the ChatView
component. Swap it for an actual PNG produced by the JavaSE simulator
running the component under the iOS Modern theme so the developer
guide shows the real rendering, not a wireframe.

- Adds ChatViewDevGuideScreenshotTest in scripts/hellocodenameone
  (under common/src/test/java, where cn1:test discovers AbstractTest
  implementers). The test installs iOSModernTheme.res, builds a Form
  with a populated ChatView, paints it to a PNG, and writes it to
  Storage as chat-view.png. Running it via mvn -pl javase -am test
  (with the test profile activator) drops ~/.cn1/chat-view.png.
- Adds docs/developer-guide/img/chat-view.png, captured from a local
  simulator run via the test above.
- Drops docs/developer-guide/img/chat-view-mockup.svg.
- Points the chapter's image:: at the new PNG with caption "ChatView
  rendered in the JavaSE simulator under the iOS Modern theme".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 28, 2026

Compared 47 screenshots: 47 matched.
✅ JavaScript-port screenshot tests passed.

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 28, 2026

Compared 116 screenshots: 116 matched.

Native Android coverage

  • 📊 Line coverage: 12.44% (7214/57972 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 10.15% (36276/357360), branch 4.27% (1445/33836), complexity 5.30% (1723/32486), method 9.24% (1406/15210), class 15.16% (321/2117)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

✅ Native Android screenshot tests passed.

Native Android coverage

  • 📊 Line coverage: 12.44% (7214/57972 lines covered) [HTML preview] (artifact android-coverage-report, jacocoAndroidReport/html/index.html)
    • Other counters: instruction 10.15% (36276/357360), branch 4.27% (1445/33836), complexity 5.30% (1723/32486), method 9.24% (1406/15210), class 15.16% (321/2117)
    • Lowest covered classes
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysKt – 0.00% (0/6327 lines covered)
      • kotlin.collections.unsigned.kotlin.collections.unsigned.UArraysKt___UArraysKt – 0.00% (0/2384 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.ClassReader – 0.00% (0/1519 lines covered)
      • kotlin.collections.kotlin.collections.CollectionsKt___CollectionsKt – 0.00% (0/1148 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.MethodWriter – 0.00% (0/923 lines covered)
      • kotlin.sequences.kotlin.sequences.SequencesKt___SequencesKt – 0.00% (0/730 lines covered)
      • kotlin.text.kotlin.text.StringsKt___StringsKt – 0.00% (0/623 lines covered)
      • org.jacoco.agent.rt.internal_b6258fc.asm.org.jacoco.agent.rt.internal_b6258fc.asm.Frame – 0.00% (0/564 lines covered)
      • kotlin.collections.kotlin.collections.ArraysKt___ArraysJvmKt – 0.00% (0/495 lines covered)
      • kotlinx.coroutines.kotlinx.coroutines.JobSupport – 0.00% (0/423 lines covered)

Benchmark Results

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 810.000 ms
Base64 CN1 encode 211.000 ms
Base64 encode ratio (CN1/native) 0.260x (74.0% faster)
Base64 native decode 936.000 ms
Base64 CN1 decode 308.000 ms
Base64 decode ratio (CN1/native) 0.329x (67.1% faster)
Image encode benchmark status skipped (SIMD unsupported)

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 28, 2026

Compared 115 screenshots: 115 matched.
✅ Native iOS Metal screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 322 seconds

Build and Run Timing

Metric Duration
Simulator Boot 89000 ms
Simulator Boot (Run) 1000 ms
App Install 15000 ms
App Launch 9000 ms
Test Execution 341000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 774.000 ms
Base64 CN1 encode 1546.000 ms
Base64 encode ratio (CN1/native) 1.997x (99.7% slower)
Base64 native decode 401.000 ms
Base64 CN1 decode 1265.000 ms
Base64 decode ratio (CN1/native) 3.155x (215.5% slower)
Base64 SIMD encode 729.000 ms
Base64 encode ratio (SIMD/native) 0.942x (5.8% faster)
Base64 encode ratio (SIMD/CN1) 0.472x (52.8% faster)
Base64 SIMD decode 1155.000 ms
Base64 decode ratio (SIMD/native) 2.880x (188.0% slower)
Base64 decode ratio (SIMD/CN1) 0.913x (8.7% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 59.000 ms
Image createMask (SIMD on) 17.000 ms
Image createMask ratio (SIMD on/off) 0.288x (71.2% faster)
Image applyMask (SIMD off) 132.000 ms
Image applyMask (SIMD on) 72.000 ms
Image applyMask ratio (SIMD on/off) 0.545x (45.5% faster)
Image modifyAlpha (SIMD off) 142.000 ms
Image modifyAlpha (SIMD on) 70.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.493x (50.7% faster)
Image modifyAlpha removeColor (SIMD off) 266.000 ms
Image modifyAlpha removeColor (SIMD on) 197.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.741x (25.9% faster)
Image PNG encode (SIMD off) 1683.000 ms
Image PNG encode (SIMD on) 1255.000 ms
Image PNG encode ratio (SIMD on/off) 0.746x (25.4% faster)
Image JPEG encode 596.000 ms

@shai-almog
Copy link
Copy Markdown
Collaborator Author

shai-almog commented May 28, 2026

Compared 116 screenshots: 116 matched.
✅ Native iOS screenshot tests passed.

Benchmark Results

  • VM Translation Time: 0 seconds
  • Compilation Time: 207 seconds

Build and Run Timing

Metric Duration
Simulator Boot 60000 ms
Simulator Boot (Run) 5000 ms
App Install 19000 ms
App Launch 8000 ms
Test Execution 378000 ms

Detailed Performance Metrics

Metric Duration
Base64 payload size 8192 bytes
Base64 benchmark iterations 6000
Base64 native encode 965.000 ms
Base64 CN1 encode 1722.000 ms
Base64 encode ratio (CN1/native) 1.784x (78.4% slower)
Base64 native decode 476.000 ms
Base64 CN1 decode 1351.000 ms
Base64 decode ratio (CN1/native) 2.838x (183.8% slower)
Base64 SIMD encode 475.000 ms
Base64 encode ratio (SIMD/native) 0.492x (50.8% faster)
Base64 encode ratio (SIMD/CN1) 0.276x (72.4% faster)
Base64 SIMD decode 518.000 ms
Base64 decode ratio (SIMD/native) 1.088x (8.8% slower)
Base64 decode ratio (SIMD/CN1) 0.383x (61.7% faster)
Image encode benchmark iterations 100
Image createMask (SIMD off) 66.000 ms
Image createMask (SIMD on) 12.000 ms
Image createMask ratio (SIMD on/off) 0.182x (81.8% faster)
Image applyMask (SIMD off) 140.000 ms
Image applyMask (SIMD on) 102.000 ms
Image applyMask ratio (SIMD on/off) 0.729x (27.1% faster)
Image modifyAlpha (SIMD off) 182.000 ms
Image modifyAlpha (SIMD on) 70.000 ms
Image modifyAlpha ratio (SIMD on/off) 0.385x (61.5% faster)
Image modifyAlpha removeColor (SIMD off) 251.000 ms
Image modifyAlpha removeColor (SIMD on) 98.000 ms
Image modifyAlpha removeColor ratio (SIMD on/off) 0.390x (61.0% faster)
Image PNG encode (SIMD off) 1194.000 ms
Image PNG encode (SIMD on) 1154.000 ms
Image PNG encode ratio (SIMD on/off) 0.966x (3.4% faster)
Image JPEG encode 826.000 ms

The original AnthropicClient and GeminiClient were scaffolds that
threw UnsupportedOperationException on every call, with documentation
telling callers to route through LlmClient.localOpenAiCompatible
manually. Both providers now publish first-party OpenAI-compatible
endpoints that speak the canonical /chat/completions wire format:

  - https://api.anthropic.com/v1/chat/completions
  - https://generativelanguage.googleapis.com/v1beta/openai/chat/completions

That is the same shape OpenAiClient already implements end-to-end --
streaming, tool calls, multi-modal image parts, structured JSON
output, the entire StreamingChatRequest plumbing. So both subclasses
now extend OpenAiClient and only override the provider name and the
default model:

  - LlmClient.anthropic(key) -> claude-sonnet-4-5
  - LlmClient.gemini(key)    -> gemini-2.0-flash

LlmClient.DEFAULT_GEMINI_URL is bumped to the OpenAI-compat path
(`/v1beta/openai`). AnthropicClient still overrides embed() with the
helpful "Anthropic doesn't publish embeddings; use Voyage AI" error
because that part remains true.

Documentation updated: the AI chapter and the initializr authoring
skill no longer hedge with "throws an LlmException until native
clients land"; both providers work out of the box, with a default-
model table per provider added to the skill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

✅ Continuous Quality Report

Test & Coverage

Static Analysis

  • SpotBugs [Report archive]
    • ByteCodeTranslator: 0 findings (no issues)
    • android: 0 findings (no issues)
    • codenameone-maven-plugin: 0 findings (no issues)
    • core-unittests: 0 findings (no issues)
    • ios: 0 findings (no issues)
  • PMD: 0 findings (no issues) [Report archive]
  • Checkstyle: 0 findings (no issues) [Report archive]

Generated automatically by the PR CI workflow.

The previous wording explained two SecureStorage code paths
(biometric-gated vs non-prompting) and ended with "remain the
right choice for credentials a human user authenticates against,"
which read more like an API tour than safety guidance. The actual
risk that needs surfacing is that hard-coded keys in a mobile
binary are extractable.

Replace the prose block with an asciidoc WARNING admonition that
spells out the rule (no key in source / resource / git, fetch from
a server the user authenticates against, then cache locally with
the non-prompting overloads) and keeps just the short SecureStorage
code sample. Mirror the same simplification in the initializr
authoring skill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@liannacasper liannacasper merged commit 8a8cd6e into master May 28, 2026
25 of 26 checks passed
shai-almog added a commit that referenced this pull request May 29, 2026
Consolidated follow-up to the May 29 weekly index. Covers the four
surfaces that moved from "you need a cn1lib for this" to "it is in
the framework" this release:

- Connectivity (PR #5021): com.codename1.io.{wifi,bonjour,usb} +
  NetworkManager.addNetworkTypeListener with the per-platform
  implementations and the three new CN1_INCLUDE_* defines that keep
  unused entitlements out of Apple's API-usage scan.
- Identity (PRs #5018, #5039): OIDC client backed by
  ASWebAuthenticationSession / Custom Tabs with PKCE; Sign in with
  Apple in core; refreshed Google/Facebook/Microsoft/Auth0/Firebase
  wrappers; WebAuthn / passkey client in W3C JSON wire format with
  iOS 16 and Android API 28 native bindings; Auth0/Firebase passkey
  helpers; legacy Oauth2 deprecated.
- Sharing (PR #5036): ShareResult callbacks
  (SHARED_TO/DISMISSED/FAILED) on iOS and Android via
  UIActivityViewController.completionWithItemsHandler and
  Intent.createChooser with IntentSender; IOSShareExtensionBuilder
  in the Maven plugin generates a complete .ios.appext bundle.
- AI (PRs #5035, #5057): com.codename1.ai with LlmClient for
  OpenAI/Anthropic/Gemini/Ollama, streaming SSE, ChatView,
  SpeechRecognizer/TextToSpeech, SecureStorage non-prompting
  overloads, simulator Ollama redirect, AiDependencyTable build-time
  injection, and the cn1-ai-mlkit-{barcode,docscan,face} cn1libs.

Closes with the structural element common to all four (scanner-driven
gating that mirrors the NFC/biometrics pattern from two weeks ago).
shai-almog added a commit that referenced this pull request May 29, 2026
Consolidated follow-up to the May 29 weekly index. Covers the four
surfaces that moved from "you need a cn1lib for this" to "it is in
the framework" this release:

- Connectivity (PR #5021): com.codename1.io.{wifi,bonjour,usb} +
  NetworkManager.addNetworkTypeListener with the per-platform
  implementations and the three new CN1_INCLUDE_* defines that keep
  unused entitlements out of Apple's API-usage scan.
- Identity (PRs #5018, #5039): OIDC client backed by
  ASWebAuthenticationSession / Custom Tabs with PKCE; Sign in with
  Apple in core; refreshed Google/Facebook/Microsoft/Auth0/Firebase
  wrappers; WebAuthn / passkey client in W3C JSON wire format with
  iOS 16 and Android API 28 native bindings; Auth0/Firebase passkey
  helpers; legacy Oauth2 deprecated.
- Sharing (PR #5036): ShareResult callbacks
  (SHARED_TO/DISMISSED/FAILED) on iOS and Android via
  UIActivityViewController.completionWithItemsHandler and
  Intent.createChooser with IntentSender; IOSShareExtensionBuilder
  in the Maven plugin generates a complete .ios.appext bundle.
- AI (PRs #5035, #5057): com.codename1.ai with LlmClient for
  OpenAI/Anthropic/Gemini/Ollama, streaming SSE, ChatView,
  SpeechRecognizer/TextToSpeech, SecureStorage non-prompting
  overloads, simulator Ollama redirect, AiDependencyTable build-time
  injection, and the cn1-ai-mlkit-{barcode,docscan,face} cn1libs.

Closes with the structural element common to all four (scanner-driven
gating that mirrors the NFC/biometrics pattern from two weeks ago).
shai-almog added a commit that referenced this pull request May 29, 2026
Consolidated follow-up to the May 29 weekly index. Covers the four
surfaces that moved from "you need a cn1lib for this" to "it is in
the framework" this release:

- Connectivity (PR #5021): com.codename1.io.{wifi,bonjour,usb} +
  NetworkManager.addNetworkTypeListener with the per-platform
  implementations and the three new CN1_INCLUDE_* defines that keep
  unused entitlements out of Apple's API-usage scan.
- Identity (PRs #5018, #5039): OIDC client backed by
  ASWebAuthenticationSession / Custom Tabs with PKCE; Sign in with
  Apple in core; refreshed Google/Facebook/Microsoft/Auth0/Firebase
  wrappers; WebAuthn / passkey client in W3C JSON wire format with
  iOS 16 and Android API 28 native bindings; Auth0/Firebase passkey
  helpers; legacy Oauth2 deprecated.
- Sharing (PR #5036): ShareResult callbacks
  (SHARED_TO/DISMISSED/FAILED) on iOS and Android via
  UIActivityViewController.completionWithItemsHandler and
  Intent.createChooser with IntentSender; IOSShareExtensionBuilder
  in the Maven plugin generates a complete .ios.appext bundle.
- AI (PRs #5035, #5057): com.codename1.ai with LlmClient for
  OpenAI/Anthropic/Gemini/Ollama, streaming SSE, ChatView,
  SpeechRecognizer/TextToSpeech, SecureStorage non-prompting
  overloads, simulator Ollama redirect, AiDependencyTable build-time
  injection, and the cn1-ai-mlkit-{barcode,docscan,face} cn1libs.

Closes with the structural element common to all four (scanner-driven
gating that mirrors the NFC/biometrics pattern from two weeks ago).
shai-almog added a commit that referenced this pull request May 29, 2026
Consolidated follow-up to the May 29 weekly index. Covers the four
surfaces that moved from "you need a cn1lib for this" to "it is in
the framework" this release:

- Connectivity (PR #5021): com.codename1.io.{wifi,bonjour,usb} +
  NetworkManager.addNetworkTypeListener with the per-platform
  implementations and the three new CN1_INCLUDE_* defines that keep
  unused entitlements out of Apple's API-usage scan.
- Identity (PRs #5018, #5039): OIDC client backed by
  ASWebAuthenticationSession / Custom Tabs with PKCE; Sign in with
  Apple in core; refreshed Google/Facebook/Microsoft/Auth0/Firebase
  wrappers; WebAuthn / passkey client in W3C JSON wire format with
  iOS 16 and Android API 28 native bindings; Auth0/Firebase passkey
  helpers; legacy Oauth2 deprecated.
- Sharing (PR #5036): ShareResult callbacks
  (SHARED_TO/DISMISSED/FAILED) on iOS and Android via
  UIActivityViewController.completionWithItemsHandler and
  Intent.createChooser with IntentSender; IOSShareExtensionBuilder
  in the Maven plugin generates a complete .ios.appext bundle.
- AI (PRs #5035, #5057): com.codename1.ai with LlmClient for
  OpenAI/Anthropic/Gemini/Ollama, streaming SSE, ChatView,
  SpeechRecognizer/TextToSpeech, SecureStorage non-prompting
  overloads, simulator Ollama redirect, AiDependencyTable build-time
  injection, and the cn1-ai-mlkit-{barcode,docscan,face} cn1libs.

Closes with the structural element common to all four (scanner-driven
gating that mirrors the NFC/biometrics pattern from two weeks ago).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants