Some quick unrefined feedback (my remarks, no bad ill intended):
UX:
It takes up a lot screen real estate without giving much info back:
Each posts displays: Title, username, communityname (twice), communityinstance, embed preview or post body, What Jerboa now displays as info in card layout: Community(icon/name/instance), User (name, icon, bot, mod), Total score, (up/down)votes, post title, post body/ post preview, time posted/edited, read/unread, pinned, deleted, featured, saved, already (upvoted/downvoted), total comments and new comments
Community name and username are bit too small, hard to read, makes touch targets very small thus hard to hit
Title fontsize too big, long titles will reap havoc (And believe me they can get long, especially the mastodons federated posts as it includes a link each time)
No user actions buttons,
to reiterate, takes up lots of precious screen real estate. (It's why current doesn't have padding between posts, only when needed). It's tough to balance: giving loads of information in easy to digest format. Its why currently it uses lots of assumptions, lack of some information can give you more, (ex: doesn't show upvotes/downvotes if it are all upvotes, community instance not included if its your home instance )
UI:
Don't like the upvote downvote , too big
Interesting filter prototype at the top there? This scrolls with the feed I assume, so once you scrolled a bit and you want to change the filter you have to scroll all the way up again? And if it popups like the topbar, then it would take up more than 10% of your screen each time
UI/UX Design is hard, definitely what I struggle the most with while contributing to Jerboa. UI wise you can't please everyone ,ppl have preferences. (The real reason why full search + filters isn't implemented yet, haven't had the time yet to prototype it, which is the biggest time sink, the actually functionality is rather simple)
Here's the most recent one. It happens once or twice a day, usually when expanding or scrolling in the replies. They're all the same exception, with the exception of the key number, but if more traces will help you I can can send all of them.
Stacktrace
java.lang.IllegalArgumentException: Key "3764992" was already used. If you are using LazyColumn/Row please make sure you provide a unique key for each item.
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose(Unknown Source:182)
at androidx.compose.foundation.lazy.layout.LazyLayoutMeasureScopeImpl.measure-0kLqBqw(Unknown Source:33)
at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1$measuredItemProvider$1.getAndMeasure(Unknown Source:18)
at androidx.compose.foundation.lazy.LazyListKt$rememberLazyListMeasurePolicy$1$1.invoke(Unknown Source:617)
at androidx.navigation.compose.NavHostKt$NavHost$14$1.invoke(SourceFile:17)
at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s(Unknown Source:91)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(Unknown Source:45)
at androidx.compose.material3.ComposableSingletons$AppBarKt$lambda-2$1.invoke-3p2s80s(Unknown Source:60)
at androidx.compose.material3.ComposableSingletons$AppBarKt$lambda-2$1.invoke(SourceFile:73)
at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(Unknown Source:12)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(Unknown Source:10)
at androidx.compose.material3.ComposableSingletons$AppBarKt$lambda-2$1.invoke-3p2s80s(Unknown Source:19)
at androidx.compose.material3.ComposableSingletons$AppBarKt$lambda-2$1.invoke(SourceFile:76)
at androidx.compose.ui.layout.LayoutModifierImpl.measure-3p2s80s(Unknown Source:12)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(Unknown Source:10)
at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s(Unknown Source:5)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(Unknown Source:10)
at androidx.compose.foundation.layout.PaddingNode.measure-3p2s80s(Unknown Source:37)
at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0(Unknown Source:10)
at okhttp3.internal.http2.Http2Connection$1.invoke(SourceFile:17)
at okhttp3.internal.http2.Http2Connection$1.invoke(SourceFile:13)
at kotlin.UNINITIALIZED_VALUE.observe(Unknown Source:63)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(Unknown Source:66)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(Unknown Source:75)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(Unknown Source:12)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(Unknown Source:109)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(Unknown Source:17)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout-0kLqBqw(Unknown Source:60)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout-0kLqBqw(Unknown Source:12)
at androidx.compose.ui.node.LayoutNode.forceRemeasure(Unknown Source:40)
at androidx.compose.foundation.MagnifierKt$magnifier$4$3.invoke(SourceFile:27)
at androidx.compose.foundation.MagnifierKt$magnifier$4$3.invoke(SourceFile:105)
at androidx.compose.foundation.gestures.DefaultScrollableState$scrollScope$1.scrollBy(Unknown Source:16)
at androidx.compose.runtime.RecomposeScopeImpl$end$1$2.invoke(Unknown Source:359)
at androidx.compose.foundation.AndroidEdgeEffectOverscrollEffect.applyToScroll-Rhakbz0(Unknown Source:327)
at androidx.compose.foundation.gestures.ScrollingLogic.dispatchScroll-3eAAhYA(Unknown Source:49)
at androidx.compose.foundation.gestures.ScrollDraggableState.dragBy(Unknown Source:15)
at androidx.compose.foundation.gestures.DraggableNode$pointerInputNode$1$1$1$1.invokeSuspend(Unknown Source:81)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(Unknown Source:8)
at kotlinx.coroutines.DispatchedTask.run(Unknown Source:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(Unknown Source:22)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(Unknown Source:9)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
at android.view.Choreographer.doCallbacks(Choreographer.java:899)
at android.view.Choreographer.doFrame(Choreographer.java:827)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
at android.os.Handler.handleCallback(Handler.java:942)
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:7918)
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:936)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.ui.platform.MotionDurationScaleImpl@d81cb45, androidx.compose.runtime.BroadcastFrameClock@890c29a, StandaloneCoroutine{Cancelling}@e09f7cb, AndroidUiDispatcher@5c08ba8]
END of stacktrace
Thread info
Name: main
ID: 2
State: RUNNABLE
Priority: 5
Thread group name: main
Thread group parent: system
Thread group active count: 39
Thread time: 0 hr 6 min, 7 sec
END of thread info
Device info
Report ID: 8e31d58f-c71f-4a1a-baf9-3e0d403f2f2f
Device ID: f08fa57315663069
Application version: 48
Default launcher: com.android.settings
Timezone name: Eastern Standard Time
Timezone ID: America/New_York
Version release: 13
Version incremental : 10385117
Version SDK: 33
Board: redfin
Bootloader: r3-0.5-9825705
Brand: google
CPU ABIS 32: armeabi-v7a, armeabi
CPU ABIS 64: arm64-v8a
Supported ABIS: arm64-v8a, armeabi-v7a, armeabi
Device: redfin
Display: TQ3A.230805.001.A2
Fingerprint: google/redfin/redfin:13/TQ3A.230805.001.A2/10385117:user/release-keys
Hardware: redfin
Host: abfarm-release-2004-0198
ID: TQ3A.230805.001.A2
Manufacturer: Google
Product: redfin
Build time: 1687810840000
Build time formatted: 26-06-2023 16:20:40
Type: user
Radio: g7250-00258-230518-B-10157620,g7250-00258-230518-B-10157620
Tags: release-keys
User: android-build
User IDs: N/A
Is sustained performance mode supported: No
Is in power save mode: No
Is in interactive state: Yes
Is ignoring battery optimizations: No
Thermal status: STATUS_NONE
Location power save mode: MODE_NO_CHANGE
Is device idle: No
Battery percentage: 81
Battery remaining time: N/A
Is battery charging: No
Is device rooted: No
CPU Model: Qualcomm Technologies, Inc LITO
Number of CPU cores: 8
Up time with sleep: 327 hr 22 min, 56 sec
Up time without sleep: 160 hr 38 min, 24 sec
END of Device info
Exit reasons
Exit reason #1
Description: null
Importance: PERCEPTIBLE
Reason: SIGNALED
Timestamp: 29-09-2023 03:20:43
END of exit reason #1
Exit reason #2
Description: remove task
Importance: CACHED
Reason: USER_REQUESTED
Timestamp: 28-09-2023 21:45:50
END of exit reason #2
Exit reason #3
Description: stop com.jerboa due to installPackageLI
Importance: CACHED
Reason: USER_REQUESTED
Timestamp: 28-09-2023 09:13:11
END of exit reason #3
END of exit reasons
Application info
App name: Jerboa
Version code: 48
Version name: 0.0.48
Package name: com.jerboa
Short package name: jerboa
Flavor: N/A
Signatures: nORRaWmGNmrBj18PL/p3svEr/s4=
Is debuggable: No
First installed: 07-06-2023 20:24:35
Last updated: 28-09-2023 09:13:11
Requested permissions: android.permission.ACCESS_NETWORK_STATE, android.permission.INTERNET, android.permission.READ_MEDIA_AUDIO, android.permission.READ_MEDIA_IMAGES, android.permission.READ_MEDIA_VIDEO, com.jerboa.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION
Default prefs: N/A
Default prefs: N/A
END of Application info
Currently running foreground/background processes
N/A
END of running foreground/background processes info