Skip to content

Commit e029e2e

Browse files
committed
style(fc/profile): add transitions between linked profile states
Signed-off-by: Brandon McAnsh <[email protected]>
1 parent ce8f805 commit e029e2e

File tree

1 file changed

+125
-75
lines changed

1 file changed

+125
-75
lines changed

flipchatApp/src/main/kotlin/xyz/flipchat/app/features/profile/ProfileScreen.kt

Lines changed: 125 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ package xyz.flipchat.app.features.profile
33
import android.app.Activity
44
import android.content.Context
55
import android.os.Parcelable
6+
import androidx.compose.animation.AnimatedVisibility
7+
import androidx.compose.animation.Crossfade
8+
import androidx.compose.animation.core.tween
9+
import androidx.compose.animation.fadeIn
10+
import androidx.compose.animation.fadeOut
11+
import androidx.compose.animation.shrinkVertically
12+
import androidx.compose.animation.slideInVertically
13+
import androidx.compose.animation.slideOutVertically
614
import androidx.compose.foundation.Image
715
import androidx.compose.foundation.layout.Column
816
import androidx.compose.foundation.layout.Spacer
@@ -184,86 +192,128 @@ private fun ProfileContent(
184192
}
185193
)
186194

187-
if (state.linkedSocialProfile == null) {
188-
Text(
189-
text = state.displayName,
190-
style = CodeTheme.typography.textLarge,
191-
color = CodeTheme.colors.textMain
192-
)
193-
if (state.canConnectAccount && state.isSelf) {
194-
val xOAuthLauncher = rememberLauncherForOAuth(OAuthProvider.X) { accessToken ->
195-
println("x access token=$accessToken")
196-
dispatchEvent(ProfileViewModel.Event.LinkXAccount(accessToken))
197-
}
195+
// Crossfade between no-account and linked-account states
196+
Crossfade(
197+
targetState = state.linkedSocialProfile != null,
198+
animationSpec = tween(durationMillis = 300)
199+
) { isLinked ->
200+
if (!isLinked) {
201+
// No account linked
202+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
203+
Text(
204+
text = state.displayName,
205+
style = CodeTheme.typography.textLarge,
206+
color = CodeTheme.colors.textMain
207+
)
208+
if (state.canConnectAccount && state.isSelf) {
209+
val xOAuthLauncher = rememberLauncherForOAuth(OAuthProvider.X) { accessToken ->
210+
println("x access token=$accessToken")
211+
dispatchEvent(ProfileViewModel.Event.LinkXAccount(accessToken))
212+
}
198213

199-
CodeButton(
200-
modifier = Modifier.fillMaxWidth()
201-
.padding(top = CodeTheme.dimens.grid.x12)
202-
.padding(horizontal = CodeTheme.dimens.inset),
203-
buttonState = ButtonState.Filled,
204-
onClick = { xOAuthLauncher.launch(OAuthProvider.X.launchIntent(context)) },
205-
content = {
206-
Image(
207-
painter = rememberVectorPainter(image = ImageVector.vectorResource(id = R.drawable.ic_twitter_x)),
208-
colorFilter = ColorFilter.tint(Color.Black),
209-
contentDescription = null
210-
)
211-
Spacer(Modifier.width(CodeTheme.dimens.grid.x2))
212-
Text(
213-
text = stringResource(R.string.action_connectYourAccount),
214-
)
214+
AnimatedVisibility(
215+
visible = true,
216+
enter = fadeIn() + slideInVertically(initialOffsetY = { it / 2 }),
217+
exit = fadeOut() + slideOutVertically(targetOffsetY = { it / 2 })
218+
) {
219+
CodeButton(
220+
modifier = Modifier
221+
.fillMaxWidth()
222+
.padding(top = CodeTheme.dimens.grid.x12)
223+
.padding(horizontal = CodeTheme.dimens.inset),
224+
buttonState = ButtonState.Filled,
225+
onClick = { xOAuthLauncher.launch(OAuthProvider.X.launchIntent(context)) },
226+
content = {
227+
Image(
228+
painter = rememberVectorPainter(image = ImageVector.vectorResource(id = R.drawable.ic_twitter_x)),
229+
colorFilter = ColorFilter.tint(Color.Black),
230+
contentDescription = null
231+
)
232+
Spacer(Modifier.width(CodeTheme.dimens.grid.x2))
233+
Text(
234+
text = stringResource(R.string.action_connectYourAccount),
235+
)
236+
}
237+
)
238+
}
215239
}
216-
)
217-
}
218-
} else {
219-
SocialUserDisplay(
220-
modifier = Modifier.fillMaxWidth(),
221-
profile = state.linkedSocialProfile
222-
)
240+
}
241+
} else {
242+
// Linked account state
243+
state.linkedSocialProfile?.let { linkedProfile ->
244+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
245+
SocialUserDisplay(
246+
modifier = Modifier.fillMaxWidth(),
247+
profile = linkedProfile
248+
)
223249

224-
state.username?.let { username ->
225-
Text(
226-
modifier = Modifier.fillMaxWidth(),
227-
text = username,
228-
style = CodeTheme.typography.textSmall,
229-
color = CodeTheme.colors.textSecondary,
230-
textAlign = TextAlign.Center
231-
)
232-
}
250+
state.username?.let { username ->
251+
AnimatedVisibility(
252+
visible = true,
253+
enter = fadeIn(),
254+
exit = fadeOut() + shrinkVertically()
255+
) {
256+
Text(
257+
modifier = Modifier.fillMaxWidth(),
258+
text = username,
259+
style = CodeTheme.typography.textSmall,
260+
color = CodeTheme.colors.textSecondary,
261+
textAlign = TextAlign.Center
262+
)
263+
}
264+
}
233265

234-
when (state.linkedSocialProfile) {
235-
is SocialProfile.Unknown -> Unit
236-
is SocialProfile.X -> {
237-
Text(
238-
modifier = Modifier
239-
.fillMaxWidth()
240-
.padding(top = CodeTheme.dimens.grid.x8),
241-
text = "${state.linkedSocialProfile.followerCountFormatted} Followers",
242-
style = CodeTheme.typography.textSmall,
243-
color = CodeTheme.colors.textSecondary,
244-
textAlign = TextAlign.Center
245-
)
246-
Text(
247-
modifier = Modifier
248-
.fillMaxWidth(0.70f)
249-
.padding(top = CodeTheme.dimens.grid.x1),
250-
text = state.linkedSocialProfile.description,
251-
style = CodeTheme.typography.textSmall,
252-
color = CodeTheme.colors.textSecondary,
253-
textAlign = TextAlign.Center,
254-
)
255-
}
256-
}
266+
when (linkedProfile) {
267+
is SocialProfile.Unknown -> Unit
268+
is SocialProfile.X -> {
269+
AnimatedVisibility(
270+
visible = true,
271+
enter = fadeIn(),
272+
exit = fadeOut() + shrinkVertically()
273+
) {
274+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
275+
Text(
276+
modifier = Modifier
277+
.fillMaxWidth()
278+
.padding(top = CodeTheme.dimens.grid.x8),
279+
text = "${linkedProfile.followerCountFormatted} Followers",
280+
style = CodeTheme.typography.textSmall,
281+
color = CodeTheme.colors.textSecondary,
282+
textAlign = TextAlign.Center
283+
)
284+
Text(
285+
modifier = Modifier
286+
.fillMaxWidth(0.70f)
287+
.padding(top = CodeTheme.dimens.grid.x1),
288+
text = linkedProfile.description,
289+
style = CodeTheme.typography.textSmall,
290+
color = CodeTheme.colors.textSecondary,
291+
textAlign = TextAlign.Center,
292+
)
293+
}
294+
}
295+
}
296+
}
257297

258-
if (!isInTab) {
259-
CodeButton(
260-
modifier = Modifier.fillMaxWidth()
261-
.padding(top = CodeTheme.dimens.grid.x12)
262-
.padding(horizontal = CodeTheme.dimens.inset),
263-
buttonState = ButtonState.Filled,
264-
onClick = { uriHandler.openUri(state.linkedSocialProfile.profileUrl) },
265-
text = stringResource(R.string.action_openProfileOnPlatform, state.linkedSocialProfile.platformTypeName)
266-
)
298+
if (!isInTab) {
299+
AnimatedVisibility(
300+
visible = true,
301+
enter = fadeIn() + slideInVertically(initialOffsetY = { it / 2 }),
302+
exit = fadeOut() + slideOutVertically(targetOffsetY = { it / 2 })
303+
) {
304+
CodeButton(
305+
modifier = Modifier
306+
.fillMaxWidth()
307+
.padding(top = CodeTheme.dimens.grid.x12)
308+
.padding(horizontal = CodeTheme.dimens.inset),
309+
buttonState = ButtonState.Filled,
310+
onClick = { uriHandler.openUri(linkedProfile.profileUrl) },
311+
text = stringResource(R.string.action_openProfileOnPlatform, linkedProfile.platformTypeName)
312+
)
313+
}
314+
}
315+
}
316+
}
267317
}
268318
}
269319
}

0 commit comments

Comments
 (0)