Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

The official Android client for Peer Network, built with modern Android development standards.

📱 **Get it on Google Play**
https://play.google.com/store/apps/details?id=eu.peernetwork.app

[![Contributing](https://img.shields.io/badge/Contributing-Guidelines-blue.svg)](https://github.com/peer-network/.github/blob/main/CONTRIBUTING.md)

## 🏗 Technology Stack
Expand Down Expand Up @@ -69,7 +72,7 @@ peer_android_frontend/
The UI acts as a composition of three distinct layers:
1. **Stateful Components (Screens)**: Composition roots (e.g., `LoginScreen`) responsible for Dependency Injection, ViewModel creation, and state collection.
2. **Stateless Components**: Complex UI compositions (e.g., `LoginPage`) that define the layout and behavioral contracts. They are pure functions receiving state and event callbacks.
3. **View Components**: Reusable, atomic building blocks (e.g., `ConnectionButton`, `DesignOutlinedButton`) shared across the application.
3. **View Components**: Reusable, atomic building blocks (e.g., `DesignTextField`, `DesignButton`) shared across the application.

## 🚀 Build & Setup

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import eu.peernetwork.core.ui.renderer.Renderer

interface CheckoutBalance : Renderer.Stateless {
@Composable
fun Charges(
fun Rate(
viewModelStoreOwner: ViewModelStoreOwner,
content: @Composable (State<DesignStreamState<UiCharge>>, () -> Unit) -> Unit
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package eu.peernetwork.ads.ui.checkout

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fun CheckoutScreen(
} }
val handleFinish by rememberUpdatedState(onFinish)
val handleProfile by rememberUpdatedState(onProfile)
component.checkoutBalance().Charges(
component.checkoutBalance().Rate(
viewModelStoreOwner = viewModelStoreOwner
) { tax, refresh ->
val price = remember { derivedStateOf {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fun CheckoutSummery(
)
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = "200",
text = "${price.toInt()}",
style = MaterialTheme.typography.labelLarge,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onBackground
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -31,11 +33,21 @@ fun OverviewError(
Column(modifier = Modifier.fillMaxSize()
.padding(horizontal = 16.dp)
.padding(vertical = 12.dp)) {
Box(modifier = Modifier.padding(bottom = 10.dp)
.fillMaxWidth()
.height(48.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surfaceContainerLowest))
Box(
contentAlignment = Alignment.CenterStart,
modifier = Modifier.padding(bottom = 10.dp)
.fillMaxWidth()
.height(48.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.surfaceContainerLowest)
.padding(horizontal = 20.dp)
) {
CompositionLocalProvider(
LocalTextStyle provides MaterialTheme.typography.bodySmall.copy(
color = MaterialTheme.colorScheme.error
)
) { updatedContent() }
}
Box(modifier = Modifier.fillMaxWidth()
.height(48.dp)
.clip(CircleShape)
Expand All @@ -52,20 +64,14 @@ fun OverviewError(
.clip(RoundedCornerShape(24.dp))
.background(MaterialTheme.colorScheme.surfaceContainerLowest)
.padding(16.dp)
) {
CompositionLocalProvider(
LocalTextStyle provides MaterialTheme.typography.bodySmall.copy(
color = MaterialTheme.colorScheme.error
)
) { updatedContent() }
}
)
}
}

@Preview
@Composable
fun PreviewOverviewError() {
DesignTheme(isDarkMode = true) {
OverviewError {}
OverviewError { Text("Error occurred!...") }
}
}
8 changes: 4 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ plugins {
android {
ndkVersion = "26.1.10909125"
defaultConfig {
versionCode = 38
versionName = "1.11.0"
versionCode = 40
versionName = "1.12.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
Expand All @@ -25,8 +25,8 @@ android {
isMinifyEnabled = false
applicationIdSuffix = ".debug"
versionNameSuffix = "-DEBUG"
buildConfigField("String", "BASE_URL", "\"https://backend.peerapp.eu\"")
buildConfigField("String", "MEDIA_URL", "\"https://media.peerapp.eu\"")
buildConfigField("String", "BASE_URL", "\"https://getpeer.eu\"")
buildConfigField("String", "MEDIA_URL", "\"https://media.getpeer.eu\"")
buildConfigField("boolean", "USE_SYSTEM_THEME", "false")
buildConfigField("String","PRIVACY_POLICY_URL","\"https://www.freeprivacypolicy.com/live/02865c3a-79db-4baf-9ca1-7d91e2cf1724\"")
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import androidx.navigation.NavHostController
import eu.peernetwork.ads.ui.article.ArticleNavigator
import eu.peernetwork.blog.ui.post.PostNavigator
import eu.peernetwork.user.ui.user.UserNavigator
import eu.peernetwork.wallet.ui.transactions.TransactionsNavigator
import java.net.URLEncoder

class NavigationInteractor(
private val context: Context,
private val controller: NavHostController
) : PostNavigator, ArticleNavigator, UserNavigator {
) : PostNavigator, ArticleNavigator, UserNavigator, TransactionsNavigator {
override fun navigate(route: PostNavigator.Route) {
when(route) {
is PostNavigator.Route.Profile -> {
Expand Down Expand Up @@ -84,4 +85,28 @@ class NavigationInteractor(
}
}
}

override fun navigate(route: TransactionsNavigator.Route) {
when(route) {
is TransactionsNavigator.Route.Profile -> {
controller.navigate("profile/${route.id}") {
launchSingleTop = true
}
}
is TransactionsNavigator.Route.Search -> {
val encoded = URLEncoder.encode(route.query, "UTF-8")
controller.navigate("search/${route.type}/$encoded") {
launchSingleTop = true
}
}
is TransactionsNavigator.Route.Link -> {
val url = if (!route.url.startsWith("http")) {
"https://${route.url}"
} else {
route.url
}
context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
}
}
}
}
4 changes: 2 additions & 2 deletions app/src/main/kotlin/eu/peernetwork/app/ui/content/Content.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import eu.peernetwork.core.ui.component.UiComponentProvider
import eu.peernetwork.social.ui.connection.Connection
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate

interface Content : ApplicationProvider {
fun settingsEvent(): SettingsEvent
Expand All @@ -36,7 +36,7 @@ interface Content : ApplicationProvider {
Confirmation,
Screen,
Detail,
Service,
Rate,
Balance,
Checkout,
Boost
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import eu.peernetwork.core.ui.factory.UiBuilderFactory
import eu.peernetwork.social.ui.connection.Connection
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate

@Module
object ContentModule {
Expand Down Expand Up @@ -100,9 +100,9 @@ object ContentModule {
@Content.Scope
@Provides
@IntoMap
@UiBuilder(Service.Builder::class)
@UiBuilder(Rate.Builder::class)
fun provideServiceBuilder(component: Content.Component): UiComponent.Builder {
return Service.Builder(component)
return Rate.Builder(component)
}

@Provides
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/kotlin/eu/peernetwork/app/ui/feed/Feed.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import eu.peernetwork.core.ui.component.UiComponentProvider
import eu.peernetwork.social.ui.connection.Connection
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate

interface Feed : ApplicationProvider {
fun settingsEvent(): SettingsEvent
Expand All @@ -37,7 +37,7 @@ interface Feed : ApplicationProvider {
Timeline,
Connection,
Confirmation,
Service,
Rate,
Balance,
Checkout,
Screen {
Expand Down
6 changes: 3 additions & 3 deletions app/src/main/kotlin/eu/peernetwork/app/ui/feed/FeedModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import eu.peernetwork.core.ui.factory.UiViewModelFactory
import eu.peernetwork.social.ui.connection.Connection
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate
import javax.inject.Provider

@Module
Expand Down Expand Up @@ -129,9 +129,9 @@ object FeedModule {
@Feed.Scope
@Provides
@IntoMap
@UiBuilder(Service.Builder::class)
@UiBuilder(Rate.Builder::class)
fun provideServiceBuilder(component: Feed.Component): UiComponent.Builder {
return Service.Builder(component)
return Rate.Builder(component)
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import eu.peernetwork.app.model.Properties
import eu.peernetwork.core.ui.component.UiComponentProvider
import eu.peernetwork.core.ui.design.compose.DesignError
import eu.peernetwork.core.ui.design.material.DesignError
import eu.peernetwork.core.ui.design.luna.DesignStream
import eu.peernetwork.core.ui.design.luna.DesignStreamState
import eu.peernetwork.core.ui.extension.builder
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/kotlin/eu/peernetwork/app/ui/profile/Profile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import eu.peernetwork.social.ui.report.Report
import eu.peernetwork.user.ui.user.User
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate as WalletDashboard

interface Profile : ApplicationProvider {
fun settingsEvent(): SettingsEvent
Expand Down Expand Up @@ -49,7 +49,7 @@ interface Profile : ApplicationProvider {
Dashboard,
Boost,
Balance,
Service,
WalletDashboard,
Checkout,
Feed,
Report,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import eu.peernetwork.social.ui.report.Report
import eu.peernetwork.user.ui.user.User
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate as WalletDashboard

@Module
object ProfileModule {
Expand Down Expand Up @@ -179,9 +179,9 @@ object ProfileModule {
@Profile.Scope
@Provides
@IntoMap
@UiBuilder(Service.Builder::class)
fun provideServiceBuilder(component: Profile.Component): UiComponent.Builder {
return Service.Builder(component)
@UiBuilder(WalletDashboard.Builder::class)
fun provideWalletDashboardBuilder(component: Profile.Component): UiComponent.Builder {
return WalletDashboard.Builder(component)
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import eu.peernetwork.core.ui.design.luna.DesignStreamState
import eu.peernetwork.core.ui.theme.PeerAppRed
import eu.peernetwork.wallet.ui.R
import eu.peernetwork.wallet.ui.balance.BalanceScreen
import eu.peernetwork.wallet.ui.service.ServiceScreen
import eu.peernetwork.wallet.ui.rate.RateScreen
import javax.inject.Inject

class BalanceRenderer @Inject constructor(
Expand Down Expand Up @@ -75,12 +75,12 @@ class BalanceRenderer @Inject constructor(
}

@Composable
override fun Charges(
override fun Rate(
viewModelStoreOwner: ViewModelStoreOwner,
content: @Composable ((State<DesignStreamState<UiCharge>>, () -> Unit) -> Unit)
) {
val updatedContent by rememberUpdatedState(content)
ServiceScreen(
RateScreen(
provider = provider,
viewModelStoreOwner = viewModelStoreOwner
) { service, action ->
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/kotlin/eu/peernetwork/app/ui/search/Search.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import eu.peernetwork.social.ui.search.tag.Tag
import eu.peernetwork.social.ui.search.title.Title
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate

interface Search : ApplicationProvider {
fun settingsEvent(): SettingsEvent
Expand All @@ -42,7 +42,7 @@ interface Search : ApplicationProvider {
Connection,
Confirmation,
Boost,
Service,
Rate,
Balance,
Checkout,
Screen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import eu.peernetwork.social.ui.search.tag.Tag
import eu.peernetwork.social.ui.search.title.Title
import eu.peernetwork.wallet.ui.balance.Balance
import eu.peernetwork.wallet.ui.confirmation.Confirmation
import eu.peernetwork.wallet.ui.service.Service
import eu.peernetwork.wallet.ui.rate.Rate

@Module
object SearchModule {
Expand Down Expand Up @@ -136,9 +136,9 @@ object SearchModule {
@Search.Scope
@Provides
@IntoMap
@UiBuilder(Service.Builder::class)
@UiBuilder(Rate.Builder::class)
fun provideServiceBuilder(component: Search.Component): UiComponent.Builder {
return Service.Builder(component)
return Rate.Builder(component)
}

@Provides
Expand Down
Loading
Loading