-
Notifications
You must be signed in to change notification settings - Fork 170
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding tablet UI for home #1723
base: main
Are you sure you want to change the base?
Conversation
@@ -115,708 +118,710 @@ class MainActivity : AppCompatActivity() { | |||
JerboaTheme( | |||
appSettings = appSettings, | |||
) { | |||
val appState = rememberJerboaAppState() | |||
Surface(modifier = Modifier.fillMaxSize()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only change here is wrapping everything in this surface: its necessary for the navigation bar scaffold, and is in most of the examples.
import it.vercruysse.lemmyapi.datatypes.PostView | ||
import it.vercruysse.lemmyapi.datatypes.SavePost | ||
import it.vercruysse.lemmyapi.datatypes.Tagline | ||
import kotlinx.coroutines.launch | ||
|
||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) | ||
@Composable | ||
fun HomeScreen( | ||
fun HomePane( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that these are panes and not screens, I don't know whether its really appropriate to pass them viewmodels. I left everything as is for now.
@@ -96,8 +98,10 @@ fun HomeScreen( | |||
postActionBarMode: PostActionBarMode, | |||
swipeToActionPreset: SwipeToActionPreset, | |||
padding: PaddingValues, | |||
onPostClick: (PostView) -> Unit, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to highjack this action, because the list-detail view uses its own pseudo navigation.
|
||
Column( | ||
modifier = Modifier | ||
.background(selectedItemContainerColor(selected)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only change here is adding the background when its selected.
// Some hacky code required to update the screen for tablet view | ||
// Necessary because the viewmodel initializes only once. | ||
if (postViewModel.id !== postOrCommentId) { | ||
postViewModel.reInitializeWithNewId(postOrCommentId) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This had me scratching my head for a while. Clicking on a new post in the list didn't re-init the viewmodel, so it kept showing the first post selected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ViewModels are bound to the lifetime of the screen (navigation target). It reuses it as long as the screen exists.
see https://developer.android.com/topic/libraries/architecture/viewmodel#jetpack-compose
Scaffold( | ||
snackbarHost = { JerboaSnackbarHost(snackbarHostState) }, | ||
content = { padding -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's strange to embed a scaffold within the adaptive scaffold, but its the only way to pass the snackbarhost for the error messages.
@@ -79,6 +79,11 @@ class PostViewModel( | |||
this.getData() | |||
} | |||
|
|||
fun reInitializeWithNewId(id: Either<PostId, CommentId>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't fully checked it out
But I think the idea was rather that you would recreate a new postViewModel each time.
I haven't this out yet but this might not play well with the state that won't be remembered. Like sorts.
app/src/main/java/com/jerboa/ui/components/common/AccountHelpers.kt
Outdated
Show resolved
Hide resolved
val window = (LocalContext.current as Activity).window | ||
val colorScheme = MaterialTheme.colorScheme | ||
|
||
DisposableEffect(Unit) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this is also gone but this was really necessary for the navigation bar to look the same as system navigation bar.
It looked quite odd. I'll check it out later to see how this looks now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see any need for these now in the jetpack compose code, maybe they were necessary once, but now with edgeToedge
, it seems to handle the navbar coloring fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not on older API levels
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ill have time this weekend for a proper review + testing |
Sweet, thx. |
Mb I'll have time tomorrow |
I am getting crashes stacktraceFATAL EXCEPTION: main
Process: com.jerboa.debug, PID: 2623
java.lang.NoSuchMethodError: No interface method removeFirst()Ljava/lang/Object; in class Ljava/util/List; or its super classes (declaration of 'java.util.List' appears in /apex/com.android.art/javalib/core-oj.jar)
at com.jerboa.UtilsKt.getCommentParentId(Utils.kt:824)
at com.jerboa.UtilsKt.recCreateAndGenMissingCommentData(Utils.kt:186)
at com.jerboa.UtilsKt.buildCommentsTree(Utils.kt:166)
at com.jerboa.ui.components.post.PostPaneKt$PostPane$14$2.invoke$lambda$36(PostPane.kt:491)
at com.jerboa.ui.components.post.PostPaneKt$PostPane$14$2.$r8$lambda$3mSIQh7EFo9ZE2NxXXAs9Y27qzY(Unknown Source:0)
at com.jerboa.ui.components.post.PostPaneKt$PostPane$14$2$$ExternalSyntheticLambda22.invoke(D8$$SyntheticClass:0)
at androidx.compose.foundation.lazy.LazyListIntervalContent.<init>(LazyListIntervalContent.kt:34)
at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProviderLambda$1$intervalContentState$1.invoke(LazyListItemProvider.kt:49)
at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProviderLambda$1$intervalContentState$1.invoke(LazyListItemProvider.kt:48)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
at androidx.compose.runtime.DerivedSnapshotState.currentRecord(DerivedState.kt:200)
at androidx.compose.runtime.DerivedSnapshotState.getValue(DerivedState.kt:272)
at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProviderLambda$1$itemProviderState$1.invoke(LazyListItemProvider.kt:52)
at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProviderLambda$1$itemProviderState$1.invoke(LazyListItemProvider.kt:51)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
at androidx.compose.runtime.DerivedSnapshotState.currentRecord(DerivedState.kt:200)
at androidx.compose.runtime.DerivedSnapshotState.getCurrentRecord(DerivedState.kt:279)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.recordRead(SnapshotStateObserver.kt:463)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.recordRead(SnapshotStateObserver.kt:436)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$readObserver$1.invoke(SnapshotStateObserver.kt:168)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$readObserver$1.invoke(SnapshotStateObserver.kt:165)
at androidx.compose.runtime.DerivedSnapshotState.getValue(DerivedState.kt:267)
at androidx.compose.foundation.lazy.LazyListItemProviderKt$rememberLazyListItemProviderLambda$1$1.get(LazyListItemProvider.kt:61)
at kotlin.jvm.internal.PropertyReference0.invoke(PropertyReference0.java:35)
at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$itemContentFactory$1$1.invoke(LazyLayout.kt:84)
at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$itemContentFactory$1$1.invoke(LazyLayout.kt:84)
at androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScopeImpl.<init>(LazyLayoutMeasureScope.kt:109)
at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke-0kLqBqw(LazyLayout.kt:114)
at androidx.compose.foundation.lazy.layout.LazyLayoutKt$LazyLayout$3$2$1.invoke(LazyLayout.kt:112)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(SubcomposeLayout.kt:725)
at androidx.compose.ui.node.InnerNodeCoordinator$LookaheadDelegateImpl.measure-BRTryo0(InnerNodeCoordinator.kt:83)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1802)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:111)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release$default(OwnerSnapshotObserver.kt:105)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:40)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1431)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:1368)
at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s(Box.kt:173)
at androidx.compose.ui.node.InnerNodeCoordinator$LookaheadDelegateImpl.measure-BRTryo0(InnerNodeCoordinator.kt:83)
at androidx.compose.foundation.layout.FillNode.measure-3p2s80s(Size.kt:699)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.foundation.layout.PaddingValuesModifier.measure-3p2s80s(Padding.kt:472)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1802)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:503)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:111)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release$default(OwnerSnapshotObserver.kt:105)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:40)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1431)
at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release(LayoutNode.kt:1204)
at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1198)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doLookaheadRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:349)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:555)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:660)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:686)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:693)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:649)
at androidx.compose.ui.platform.AndroidComposeView.forceMeasureTheSubtree(AndroidComposeView.android.kt:1299)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1441)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.measure-BRTryo0(LayoutNodeLayoutDelegate.kt:1368)
at androidx.compose.animation.AnimatedEnterExitMeasurePolicy.measure-3p2s80s(AnimatedVisibility.kt:812)
at androidx.compose.ui.node.InnerNodeCoordinator$LookaheadDelegateImpl.measure-BRTryo0(InnerNodeCoordinator.kt:83)
at androidx.compose.animation.EnterExitTransitionModifierNode.measure-3p2s80s(EnterExitTransition.kt:1160)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.ui.graphics.BlockGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:578)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.animation.AnimatedVisibilityKt$AnimatedVisibilityImpl$1$1.invoke-3p2s80s(AnimatedVisibility.kt:699)
at androidx.compose.animation.AnimatedVisibilityKt$AnimatedVisibilityImpl$1$1.invoke(AnimatedVisibility.kt:698)
at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(LayoutModifier.kt:294)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(GraphicsLayerModifier.kt:646)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.material3.adaptive.layout.AnimateBoundsNode.measure-3p2s80s(AnimateBoundsModifier.kt:116)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator$LookaheadDelegateForLayoutModifierNode.measure-BRTryo0(LayoutModifierNodeCoordinator.kt:94)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1802)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performLookaheadMeasure$1.invoke(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.kt:2441)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:502)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:258)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:111)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release$default(OwnerSnapshotObserver.kt:105)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1801)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performLookaheadMeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:40)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:1431)
at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release(LayoutNode.kt:1204)
at androidx.compose.ui.node.LayoutNode.lookaheadRemeasure-_Sx5XlM$ui_release$default(LayoutNode.kt:1198)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doLookaheadRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:349)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:555)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:534)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:390)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:1268)
at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.kt:248)
at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1556)
at android.view.View.draw(View.java:22647)
at android.view.View.updateDisplayListIfDirty(View.java:21519)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4512)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4485)
at android.view.View.updateDisplayListIfDirty(View.java:21475)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:534)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:540)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:616)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4421)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4149)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3309)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2126)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8653)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037)
at android.view.Choreographer.doCallbacks(Choreographer.java:845)
at android.view.Choreographer.doFrame(Choreographer.java:780)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
|
Unfortunately it'll be ~a week before I can check this one out. |
I've added:
Scaffold.bottomBar
to an adaptive navigation bar.Example of tablet UI:
Screen_Recording_20241120_111952_Jerboa.Debug.mp4
Fixes #127