Images
Ship images and icons with a plugin.
Import an image like a module. A PNG, JPEG, WebP or GIF gives an asset id for source props. An SVG gives an icon component.
Quick Start
import { Image } from 'react-native';
import star from '../assets/icons/star.png';
export function Rating() {
return <Image source={star} style={{ width: 24, height: 24 }} />;
}ubd build copies the file into dist/ and lists it in the built manifest. Unbound registers it with Discord's asset registry when your plugin starts. The id works anywhere Discord takes a source:
import { Discord } from '@unbound-app/api/metro/components';
import star from '~/images/star.png';
<Discord.TableRow label='Favourites' icon={<Discord.TableRowIcon source={star} />} />;Images can live anywhere. Import with a relative path or ~/ (which points at src/).
Reference
| Import or call | Gives |
|---|---|
import id from './star.png' (also .jpg, .jpeg, .webp, .gif) | The asset id, a number |
import Star from './star.svg' | An icon component |
assets.getIdByName(name, type?) | The id, or undefined. Your plugin's names first, then Discord's |
assets.getByName(name, type?) | The asset record, or undefined |
assets.getById(id) | The asset record, or undefined |
assets.find(filter) | The first asset filter accepts |
assets.getAll() | Every registered asset |
assets.register(options) | Registers a runtime image. Returns { id, unregister } |
assets.onAssetRegistered(listener) | Calls listener(asset, id) for each later asset. Returns a remover |
Other file types fail the build, naming the file. Full signatures: assets in the SDK reference.
An imported image always ships. Every asset and listener your plugin registered is removed when it stops. An unregistered id draws nothing.
Screen Densities
Put larger versions beside the file with @2x or @3x. Import the plain name, and Unbound picks the right file.
assets/icons/star.png 24 × 24
assets/icons/[email protected] 48 × 48
assets/icons/[email protected] 72 × 72The build reads each image's size, so <Image source={star} /> needs no style. Shipping only @3x works.
SVGs
An SVG import is an icon component like Discord's own WrenchIcon. Pass the component to IconComponent props, and an element to icon props:
import { Discord } from '@unbound-app/api/metro/components';
import Star from '../assets/star.svg';
<Discord.TableRow label='Favourites' icon={<Discord.TableRowIcon IconComponent={Star} />} />;
<Discord.ActionSheetRow label='Favourite' icon={<Discord.ActionSheetRow.Icon IconComponent={Star} />} />;
<Discord.IconButton icon={<Star />} />;Unbound's APIs take an asset id, an element or a component:
import { toasts, ui } from '@unbound-app/api';
import Star from '../assets/star.svg';
toasts.show({ title: 'Starred', icon: Star });
<ui.Row label='Favourites' icon={Star} />;| Prop | Takes | The icon gets |
|---|---|---|
TableRowIcon, ActionSheetRow.Icon IconComponent | A component | size and color for the row |
A settings entry's IconComponent | A component | The same, through TableRowIcon |
MenuItem, ContextMenuItem IconComponent | A component | size: 'sm', and color in a context menu |
TableRow, ActionSheetRow, Button, IconButton icon | An element | Nothing. Own size and colour |
ui.Row, ui.SwitchRow, toasts.show icon, a toast button's icon | An id, element or component | TableRowIcon, or md in a toast |
Size and Colour
| Prop | Values |
|---|---|
size | 'xxs' (12), 'xs' (16), 'sm' (18), 'md' (24, default), 'lg' (32), a number, or 'custom' to size with style. width and height win |
color | A theme token such as Theme.colors.TEXT_LINK, or a colour. Default: the theme's icon colour |
A one-colour SVG (default black fill included) is tinted by color. One with two or more colours, gradients, masks, <style> or class keeps its colours. To show a one-colour SVG in its own colour, pass that colour.
Build Behaviour
- Strips comments, doctype, editor metadata (
<metadata>,sodipodi:*,inkscape:*) and whitespace between tags. - Fails on malformed XML or a root that isn't
<svg>. - Warns above 32 KB. Simplify it or export a PNG.
- Inlines each file once, however often it is imported. Nothing loads until first render.
- Never registers an SVG as an asset. For a
sourceprop, use a PNG.
Lookup by Name
An image's name is its path without extension or scale suffix. Under assets/ it starts inside that folder: assets/icons/star.png is icons/star. Elsewhere it starts at the plugin root: src/images/star.png is src/images/star.
import { assets } from '@unbound-app/api';
const star = assets.getIdByName('icons/star');Two plugins can both have icons/star without conflict.
Runtime Images
assets.register registers an image made while running, such as a data: URI or a file written with fs.
import { assets, fs } from '@unbound-app/api';
import { Image } from 'react-native';
const avatar = assets.register({
name: 'avatar',
path: `${fs.documentsPath}/MyPlugin/avatar.png`,
width: 32,
height: 32,
type: 'png',
});
<Image source={avatar.id} />;| Option | What it does |
|---|---|
name | The lookup name. Registering a name again reuses its id |
uri or path | The image at scale 1: a URI (data:, https:) or an absolute path |
width, height | Size in points |
type | File type, such as png |
scales | Other densities: { 2: uri, 3: uri } |
While Developing
ubd dev rebuilds and pushes when you add, edit or replace an image. Files are named by content, so a replaced image never shows a cached copy.