Moves the account import idea to a route after login
This commit is contained in:
@@ -97,6 +97,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.list.ListOfPeopleList
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.list.metadata.FollowPackMetadataScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.list.metadata.PeopleListMetadataScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.lists.memberEdit.FollowListAndPackAndUserScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.newUser.ImportFollowListScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.NotificationScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.publicMessages.NewPublicMessageScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.privacy.PrivacyOptionsScreen
|
||||
@@ -177,6 +178,8 @@ fun AppNavigation(
|
||||
composableFromEnd<Route.Settings> { SettingsScreen(accountViewModel, nav) }
|
||||
composableFromEnd<Route.UserSettings> { UserSettingsScreen(accountViewModel, nav) }
|
||||
composableFromEnd<Route.ReactionsSettings> { ReactionsSettingsScreen(accountViewModel, nav) }
|
||||
composableFromEnd<Route.ImportFollows> { ImportFollowListScreen(accountViewModel, nav) }
|
||||
|
||||
composableFromEndArgs<Route.Nip47NWCSetup> { NIP47SetupScreen(accountViewModel, nav, it.nip47) }
|
||||
composableFromEndArgs<Route.UpdateZapAmount> { UpdateZapAmountScreen(accountViewModel, nav, it.nip47) }
|
||||
composableFromEndArgs<Route.EditRelays> { AllRelayListScreen(accountViewModel, nav) }
|
||||
|
||||
@@ -53,6 +53,8 @@ sealed class Route {
|
||||
|
||||
@Serializable object BookmarkGroups : Route()
|
||||
|
||||
@Serializable object ImportFollows : Route()
|
||||
|
||||
@Serializable data class BookmarkGroupView(
|
||||
val dTag: String,
|
||||
val bookmarkType: BookmarkType,
|
||||
|
||||
@@ -29,27 +29,16 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.service.followimport.Kind3EventData
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.LoggedInPage
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedOff.LoginOrSignupScreen
|
||||
import com.vitorpamplona.amethyst.ui.screen.signup.ImportFollowListSection
|
||||
import com.vitorpamplona.amethyst.ui.screen.signup.ImportFollowListViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun AccountScreen(accountSessionManager: AccountSessionManager) {
|
||||
@@ -75,11 +64,7 @@ fun AccountScreen(accountSessionManager: AccountSessionManager) {
|
||||
}
|
||||
|
||||
is AccountState.LoggedIn -> {
|
||||
if (state.isNewAccount) {
|
||||
NewAccountImportFollowsSetup(state.account, accountSessionManager)
|
||||
} else {
|
||||
LoggedInSetup(state, accountSessionManager)
|
||||
}
|
||||
LoggedInSetup(state, accountSessionManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,80 +124,3 @@ fun LoggedInSetup(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NewAccountImportFollowsSetup(
|
||||
account: Account,
|
||||
accountSessionManager: AccountSessionManager,
|
||||
) {
|
||||
val importViewModel: ImportFollowListViewModel = viewModel()
|
||||
|
||||
LaunchedEffect(account) {
|
||||
importViewModel.configure(
|
||||
fetchEvent = { kind, author, limit, onEvent ->
|
||||
val filter =
|
||||
Filter(
|
||||
kinds = listOf(kind),
|
||||
authors = listOf(author),
|
||||
limit = limit,
|
||||
)
|
||||
val relayUrls =
|
||||
listOf(
|
||||
"wss://relay.damus.io",
|
||||
"wss://nos.lol",
|
||||
"wss://relay.nostr.band",
|
||||
"wss://purplepag.es",
|
||||
)
|
||||
val filterMap =
|
||||
relayUrls.associate { url ->
|
||||
RelayUrlNormalizer.normalize(url) to listOf(filter)
|
||||
}
|
||||
val listener =
|
||||
object : com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener {
|
||||
override fun onEvent(
|
||||
event: com.vitorpamplona.quartz.nip01Core.core.Event,
|
||||
isLive: Boolean,
|
||||
relay: com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
if (event is ContactListEvent) {
|
||||
onEvent(
|
||||
Kind3EventData(
|
||||
pTags =
|
||||
event.tags
|
||||
.filter { it.size >= 2 && it[0] == "p" }
|
||||
.map { it.drop(1) },
|
||||
createdAt = event.createdAt,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
val subId =
|
||||
com.vitorpamplona.quartz.nip01Core.relay.client.single
|
||||
.newSubId()
|
||||
Amethyst.instance.client.openReqSubscription(subId, filterMap, listener)
|
||||
AutoCloseable { Amethyst.instance.client.close(subId) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
) {
|
||||
ImportFollowListSection(
|
||||
onFollowsApplied = { entries ->
|
||||
withContext(Dispatchers.IO) {
|
||||
for (entry in entries) {
|
||||
val user = account.cache.getOrCreateUser(entry.pubkeyHex)
|
||||
account.follow(user)
|
||||
}
|
||||
}
|
||||
},
|
||||
onSkip = { accountSessionManager.finishNewAccountSetup() },
|
||||
onDone = { accountSessionManager.finishNewAccountSetup() },
|
||||
viewModel = importViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
-13
@@ -87,7 +87,6 @@ sealed class AccountState {
|
||||
class LoggedIn(
|
||||
val account: Account,
|
||||
var route: Route? = null,
|
||||
val isNewAccount: Boolean = false,
|
||||
) : AccountState()
|
||||
}
|
||||
|
||||
@@ -184,20 +183,10 @@ class AccountSessionManager(
|
||||
fun startUI(
|
||||
accountSettings: AccountSettings,
|
||||
route: Route? = null,
|
||||
isNewAccount: Boolean = false,
|
||||
) {
|
||||
val account = accountsCache.loadAccount(accountSettings)
|
||||
_accountContent.update {
|
||||
AccountState.LoggedIn(account, route, isNewAccount = isNewAccount)
|
||||
}
|
||||
}
|
||||
|
||||
fun finishNewAccountSetup() {
|
||||
val current = _accountContent.value
|
||||
if (current is AccountState.LoggedIn && current.isNewAccount) {
|
||||
_accountContent.update {
|
||||
AccountState.LoggedIn(current.account, current.route, isNewAccount = false)
|
||||
}
|
||||
AccountState.LoggedIn(account, route)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +278,7 @@ class AccountSessionManager(
|
||||
|
||||
localPreferences.setDefaultAccount(accountSettings)
|
||||
|
||||
startUI(accountSettings, isNewAccount = true)
|
||||
startUI(accountSettings, route = Route.ImportFollows)
|
||||
|
||||
scope.launch(Dispatchers.IO) {
|
||||
delay(2000) // waits for the new user to connect to the new relays.
|
||||
|
||||
+83
-60
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.signup
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.newUser
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
@@ -50,8 +50,6 @@ import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.PersonAdd
|
||||
import androidx.compose.material.icons.outlined.Circle
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
@@ -59,6 +57,7 @@ import androidx.compose.material3.Icon
|
||||
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.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -72,20 +71,59 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.service.followimport.FollowEntry
|
||||
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
|
||||
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarExtensibleWithBackButton
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
// ── Public entry points ────────────────────────────────────────────────
|
||||
@Composable
|
||||
fun ImportFollowListScreen(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val importViewModel: ImportFollowListViewModel = viewModel()
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
topBar = {
|
||||
TopBarExtensibleWithBackButton(
|
||||
title = {},
|
||||
popBack = nav::popBack,
|
||||
)
|
||||
},
|
||||
) { padding ->
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(padding),
|
||||
) {
|
||||
ImportFollowListSection(
|
||||
onFollowsApplied = { entries ->
|
||||
withContext(Dispatchers.IO) {
|
||||
for (entry in entries) {
|
||||
val user = accountViewModel.getOrCreateUser(entry.pubkeyHex)
|
||||
accountViewModel.follow(user)
|
||||
}
|
||||
}
|
||||
},
|
||||
onSkip = nav::popBack,
|
||||
onDone = nav::popBack,
|
||||
viewModel = importViewModel,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeddable section for the signup wizard.
|
||||
*/
|
||||
@Composable
|
||||
fun ImportFollowListSection(
|
||||
onFollowsApplied: suspend (List<FollowEntry>) -> Unit,
|
||||
@@ -117,11 +155,11 @@ fun ImportFollowListSection(
|
||||
}
|
||||
|
||||
is ImportFollowState.Resolving -> {
|
||||
LoadingIndicator("Resolving ${s.identifier}…")
|
||||
LoadingIndicator(stringResource(R.string.resolving, s.identifier))
|
||||
}
|
||||
|
||||
is ImportFollowState.Fetching -> {
|
||||
LoadingIndicator("Fetching follow list…")
|
||||
LoadingIndicator(stringResource(R.string.fetching_follow_list))
|
||||
}
|
||||
|
||||
is ImportFollowState.Preview -> {
|
||||
@@ -133,7 +171,7 @@ fun ImportFollowListSection(
|
||||
}
|
||||
|
||||
is ImportFollowState.Applying -> {
|
||||
LoadingIndicator("Following ${s.count} accounts…")
|
||||
LoadingIndicator(stringResource(R.string.following_accounts, s.count))
|
||||
}
|
||||
|
||||
is ImportFollowState.Done -> {
|
||||
@@ -151,30 +189,6 @@ fun ImportFollowListSection(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standalone dialog for post-signup use (settings / profile screen).
|
||||
*/
|
||||
@Composable
|
||||
fun ImportFollowListDialog(
|
||||
onDismiss: () -> Unit,
|
||||
onFollowsApplied: suspend (List<FollowEntry>) -> Unit,
|
||||
) {
|
||||
Dialog(onDismissRequest = onDismiss) {
|
||||
Card(
|
||||
modifier = Modifier.fillMaxWidth().padding(8.dp),
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 8.dp),
|
||||
) {
|
||||
ImportFollowListSection(
|
||||
onFollowsApplied = onFollowsApplied,
|
||||
onSkip = onDismiss,
|
||||
onDone = onDismiss,
|
||||
modifier = Modifier.height(600.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── Internal composables ───────────────────────────────────────────────
|
||||
|
||||
@Composable
|
||||
@@ -189,14 +203,14 @@ private fun ImportHeader() {
|
||||
)
|
||||
Spacer(Modifier.width(10.dp))
|
||||
Text(
|
||||
"Import Follow List",
|
||||
stringResource(R.string.import_follow_list),
|
||||
style = MaterialTheme.typography.headlineSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
"Start with a great feed by following the same people as someone you trust.",
|
||||
stringResource(R.string.start_with_a_great_feed_by_following_the_same_people_as_someone_you_trust),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -215,15 +229,15 @@ private fun InputSection(
|
||||
OutlinedTextField(
|
||||
value = identifier,
|
||||
onValueChange = { identifier = it },
|
||||
label = { Text("Profile to import from") },
|
||||
placeholder = { Text("npub1…, alice@example.com, or example.bit") },
|
||||
label = { Text(stringResource(R.string.profile_to_import_from)) },
|
||||
placeholder = { Text(stringResource(R.string.name_search_npub1_alice_example_com)) },
|
||||
singleLine = true,
|
||||
enabled = enabled,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
supportingText = {
|
||||
Text(
|
||||
"Supports npub, NIP-05, hex, and Namecoin (.bit / d/ / id/)",
|
||||
stringResource(R.string.supports_npub_nip_05_hex_and_namecoin_bit_d_id),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
||||
)
|
||||
@@ -244,7 +258,7 @@ private fun InputSection(
|
||||
enabled = enabled && identifier.isNotBlank(),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
) { Text("Look Up Follow List") }
|
||||
) { Text(stringResource(R.string.look_up_follow_list)) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,16 +267,14 @@ private fun IdleHint() {
|
||||
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.padding(24.dp)) {
|
||||
Text(
|
||||
"Tip",
|
||||
stringResource(R.string.tip),
|
||||
style = MaterialTheme.typography.labelLarge,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Spacer(Modifier.height(4.dp))
|
||||
Text(
|
||||
"Enter the profile of a friend or community leader. " +
|
||||
"You can use their npub, NIP-05 address, or a Namecoin name " +
|
||||
"like alice@example.bit or id/alice for blockchain-verified identities.",
|
||||
stringResource(R.string.import_follows_tips),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -303,17 +315,19 @@ private fun PreviewList(
|
||||
|
||||
// Summary
|
||||
Row(
|
||||
Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 4.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Text(
|
||||
"${state.totalCount} accounts found",
|
||||
stringResource(R.string.accounts_found, state.totalCount),
|
||||
style = MaterialTheme.typography.titleSmall,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Text(
|
||||
"${state.selectedCount} selected",
|
||||
stringResource(R.string.selected, state.selectedCount),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
@@ -321,7 +335,10 @@ private fun PreviewList(
|
||||
|
||||
// Select all
|
||||
Row(
|
||||
Modifier.fillMaxWidth().clickable { onSelectAll(state.selectedCount < state.totalCount) }.padding(vertical = 8.dp),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onSelectAll(state.selectedCount < state.totalCount) }
|
||||
.padding(vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Checkbox(
|
||||
@@ -362,7 +379,7 @@ private fun NamecoinResolvedBadge(namecoinSource: String) {
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Column {
|
||||
Text(
|
||||
"Resolved via Namecoin",
|
||||
stringResource(R.string.resolved_via_namecoin),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = Color(0xFF4A90D9),
|
||||
@@ -383,7 +400,10 @@ private fun FollowEntryRow(
|
||||
onToggle: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth().clickable(onClick = onToggle).padding(vertical = 6.dp, horizontal = 4.dp),
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onToggle)
|
||||
.padding(vertical = 6.dp, horizontal = 4.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
@@ -399,7 +419,10 @@ private fun FollowEntryRow(
|
||||
)
|
||||
Spacer(Modifier.width(10.dp))
|
||||
Box(
|
||||
Modifier.size(32.dp).clip(CircleShape).background(MaterialTheme.colorScheme.primaryContainer),
|
||||
Modifier
|
||||
.size(32.dp)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.primaryContainer),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
@@ -455,13 +478,13 @@ private fun DoneMessage(
|
||||
)
|
||||
Spacer(Modifier.height(12.dp))
|
||||
Text(
|
||||
"Now following $count accounts",
|
||||
stringResource(R.string.now_following_accounts, count),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
Spacer(Modifier.height(6.dp))
|
||||
Text(
|
||||
"Your feed is ready.",
|
||||
stringResource(R.string.your_feed_is_ready),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
@@ -499,14 +522,14 @@ private fun BottomActions(
|
||||
when (state) {
|
||||
is ImportFollowState.Preview -> {
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
TextButton(onClick = onSkip) { Text("Skip") }
|
||||
TextButton(onClick = onSkip) { Text(stringResource(R.string.skip)) }
|
||||
Row {
|
||||
OutlinedButton(onClick = onSearchAnother, shape = RoundedCornerShape(12.dp)) {
|
||||
Text("Search Another")
|
||||
Text(stringResource(R.string.search_another))
|
||||
}
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Button(onClick = onApply, enabled = state.selectedCount > 0, shape = RoundedCornerShape(12.dp)) {
|
||||
Text("Follow ${state.selectedCount} accounts")
|
||||
Text(stringResource(R.string.follow_accounts, state.selectedCount))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,15 +538,15 @@ private fun BottomActions(
|
||||
is ImportFollowState.Done -> {
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
OutlinedButton(onClick = onSearchAnother, shape = RoundedCornerShape(12.dp)) {
|
||||
Text("Import More")
|
||||
Text(stringResource(R.string.import_more))
|
||||
}
|
||||
Button(onClick = onDone, shape = RoundedCornerShape(12.dp)) { Text("Continue") }
|
||||
Button(onClick = onDone, shape = RoundedCornerShape(12.dp)) { Text(stringResource(R.string.continue_txt)) }
|
||||
}
|
||||
}
|
||||
|
||||
is ImportFollowState.Idle, is ImportFollowState.Error -> {
|
||||
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) {
|
||||
TextButton(onClick = onSkip) { Text("Skip for now") }
|
||||
TextButton(onClick = onSkip) { Text(stringResource(R.string.skip_for_now)) }
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.signup
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.newUser
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.lifecycle.ViewModel
|
||||
@@ -1229,6 +1229,7 @@
|
||||
<string name="route_video">Shorts</string>
|
||||
<string name="route_chess">Chess</string>
|
||||
<string name="route_security_filters">Security Filters</string>
|
||||
<string name="route_import_follows">Import Follows</string>
|
||||
|
||||
<string name="new_post">New Post</string>
|
||||
<string name="new_short">New Shorts: images or videos</string>
|
||||
@@ -1715,4 +1716,26 @@
|
||||
<string name="kind_voice_msg">Voice Msg</string>
|
||||
<string name="kind_voice_reply">Voice Reply</string>
|
||||
<string name="kind_wiki">Wiki</string>
|
||||
<string name="start_with_a_great_feed_by_following_the_same_people_as_someone_you_trust">Start with a great feed by following the same people as someone you trust.</string>
|
||||
<string name="import_follow_list">Import Follow List</string>
|
||||
<string name="profile_to_import_from">Profile to import from</string>
|
||||
<string name="name_search_npub1_alice_example_com">name search, npub1…, alice@example.com</string>
|
||||
<string name="supports_npub_nip_05_hex_and_namecoin_bit_d_id">Supports npub, NIP-05, hex, and Namecoin (.bit / d/ / id/)</string>
|
||||
<string name="look_up_follow_list">Look Up Follow List</string>
|
||||
<string name="tip">Tip</string>
|
||||
<string name="accounts_found">%1$d accounts found</string>
|
||||
<string name="selected">%1$d selected</string>
|
||||
<string name="resolved_via_namecoin">Resolved via Namecoin</string>
|
||||
<string name="now_following_accounts">Now following %1$d accounts</string>
|
||||
<string name="your_feed_is_ready">Your feed is ready.</string>
|
||||
<string name="skip">Skip</string>
|
||||
<string name="search_another">Search Another</string>
|
||||
<string name="follow_accounts">Follow %1$d accounts</string>
|
||||
<string name="import_more">Import More</string>
|
||||
<string name="continue_txt">Continue</string>
|
||||
<string name="skip_for_now">Skip for now</string>
|
||||
<string name="resolving">Resolving %1$s…</string>
|
||||
<string name="fetching_follow_list">Fetching follow list…</string>
|
||||
<string name="following_accounts">Following %1$d accounts…</string>
|
||||
<string name="import_follows_tips">"Enter the profile of a friend or community leader. You can use their npub, NIP-05 address, or a Namecoin name like alice@example.bit or id/alice for blockchain-verified identities."</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user