ui
Ready-made Jetpack Compose screens, the blocks to build your own, and the design system that themes them.
Every screen is self-contained: give it what to show and a callback, and it fetches, paginates and renders on its own. It never navigates: downloads, saving for later and its own menus are handled in place, and the taps that lead elsewhere are reported through a sealed event type, the destination left to you.
CgsTheme(colorScheme = cgsColorScheme(isSystemInDarkTheme())) {
PublicationScreen(publicationId = id) { event ->
when (event) {
is PublicationEvent.ClickOnIssue -> CGS.reader().open(activity, event.issue.id, event.page)
is PublicationEvent.ClickOnArticle -> CGS.reader().open(activity, event.articles.map { it.id }, event.index)
is PublicationEvent.ClickOnSeeAllArticles -> navigateToArticleList(event.publication.id)
is PublicationEvent.ClickOnSeeAllArchives -> navigateToArchives(event.publication.id)
}
}
}| PublicationScreen | A publication: its latest issue with that issue's first articles and its add-ins, then a preview of its archives. |
| ArticleListScreen | Every article of a publication's latest issue, paginated. |
| ArchivesScreen | Every archived issue of a publication, year by year. |
| LibraryScreen | The current profile's downloads, finished or not. |
| CorporateMediaScreen | A corporate media's documents. |
| VideoMediaScreen | Videos across a set of publications. |
Blocks
When no screen fits, build your own from blocks. IssuesBlock and ArticlesBlock are sections you drop into your own layout, and BlockPage stacks several of them, with sections of your own, into one scrolling screen. Like a screen, a block fetches, paginates and recovers on its own and never navigates; unlike one, you choose what it shows — its source — and how it is laid out.
BlockPage {
issues(
source = IssuesBlockSource.ofPublications(listOf(publicationId)),
title = "Latest issues",
onEvent = { event ->
if (event is IssuesBlockEvent.ItemClick) CGS.reader().open(activity, event.issue.id, event.page)
}
)
articles(
source = ArticlesBlockSource.ofPublications(listOf(publicationId)),
title = "Latest articles",
limit = 5,
onEvent = { event ->
if (event is ArticlesBlockEvent.ItemClick) {
CGS.reader().open(activity, event.articles.map { it.id }, event.position.index)
}
}
)
}A page scrolls as one, so a grid or a vertical list in it must be capped with limit, and the page throws for one that is not; a carousel, the issues block's default, needs no cap.
Theming
Wrap anything from this module in CgsTheme. Out of the box it uses the SDK's own palette and type scale; above that:
Your brand color — cgsColorScheme(darkTheme, brand, accent) derives a complete scheme from two colors: the other brand tones are rebuilt from the brand's hue and saturation, and the neutral and status tokens stay the SDK's own. Only the text on the accent is picked for contrast, so check how the result reads with your brand.
Group by group — lightColorScheme and darkColorScheme take a replacement for any group of the palette. A group is replaced whole, and a replaced brand group does not re-tint the brand tokens of the other groups.
The type scale —
CgsTheme'stypographytakes a CgsTypography, whose constructors default every style to the SDK's own, so you can replace one style at a time.
LibraryScreen, CorporateMediaScreen and VideoMediaScreen also take a colors parameter, to re-colour that screen alone without touching the theme. Its constructor takes every color: the defaults are not exposed to start from.
Permissions
This module declares one permission, which the reader engine behind core already brings into your merged manifest:
ACCESS_NETWORK_STATE | A block — a section of the publication, article-list or archives screen, or of a BlockPage — that failed for want of a connection reloads itself the moment the connection is back, instead of waiting for the user to hit retry. |
It is an install-time permission: the manifest merger adds it to your app, it is never requested at runtime, and the user is never prompted. An app that must not declare it can strip it with tools:node="remove" — the blocks keep working, they simply stop recovering on their own and fall back to the retry they already offer, and the reader stops reloading failed images when the connection comes back.
Packages
Self-contained sections of content — a shelf of issues, a list of articles — for building a screen of your own. A source says what a block shows and a layout how it is arranged; the block loads, paginates, retries and collapses on its own, and reports taps through a sealed event type without ever navigating. BlockPage stacks several blocks into one scrolling screen, with a single retry, empty state and pull-to-refresh across them.
The color sets the components and screens accept. A component left alone reads its set from the current CgsTheme; to re-colour one, build a set with its constructor. Every color is required: the SDK's defaults are not exposed to start from.
The design system: CgsTheme, the color palette, and the type scale. This is what you touch to make the SDK's screens look like your app.