Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions docs/sdks/ios/sparkscan/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,69 @@ sidebar_position: 1
displayed_sidebar: iosSidebar
pagination_prev: null
framework: ios
product: sparkscan
user_intents:
- "scan one barcode at a time on iOS"
- "add a ready-made scanning UI without building your own"
- "scan items one by one to build a list (inventory, receiving)"
not_for:
- "scan and count many barcodes at once — use MatrixScan Count"
- "build a fully custom scanning UI — use Barcode Capture"
keywords:
- ios
---

import ProductChooser from '@site/src/components/ProductChooser';

# About SparkScan

import AboutSparkScan from '../../../partials/intro/_about-sparkscan.mdx';

SparkScan bundles multiple scanning features together and addresses many common challenges associated with scanning on smart devices. It is designed to be easily integrated into any application, and can be customized to fit your specific needs.

<ProductChooser frontMatter={frontMatter}/>

## UI Overview

The UI elements in SparkScan are intentionally minimalistic, meant to be overlayed on any application without the need to adapt the existing app while offering the best user experience.

Two main elements compose the UI:

![SparkScan UI](/img/sparkscan/features_web.png)

- **Camera preview**: A small camera preview that helps with aiming and shows scan feedback. When not in use, the camera preview is hidden. It can be expanded and hosts easy to access controls (zoom level, flash etc).
- **Trigger button**: A large-sized, semi-transparent floating button that users can drag to position it in the most ergonomic position. When not in use, the trigger button collapses to occupy less space.

There are additional UI elements available for displaying additional scanning modes, errors, or providing feedback to the user. These are described in the [Advanced](./advanced.md) section.

## Workflow Description

When SparkScan is started, the UI presents just the trigger button, collapsed. The user can move the trigger button by simply dragging it around: the position of the trigger button is remembered across sessions, so the user can place the button where it's the most comfortable to use.
To start scanning, the user can simply tap on it.

When the scanner is active, the mini preview is shown. The mini preview too can be placed anywhere in the view by simply pressing on it for a little while and then dragging it around. Also the position of the mini preview is remembered across sessions, so the user can place it where it prefers (e.g. not to cover an important information at the top of the app).

In the default configuration:
- Upon scan the user will receive audio/haptic feedback confirming the scan, and the mini preview will display the scanned barcode for a small amount of time before fading away.
- Tapping on the trigger button or the mini preview will restart immediately the scanner.

Upon completing the scanning process (or to interact with the customer app layer), the user can tap in any area outside the trigger button and the mini preview. This collapses the scanner button, going back to the initial state.

If instead of tapping on the trigger button the user taps and holds it pressed, he will be able to scan multiple barcodes in a row. The scanner will stop when the trigger button is released.

<p align="center">
<img src="/img/sparkscan/workflow-example.gif" alt="SparkScan Workflow" /><br></br>List building use case using SparkScan.
</p>

The default workflow just described has been carefully designed as a result of extensive user testing and customer feedback from the field.

But not all use-cases look the same, and your needs may differ for most users. That's why SparkScan comes with a set of options to configure the scanner and to best fit in the desired workflow. Check the [Workflow Options](./advanced.md#workflow-options) guide to discover more.

## Supported Symbologies

SparkScan supports all of the major symbologies listed here: [Barcode Symbologies](../barcode-symbologies.mdx).

## AI-Powered Features

SparkScan includes AI-powered scanning capabilities that enhance accuracy and user experience. These features automatically handle challenging scenarios such as avoiding unintentional scans, selecting barcodes in dense environments, scanning damaged barcodes with OCR fallback, and intelligently filtering duplicate scans. Learn more about these capabilities in our [AI-Powered Barcode Scanning](../ai-powered-barcode-scanning.md) guide.
<AboutSparkScan framework="ios"/>
29 changes: 29 additions & 0 deletions docs/start.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: "Not sure which Scandit product? Start here"
description: "Pick what you want to scan and the task you need to do, and go straight to the right Scandit product's docs for your platform."
sidebar_position: 0
pagination_prev: null
pagination_next: null
keywords:
- get started
- which product
- product chooser
- start here
- scan one item
- stocktake
- order picking
- proof of delivery
---

import IntentNavigator from '@site/src/components/IntentNavigator';

# Not sure which Scandit product? Start here

The home page's platform picker assumes you already know your product. This is the other
axis — **pick your intent, get the product** — for the cross-product confusion the replay
and ticket data shows (SparkScan vs Barcode Capture, ID Capture vs ID Bolt…). It is driven
by **one shared intent taxonomy**, the same scan type → task → product map the sign-up quiz
uses, so the docs and sign-up recommend the **same product**. Each recommendation links to
that product's docs for your platform.

<IntentNavigator/>
41 changes: 41 additions & 0 deletions docs/troubleshooting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: "Troubleshooting: Scandit SDK error messages and fixes"
description: "Paste a Scandit SDK error message to find its cause and fix — licensing, activation, and camera errors."
product: [sparkscan, barcode-capture, id-capture]
topic_type: troubleshooting
version_status: current
canonical_id: scandit.troubleshooting.error-codes
user_intents:
- "find out what a Scandit SDK error message means"
- "fix a Scandit license or activation error"
- "resolve a camera permission error when scanning"
not_for:
- "reporting a new bug — contact support instead"
keywords:
- error
- error code
- license error
- invalid license
- license expired
- troubleshooting
- activation
hide_table_of_contents: true
---

import ErrorCodeFinder from '@site/src/components/ErrorCodeFinder';

# Troubleshooting: Scandit SDK error messages and fixes

Hit an error while integrating the SDK? **Paste the exact message from your console** into the box below (or start typing a few words from it). The list narrows to the matching issue with its cause and fix. You can also press <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>F</kbd> to search the page directly.

Most integration failures are licensing problems — an invalid, expired, or wrong-application key, or the documentation placeholder left in the code. Those are grouped first.

:::caution Demo preview — sample content
The entries below are **illustrative samples** (each tagged `SAMPLE` with a `SAMPLE-…` code) that demonstrate the finder. They are **not** real Scandit error messages and must not be relied on. Verified messages and fixes will replace them once the support/licensing error data is supplied.
:::

<ErrorCodeFinder/>

## Still stuck?

If your error isn't listed, or a fix doesn't resolve it, contact [Scandit support](https://www.scandit.com/support/) with the full console output, your SDK version, and the framework you're using.
145 changes: 145 additions & 0 deletions src/components/ErrorCodeFinder/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React from 'react';
import Head from '@docusaurus/Head';
import Link from '@docusaurus/Link';
import errorData from '@site/src/data/troubleshooting-errors.json';
import styles from './styles.module.css';

/**
* ErrorCodeFinder — the paste-to-filter troubleshooting index (backlog #5).
*
* A reader who hits an SDK error pastes the console message here and the list
* narrows to the matching entry with its cause and fix. Typing a fragment works
* too. A get-started page links here with the input auto-focused so the reader
* can paste immediately; a `?q=` URL param pre-filters (e.g. a deep link).
*
* LLM / GEO retrieval:
* - The full entry list is rendered SERVER-SIDE (not behind BrowserOnly), so
* every message/cause/fix is in the static HTML for crawlers, Algolia, and
* our knowledge-extractor. The search box is progressive enhancement:
* with no JS every entry still shows.
* - Each entry has a stable anchor id, so an answer can cite
* /troubleshooting/#<id>.
* - We emit schema.org FAQPage JSON-LD built from the same catalog, so
* search engines and LLMs get a machine-readable question→answer map.
*/

interface ErrorEntry {
id: string;
code: string;
area: string;
sample?: boolean;
title: string;
message: string;
match?: string[];
cause: string;
fix: string;
link?: string;
linkLabel?: string;
}

const ENTRIES = ((errorData as { entries?: ErrorEntry[] }).entries || []) as ErrorEntry[];

function normalize(s: string | undefined): string {
return (s || '').toLowerCase().replace(/\s+/g, ' ').trim();
}

/** Match either way: a typed fragment appears in a field, OR the reader pasted
* a whole console line that CONTAINS one of the entry's invariant substrings
* (their own key/app id in the pasted text is ignored this way). */
function matches(entry: ErrorEntry, nq: string): boolean {
if (!nq) return true;
const fields = [entry.title, entry.code, entry.message, entry.cause, ...(entry.match || [])].map(
normalize,
);
const forwardHit = fields.some((h) => h && h.includes(nq));
const invariants = [entry.message, ...(entry.match || [])].map(normalize).filter(Boolean);
const pasteHit = nq.length >= 12 && invariants.some((h) => nq.includes(h));
return forwardHit || pasteHit;
}

function buildJsonLd() {
return {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: ENTRIES.map((e) => ({
'@type': 'Question',
name: e.message,
acceptedAnswer: {
'@type': 'Answer',
text: `Cause: ${e.cause} Fix: ${e.fix}`,
},
})),
};
}

export default function ErrorCodeFinder(): JSX.Element {
const [q, setQ] = React.useState('');
const inputRef = React.useRef<HTMLInputElement>(null);

React.useEffect(() => {
try {
const fromQuery = new URLSearchParams(window.location.search).get('q') || '';
if (fromQuery) setQ(fromQuery);
} catch {
/* SSR / no window */
}
inputRef.current?.focus();
}, []);

const nq = normalize(q);
const visible = ENTRIES.filter((e) => matches(e, nq));

return (
<div className={styles.finder}>
<Head>
<script type="application/ld+json">{JSON.stringify(buildJsonLd())}</script>
</Head>

<input
ref={inputRef}
className={styles.search}
type="search"
value={q}
onChange={(e) => setQ(e.target.value)}
placeholder="Paste your error message here, or start typing…"
aria-label="Search Scandit error messages"
spellCheck={false}
autoComplete="off"
/>
<p className={styles.count}>
{q ? `${visible.length} of ${ENTRIES.length} matching` : `${ENTRIES.length} known issues`}
</p>

{visible.length === 0 && (
<p className={styles.empty}>
No match yet. Try pasting a shorter part of the message, or search the full documentation.
</p>
)}

<ul className={styles.list}>
{visible.map((e) => (
<li key={e.id} id={e.id} className={styles.card}>
<div className={styles.head}>
<span className={styles.area}>{e.area}</span>
{e.sample && <span className={styles.sampleTag}>SAMPLE</span>}
<code className={styles.code}>{e.code}</code>
</div>
<h3 className={styles.title}>{e.title}</h3>
<blockquote className={styles.message}>{e.message}</blockquote>
<p className={styles.line}>
<strong>Cause:</strong> {e.cause}
</p>
<p className={styles.line}>
<strong>Fix:</strong> {e.fix}
</p>
{e.link && (
<Link className={styles.link} to={e.link}>
{e.linkLabel || 'Learn more'} →
</Link>
)}
</li>
))}
</ul>
</div>
);
}
Loading
Loading