Skip to content

Commit

Permalink
Merge branch 'PrimalHQ:main' into add-translation-swedish
Browse files Browse the repository at this point in the history
  • Loading branch information
davotoula authored Mar 11, 2024
2 parents bccb250 + 0446a0c commit 60e1ad6
Show file tree
Hide file tree
Showing 45 changed files with 1,050 additions and 868 deletions.
11 changes: 6 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ android {
applicationId = "net.primal.android"
minSdk = 26
targetSdk = 34
versionCode = 98
versionName = "0.95.4"
versionCode = 100
versionName = "0.96.1"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -214,6 +214,7 @@ dependencies {
implementation(libs.lifecycle.runtime.ktx)
implementation(libs.activity.compose)
implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.activity.ktx)
runtimeOnly(libs.androidx.appcompat)

implementation(platform(libs.compose.bom))
Expand All @@ -229,9 +230,6 @@ dependencies {

implementation(libs.androidx.material.icons.extended)
implementation(libs.androidx.emoji2.emojipicker)
implementation("com.google.guava:guava:33.0.0-android")
implementation("com.wajahatkarim:flippable:1.5.4")
implementation("org.bitcoinj:bitcoinj-core:0.16.2")

implementation(libs.navigation.material)

Expand Down Expand Up @@ -259,6 +257,7 @@ dependencies {

implementation(libs.retrofit.serialization.converter)
implementation(libs.kotlinx.serialization.json)
implementation(libs.guava)

implementation(libs.coil)
implementation(libs.coil.compose)
Expand All @@ -267,9 +266,11 @@ dependencies {
implementation(libs.telephoto.zoomable.image.coil)

implementation(libs.lottie.compose)
implementation(libs.flippable)

implementation(libs.timber)

implementation(libs.bitcoinj.core)
implementation(libs.secp256k1.kmp.jvm)
implementation(libs.secp256k1.kmp.jni.android)
testImplementation(libs.secp256k1.kmp.jni.jvm)
Expand Down
10 changes: 3 additions & 7 deletions app/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
<ID>CyclomaticComplexMethod:CreateTransactionScreen.kt$@ExperimentalComposeUiApi @ExperimentalMaterial3Api @Composable fun CreateTransactionScreen( state: CreateTransactionContract.UiState, eventPublisher: (CreateTransactionContract.UiEvent) -&gt; Unit, onClose: () -&gt; Unit, )</ID>
<ID>CyclomaticComplexMethod:FeedLazyColumn.kt$@ExperimentalMaterial3Api @ExperimentalFoundationApi @Composable fun FeedLazyColumn( pagingItems: LazyPagingItems&lt;FeedPostUi&gt;, contentPadding: PaddingValues, listState: LazyListState, zappingState: ZappingState, onPostClick: (String) -&gt; Unit, onProfileClick: (String) -&gt; Unit, onPostLikeClick: (FeedPostUi) -&gt; Unit, onRepostClick: (FeedPostUi) -&gt; Unit, onZapClick: (FeedPostUi, ULong?, String?) -&gt; Unit, onPostReplyClick: (String) -&gt; Unit, onPostQuoteClick: (FeedPostUi) -&gt; Unit, onHashtagClick: (String) -&gt; Unit, onMediaClick: (String, String) -&gt; Unit, onGoToWallet: () -&gt; Unit, onMuteClick: ((String) -&gt; Unit)? = null, shouldShowLoadingState: Boolean = true, shouldShowNoContentState: Boolean = true, showReplyTo: Boolean = true, header: @Composable (LazyItemScope.() -&gt; Unit)? = null, stickyHeader: @Composable (LazyItemScope.() -&gt; Unit)? = null, )</ID>
<ID>CyclomaticComplexMethod:FeedRemoteMediator.kt$FeedRemoteMediator$override suspend fun load(loadType: LoadType, state: PagingState&lt;Int, FeedPost&gt;): MediatorResult</ID>
<ID>CyclomaticComplexMethod:LoginScreen.kt$@OptIn(ExperimentalComposeUiApi::class) @Composable fun LoginContent( state: LoginContract.UiState, paddingValues: PaddingValues, onLogin: (String) -&gt; Unit, )</ID>
<ID>CyclomaticComplexMethod:MessagesRemoteMediator.kt$MessagesRemoteMediator$override suspend fun load(loadType: LoadType, state: PagingState&lt;Int, DirectMessage&gt;): MediatorResult</ID>
<ID>CyclomaticComplexMethod:NoteEditorScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun NoteEditorScreen( state: NoteEditorContract.UiState, onClose: () -&gt; Unit, eventPublisher: (UiEvent) -&gt; Unit, )</ID>
<ID>CyclomaticComplexMethod:NotificationEvents.kt$private fun ContentPrimalNotification.parseActionPostId(type: NotificationType): String?</ID>
Expand Down Expand Up @@ -41,7 +40,6 @@
<ID>LongMethod:FeedScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun FeedScreen( state: FeedContract.UiState, eventPublisher: (FeedContract.UiEvent) -&gt; Unit, onFeedsClick: () -&gt; Unit, onNewPostClick: (String?) -&gt; Unit, onPostClick: (String) -&gt; Unit, onPostReplyClick: (String) -&gt; Unit, onProfileClick: (String) -&gt; Unit, onHashtagClick: (String) -&gt; Unit, onMediaClick: (String, String) -&gt; Unit, onGoToWallet: () -&gt; Unit, onPrimaryDestinationChanged: (PrimalTopLevelDestination) -&gt; Unit, onDrawerDestinationClick: (DrawerScreenDestination) -&gt; Unit, )</ID>
<ID>LongMethod:FeedsSettingsScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun FeedsSettingsScreen( state: FeedsSettingsContract.UiState, eventPublisher: (FeedsSettingsContract.UiEvent) -&gt; Unit, onClose: () -&gt; Unit, )</ID>
<ID>LongMethod:FollowRecommendedAccountsStep.kt$@OptIn(ExperimentalFoundationApi::class) @Composable fun FollowRecommendedAccountsStep( state: CreateAccountContract.UiState, eventPublisher: (CreateAccountContract.UiEvent) -&gt; Unit, )</ID>
<ID>LongMethod:LoginScreen.kt$@OptIn(ExperimentalComposeUiApi::class) @Composable fun LoginContent( state: LoginContract.UiState, paddingValues: PaddingValues, onLogin: (String) -&gt; Unit, )</ID>
<ID>LongMethod:MessageConversationListScreen.kt$@Composable private fun MessagesTabs( relation: ConversationRelation, onFollowsTabClick: () -&gt; Unit, onOtherTabClick: () -&gt; Unit, onMarkAllRead: () -&gt; Unit, )</ID>
<ID>LongMethod:NoteDropdownMenu.kt$@Composable fun NoteDropdownMenuIcon( modifier: Modifier, noteId: String, noteContent: String, noteRawData: String, authorId: String, onMuteUserClick: () -&gt; Unit, )</ID>
<ID>LongMethod:NoteEditorScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun NoteEditorScreen( state: NoteEditorContract.UiState, onClose: () -&gt; Unit, eventPublisher: (UiEvent) -&gt; Unit, )</ID>
Expand All @@ -64,12 +62,12 @@
<ID>LongMethod:ThreadScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun ThreadScreen( state: ThreadContract.UiState, onClose: () -&gt; Unit, onPostClick: (String) -&gt; Unit, onPostReplyClick: (String) -&gt; Unit, onPostQuoteClick: (String) -&gt; Unit, onProfileClick: (String) -&gt; Unit, onHashtagClick: (String) -&gt; Unit, onMediaClick: (String, String) -&gt; Unit, onGoToWallet: () -&gt; Unit, onReplyInNoteEditor: (String, Uri?, String) -&gt; Unit, eventPublisher: (ThreadContract.UiEvent) -&gt; Unit, )</ID>
<ID>LongMethod:TransactionEditor.kt$@Composable private fun TransactionHeaderColumn( modifier: Modifier, uiMode: UiDensityMode, state: CreateTransactionContract.UiState, keyboardVisible: Boolean, onAmountClick: () -&gt; Unit, )</ID>
<ID>LongMethod:TransactionEditor.kt$@ExperimentalMaterial3Api @ExperimentalComposeUiApi @Composable fun TransactionEditor( modifier: Modifier, state: CreateTransactionContract.UiState, paddingValues: PaddingValues, eventPublisher: (CreateTransactionContract.UiEvent) -&gt; Unit, onCancelClick: () -&gt; Unit, )</ID>
<ID>LongMethod:WalletActivationScreen.kt$@ExperimentalComposeUiApi @Composable private fun WalletCodeActivationInput( working: Boolean, error: Throwable?, email: String, onCodeChanged: () -&gt; Unit, onCodeConfirmation: (String) -&gt; Unit, isKeyboardVisible: Boolean, )</ID>
<ID>LongMethod:WalletActivationScreen.kt$@Suppress("MagicNumber") @OptIn(ExperimentalMaterial3Api::class) @ExperimentalComposeUiApi @Composable private fun WalletActivationDataInput( data: WalletActivationData, working: Boolean, error: Throwable?, onErrorDismiss: () -&gt; Unit, onDataChanged: (WalletActivationData) -&gt; Unit, onActivationCodeRequest: (WalletActivationData) -&gt; Unit, )</ID>
<ID>LongMethod:WalletActivationScreen.kt$@ExperimentalComposeUiApi @Composable private fun WalletCodeActivationInput( modifier: Modifier = Modifier, working: Boolean, error: Throwable?, email: String, onCodeChanged: () -&gt; Unit, onCodeConfirmation: (String) -&gt; Unit, isKeyboardVisible: Boolean, )</ID>
<ID>LongMethod:WalletActivationScreen.kt$@ExperimentalMaterial3Api @ExperimentalComposeUiApi @Composable fun WalletActivationScreen( uiState: WalletActivationContract.UiState, eventPublisher: (UiEvent) -&gt; Unit, onClose: () -&gt; Unit, )</ID>
<ID>LongMethod:WalletActivationScreen.kt$@Suppress("MagicNumber") @OptIn(ExperimentalMaterial3Api::class) @ExperimentalComposeUiApi @Composable private fun WalletActivationDataInput( modifier: Modifier = Modifier, data: WalletActivationData, working: Boolean, error: Throwable?, onErrorDismiss: () -&gt; Unit, onDataChanged: (WalletActivationData) -&gt; Unit, onActivationCodeRequest: (WalletActivationData) -&gt; Unit, )</ID>
<ID>LongMethod:WalletDashboardScreen.kt$@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable fun WalletDashboardScreen( state: WalletDashboardContract.UiState, onPrimaryDestinationChanged: (PrimalTopLevelDestination) -&gt; Unit, onDrawerDestinationClick: (DrawerScreenDestination) -&gt; Unit, onWalletActivateClick: () -&gt; Unit, onProfileClick: (String) -&gt; Unit, onTransactionClick: (String) -&gt; Unit, onSendClick: () -&gt; Unit, onScanClick: () -&gt; Unit, onReceiveClick: () -&gt; Unit, eventPublisher: (UiEvent) -&gt; Unit, )</ID>
<ID>LongMethod:WalletSettingsScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun WalletSettingsScreen( state: WalletSettingsContract.UiState, onClose: () -&gt; Unit, onEditProfileClick: () -&gt; Unit, eventPublisher: (UiEvent) -&gt; Unit, )</ID>
<ID>LongMethod:WelcomeScreen.kt$@Composable fun WelcomeScreen(onSignInClick: () -&gt; Unit, onCreateAccountClick: () -&gt; Unit)</ID>
<ID>LongMethod:ZapBottomSheet.kt$@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) @Composable fun ZapBottomSheet( receiverName: String, zappingState: ZappingState, onDismissRequest: () -&gt; Unit, onZap: (Long, String?) -&gt; Unit, )</ID>
<ID>LongMethod:ZapSettingsScreen.kt$@OptIn(ExperimentalMaterial3Api::class) @Composable fun ZapSettingsScreen( uiState: ZapSettingsContract.UiState, onClose: () -&gt; Unit, eventPublisher: (ZapSettingsContract.UiEvent) -&gt; Unit, )</ID>
<ID>LongParameterList:CreateAccountViewModel.kt$CreateAccountViewModel$( private val dispatcherProvider: CoroutineDispatcherProvider, private val authRepository: AuthRepository, private val settingsRepository: SettingsRepository, private val profileRepository: ProfileRepository, private val userRepository: UserRepository, private val recommendedFollowsApi: RecommendedFollowsApi, private val relayRepository: RelayRepository, )</ID>
<ID>LongParameterList:ExploreFeedViewModel.kt$ExploreFeedViewModel$( savedStateHandle: SavedStateHandle, private val dispatcherProvider: CoroutineDispatcherProvider, private val activeAccountStore: ActiveAccountStore, private val feedRepository: FeedRepository, private val postRepository: PostRepository, private val profileRepository: ProfileRepository, private val zapHandler: ZapHandler, private val settingsRepository: SettingsRepository, private val mutedUserRepository: MutedUserRepository, )</ID>
Expand Down Expand Up @@ -100,7 +98,6 @@
<ID>MagicNumber:FeedNoteList.kt$30</ID>
<ID>MagicNumber:FeedNoteList.kt$5</ID>
<ID>MagicNumber:FeedViewModel.kt$FeedViewModel$3</ID>
<ID>MagicNumber:Insets.kt$0.5f</ID>
<ID>MagicNumber:IntUtils.kt$10</ID>
<ID>MagicNumber:IntUtils.kt$1000</ID>
<ID>MagicNumber:IntUtils.kt$1000.0</ID>
Expand Down Expand Up @@ -131,7 +128,6 @@
<ID>MagicNumber:Timestamps.kt$7</ID>
<ID>MagicNumber:ValidationUtils.kt$32</ID>
<ID>MagicNumber:WalletDashboardScreen.kt$0.42f</ID>
<ID>MagicNumber:ZapBottomSheet.kt$3</ID>
<ID>MatchingDeclarationName:__PrimalIcons.kt$PrimalIcons</ID>
<ID>NestedBlockDepth:FeedRemoteMediator.kt$FeedRemoteMediator$override suspend fun load(loadType: LoadType, state: PagingState&lt;Int, FeedPost&gt;): MediatorResult</ID>
<ID>ReturnCount:FeedRemoteMediator.kt$FeedRemoteMediator$override suspend fun load(loadType: LoadType, state: PagingState&lt;Int, FeedPost&gt;): MediatorResult</ID>
Expand Down
10 changes: 4 additions & 6 deletions app/src/main/github/release-notes/github.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
## Changes
- Stability improvements across the app.
- Improved btc address validation.
- Improved ui performance when uploading photos.
- Improved edge-cases handling of Google's in-app purchase flow.
- Implemented opening note1 and npub1 directly from search query.
- Implemented fixed top bar on threads screens.
- New welcome screen;
- New login screen;
- App now follows dark theme system settings until user manually changes theme;
- Implemented new api for edge to edge screen support - improved screen transitions with full screen colors;
17 changes: 3 additions & 14 deletions app/src/main/kotlin/net/primal/android/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,17 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material.ripple.LocalRippleTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.graphics.toArgb
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch
import net.primal.android.core.compose.ApplyEdgeToEdge
import net.primal.android.navigation.PrimalAppNavigation
import net.primal.android.theme.PrimalRippleTheme
import net.primal.android.theme.PrimalTheme
Expand All @@ -34,12 +32,11 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen()
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
observeThemeChanges()

setContent {
val userTheme = themeStore.userThemeState.collectAsState()
val primalTheme = userTheme.value ?: initDefaultTheme()
val primalTheme = userTheme.value ?: defaultPrimalTheme()

PrimalTheme(
primalTheme = primalTheme,
Expand All @@ -48,21 +45,13 @@ class MainActivity : ComponentActivity() {
LocalPrimalTheme provides primalTheme,
LocalRippleTheme provides PrimalRippleTheme,
) {
ApplyEdgeToEdge()
PrimalAppNavigation()
}
}
}
}

@Composable
private fun initDefaultTheme(): PrimalTheme {
val defaultTheme = defaultPrimalTheme()
LaunchedEffect(Unit) {
themeStore.setUserTheme(theme = defaultTheme.themeName)
}
return defaultTheme
}

private fun observeThemeChanges() =
lifecycleScope.launch {
themeStore.userThemeState
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.primal.android.auth.compose

import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.widthIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import net.primal.android.core.compose.button.PrimalLoadingButton

@Composable
fun OnboardingButton(
modifier: Modifier = Modifier,
text: String,
onClick: () -> Unit,
enabled: Boolean = true,
loading: Boolean = false,
) {
PrimalLoadingButton(
modifier = modifier
.widthIn(240.dp, MAX_COMPONENT_WIDTH.dp)
.fillMaxWidth(),
containerColor = Color.Black,
disabledContainerColor = Color.Black.copy(alpha = 0.20f),
contentColor = Color.White,
enabled = enabled,
loading = loading,
onClick = onClick,
text = text,
)
}
5 changes: 5 additions & 0 deletions app/src/main/kotlin/net/primal/android/auth/compose/Sizes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package net.primal.android.auth.compose

const val MAX_COMPONENT_WIDTH = 320
const val ONE_HALF = 0.5f
const val TWO_FIFTHS = 0.4f
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package net.primal.android.auth.login

import net.primal.android.core.compose.profile.model.ProfileDetailsUi

interface LoginContract {

data class UiState(
val loading: Boolean = false,
val loginInput: String = "",
val profileDetails: ProfileDetailsUi? = null,
val fetchingProfileDetails: Boolean = false,
val error: LoginError? = null,
) {
sealed class LoginError {
Expand All @@ -12,7 +17,8 @@ interface LoginContract {
}

sealed class UiEvent {
data class LoginEvent(val nostrKey: String) : UiEvent()
data object LoginRequestEvent : UiEvent()
data class UpdateLoginInput(val newInput: String) : UiEvent()
}

sealed class SideEffect {
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/kotlin/net/primal/android/auth/login/LoginHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net.primal.android.auth.login

import javax.inject.Inject
import net.primal.android.auth.AuthRepository
import net.primal.android.feed.repository.FeedRepository
import net.primal.android.settings.muted.repository.MutedUserRepository
import net.primal.android.settings.repository.SettingsRepository
import net.primal.android.user.repository.UserRepository

class LoginHandler @Inject constructor(
private val settingsRepository: SettingsRepository,
private val authRepository: AuthRepository,
private val userRepository: UserRepository,
private val mutedUserRepository: MutedUserRepository,
private val feedRepository: FeedRepository,
) {

suspend fun loginAndReturnDefaultFeed(nostrKey: String): String {
val userId = authRepository.login(nostrKey = nostrKey)
userRepository.fetchAndUpdateUserAccount(userId = userId)
settingsRepository.fetchAndPersistAppSettings(userId = userId)
mutedUserRepository.fetchAndPersistMuteList(userId = userId)
val defaultFeed = feedRepository.defaultFeed()
return defaultFeed?.directive ?: userId
}
}
Loading

0 comments on commit 60e1ad6

Please sign in to comment.