Skip to content

Conversation

jbsession
Copy link
Collaborator

This PR removes portrait lock.

This PR also adds some new composables for different orientations.

TODO: Full end to end testing for landscape.

@jbsession jbsession self-assigned this Sep 22, 2025
@damajor damajor mentioned this pull request Sep 29, 2025
@ThomasSession
Copy link
Collaborator

Here are a few issues from testing the branch:

  • The horizontal paddings are not respected when in landscape mode. The app extends below the three dot menu on the left and below the status bar on the right. We should be handling that properly as you can otherwise lose some content.
    In the homescreen for example, the dates are cut off on the right.
    I'm not sure if we should allow content directly below the inset either. Google apps seems to leave a gap on the right hand side to cater for the camera inset space. It's quite jarring in a conversation for example, where the message bubble and content is hidden below the inset.
    You also can't hit the back button from the top app bar in a conversation as it is hidden below the "three button" menu from the system.
  • android:screenOrientation="portrait" is still present on the webrtc call activity. With android 16 this type of call won't be allowed so we need to handle landscape in there accordingly and make sure it works fine, including with the camera on and the phone changing from portrait to landscape as there are some hardcoded logic in the screen for this, which auto rotates the icons based on orientation.
  • Viewing the QR code in recovery password creates a very large qr code that can't be viewed properly. It should probably try to scale itself like in other places, like the qr code acceissible from the qr icon in the top right of the settings.
  • The "create group" bottomsheet has very little space for the user list, though I'm not sure we can do much about this. We could have the title and search also scroll with the rest to give more space, but that's something we'd have to discuss with the team, as it might not be as good of a behaviour for portrait where it's nice to only scroll the users and not the rest of the content.
  • The seesion network page looks a bit ugly with the giant node icon. Not a huge deal breaker but we could optimise it.

modifier = Modifier.fillMaxWidth().padding(24.dp),
contentAlignment = Alignment.Center
) {
Text(text = stringResource(messageId), style = MaterialTheme.typography.bodyMedium)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't reference material's typography in the app, but instead use our own type system.
Instead of MaterialTheme.typography.bodyMedium this should use LocalType.current.large (because large matches the 16sp that were used in the xml file).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@Composable
private fun GiphyLoading() {
Box(
modifier = Modifier.fillMaxWidth().padding(vertical = 24.dp),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For common spacing we should defer to our Dimensions file. so instead of hardcoding 24.dp here (and in line 42) you can use LocalDimensions.current.spacing

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

}).attach();
// new TabLayoutMediator(binding.tabLayout, binding.giphyPager, (tab, position) -> {
// tab.setText(position == 0 ? NonTranslatableStringConstants.GIF : getString(R.string.stickers));
// }).attach();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be deleted if we are no longer using it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

selectedIndex: Int,
onSelect: (Int) -> Unit
) {
val indicatorColor = colorFromAttrOr(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't rely on material themes directly in the app.
We already have a SessionTabRow that is styled as per the rest of the app, so it should be used here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

}

@Composable
private fun colorFromAttrOr(@AttrRes attrResId: Int, fallback: Color): Color {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This likely can be deleted as we already have a styled tab component, SessionTabRow

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed
)

composeView.setContent {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a huge deal but this doesn't really match our existing format when it comes to compose content.
You could have the lines above directly in the activity.
And the lines below here could be in the GiphyScreen composable (with the file renamed too), matching the way we handle compose content in other screens.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I might have to convert the activity here to Kotlin before I change this.

import androidx.compose.ui.platform.LocalConfiguration

object AdaptiveBreakpoints {
const val TWO_PANE_LANDSCAPE_MIN_WIDTH_DP = 480
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is full of specific values and mentions of two pane, which is a specific UI paradigm we are not yet handling, like showing two panes: one for the conversation list and the other for the conversation screen itself, all in the same window.
I don't think we should reinvent the wheel here, and instead we should rely on existing material values

Copy link
Collaborator Author

@jbsession jbsession Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the initial two pane content here and kept the landscape for now. I'll add to this helper in the future when we decide to cater for multiple screen sizes.

}

@Composable
private fun TwoPaneContent(string: String) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to be careful with naming things like this as two panes UI is a specific thing, which we will need to handle in the future, with the material adaptive library. But these are two panes, but more like a landscape version of a UI.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to specify Landscape and Portrait.

}

@Composable
private fun TwoPaneContent(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. We need to be careful with concept like two pane which is a material adaptive concept that is a bit different. Here you could simply have a portrait and a landscape version of the composable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to specify Landscape and Portrait.

modifier = Modifier.verticalScroll(rememberScrollState())
) {
ActionList(navigateTo = navigateTo)
Column(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there a way for both landscape and portrait to reuse some element instead of redeclaring them here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, I made the QrPanel reusable.

import network.loki.messenger.R

/** Called from Java to set Compose content for the loading view. */
fun setGiphyLoading(composeView: ComposeView) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that is is very efficient. Setting the overall content of the screen and resetting the strategy each time.
The whole content should exist in the one composable: the loading, the 'no result' and the list of results.
If not then maybe it was better off in the initial xml format, otherwise it becomes conceptually broken?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated this one to use a state now instead of redeclaring and resetting it every time. I think that made it more efficient?

@jbsession
Copy link
Collaborator Author

jbsession commented Oct 8, 2025

Here are a few issues from testing the branch:

  • The horizontal paddings are not respected when in landscape mode. The app extends below the three dot menu on the left and below the status bar on the right. We should be handling that properly as you can otherwise lose some content.
    In the homescreen for example, the dates are cut off on the right.
    I'm not sure if we should allow content directly below the inset either. Google apps seems to leave a gap on the right hand side to cater for the camera inset space. It's quite jarring in a conversation for example, where the message bubble and content is hidden below the inset.
    You also can't hit the back button from the top app bar in a conversation as it is hidden below the "three button" menu from the system.
  • android:screenOrientation="portrait" is still present on the webrtc call activity. With android 16 this type of call won't be allowed so we need to handle landscape in there accordingly and make sure it works fine, including with the camera on and the phone changing from portrait to landscape as there are some hardcoded logic in the screen for this, which auto rotates the icons based on orientation.
  • Viewing the QR code in recovery password creates a very large qr code that can't be viewed properly. It should probably try to scale itself like in other places, like the qr code acceissible from the qr icon in the top right of the settings.
  • The "create group" bottomsheet has very little space for the user list, though I'm not sure we can do much about this. We could have the title and search also scroll with the rest to give more space, but that's something we'd have to discuss with the team, as it might not be as good of a behaviour for portrait where it's nice to only scroll the users and not the rest of the content.
  • The seesion network page looks a bit ugly with the giant node icon. Not a huge deal breaker but we could optimise it.

Updates on this:

  • Insets are fixed in home, conversation screens. Also how do we feel about the camera insets? (Other screens currently in progress)
  • Removed the protrait lock for WebRtc call activity
  • Updated the large QR code in recovery password
  • Session network's node icon optimization

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants