Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
42d5845
chore: scaffold android
hurali97 Feb 25, 2026
a2fb807
feat: add cpp bindings
hurali97 Feb 25, 2026
84d2e7c
feat: add compiler flags and target linkages
hurali97 Feb 25, 2026
7b79bd4
feat: use brownie on android
hurali97 Feb 25, 2026
87f7ba4
refactor: use new module registration API
hurali97 Feb 26, 2026
c13fc2a
refactor: remove redundancy
hurali97 Feb 26, 2026
aca462e
refactor: remove unused methods
hurali97 Feb 26, 2026
031acba
feat: improve Android DX
hurali97 Feb 26, 2026
7ee8e07
refactor: split impl between files
hurali97 Feb 26, 2026
1d9f047
docs: add brownie android
hurali97 Feb 26, 2026
6d7eb53
docs: update pre-req
hurali97 Feb 26, 2026
09db44d
fix: add kotlin to platforms
hurali97 Feb 27, 2026
456095d
fix: separate imports by flavor
hurali97 Feb 27, 2026
7348660
fix: add brownie config block
hurali97 Feb 27, 2026
7be432d
chore: run changeset
hurali97 Feb 27, 2026
902c825
feat: exclude libc++ at brownie level
hurali97 Feb 27, 2026
dc18c23
chore: run changeset
hurali97 Feb 27, 2026
1061baf
fix: add kotlin to cli choices
hurali97 Feb 27, 2026
2704cd8
refactor: remove unused style
hurali97 Feb 27, 2026
2012b86
feat: rely on StoreManager instead of custom tracker
hurali97 Feb 27, 2026
524b041
fix: add guard
hurali97 Feb 27, 2026
615f7cc
fix: notify state update only once
hurali97 Feb 27, 2026
2b008d8
chore: add consumer-rules to avoid required function name strip
hurali97 Feb 27, 2026
7f9b059
docs: update
hurali97 Mar 14, 2026
ff88a51
feat: changes after rebase
hurali97 Mar 14, 2026
51c55bd
fix: brownfield store
hurali97 Mar 30, 2026
9b6ddb8
fix: expo apps
hurali97 Mar 30, 2026
2ee8e75
fix: pin xcode 26.3
hurali97 Mar 31, 2026
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
8 changes: 8 additions & 0 deletions .changeset/red-llamas-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@callstack/brownie': minor
'@callstack/brownfield-cli': minor
'brownfield': minor
'@callstack/react-native-brownfield': minor
---

add brownie android
2 changes: 1 addition & 1 deletion .github/actions/prepare-ios/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ runs:
- name: Use appropriate Xcode version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: '26'
xcode-version: '26.3'

- name: Setup Ruby
uses: ruby/setup-ruby@5dd816ae0186f20dfa905997a64104db9a8221c7 # v1.280.0
Expand Down
7 changes: 4 additions & 3 deletions apps/AndroidApp/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,19 @@ android {
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "11"
jvmTarget = "17"
}
buildFeatures {
compose = true
}
}

