From ff8422271e1da55007b40f382fe0b29297585f95 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 12:00:39 +0300 Subject: [PATCH 1/6] created common topbar and back button --- .../modelpulse/ui/common/ModelPulseTopBar.kt | 41 ++++++++++++++ .../modelpulse/ui/common/TopBarBackButton.kt | 56 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 app/src/main/java/com/fedo/modelpulse/ui/common/ModelPulseTopBar.kt create mode 100644 app/src/main/java/com/fedo/modelpulse/ui/common/TopBarBackButton.kt diff --git a/app/src/main/java/com/fedo/modelpulse/ui/common/ModelPulseTopBar.kt b/app/src/main/java/com/fedo/modelpulse/ui/common/ModelPulseTopBar.kt new file mode 100644 index 0000000..a921395 --- /dev/null +++ b/app/src/main/java/com/fedo/modelpulse/ui/common/ModelPulseTopBar.kt @@ -0,0 +1,41 @@ +package com.fedo.modelpulse.ui.common + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarScrollBehavior +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight + +/** + * @see TopBarBackButton + */ +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ModelPulseTopBar( + title: String, + modifier: Modifier = Modifier, + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, + scrollBehavior: TopAppBarScrollBehavior? = null, +) { + LargeTopAppBar( + title = { + Text( + title, + style = MaterialTheme.typography.headlineLarge.copy( + fontWeight = FontWeight.Bold + ) + ) + }, + actions = actions, + navigationIcon = navigationIcon, + scrollBehavior = scrollBehavior, + modifier = modifier + ) + +} \ No newline at end of file diff --git a/app/src/main/java/com/fedo/modelpulse/ui/common/TopBarBackButton.kt b/app/src/main/java/com/fedo/modelpulse/ui/common/TopBarBackButton.kt new file mode 100644 index 0000000..7701759 --- /dev/null +++ b/app/src/main/java/com/fedo/modelpulse/ui/common/TopBarBackButton.kt @@ -0,0 +1,56 @@ +package com.fedo.modelpulse.ui.common + +import android.content.res.Configuration +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.IconButtonDefaults +import androidx.compose.material3.MaterialTheme.colorScheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.fedo.modelpulse.R +import com.fedo.modelpulse.ui.theme.ModelPulseTheme + + +@Composable +fun TopBarBackButton( + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + FilledIconButton( + onClick = onClick, modifier, + colors = IconButtonDefaults.filledIconButtonColors( + containerColor = colorScheme.surfaceVariant, + contentColor = colorScheme.onSurfaceVariant, + ), + ) { + Icon( + painter = painterResource(R.drawable.ic_arrow_back), + contentDescription = stringResource(R.string.detail_back), + ) + } +} + +@Preview(name = "Light") +@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES) +private annotation class ThemePreviews + +@ThemePreviews +@Composable +private fun TopBarBackButtonPreview() { + ModelPulseTheme { + Surface { + Box(Modifier.padding(16.dp)) { + TopBarBackButton({}) + } + } + } +} \ No newline at end of file From f6576fd10132206784680deef4c09d9c18280a92 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 12:00:49 +0300 Subject: [PATCH 2/6] use common topBar in all screens --- .../modelpulse/ui/detail/ModelDetailScreen.kt | 35 ++++++++++--------- .../fedo/modelpulse/ui/models/ModelsScreen.kt | 5 +-- .../modelpulse/ui/settings/SettingsScreen.kt | 20 +++++++---- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/fedo/modelpulse/ui/detail/ModelDetailScreen.kt b/app/src/main/java/com/fedo/modelpulse/ui/detail/ModelDetailScreen.kt index 7bb3183..b0d1ad5 100644 --- a/app/src/main/java/com/fedo/modelpulse/ui/detail/ModelDetailScreen.kt +++ b/app/src/main/java/com/fedo/modelpulse/ui/detail/ModelDetailScreen.kt @@ -23,11 +23,14 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.ClipEntry import androidx.compose.ui.platform.LocalClipboard import androidx.compose.ui.res.painterResource @@ -45,6 +48,8 @@ import com.fedo.modelpulse.data.Price import com.fedo.modelpulse.data.contextLabel import com.fedo.modelpulse.data.perMillionLabel import com.fedo.modelpulse.data.relativeLabel +import com.fedo.modelpulse.ui.common.ModelPulseTopBar +import com.fedo.modelpulse.ui.common.TopBarBackButton import com.fedo.modelpulse.ui.mergePaddingValues import com.fedo.modelpulse.ui.theme.ModelPulseTheme import java.math.BigDecimal @@ -88,26 +93,18 @@ internal fun ModelDetailScreen( modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues() ) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + Scaffold( modifier = modifier.fillMaxSize(), topBar = { - TopAppBar( - title = { - Text( - text = (uiState as? ModelDetailUiState.Success) - ?.model - ?.shortName - .orEmpty(), - ) - }, - navigationIcon = { - IconButton(onClick = onBackClick) { - Icon( - painter = painterResource(R.drawable.ic_arrow_back), - contentDescription = stringResource(R.string.detail_back), - ) - } - }, + ModelPulseTopBar( + title = (uiState as? ModelDetailUiState.Success) + ?.model + ?.shortName + .orEmpty(), + navigationIcon = { TopBarBackButton(onBackClick) }, + scrollBehavior = scrollBehavior ) }, ) { innerPadding -> @@ -129,15 +126,18 @@ internal fun ModelDetailScreen( is ModelDetailUiState.Success -> ModelDetailContent( model = uiState.model, onCopyId = onCopyId, + scrollBehavior = scrollBehavior, contentPadding = mergedContentPadding, ) } } } +@OptIn(ExperimentalMaterial3Api::class) @Composable private fun ModelDetailContent( model: AiModel, + scrollBehavior: TopAppBarScrollBehavior, onCopyId: (String) -> Unit, modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues() @@ -146,6 +146,7 @@ private fun ModelDetailContent( modifier = modifier .fillMaxSize() // A long description scrolls rather than clipping. + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(rememberScrollState()) .padding(contentPadding) .padding(horizontal = 16.dp, vertical = 8.dp) diff --git a/app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt b/app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt index 36ba09f..dddf251 100644 --- a/app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt +++ b/app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt @@ -62,6 +62,7 @@ import com.fedo.modelpulse.data.contextLabel import com.fedo.modelpulse.data.perMillionLabel import com.fedo.modelpulse.data.providerFilters import com.fedo.modelpulse.data.relativeLabel +import com.fedo.modelpulse.ui.common.ModelPulseTopBar import com.fedo.modelpulse.ui.mergePaddingValues import com.fedo.modelpulse.ui.theme.ModelPulseTheme import com.fedo.sdk.ui.FedoCreateFeedbackSheet @@ -134,8 +135,8 @@ internal fun ModelsScreen( .nestedScroll(scrollBehavior.nestedScrollConnection), snackbarHost = { SnackbarHost(snackbarHostState) }, topBar = { - MediumFlexibleTopAppBar( - title = { Text(stringResource(R.string.models_title)) }, + ModelPulseTopBar( + title = stringResource(R.string.models_title), scrollBehavior = scrollBehavior, ) }, diff --git a/app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsScreen.kt b/app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsScreen.kt index 77f1972..10e1c6c 100644 --- a/app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsScreen.kt @@ -11,15 +11,18 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Button import androidx.compose.material3.Card +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.tooling.preview.Preview @@ -28,6 +31,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.fedo.modelpulse.R +import com.fedo.modelpulse.ui.common.ModelPulseTopBar import com.fedo.modelpulse.ui.mergePaddingValues import com.fedo.modelpulse.ui.theme.ModelPulseTheme import org.koin.androidx.compose.koinViewModel @@ -51,6 +55,7 @@ internal fun SettingsRoute( ) } +@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun SettingsScreen( uiState: SettingsUiState, @@ -61,25 +66,28 @@ internal fun SettingsScreen( modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues() ) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + Scaffold( modifier = modifier, + topBar = { + ModelPulseTopBar( + title = stringResource(R.string.settings_title), + scrollBehavior = scrollBehavior + ) + } ) { innerPadding -> val mergedContentPadding = mergePaddingValues(innerPadding, contentPadding) Column( - modifier = Modifier .fillMaxSize() + .nestedScroll(scrollBehavior.nestedScrollConnection) .verticalScroll(rememberScrollState()) .padding(mergedContentPadding) .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp), ) { - Text( - text = stringResource(R.string.settings_title), - style = MaterialTheme.typography.headlineSmall, - ) - SdkStatusCard(isConfigured = uiState.isConfigured) DemoAccountCard( From e5d3327c62fdc9660fafb20459e01b849209c272 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 12:03:43 +0300 Subject: [PATCH 3/6] remove back button from roadmap screen --- .../com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt b/app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt index 910024e..7c64291 100644 --- a/app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt +++ b/app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt @@ -19,6 +19,8 @@ import androidx.compose.ui.unit.dp import com.fedo.modelpulse.R import com.fedo.modelpulse.ui.theme.ModelPulseTheme import com.fedo.sdk.ui.FedoFeedbackScreen +import com.fedo.sdk.ui.FedoFeedbackScreenDefaults +import com.fedo.sdk.ui.FedoFeedbackScreenSlots /** * The Roadmap destination. With a key it is the SDK's board, which owns its @@ -33,7 +35,13 @@ internal fun RoadmapScreen( modifier: Modifier = Modifier, ) { if (isConfigured) { - FedoFeedbackScreen(modifier = modifier.fillMaxSize(), onDismiss = onBack) + FedoFeedbackScreen( + modifier = modifier.fillMaxSize(), + onDismiss = onBack, + slots = FedoFeedbackScreenDefaults.slots().copy( + backButtonIcon = null + ) + ) } else { NotConfiguredState(modifier) } From 3f137e4edbe69270820a17c9964adf6b7eab2192 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 12:08:11 +0300 Subject: [PATCH 4/6] updated compose patten spec --- specs/compose-pattern.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/specs/compose-pattern.md b/specs/compose-pattern.md index 8ce1832..ff4e75d 100644 --- a/specs/compose-pattern.md +++ b/specs/compose-pattern.md @@ -70,6 +70,33 @@ internal fun ModelsScreen( - Previews work without Koin - Navigation stays in one place +## Top Bar +```kotlin + +@Composable +internal fun ModelsScreen( + // ... + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + Scaffold( + modifier = modifier.fillMaxSize(), + topBar = { + ModelPulseTopBar( + title = stringResource(R.string.something), + navigationIcon = { TopBarBackButton(onBack) }, + ) + }, + ) { innerPadding -> + // screen content + } +} +``` +Always use `ModelPulseTopBar` for top bar and `TopBarBackButton` for top bar navigation icon + +## + ## State Management ### Sealed Interface for UI State From db3432bc036795889c55c48342b3a24673cce5d5 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 12:09:11 +0300 Subject: [PATCH 5/6] updated readme --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 94db285..422a09c 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ Single `:app` module. Compose, Koin, OkHttp, kotlinx.serialization and Navigatio ## Screenshots -| Models | Model detail | Roadmap | Settings | -| --- | --- | --- | --- | +| Models | Model detail | Roadmap | Settings | +|----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| | Models list, newest first, with search and provider filter | Model detail with prices, context window and copyable id | The Fedo feedback board in the Roadmap destination | Settings showing SDK status and the demo account |
Light theme -| Models | Model detail | Roadmap | Settings | -| --- | --- | --- | --- | +| Models | Model detail | Roadmap | Settings | +|--------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------| | Models list in light theme | Model detail in light theme | The Fedo feedback board in light theme | Settings in light theme |
@@ -62,14 +62,14 @@ No key yet? The app still builds and runs: the models list, search, filter and d ## Where Fedo is used -| API | File | What it does | -| --- | --- | --- | -| `Fedo.initialize(context, apiKey) { }` | [`ModelPulseApplication.kt`](app/src/main/java/com/fedo/modelpulse/ModelPulseApplication.kt) | Initializes the SDK once at startup, with debug logging in debug builds. Skipped entirely when no key is configured. | -| `FedoFeedbackScreen(onDismiss = …)` | [`RoadmapScreen.kt`](app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt) | The Roadmap destination: the whole feedback board. It owns its internal navigation, so `onDismiss` only fires at the board root and pops the app's own back stack. | +| API | File | What it does | +|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `Fedo.initialize(context, apiKey) { }` | [`ModelPulseApplication.kt`](app/src/main/java/com/fedo/modelpulse/ModelPulseApplication.kt) | Initializes the SDK once at startup, with debug logging in debug builds. Skipped entirely when no key is configured. | +| `FedoFeedbackScreen(onDismiss = …)` | [`RoadmapScreen.kt`](app/src/main/java/com/fedo/modelpulse/ui/roadmap/RoadmapScreen.kt) | The Roadmap destination: the whole feedback board. It owns its internal navigation, so `onDismiss` only fires at the board root and pops the app's own back stack. | | `Fedo.setUserID(…)`
`Fedo.setUserDisplayName(…)`
`Fedo.setUserEmail(…)` | [`SettingsViewModel.kt`](app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsViewModel.kt) | Demo sign-in. Feedback, votes and comments left as a guest move to the signed-in account. The demo id is a generated `demo-` UUID, never the email — a real app passes its own backend user id and keeps PII out of it. | -| `Fedo.setUserProperty("favorite_provider", …)` | [`ModelsViewModel.kt`](app/src/main/java/com/fedo/modelpulse/ui/models/ModelsViewModel.kt) | Records the provider picked in the filter as a user property, so feedback can be segmented by what the user cares about. Properties are user-level and last-write-wins; clearing the filter writes an empty value. | -| `FedoCreateFeedbackSheet(onDismiss = …)` | [`ModelsScreen.kt`](app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt) | The contextual sheet: "Missing a model? Request it" in the no-results state and "Report a problem" in the load-error state. Both appear only when a key is configured. | -| `Fedo.logout()` | [`SettingsViewModel.kt`](app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsViewModel.kt) | Demo sign-out: clears the identity and starts a new guest. | +| `Fedo.setUserProperty("favorite_provider", …)` | [`ModelsViewModel.kt`](app/src/main/java/com/fedo/modelpulse/ui/models/ModelsViewModel.kt) | Records the provider picked in the filter as a user property, so feedback can be segmented by what the user cares about. Properties are user-level and last-write-wins; clearing the filter writes an empty value. | +| `FedoCreateFeedbackSheet(onDismiss = …)` | [`ModelsScreen.kt`](app/src/main/java/com/fedo/modelpulse/ui/models/ModelsScreen.kt) | The contextual sheet: "Missing a model? Request it" in the no-results state and "Report a problem" in the load-error state. Both appear only when a key is configured. | +| `Fedo.logout()` | [`SettingsViewModel.kt`](app/src/main/java/com/fedo/modelpulse/ui/settings/SettingsViewModel.kt) | Demo sign-out: clears the identity and starts a new guest. | How each surface is meant to behave, including without a key, is written down in [specs/fedo-showcase.md](specs/fedo-showcase.md). The full SDK guide is in the [Fedo docs](https://docs.getfedo.com/guide/getting-started/). From 6fd9bbb23654ebdb116446014e56ca8917620829 Mon Sep 17 00:00:00 2001 From: MABD Date: Wed, 23 Sep 2026 13:09:01 +0300 Subject: [PATCH 6/6] update github links --- .github/ISSUE_TEMPLATE/config.yml | 2 +- CONTRIBUTING.md | 2 +- README.md | 2 +- specs/decisions/0001-library-versions.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 74f1959..2d8c19f 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Fedo Android SDK issues - url: https://github.com/kusa-software/fedo-sdk/issues + url: https://github.com/getfedo/fedo-sdk/issues about: Bugs and feature requests for the Fedo Android SDK (com.getfedo:sdk-android) belong in the SDK repository. - name: Fedo documentation url: https://docs.getfedo.com/next/guide/getting-started/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 38d20fb..2a3521f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,6 +122,6 @@ they only come alive once the code is pushed there. ## Where to report - Bugs and ideas for this example app: [GitHub issues](https://github.com/getfedo/fedo-android-example/issues) in this repository. -- Bugs in the Fedo Android SDK itself: [kusa-software/fedo-sdk issues](https://github.com/kusa-software/fedo-sdk/issues). +- Bugs in the Fedo Android SDK itself: [getfedo/fedo-sdk issues](https://github.com/getfedo/fedo-sdk/issues). - Security vulnerabilities: privately, as described in [SECURITY.md](SECURITY.md). - Conduct concerns: see the [Code of Conduct](CODE_OF_CONDUCT.md). diff --git a/README.md b/README.md index 422a09c..5f3cbe0 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ specs/ constitution, architecture, Compose and testing patterns, decis ## Contributing -Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup and guidelines, and follow the [Code of Conduct](CODE_OF_CONDUCT.md). Report security vulnerabilities privately as described in [SECURITY.md](SECURITY.md). Bugs in the SDK itself belong in [kusa-software/fedo-sdk](https://github.com/kusa-software/fedo-sdk/issues). +Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup and guidelines, and follow the [Code of Conduct](CODE_OF_CONDUCT.md). Report security vulnerabilities privately as described in [SECURITY.md](SECURITY.md). Bugs in the SDK itself belong in [getfedo/fedo-sdk](https://github.com/getfedo/fedo-sdk/issues). ## Credits diff --git a/specs/decisions/0001-library-versions.md b/specs/decisions/0001-library-versions.md index a01a8a5..1041875 100644 --- a/specs/decisions/0001-library-versions.md +++ b/specs/decisions/0001-library-versions.md @@ -73,7 +73,7 @@ Rejected: `MockEngine` are present in `classes7.dex`/`classes8.dex` of a debug build. The debug APK is ~46 MB. -This is a packaging bug in the SDK (`kusa-software/fedo-sdk`), not something +This is a packaging bug in the SDK (`getfedo/fedo-sdk`), not something this repo can fix properly. Workaround if it blocks a release: ```kotlin