Adding tablet UI for home#1723
Conversation
| appSettings = appSettings, | ||
| ) { | ||
| val appState = rememberJerboaAppState() | ||
| Surface(modifier = Modifier.fillMaxSize()) { |
There was a problem hiding this comment.
Only change here is wrapping everything in this surface: its necessary for the navigation bar scaffold, and is in most of the examples.
There was a problem hiding this comment.
Does it need to be all they way up here?
| postActionBarMode: PostActionBarMode, | ||
| swipeToActionPreset: SwipeToActionPreset, | ||
| padding: PaddingValues, | ||
| onPostClick: (PostView) -> Unit, |
There was a problem hiding this comment.
We need to highjack this action, because the list-detail view uses its own pseudo navigation.
| Scaffold( | ||
| snackbarHost = { JerboaSnackbarHost(snackbarHostState) }, | ||
| content = { padding -> |
There was a problem hiding this comment.
It's strange to embed a scaffold within the adaptive scaffold, but its the only way to pass the snackbarhost for the error messages.
| this.getData() | ||
| } | ||
|
|
||
| fun reInitializeWithNewId(id: Either<PostId, CommentId>) { |
There was a problem hiding this comment.
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.
| val window = (LocalContext.current as Activity).window | ||
| val colorScheme = MaterialTheme.colorScheme | ||
|
|
||
| DisposableEffect(Unit) { |
There was a problem hiding this comment.
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.
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.
|
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. |
|
K, updated, so hopefully this won't crash. |
| @@ -1,4 +1,3 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <resources> | |||
| <string name="app_name">Jerboa (ОТЛАДКА)</string> | |||
There was a problem hiding this comment.
If you remove this then you might as well remove the entire file
There was a problem hiding this comment.
Will do. There's a lot of other translation lints that android studio is telling us to fix, but that can be done in a separate PR.
Eventually we can switch to weblate, I've done that for a few other repos now.
| </intent-filter> | ||
|
|
||
| <intent-filter> | ||
| <intent-filter android:autoVerify="true"> |
There was a problem hiding this comment.
Are we actually hosting a Digital Asset Links json on all lemmy domains that have Jerboa in there?
https://developer.android.com/training/app-links/verify-android-applinks
There was a problem hiding this comment.
Nope, I shouldn't have followed that manifest lint. I'll remove.
| fun amMod( | ||
| moderators: List<PersonId>?, | ||
| myId: PersonId, | ||
| ): Boolean = moderators?.contains(myId) ?: false |
There was a problem hiding this comment.
Imo the previous reads easier but you can leave as is.
|
I cant reproduce those crashes anymore. So that is good |
|
I still need to do a lot of testing on comment creation / updating, because how we're passing data using the navcontroller, is still an issue since this switches to a list-detail view for the home screen, where the panes are no longer their own nav route. |
|
Hey, I recently discovered https://android-developers.googleblog.com/2025/05/announcing-jetpack-navigation-3-for-compose.html They are building a new navigation lib, this one should have better support for adaptive layouts. But its still in Alpha, so we definitely need to wait until we get a stable release to try it out. |
|
Perfect. Yep these navigation problems when dealing with panes vs screens need to get handled upstream. |
|
Resurrecting this finally. The new non-alpha dep updates for adaptive layouts seemed to fix all the issues we had with navigation. Since there are a lot of changes here, I'd like the |
|
The adaptive navigation bar has odd behaviour with with our custom navigation options (hide / smaller with no text) |
|
The All these vital locations (like inbox, reports, etc) don't exist anywhere else in the UI, so maybe I should just remove that setting, or hide it for now. |
|
they do exist in the hamburger menu when its hidden from the navigation rail |



I've added:
Scaffold.bottomBarto an adaptive navigation bar.Example of tablet UI:
Screen_Recording_20241120_111952_Jerboa.Debug.mp4
Fixes #127