diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml deleted file mode 100644 index f7b881c..0000000 --- a/.idea/deploymentTargetSelector.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..a76f118 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,329 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/objectionapp/Constants.kt b/app/src/main/java/com/example/objectionapp/Constants.kt index 6f921ec..1e86b97 100644 --- a/app/src/main/java/com/example/objectionapp/Constants.kt +++ b/app/src/main/java/com/example/objectionapp/Constants.kt @@ -14,4 +14,4 @@ val lightForegroundColor = Color(red = 12, green = 12, blue = 20) val darkForegroundColor = Color(red = 240, green = 240, blue = 255) val defaultThemeId = "theme_default" -val defaultLayoutId = "layout_default" \ No newline at end of file +val defaultLayoutId = "layout_default" diff --git a/app/src/main/java/com/example/objectionapp/Logger.kt b/app/src/main/java/com/example/objectionapp/Logger.kt index 9b172ff..0748106 100644 --- a/app/src/main/java/com/example/objectionapp/Logger.kt +++ b/app/src/main/java/com/example/objectionapp/Logger.kt @@ -10,7 +10,7 @@ class Logger(private var session: Session, private var scope: String) { } fun warn(message: String) { - session.pushLog("WARN: $message") + session.pushLog("[$scope] WARN: $message") } fun info(message: String) { diff --git a/app/src/main/java/com/example/objectionapp/ObjectData.kt b/app/src/main/java/com/example/objectionapp/ObjectData.kt index 630a4fe..3507630 100644 --- a/app/src/main/java/com/example/objectionapp/ObjectData.kt +++ b/app/src/main/java/com/example/objectionapp/ObjectData.kt @@ -9,12 +9,10 @@ import kotlinx.serialization.json.JsonClassDiscriminator @OptIn(ExperimentalSerializationApi::class) @Serializable @JsonClassDiscriminator("kind") +@ContentKey("def") sealed class Object { @Serializable - data class PlainPage(val def: com.example.objectionapp.PlainPage) : Object() - -// @Serializable -// data class ProfilePage(val def: com.example.objectionapp.ProfilePage) : Object() + data class Page(val def: com.example.objectionapp.Page) : Object() @Serializable data class PostPage(val def: com.example.objectionapp.PostPage) : Object() @@ -24,10 +22,6 @@ sealed class Object { @Serializable data class Layout(val def: com.example.objectionapp.Layout) : Object() - - fun assertPostPage(): PostPage { - - } } @OptIn(ExperimentalSerializationApi::class) diff --git a/app/src/main/java/com/example/objectionapp/Page.kt b/app/src/main/java/com/example/objectionapp/Page.kt index 37fa9f3..cf381c8 100644 --- a/app/src/main/java/com/example/objectionapp/Page.kt +++ b/app/src/main/java/com/example/objectionapp/Page.kt @@ -32,115 +32,117 @@ import coil.compose.AsyncImage import kotlinx.serialization.Serializable @Serializable -data class PlainPage( - @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? = null, - @Description("The page subtitle is displayed directly under any images on the page") val subtitle: String? = null, +data class Page( + @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? = 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 searchPage: 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, - // TODO: refine these - val content: List = listOf(), - val actions: List = listOf(), + val type: PageType, + +// // TODO: refine these +// val content: List = listOf(), +// val actions: List = listOf(), ) @Serializable -data class PostPage( - @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? = 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, - - - - @Description( - "The page that will be pulled up for a presumed search through the contents of this page" - ) @ObjectReference(Object.PostPage::class) val searchPage: String? = null, - - val view: View? = null, - - // TODO: refine these - val actions: List = listOf(), +sealed data class PageType( + data class Post( + @Description("The images will be displayed in carousel form, directly below the title") + val imageUrls: List? = 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() + + data class Profile( + val bannerImageUrl: String, + val avatarImageUrl: String, + ): PageType() + + object class 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 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)) + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/objectionapp/Providers.kt b/app/src/main/java/com/example/objectionapp/Providers.kt index bb773fd..4057994 100644 --- a/app/src/main/java/com/example/objectionapp/Providers.kt +++ b/app/src/main/java/com/example/objectionapp/Providers.kt @@ -27,7 +27,6 @@ private var LocalNavController = compositionLocalOf { null } @Composable fun Provider(controller: Controller = Controller.fromConstants()) { - CompositionLocalProvider(LocalController provides controller) { val navController = rememberNavController() val hasInternet = remember { mutableStateOf(controller.bridge.onHasInternet.getLastValue() ?: true) } @@ -157,10 +156,10 @@ fun useDefaultLayout(): Layout { } @Composable -fun usePage(id: String?): PostPage? { +fun usePage(id: String?): Page? { val obj = useObject(id) ?: return null - return if (obj is Object.PostPage) obj.def else throw Exception("Object '$id' was not a page") + return if (obj is Object.Page) obj.def else throw Exception("Object '$id' was not a page") } @Composable diff --git a/app/src/main/java/com/example/objectionapp/Theme.kt b/app/src/main/java/com/example/objectionapp/Theme.kt index 0fb7e74..6fba1bb 100644 --- a/app/src/main/java/com/example/objectionapp/Theme.kt +++ b/app/src/main/java/com/example/objectionapp/Theme.kt @@ -62,8 +62,6 @@ enum class CornerRounding { EXTRA_ROUND, } - - @Composable fun RenderTheme(content: @Composable () -> Unit) { val theme = useDefaultTheme()