Refactors chats into public, private and list views for tablets and phones
This commit is contained in:
+1
-1
@@ -81,7 +81,7 @@ import com.vitorpamplona.amethyst.ui.note.SearchIcon
|
|||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.ChannelName
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.ChannelName
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.search.SearchBarViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.search.SearchBarViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ import com.vitorpamplona.amethyst.ui.note.UserCompose
|
|||||||
import com.vitorpamplona.amethyst.ui.note.timeAgo
|
import com.vitorpamplona.amethyst.ui.note.timeAgo
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.LoadUser
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.LoadUser
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
import com.vitorpamplona.amethyst.ui.note.elements.TimeAgo
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.NewItemsBubble
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.NewItemsBubble
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.LoadRedirectScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.LoadRedirectScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.NewPostScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.NewPostScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarks.BookmarkListScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.bookmarks.BookmarkListScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.ChatroomListScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.MessagesScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomScreenByAuthor
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomScreenByAuthor
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ChannelScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ChannelScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.CommunityScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.communities.CommunityScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.DiscoverScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.DiscoverScreen
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.drafts.DraftListScreen
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.drafts.DraftListScreen
|
||||||
@@ -120,7 +120,7 @@ fun AppNavigation(
|
|||||||
exitTransition = { fadeOut(animationSpec = tween(200)) },
|
exitTransition = { fadeOut(animationSpec = tween(200)) },
|
||||||
) {
|
) {
|
||||||
composable(Route.Home.route) { HomeScreen(accountViewModel, nav) }
|
composable(Route.Home.route) { HomeScreen(accountViewModel, nav) }
|
||||||
composable(Route.Message.route) { ChatroomListScreen(accountViewModel, nav) }
|
composable(Route.Message.route) { MessagesScreen(accountViewModel, nav) }
|
||||||
composable(Route.Video.route) { VideoScreen(accountViewModel, nav) }
|
composable(Route.Video.route) { VideoScreen(accountViewModel, nav) }
|
||||||
composable(Route.Discover.route) { DiscoverScreen(accountViewModel, nav) }
|
composable(Route.Discover.route) { DiscoverScreen(accountViewModel, nav) }
|
||||||
composable(Route.Notification.route) { NotificationScreen(sharedPreferencesViewModel, accountViewModel, nav) }
|
composable(Route.Notification.route) { NotificationScreen(sharedPreferencesViewModel, accountViewModel, nav) }
|
||||||
|
|||||||
@@ -78,11 +78,11 @@ import com.vitorpamplona.amethyst.ui.layouts.LeftPictureLayout
|
|||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.BannerImage
|
import com.vitorpamplona.amethyst.ui.note.elements.BannerImage
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ChannelHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ChannelHeader
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.EndedFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.EndedFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.LiveFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.LiveFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.OfflineFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.OfflineFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ScheduledFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ScheduledFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.dvms.observeAppDefinition
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.dvms.observeAppDefinition
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CheckIfVideoIsOnline
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CheckIfVideoIsOnline
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ import com.vitorpamplona.amethyst.ui.note.types.RenderTorrentComment
|
|||||||
import com.vitorpamplona.amethyst.ui.note.types.RenderWikiContent
|
import com.vitorpamplona.amethyst.ui.note.types.RenderWikiContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.types.VideoDisplay
|
import com.vitorpamplona.amethyst.ui.note.types.VideoDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.RenderChannelHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.RenderChannelHeader
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Font12SP
|
import com.vitorpamplona.amethyst.ui.theme.Font12SP
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
|
|||||||
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.LoadUser
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.LoadUser
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ChannelHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ChannelHeader
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
|
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
|||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomHeader
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKeyable
|
||||||
|
|||||||
+1
-1
@@ -49,7 +49,7 @@ import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
|||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomHeader
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding
|
import com.vitorpamplona.amethyst.ui.theme.HalfVertPadding
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ import com.vitorpamplona.amethyst.ui.note.ZapReaction
|
|||||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
|
import com.vitorpamplona.amethyst.ui.note.elements.MoreOptionsButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.JoinCommunityButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.JoinCommunityButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.LeaveCommunityButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.LeaveCommunityButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.NormalTimeAgo
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.NormalTimeAgo
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.DoubleHorzSpacer
|
||||||
|
|||||||
@@ -58,8 +58,8 @@ import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
|||||||
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.LiveFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.LiveFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ScheduledFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ScheduledFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CheckIfVideoIsOnline
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CheckIfVideoIsOnline
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ChannelHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ChannelHeader
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
|||||||
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContent
|
import com.vitorpamplona.amethyst.ui.note.LoadDecryptedContent
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
import com.vitorpamplona.amethyst.ui.note.elements.DisplayUncitedHashtags
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomHeader
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
|
|||||||
-515
@@ -1,515 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2024 Vitor Pamplona
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
* this software and associated documentation files (the "Software"), to deal in
|
|
||||||
* the Software without restriction, including without limitation the rights to use,
|
|
||||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
||||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
* subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist
|
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.systemBarsPadding
|
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
|
||||||
import androidx.compose.foundation.pager.PagerState
|
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
|
||||||
import androidx.compose.material3.DrawerState
|
|
||||||
import androidx.compose.material3.DropdownMenu
|
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Tab
|
|
||||||
import androidx.compose.material3.TabRow
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.DisposableEffect
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.derivedStateOf
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
|
||||||
import com.google.accompanist.adaptive.FoldAwareConfiguration
|
|
||||||
import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy
|
|
||||||
import com.google.accompanist.adaptive.TwoPane
|
|
||||||
import com.vitorpamplona.amethyst.R
|
|
||||||
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
|
|
||||||
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.AppBottomBar
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.MainTopBar
|
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.Route
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.Chatroom
|
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.Channel
|
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size20dp
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChatroomListScreen(
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
val windowSizeClass by accountViewModel.settings.windowSizeClass
|
|
||||||
|
|
||||||
val twoPane by remember {
|
|
||||||
derivedStateOf {
|
|
||||||
when (windowSizeClass?.widthSizeClass) {
|
|
||||||
WindowWidthSizeClass.Compact -> false
|
|
||||||
WindowWidthSizeClass.Expanded,
|
|
||||||
WindowWidthSizeClass.Medium,
|
|
||||||
-> true
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (twoPane && windowSizeClass != null) {
|
|
||||||
ChatroomListTwoPane(
|
|
||||||
knownFeedContentState = accountViewModel.feedStates.dmKnown,
|
|
||||||
newFeedContentState = accountViewModel.feedStates.dmNew,
|
|
||||||
widthSizeClass = windowSizeClass!!.widthSizeClass,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ScaffoldChatroomListScreenOnlyList(
|
|
||||||
knownFeedContentState = accountViewModel.feedStates.dmKnown,
|
|
||||||
newFeedContentState = accountViewModel.feedStates.dmNew,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TwoPaneNav(
|
|
||||||
val nav: INav,
|
|
||||||
val scope: CoroutineScope,
|
|
||||||
) : INav {
|
|
||||||
override val drawerState: DrawerState = nav.drawerState
|
|
||||||
|
|
||||||
val innerNav = mutableStateOf<RouteId?>(null)
|
|
||||||
|
|
||||||
override fun nav(route: String) {
|
|
||||||
if (route.startsWith("Room/") || route.startsWith("Channel/")) {
|
|
||||||
innerNav.value = RouteId(route.substringBefore("/"), route.substringAfter("/"))
|
|
||||||
} else {
|
|
||||||
nav.nav(route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun nav(routeMaker: suspend () -> String) {
|
|
||||||
scope.launch(Dispatchers.Default) {
|
|
||||||
val route = routeMaker()
|
|
||||||
if (route.startsWith("Room/") || route.startsWith("Channel/")) {
|
|
||||||
innerNav.value = RouteId(route.substringBefore("/"), route.substringAfter("/"))
|
|
||||||
} else {
|
|
||||||
nav.nav(route)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newStack(route: String) {
|
|
||||||
nav.newStack(route)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popBack() {
|
|
||||||
nav.popBack()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popUpTo(
|
|
||||||
route: String,
|
|
||||||
upTo: String,
|
|
||||||
) {
|
|
||||||
nav.popUpTo(route, upTo)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun closeDrawer() {
|
|
||||||
nav.closeDrawer()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun openDrawer() {
|
|
||||||
nav.openDrawer()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class RouteId(
|
|
||||||
val route: String,
|
|
||||||
val id: String,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChatroomListTwoPane(
|
|
||||||
knownFeedContentState: FeedContentState,
|
|
||||||
newFeedContentState: FeedContentState,
|
|
||||||
widthSizeClass: WindowWidthSizeClass,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
/** The index of the currently selected word, or `null` if none is selected */
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
val twoPaneNav = remember { TwoPaneNav(nav, scope) }
|
|
||||||
|
|
||||||
val strategy =
|
|
||||||
remember {
|
|
||||||
if (widthSizeClass == WindowWidthSizeClass.Expanded) {
|
|
||||||
HorizontalTwoPaneStrategy(
|
|
||||||
splitFraction = 1f / 3f,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
HorizontalTwoPaneStrategy(
|
|
||||||
splitFraction = 1f / 2.5f,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisappearingScaffold(
|
|
||||||
isInvertedLayout = false,
|
|
||||||
topBar = {
|
|
||||||
Column {
|
|
||||||
MainTopBar(accountViewModel, nav)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
bottomBar = {
|
|
||||||
AppBottomBar(Route.Message, accountViewModel) { route, _ ->
|
|
||||||
nav.newStack(route.base)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
) {
|
|
||||||
TwoPane(
|
|
||||||
first = {
|
|
||||||
Box(Modifier.fillMaxSize().systemBarsPadding(), contentAlignment = Alignment.BottomEnd) {
|
|
||||||
ChatroomListScreenOnlyList(
|
|
||||||
knownFeedContentState,
|
|
||||||
newFeedContentState,
|
|
||||||
accountViewModel,
|
|
||||||
twoPaneNav,
|
|
||||||
)
|
|
||||||
|
|
||||||
Box(Modifier.padding(Size20dp), contentAlignment = Alignment.Center) {
|
|
||||||
ChannelFabColumn(accountViewModel, nav)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
second = {
|
|
||||||
Box(Modifier.fillMaxSize().systemBarsPadding()) {
|
|
||||||
twoPaneNav.innerNav.value?.let {
|
|
||||||
if (it.route == "Room") {
|
|
||||||
Chatroom(
|
|
||||||
roomId = it.id,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.route == "Channel") {
|
|
||||||
Channel(
|
|
||||||
channelId = it.id,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
strategy = strategy,
|
|
||||||
displayFeatures = accountViewModel.settings.displayFeatures.value,
|
|
||||||
foldAwareConfiguration = FoldAwareConfiguration.VerticalFoldsOnly,
|
|
||||||
modifier = Modifier.padding(it).consumeWindowInsets(it).fillMaxSize(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun ChatroomListScreenOnlyList(
|
|
||||||
knownFeedContentState: FeedContentState,
|
|
||||||
newFeedContentState: FeedContentState,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
val pagerState = rememberPagerState { 2 }
|
|
||||||
|
|
||||||
val markKnownAsRead = remember { mutableStateOf(false) }
|
|
||||||
val markNewAsRead = remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
WatchAccountForListScreen(knownFeedContentState, newFeedContentState, accountViewModel)
|
|
||||||
WatchLifecycleAndRefreshDataSource(accountViewModel)
|
|
||||||
|
|
||||||
val tabs by
|
|
||||||
remember(knownFeedContentState, markKnownAsRead) {
|
|
||||||
derivedStateOf {
|
|
||||||
listOf(
|
|
||||||
ChatroomListTabItem(R.string.known, knownFeedContentState, markKnownAsRead),
|
|
||||||
ChatroomListTabItem(R.string.new_requests, newFeedContentState, markNewAsRead),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Column {
|
|
||||||
ChatroomListOnlyTabs(
|
|
||||||
pagerState,
|
|
||||||
tabs,
|
|
||||||
{ markKnownAsRead.value = true },
|
|
||||||
{ markNewAsRead.value = true },
|
|
||||||
)
|
|
||||||
|
|
||||||
ChatroomListTabs(
|
|
||||||
pagerState,
|
|
||||||
tabs,
|
|
||||||
PaddingValues(0.dp),
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun ScaffoldChatroomListScreenOnlyList(
|
|
||||||
knownFeedContentState: FeedContentState,
|
|
||||||
newFeedContentState: FeedContentState,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
val pagerState = rememberPagerState { 2 }
|
|
||||||
|
|
||||||
val markKnownAsRead = remember { mutableStateOf(false) }
|
|
||||||
val markNewAsRead = remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
WatchAccountForListScreen(knownFeedContentState, newFeedContentState, accountViewModel)
|
|
||||||
WatchLifecycleAndRefreshDataSource(accountViewModel)
|
|
||||||
|
|
||||||
val tabs by
|
|
||||||
remember(knownFeedContentState, markKnownAsRead) {
|
|
||||||
derivedStateOf {
|
|
||||||
listOf(
|
|
||||||
ChatroomListTabItem(R.string.known, knownFeedContentState, markKnownAsRead),
|
|
||||||
ChatroomListTabItem(R.string.new_requests, newFeedContentState, markNewAsRead),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DisappearingScaffold(
|
|
||||||
isInvertedLayout = false,
|
|
||||||
topBar = {
|
|
||||||
Column {
|
|
||||||
MainTopBar(accountViewModel, nav)
|
|
||||||
ChatroomListOnlyTabs(
|
|
||||||
pagerState,
|
|
||||||
tabs,
|
|
||||||
{ markKnownAsRead.value = true },
|
|
||||||
{ markNewAsRead.value = true },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
bottomBar = {
|
|
||||||
AppBottomBar(Route.Message, accountViewModel) { route, _ ->
|
|
||||||
if (route == Route.Message) {
|
|
||||||
tabs[pagerState.currentPage].feedContentState.sendToTop()
|
|
||||||
} else {
|
|
||||||
nav.newStack(route.base)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
floatingButton = {
|
|
||||||
ChannelFabColumn(accountViewModel, nav)
|
|
||||||
},
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
) {
|
|
||||||
ChatroomListTabs(
|
|
||||||
pagerState,
|
|
||||||
tabs,
|
|
||||||
it,
|
|
||||||
accountViewModel,
|
|
||||||
nav,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun WatchLifecycleAndRefreshDataSource(accountViewModel: AccountViewModel) {
|
|
||||||
val lifeCycleOwner = LocalLifecycleOwner.current
|
|
||||||
DisposableEffect(lifeCycleOwner) {
|
|
||||||
val observer =
|
|
||||||
LifecycleEventObserver { _, event ->
|
|
||||||
if (event == Lifecycle.Event.ON_RESUME) {
|
|
||||||
NostrChatroomListDataSource.account = accountViewModel.account
|
|
||||||
NostrChatroomListDataSource.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lifeCycleOwner.lifecycle.addObserver(observer)
|
|
||||||
onDispose { lifeCycleOwner.lifecycle.removeObserver(observer) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
private fun ChatroomListTabs(
|
|
||||||
pagerState: PagerState,
|
|
||||||
tabs: List<ChatroomListTabItem>,
|
|
||||||
paddingValues: PaddingValues,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: INav,
|
|
||||||
) {
|
|
||||||
HorizontalPager(
|
|
||||||
contentPadding = paddingValues,
|
|
||||||
state = pagerState,
|
|
||||||
userScrollEnabled = false,
|
|
||||||
) { page ->
|
|
||||||
ChatroomListFeedView(
|
|
||||||
feedContentState = tabs[page].feedContentState,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
markAsRead = tabs[page].markAsRead,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
private fun ChatroomListOnlyTabs(
|
|
||||||
pagerState: PagerState,
|
|
||||||
tabs: List<ChatroomListTabItem>,
|
|
||||||
onMarkKnownAsRead: () -> Unit,
|
|
||||||
onMarkNewAsRead: () -> Unit,
|
|
||||||
) {
|
|
||||||
var moreActionsExpanded by remember { mutableStateOf(false) }
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
Box(Modifier.fillMaxWidth()) {
|
|
||||||
TabRow(
|
|
||||||
containerColor = Color.Transparent,
|
|
||||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
|
||||||
selectedTabIndex = pagerState.currentPage,
|
|
||||||
modifier = TabRowHeight,
|
|
||||||
) {
|
|
||||||
tabs.forEachIndexed { index, tab ->
|
|
||||||
Tab(
|
|
||||||
selected = pagerState.currentPage == index,
|
|
||||||
text = { Text(text = stringRes(tab.resource)) },
|
|
||||||
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IconButton(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.size(40.dp)
|
|
||||||
.align(Alignment.CenterEnd),
|
|
||||||
onClick = { moreActionsExpanded = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Default.MoreVert,
|
|
||||||
contentDescription = stringRes(id = R.string.more_options),
|
|
||||||
tint = MaterialTheme.colorScheme.placeholderText,
|
|
||||||
)
|
|
||||||
|
|
||||||
ChatroomTabMenu(
|
|
||||||
moreActionsExpanded,
|
|
||||||
{ moreActionsExpanded = false },
|
|
||||||
onMarkKnownAsRead,
|
|
||||||
onMarkNewAsRead,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun WatchAccountForListScreen(
|
|
||||||
knownFeedContentState: FeedContentState,
|
|
||||||
newFeedContentState: FeedContentState,
|
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
) {
|
|
||||||
LaunchedEffect(accountViewModel) {
|
|
||||||
launch(Dispatchers.IO) {
|
|
||||||
NostrChatroomListDataSource.account = accountViewModel.account
|
|
||||||
NostrChatroomListDataSource.start()
|
|
||||||
knownFeedContentState.invalidateData(true)
|
|
||||||
newFeedContentState.invalidateData(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
class ChatroomListTabItem(
|
|
||||||
val resource: Int,
|
|
||||||
val feedContentState: FeedContentState,
|
|
||||||
val markAsRead: MutableState<Boolean>,
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ChatroomTabMenu(
|
|
||||||
expanded: Boolean,
|
|
||||||
onDismiss: () -> Unit,
|
|
||||||
onMarkKnownAsRead: () -> Unit,
|
|
||||||
onMarkNewAsRead: () -> Unit,
|
|
||||||
) {
|
|
||||||
DropdownMenu(expanded = expanded, onDismissRequest = onDismiss) {
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringRes(R.string.mark_all_known_as_read)) },
|
|
||||||
onClick = {
|
|
||||||
onMarkKnownAsRead()
|
|
||||||
onDismiss()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringRes(R.string.mark_all_new_as_read)) },
|
|
||||||
onClick = {
|
|
||||||
onMarkNewAsRead()
|
|
||||||
onDismiss()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
DropdownMenuItem(
|
|
||||||
text = { Text(stringRes(R.string.mark_all_as_read)) },
|
|
||||||
onClick = {
|
|
||||||
onMarkKnownAsRead()
|
|
||||||
onMarkNewAsRead()
|
|
||||||
onDismiss()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list
|
||||||
|
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.singlepane.MessagesSinglePane
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.twopane.MessagesTwoPane
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesScreen(
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val windowSizeClass by accountViewModel.settings.windowSizeClass
|
||||||
|
|
||||||
|
val twoPane by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
when (windowSizeClass?.widthSizeClass) {
|
||||||
|
WindowWidthSizeClass.Compact -> false
|
||||||
|
WindowWidthSizeClass.Expanded,
|
||||||
|
WindowWidthSizeClass.Medium,
|
||||||
|
-> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (twoPane && windowSizeClass != null) {
|
||||||
|
MessagesTwoPane(
|
||||||
|
knownFeedContentState = accountViewModel.feedStates.dmKnown,
|
||||||
|
newFeedContentState = accountViewModel.feedStates.dmNew,
|
||||||
|
widthSizeClass = windowSizeClass!!.widthSizeClass,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
MessagesSinglePane(
|
||||||
|
knownFeedContentState = accountViewModel.feedStates.dmKnown,
|
||||||
|
newFeedContentState = accountViewModel.feedStates.dmNew,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
|
||||||
|
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WatchAccountForListScreen(
|
||||||
|
knownFeedContentState: FeedContentState,
|
||||||
|
newFeedContentState: FeedContentState,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
) {
|
||||||
|
LaunchedEffect(accountViewModel) {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
NostrChatroomListDataSource.account = accountViewModel.account
|
||||||
|
NostrChatroomListDataSource.start()
|
||||||
|
knownFeedContentState.invalidateData(true)
|
||||||
|
newFeedContentState.invalidateData(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
|
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun WatchLifecycleAndRefreshDataSource(accountViewModel: AccountViewModel) {
|
||||||
|
val lifeCycleOwner = LocalLifecycleOwner.current
|
||||||
|
DisposableEffect(lifeCycleOwner) {
|
||||||
|
val observer =
|
||||||
|
LifecycleEventObserver { _, event ->
|
||||||
|
if (event == Lifecycle.Event.ON_RESUME) {
|
||||||
|
NostrChatroomListDataSource.account = accountViewModel.account
|
||||||
|
NostrChatroomListDataSource.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lifeCycleOwner.lifecycle.addObserver(observer)
|
||||||
|
onDispose { lifeCycleOwner.lifecycle.removeObserver(observer) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-2
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed
|
||||||
|
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
@@ -42,6 +42,7 @@ import com.vitorpamplona.amethyst.ui.feeds.LoadingFeed
|
|||||||
import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox
|
import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.ChatroomHeaderCompose
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||||
|
|
||||||
@@ -52,7 +53,9 @@ fun ChatroomListFeedView(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
markAsRead: MutableState<Boolean>,
|
markAsRead: MutableState<Boolean>,
|
||||||
) {
|
) {
|
||||||
RefresheableBox(feedContentState, true) { CrossFadeState(feedContentState, accountViewModel, nav, markAsRead) }
|
RefresheableBox(feedContentState, true) {
|
||||||
|
CrossFadeState(feedContentState, accountViewModel, nav, markAsRead)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
+169
@@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.PagerState
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
|
import androidx.compose.material3.TabRow
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class MessagesTabItem(
|
||||||
|
val resource: Int,
|
||||||
|
val feedContentState: FeedContentState,
|
||||||
|
val markAsRead: MutableState<Boolean>,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesTabHeader(
|
||||||
|
pagerState: PagerState,
|
||||||
|
tabs: List<MessagesTabItem>,
|
||||||
|
onMarkKnownAsRead: () -> Unit,
|
||||||
|
onMarkNewAsRead: () -> Unit,
|
||||||
|
) {
|
||||||
|
var moreActionsExpanded by remember { mutableStateOf(false) }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
Box(Modifier.fillMaxWidth()) {
|
||||||
|
TabRow(
|
||||||
|
containerColor = Color.Transparent,
|
||||||
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||||
|
selectedTabIndex = pagerState.currentPage,
|
||||||
|
modifier = TabRowHeight,
|
||||||
|
) {
|
||||||
|
tabs.forEachIndexed { index, tab ->
|
||||||
|
Tab(
|
||||||
|
selected = pagerState.currentPage == index,
|
||||||
|
text = { Text(text = stringRes(tab.resource)) },
|
||||||
|
onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.size(40.dp)
|
||||||
|
.align(Alignment.CenterEnd),
|
||||||
|
onClick = { moreActionsExpanded = true },
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.MoreVert,
|
||||||
|
contentDescription = stringRes(id = R.string.more_options),
|
||||||
|
tint = MaterialTheme.colorScheme.placeholderText,
|
||||||
|
)
|
||||||
|
|
||||||
|
MessagesTabMenu(
|
||||||
|
moreActionsExpanded,
|
||||||
|
{ moreActionsExpanded = false },
|
||||||
|
onMarkKnownAsRead,
|
||||||
|
onMarkNewAsRead,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesPager(
|
||||||
|
pagerState: PagerState,
|
||||||
|
tabs: List<MessagesTabItem>,
|
||||||
|
paddingValues: PaddingValues,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
HorizontalPager(
|
||||||
|
contentPadding = paddingValues,
|
||||||
|
state = pagerState,
|
||||||
|
userScrollEnabled = false,
|
||||||
|
) { page ->
|
||||||
|
ChatroomListFeedView(
|
||||||
|
feedContentState = tabs[page].feedContentState,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
markAsRead = tabs[page].markAsRead,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesTabMenu(
|
||||||
|
expanded: Boolean,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onMarkKnownAsRead: () -> Unit,
|
||||||
|
onMarkNewAsRead: () -> Unit,
|
||||||
|
) {
|
||||||
|
DropdownMenu(expanded = expanded, onDismissRequest = onDismiss) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringRes(R.string.mark_all_known_as_read)) },
|
||||||
|
onClick = {
|
||||||
|
onMarkKnownAsRead()
|
||||||
|
onDismiss()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringRes(R.string.mark_all_new_as_read)) },
|
||||||
|
onClick = {
|
||||||
|
onMarkNewAsRead()
|
||||||
|
onDismiss()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text(stringRes(R.string.mark_all_as_read)) },
|
||||||
|
onClick = {
|
||||||
|
onMarkKnownAsRead()
|
||||||
|
onMarkNewAsRead()
|
||||||
|
onDismiss()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.singlepane
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.AppBottomBar
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.MainTopBar
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.ChannelFabColumn
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.WatchAccountForListScreen
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.WatchLifecycleAndRefreshDataSource
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesPager
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesTabHeader
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesTabItem
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesSinglePane(
|
||||||
|
knownFeedContentState: FeedContentState,
|
||||||
|
newFeedContentState: FeedContentState,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val pagerState = rememberPagerState { 2 }
|
||||||
|
|
||||||
|
val markKnownAsRead = remember { mutableStateOf(false) }
|
||||||
|
val markNewAsRead = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
WatchAccountForListScreen(knownFeedContentState, newFeedContentState, accountViewModel)
|
||||||
|
WatchLifecycleAndRefreshDataSource(accountViewModel)
|
||||||
|
|
||||||
|
val tabs by
|
||||||
|
remember(knownFeedContentState, markKnownAsRead) {
|
||||||
|
derivedStateOf {
|
||||||
|
listOf(
|
||||||
|
MessagesTabItem(R.string.known, knownFeedContentState, markKnownAsRead),
|
||||||
|
MessagesTabItem(R.string.new_requests, newFeedContentState, markNewAsRead),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DisappearingScaffold(
|
||||||
|
isInvertedLayout = false,
|
||||||
|
topBar = {
|
||||||
|
Column {
|
||||||
|
MainTopBar(accountViewModel, nav)
|
||||||
|
MessagesTabHeader(
|
||||||
|
pagerState,
|
||||||
|
tabs,
|
||||||
|
{ markKnownAsRead.value = true },
|
||||||
|
{ markNewAsRead.value = true },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bottomBar = {
|
||||||
|
AppBottomBar(Route.Message, accountViewModel) { route, _ ->
|
||||||
|
if (route == Route.Message) {
|
||||||
|
tabs[pagerState.currentPage].feedContentState.sendToTop()
|
||||||
|
} else {
|
||||||
|
nav.newStack(route.base)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
floatingButton = {
|
||||||
|
ChannelFabColumn(accountViewModel, nav)
|
||||||
|
},
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
) {
|
||||||
|
MessagesPager(
|
||||||
|
pagerState,
|
||||||
|
tabs,
|
||||||
|
it,
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.twopane
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.WatchAccountForListScreen
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.WatchLifecycleAndRefreshDataSource
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesPager
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesTabHeader
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.feed.MessagesTabItem
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChatroomList(
|
||||||
|
knownFeedContentState: FeedContentState,
|
||||||
|
newFeedContentState: FeedContentState,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
val pagerState = rememberPagerState { 2 }
|
||||||
|
|
||||||
|
val markKnownAsRead = remember { mutableStateOf(false) }
|
||||||
|
val markNewAsRead = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
WatchAccountForListScreen(knownFeedContentState, newFeedContentState, accountViewModel)
|
||||||
|
WatchLifecycleAndRefreshDataSource(accountViewModel)
|
||||||
|
|
||||||
|
val tabs by
|
||||||
|
remember(knownFeedContentState, markKnownAsRead) {
|
||||||
|
derivedStateOf {
|
||||||
|
listOf(
|
||||||
|
MessagesTabItem(R.string.known, knownFeedContentState, markKnownAsRead),
|
||||||
|
MessagesTabItem(R.string.new_requests, newFeedContentState, markNewAsRead),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
MessagesTabHeader(
|
||||||
|
pagerState,
|
||||||
|
tabs,
|
||||||
|
{ markKnownAsRead.value = true },
|
||||||
|
{ markNewAsRead.value = true },
|
||||||
|
)
|
||||||
|
|
||||||
|
MessagesPager(
|
||||||
|
pagerState,
|
||||||
|
tabs,
|
||||||
|
PaddingValues(0.dp),
|
||||||
|
accountViewModel,
|
||||||
|
nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.twopane
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.systemBarsPadding
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.google.accompanist.adaptive.FoldAwareConfiguration
|
||||||
|
import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy
|
||||||
|
import com.google.accompanist.adaptive.TwoPane
|
||||||
|
import com.vitorpamplona.amethyst.ui.feeds.FeedContentState
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.AppBottomBar
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.MainTopBar
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.Route
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.ChannelFabColumn
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.Chatroom
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.Channel
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size20dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MessagesTwoPane(
|
||||||
|
knownFeedContentState: FeedContentState,
|
||||||
|
newFeedContentState: FeedContentState,
|
||||||
|
widthSizeClass: WindowWidthSizeClass,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: INav,
|
||||||
|
) {
|
||||||
|
/** The index of the currently selected word, or `null` if none is selected */
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val twoPaneNav = remember { TwoPaneNav(nav, scope) }
|
||||||
|
|
||||||
|
val strategy =
|
||||||
|
remember {
|
||||||
|
if (widthSizeClass == WindowWidthSizeClass.Expanded) {
|
||||||
|
HorizontalTwoPaneStrategy(
|
||||||
|
splitFraction = 1f / 3f,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
HorizontalTwoPaneStrategy(
|
||||||
|
splitFraction = 1f / 2.5f,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DisappearingScaffold(
|
||||||
|
isInvertedLayout = false,
|
||||||
|
topBar = {
|
||||||
|
Column {
|
||||||
|
MainTopBar(accountViewModel, nav)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bottomBar = {
|
||||||
|
AppBottomBar(Route.Message, accountViewModel) { route, _ ->
|
||||||
|
nav.newStack(route.base)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
) { padding ->
|
||||||
|
TwoPane(
|
||||||
|
first = {
|
||||||
|
Box(Modifier.fillMaxSize().systemBarsPadding(), contentAlignment = Alignment.BottomEnd) {
|
||||||
|
ChatroomList(
|
||||||
|
knownFeedContentState,
|
||||||
|
newFeedContentState,
|
||||||
|
accountViewModel,
|
||||||
|
twoPaneNav,
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(Modifier.padding(Size20dp), contentAlignment = Alignment.Center) {
|
||||||
|
ChannelFabColumn(accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
second = {
|
||||||
|
Box(Modifier.fillMaxSize().systemBarsPadding()) {
|
||||||
|
twoPaneNav.innerNav.value?.let {
|
||||||
|
if (it.route == "Room") {
|
||||||
|
Chatroom(
|
||||||
|
roomId = it.id,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.route == "Channel") {
|
||||||
|
Channel(
|
||||||
|
channelId = it.id,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
strategy = strategy,
|
||||||
|
displayFeatures = accountViewModel.settings.displayFeatures.value,
|
||||||
|
foldAwareConfiguration = FoldAwareConfiguration.VerticalFoldsOnly,
|
||||||
|
modifier = Modifier.padding(padding).consumeWindowInsets(padding).fillMaxSize(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.twopane
|
||||||
|
|
||||||
|
import androidx.compose.material3.DrawerState
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class TwoPaneNav(
|
||||||
|
val nav: INav,
|
||||||
|
val scope: CoroutineScope,
|
||||||
|
) : INav {
|
||||||
|
override val drawerState: DrawerState = nav.drawerState
|
||||||
|
|
||||||
|
val innerNav = mutableStateOf<RouteId?>(null)
|
||||||
|
|
||||||
|
override fun nav(route: String) {
|
||||||
|
if (route.startsWith("Room/") || route.startsWith("Channel/")) {
|
||||||
|
innerNav.value = RouteId(route.substringBefore("/"), route.substringAfter("/"))
|
||||||
|
} else {
|
||||||
|
nav.nav(route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun nav(routeMaker: suspend () -> String) {
|
||||||
|
scope.launch(Dispatchers.Default) {
|
||||||
|
val route = routeMaker()
|
||||||
|
if (route.startsWith("Room/") || route.startsWith("Channel/")) {
|
||||||
|
innerNav.value = RouteId(route.substringBefore("/"), route.substringAfter("/"))
|
||||||
|
} else {
|
||||||
|
nav.nav(route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newStack(route: String) {
|
||||||
|
nav.newStack(route)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popBack() {
|
||||||
|
nav.popBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popUpTo(
|
||||||
|
route: String,
|
||||||
|
upTo: String,
|
||||||
|
) {
|
||||||
|
nav.popUpTo(route, upTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun closeDrawer() {
|
||||||
|
nav.closeDrawer()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun openDrawer() {
|
||||||
|
nav.openDrawer()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RouteId(
|
||||||
|
val route: String,
|
||||||
|
val id: String,
|
||||||
|
)
|
||||||
|
}
|
||||||
+36
-2
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
@@ -106,7 +106,7 @@ private fun BubblePreview() {
|
|||||||
|
|
||||||
ChatBubbleLayout(
|
ChatBubbleLayout(
|
||||||
isLoggedInUser = true,
|
isLoggedInUser = true,
|
||||||
isDraft = true,
|
isDraft = false,
|
||||||
innerQuote = false,
|
innerQuote = false,
|
||||||
isComplete = true,
|
isComplete = true,
|
||||||
hasDetailsToShow = true,
|
hasDetailsToShow = true,
|
||||||
@@ -138,6 +138,40 @@ private fun BubblePreview() {
|
|||||||
Text("This is a very long long loong note")
|
Text("This is a very long long loong note")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatBubbleLayout(
|
||||||
|
isLoggedInUser = true,
|
||||||
|
isDraft = true,
|
||||||
|
innerQuote = false,
|
||||||
|
isComplete = true,
|
||||||
|
hasDetailsToShow = true,
|
||||||
|
drawAuthorInfo = true,
|
||||||
|
parentBackgroundColor = backgroundBubbleColor,
|
||||||
|
onClick = { false },
|
||||||
|
onAuthorClick = {},
|
||||||
|
actionMenu = { onDismiss ->
|
||||||
|
},
|
||||||
|
drawAuthorLine = {
|
||||||
|
UserDisplayNameLayout(
|
||||||
|
picture = {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.Person,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.size(Size20dp)
|
||||||
|
.clip(CircleShape),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
name = {
|
||||||
|
Text("Me", fontWeight = FontWeight.Bold)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
detailRow = { Text("Relays and Actions") },
|
||||||
|
) { backgroundBubbleColor ->
|
||||||
|
Text("This is a draft note")
|
||||||
|
}
|
||||||
|
|
||||||
ChatBubbleLayout(
|
ChatBubbleLayout(
|
||||||
isLoggedInUser = true,
|
isLoggedInUser = true,
|
||||||
isDraft = false,
|
isDraft = false,
|
||||||
+1
-3
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
@@ -40,11 +40,9 @@ import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerName
|
|||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
|
||||||
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMediaProcessing
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.quartz.nip01Core.tags.geohash.geohash
|
|
||||||
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
import com.vitorpamplona.quartz.nip17Dm.base.ChatroomKey
|
||||||
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
import com.vitorpamplona.quartz.nip17Dm.files.ChatMessageEncryptedFileHeaderEvent
|
||||||
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
|
import com.vitorpamplona.quartz.nip17Dm.files.encryption.AESGCM
|
||||||
import com.vitorpamplona.quartz.nip30CustomEmoji.emojis
|
|
||||||
import com.vitorpamplona.quartz.nip31Alts.alt
|
import com.vitorpamplona.quartz.nip31Alts.alt
|
||||||
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
import com.vitorpamplona.quartz.nip36SensitiveContent.contentWarning
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
+1
-2
@@ -18,14 +18,13 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
+6
-6
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@@ -103,11 +103,11 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.CloseButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.PostButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.PostButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.DisplayRoomSubject
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.DisplayRoomSubject
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.DisplayUserSetAsSubject
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.DisplayUserSetAsSubject
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.LoadUser
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.LoadUser
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils.DisplayReplyingToNote
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils.MyTextField
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.MyTextField
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
|
import com.vitorpamplona.amethyst.ui.theme.BottomTopHeight
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
+5
-6
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -31,7 +31,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
@@ -120,10 +119,10 @@ import com.vitorpamplona.amethyst.ui.note.timeAgoShort
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.NostrChannelFeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.NostrChannelFeedViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.RefreshingChatroomFeedView
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.RefreshingChatroomFeedView
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ThinSendButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ThinSendButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils.DisplayReplyingToNote
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.DisplayReplyingToNote
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils.MyTextField
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils.MyTextField
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.home.CrossfadeCheckIfVideoIsOnline
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.equalImmutableLists
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
+2
-2
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils
|
||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -39,7 +39,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ChatroomMessageCompose
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ChatroomMessageCompose
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
|
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.utils
|
package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.utils
|
||||||
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
import androidx.compose.foundation.interaction.collectIsFocusedAsState
|
||||||
+1
-1
@@ -75,7 +75,7 @@ import com.vitorpamplona.amethyst.ui.note.UserCompose
|
|||||||
import com.vitorpamplona.amethyst.ui.note.elements.ObserveRelayListForSearchAndDisplayIfNotFound
|
import com.vitorpamplona.amethyst.ui.note.elements.ObserveRelayListForSearchAndDisplayIfNotFound
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.DisappearingScaffold
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.ChannelName
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.list.ChannelName
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||||
|
|||||||
+2
-2
@@ -147,8 +147,8 @@ import com.vitorpamplona.amethyst.ui.note.types.VideoDisplay
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.LevelFeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.LevelFeedViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.RenderFeedState
|
import com.vitorpamplona.amethyst.ui.screen.RenderFeedState
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.private.ThinSendButton
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.private.ThinSendButton
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chatlist.public.ChannelHeader
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.public.ChannelHeader
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.mockAccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
|
|||||||
Reference in New Issue
Block a user