dependencies {
implementation("com.google.code.gson:gson:2.13.1")
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.callstack.brownfield.android.example

typealias BrownfieldStore = com.callstack.rnbrownfield.demo.expoapp54.BrownfieldStore
typealias User = com.callstack.rnbrownfield.demo.expoapp54.User
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.callstack.brownfield.android.example

object ReactNativeConstants {
const val MAIN_MODULE_NAME = "main"
const val MAIN_MODULE_NAME = "RNApp"
const val APP_NAME = "Android (Expo 54)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.callstack.brownfield.android.example

typealias BrownfieldStore = com.callstack.rnbrownfield.demo.expoapp55.BrownfieldStore
typealias User = com.callstack.rnbrownfield.demo.expoapp55.User
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.callstack.brownfield.android.example

object ReactNativeConstants {
const val MAIN_MODULE_NAME = "main"
const val MAIN_MODULE_NAME = "RNApp"
const val APP_NAME = "Android (Expo 55)"
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import androidx.fragment.compose.AndroidFragment
import com.callstack.brownfield.android.example.components.GreetingCard
import com.callstack.brownfield.android.example.components.PostMessageCard
import com.callstack.brownfield.android.example.ui.theme.AndroidBrownfieldAppTheme
import com.callstack.brownie.registerStoreIfNeeded
import com.callstack.nativebrownfieldnavigation.BrownfieldNavigationDelegate
import com.callstack.nativebrownfieldnavigation.BrownfieldNavigationManager
import com.callstack.reactnativebrownfield.ReactNativeFragment
Expand All @@ -52,6 +53,15 @@ class MainActivity : AppCompatActivity(), BrownfieldNavigationDelegate {
Toast.LENGTH_LONG
).show()
}

registerStoreIfNeeded(
storeName = BrownfieldStore.STORE_NAME
) {
BrownfieldStore(
counter = 0.0,
user = User(name = "Username")
)
}
}

setContent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,42 @@ import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.callstack.brownfield.android.example.BrownfieldStore
import com.callstack.brownie.Store
import com.callstack.brownie.StoreManager
import com.callstack.brownie.store
import com.callstack.brownie.subscribe

private fun brownieStore(): Store<BrownfieldStore>? {
return StoreManager.shared.store(BrownfieldStore.STORE_NAME)
}

@Composable
fun GreetingCard(
name: String,
) {
var counter by rememberSaveable { mutableIntStateOf(0) }
var counter by remember { mutableIntStateOf(0) }

DisposableEffect(Unit) {
val store = brownieStore()
val unsubscribe = store?.subscribe(
selector = { state -> state.counter.toInt() },
onChange = { updatedCounter -> counter = updatedCounter }
) ?: {}

onDispose {
unsubscribe()
}
}

MaterialCard {
Column(
Expand All @@ -43,7 +65,11 @@ fun GreetingCard(
style = MaterialTheme.typography.bodyMedium
)

Button(onClick = { counter++ }) {
Button(onClick = {
brownieStore()?.set { state ->
state.copy(counter = state.counter + 1)
}
}) {
Text("Increment counter")
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.callstack.brownfield.android.example

typealias BrownfieldStore = com.rnapp.brownfieldlib.BrownfieldStore
typealias User = com.rnapp.brownfieldlib.User
33 changes: 0 additions & 33 deletions apps/ExpoApp54/components/counter/index.ios.tsx

This file was deleted.

14 changes: 11 additions & 3 deletions apps/ExpoApp54/components/counter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, Button } from 'react-native';
import { useStore } from '@callstack/brownie';

const Counter = () => {
const [counter, setState] = useStore('BrownfieldStore', (s) => s.counter);

return (
<>
<Text style={styles.text}>Brownie: To be implemented</Text>
<Text style={styles.text}>Count: {counter}</Text>

<Button
onPress={() => setState((prev) => ({ counter: prev.counter + 1 }))}
title="Increment"
/>
</>
);
};
Expand All @@ -12,7 +20,7 @@ export default Counter;

const styles = StyleSheet.create({
text: {
fontSize: 18,
fontSize: 30,
fontWeight: 'bold',
margin: 10,
},
Expand Down
4 changes: 4 additions & 0 deletions apps/ExpoApp54/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"eslint": "^9.25.0",
"eslint-config-expo": "~10.0.0",
"typescript": "~5.9.3"
},
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp54/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp54"
}
}
2 changes: 1 addition & 1 deletion apps/ExpoApp55/RNApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { SafeAreaView } from 'react-native-safe-area-context';
import { Button, StyleSheet, Text, View } from 'react-native';
import BrownfieldNavigation from '@callstack/brownfield-navigation';

import Counter from './components/counter';
import Counter from './src/components/counter';

export default function RNApp() {
return (
Expand Down
8 changes: 6 additions & 2 deletions apps/ExpoApp55/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@callstack/brownfield-example-expo-app-55",
"main": "expo-router/entry",
"main": "./entry.tsx",
"version": "1.0.0",
"scripts": {
"start": "expo start",
Expand Down Expand Up @@ -51,5 +51,9 @@
"eslint-config-expo": "~55.0.0",
"typescript": "~5.9.2"
},
"private": true
"private": true,
"brownie": {
"kotlin": "./android/brownfieldlib/src/main/java/com/callstack/rnbrownfield/demo/expoapp55/Generated/",
"kotlinPackageName": "com.callstack.rnbrownfield.demo.expoapp55"
}
}
33 changes: 0 additions & 33 deletions apps/ExpoApp55/src/components/counter/index.ios.tsx

This file was deleted.

20 changes: 17 additions & 3 deletions apps/ExpoApp55/src/components/counter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { StyleSheet, Text } from 'react-native';
import { StyleSheet, Text, Button } from 'react-native';
import { useStore } from '@callstack/brownie';

const Counter = () => {
const [counter, setState] = useStore('BrownfieldStore', (s) => s.counter);

return (
<>
<Text style={styles.text}>Brownie: To be implemented</Text>
<Text style={styles.text}>Count: {counter}</Text>

<Button
onPress={() => setState((prev) => ({ counter: prev.counter + 1 }))}
title="Increment"
/>
</>
);
};

export default Counter;

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
text: {
fontSize: 18,
fontSize: 30,
fontWeight: 'bold',
margin: 10,
},
Expand Down
4 changes: 4 additions & 0 deletions apps/RNApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
"react-test-renderer": "19.1.1",
"typescript": "^5.9.3"
},
"brownie": {
"kotlin": "./android/BrownfieldLib/src/main/java/com/rnapp/brownfieldlib/Generated/",
"kotlinPackageName": "com.rnapp.brownfieldlib"
},
"engines": {
"node": ">=20"
}
Expand Down
40 changes: 0 additions & 40 deletions apps/RNApp/src/components/counter/index.ios.tsx

This file was deleted.

Loading
Loading