Skip to content

Commit

Permalink
Merge branch 'next' of github.com:radical-ui/apage into next
Browse files Browse the repository at this point in the history
  • Loading branch information
Vehmloewff committed Oct 2, 2024
2 parents 9a3609d + d3f94fa commit 30be7da
Showing 1 changed file with 166 additions and 87 deletions.
253 changes: 166 additions & 87 deletions app/src/main/java/com/example/objectionapp/Page.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,116 +33,195 @@ import kotlinx.serialization.Serializable

@Serializable
data class Page(
@Description("The page title will be displayed prominently at the top of the screen") val title: String? = null,
@Description("The page title will be displayed prominently at the top of the screen") val title: String? = null,
// @Description("The images will be displayed in carousel form, directly below the title") val imageUrls: List<String>? = null,
// @Description("The page subtitle is displayed directly under any images on the page") val subtitle: String? = null,

@Description(
"The page that will be pulled up for a presumed search through the contents of this page"
) @ObjectReference(Object.PlainPage::class) val searchPageId: String? = null,
@Description(
"The page that will be pulled up for a presumed search through the contents of this page"
) @ObjectReference(Object.PlainPage::class) val searchPageId: String? = null,

val view: View? = null,
val view: View? = null,

val type: PageType,

// // TODO: refine these
// val content: List<Content> = listOf(),
// val actions: List<Action> = listOf(),
val type: PageType,
)

@Serializable
sealed data class PageType(
sealed class PageType {
@Serializable
data class Post(
@Description("The images will be displayed in carousel form, directly below the title")
val imageUrls: List<String>? = null,
@Description("The page supertitle is displayed directly below any images on the page")
val supertitle: String? = null,
@Description("The additional info is displayed directly below any images on the page")
val aditionalInfo: String? = null,
): PageType()
) : PageType()

@Serializable
data class Profile(
@Description("The the banner image for the user profile")
val bannerImageUrl: String,
@Description("The avatar image for the user profile")
val avatarImageUrl: String,
): PageType()
) : PageType()

object class Plain(): PageType()
)

@Serializable
data object Plain : PageType()
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
fun SharedTransitionScope.PageRender(
id: String, bottomPadding: Dp, animatedVisibilityScope: AnimatedVisibilityScope?
id: String,
bottomPadding: Dp,
animatedVisibilityScope: AnimatedVisibilityScope?,
) {
val navController = useNavController()
val layout = useDefaultLayout()
val isRoot = layout.getRoots().contains(id)
val page = usePage(id)

val scrollBehavior = if (isRoot) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
} else {
TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
}

Column(
Modifier.padding(bottom = bottomPadding)
) {
if (isRoot) {
LargeTopAppBar(
title = { Text("${page?.title}") },
scrollBehavior = scrollBehavior,
)
} else {
TopAppBar(
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
StandardIcon("ArrowBack")
}
},
title = { Text("${page?.title}") },
scrollBehavior = scrollBehavior,
)
}

LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp),
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection)
.fillMaxWidth()
.fillMaxHeight()
) {
val childPadding = PaddingValues(horizontal = 16.dp)

// TODO support multiple images, but keep in mind that probably only the first one should take part in
// the shared element animation
page?.imageUrls?.first()?.let { url ->
item {
AsyncImage(
model = url,
contentDescription = "An image",
clipToBounds = true,
contentScale = ContentScale.Crop,
modifier = if (animatedVisibilityScope != null) {
Modifier.sharedElement(state = rememberSharedContentState("${id}/image"),
animatedVisibilityScope = animatedVisibilityScope,
boundsTransform = { _, _ ->
tween(durationMillis = 300)
})
} else {
Modifier
}
.padding(childPadding)
.clip(RoundedCornerShape(8))
.height(300.dp)
.fillMaxWidth()
)
}
}

item {
Box(Modifier.padding(vertical = 8.dp))
}
}
}
val page = usePage(id) ?: return


when (page.type) {
is PageType.Plain -> PlainPageRender(
id,
bottomPadding,
animatedVisibilityScope,
pageType = page.type,
view = page.view,
title = page.title,
searchPageId = page.searchPageId
)

is PageType.Post -> PostPageRender(
id,
bottomPadding,
animatedVisibilityScope,
pageType = page.type,
view = page.view,
title = page.title,
searchPageId = page.searchPageId
)

is PageType.Profile -> ProfilePageRender(
id,
bottomPadding,
animatedVisibilityScope,
pageType = page.type,
view = page.view,
title = page.title,
searchPageId = page.searchPageId
)
}
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
fun SharedTransitionScope.ProfilePageRender(
id: String,
bottomPadding: Dp,
animatedVisibilityScope: AnimatedVisibilityScope?,
pageType: PageType.Profile,
view: View? = null,
title: String? = null,
searchPageId: String? = null,
) {
return
}

@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
fun SharedTransitionScope.PlainPageRender(
id: String,
bottomPadding: Dp,
animatedVisibilityScope: AnimatedVisibilityScope?,
pageType: PageType.Plain,
view: View? = null,
title: String? = null,
searchPageId: String? = null,
) {
return
}


@OptIn(ExperimentalMaterial3Api::class, ExperimentalSharedTransitionApi::class)
@Composable
fun SharedTransitionScope.PostPageRender(
id: String,
bottomPadding: Dp,
animatedVisibilityScope: AnimatedVisibilityScope?,
pageType: PageType.Post,
view: View? = null,
title: String? = null,
searchPageId: String? = null,
) {
val navController = useNavController()
val layout = useDefaultLayout()
val isRoot = layout.getRoots().contains(id)

val scrollBehavior = if (isRoot) {
TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
} else {
TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
}

Column(
Modifier.padding(bottom = bottomPadding)
) {
if (isRoot) {
LargeTopAppBar(
title = { Text("$title") },
scrollBehavior = scrollBehavior,
)
} else {
TopAppBar(
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
StandardIcon("ArrowBack")
}
},
title = { Text("$title") },
scrollBehavior = scrollBehavior,
)
}

LazyColumn(
verticalArrangement = Arrangement.spacedBy(20.dp),
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection)
.fillMaxWidth()
.fillMaxHeight()
) {
val childPadding = PaddingValues(horizontal = 16.dp)

// TODO support multiple images, but keep in mind that probably only the first one should take part in
// the shared element animation
pageType.imageUrls?.first()?.let { url ->
item {
AsyncImage(
model = url,
contentDescription = "An image",
clipToBounds = true,
contentScale = ContentScale.Crop,
modifier = if (animatedVisibilityScope != null) {
Modifier.sharedElement(state = rememberSharedContentState("${id}/image"),
animatedVisibilityScope = animatedVisibilityScope,
boundsTransform = { _, _ ->
tween(durationMillis = 300)
})
} else {
Modifier
}
.padding(childPadding)
.clip(RoundedCornerShape(8))
.height(300.dp)
.fillMaxWidth()
)
}
}

item {
Box(Modifier.padding(vertical = 8.dp))
}
}
}
}

0 comments on commit 30be7da

Please sign in to comment.