diff --git a/content/docs/(reference)/swift-sdk.mdx b/content/docs/(reference)/swift-sdk.mdx index f49cc9b5..d93966fe 100644 --- a/content/docs/(reference)/swift-sdk.mdx +++ b/content/docs/(reference)/swift-sdk.mdx @@ -284,6 +284,7 @@ _ = try await api.register(itemType: entry) | --- | --- | | `check(itemType:)` | [Check a type definition](/api-reference/types/normalizeType) without registering it. | | `register(itemType:)`, `replace(itemType:with:)`, `delete(itemType:force:)` | [Register](/api-reference/types/registerType), [replace](/api-reference/types/replaceType) or [delete](/api-reference/types/deleteType) an item type. | +| `set(icon:forType:)`, `clearIcon(ofType:)` | [Set](/api-reference/types/setTypeIcon) or [clear](/api-reference/types/clearTypeIcon) the owner's icon for a type. [Draw a type's icon](#draw-a-types-icon) shows them. | | `register(edgeType:)`, `edgeTypes()`, `delete(edgeType:force:)` | [Register](/api-reference/edge-types/registerEdgeType), [list](/api-reference/edge-types/listEdgeTypes) or [delete](/api-reference/edge-types/deleteEdgeType) an edge type. | Every other operation the client makes is a method named after its operation ID, such as `listItemVersions(path:)` or `listAuditLog()`. A refusal throws a `MarfaError`, so read a success from the answer's `ok` case: `try await api.listAuditLog().ok.body.json`. @@ -321,6 +322,31 @@ if job.status == .completed, job.result?.settingsRewritten == true { A move refuses with `server` and the code `type_move_blocked` when a setting names the type in a way it can't rewrite, and moves nothing. **A delete of a type that an item, folder, view or webhook still names is refused with `server`, status 409 and the code `type_in_use`.** The `message` of both ends with the refusal's `details` as JSON, which lists each setting by its `kind`, `id` and `field`. +## Draw a type's icon + +Every item type carries one icon: the name of an icon in the [Lucide](https://lucide.dev/icons/) release Marfa pins, such as `book-open`. **`ItemType.icon` holds the name the type resolves to**: the owner's own choice for the type or its nearest parent that has one, else the nearest author's. It is `nil` when no type in the chain sets one. [Display hints](/catalog/your-own-types) explains how a type gets its icon. + +The `MarfaIcons` product draws the name, so an app adds it beside `Marfa`: + +```swift +import MarfaIcons + +TypeIcon(type) // from an ItemType +TypeIcon(name: type.icon) // from a name +Image(typeIcon: type.icon) // where a view needs an Image +``` + +Apple apps draw SF Symbols, so `TypeIcon` uses the SF Symbol that stands for the Lucide name, and for a name with no good match it draws Lucide's own artwork, shipped in the package as a template image. **Both tint with `foregroundStyle`**, follow light and dark appearance, and size with the surrounding font. A type with no icon, and a name this version of the SDK doesn't know, draw a fallback symbol and never fail, because an instance newer than the SDK can send such a name. + +The owner can choose the icon of any type, including one Marfa ships. `Client` sets and clears the choice, and answers the type as the instance now reads it, so the app can draw the new icon at once: + +```swift +let type = try await api.set(icon: "scale", forType: "app.readinglist.entry") +_ = try await api.clearIcon(ofType: "app.readinglist.entry") +``` + +Both calls need a credential with `schema.write` and write on the type, and throw `forbidden` without them: with the code `forbidden` when the credential lacks `schema.write`, and `type_not_permitted` when it may not write the type. **A name outside the pinned Lucide release is refused** with `validation` and the code `invalid_schema`. Clearing a type that has no owner icon succeeds and changes nothing. The copy's `catalog` takes the change the next time it reads the catalog, as [Display hints](/catalog/your-own-types) describes, so another device shows it later. + ## Follow changes Each `Change` names the `itemId` or `edgeId` it concerns, and its `origin` says where it came from: