feat: double click management (#130)
This commit is contained in:
parent
aecf2549fb
commit
e474c9227d
@ -26,6 +26,7 @@ object IconSize {
|
|||||||
val s = 20.dp
|
val s = 20.dp
|
||||||
val m = 26.dp
|
val m = 26.dp
|
||||||
val l = 30.dp
|
val l = 30.dp
|
||||||
|
val xl = 46.dp
|
||||||
val xxl = 60.dp
|
val xxl = 60.dp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ fun FloatingActionButtonMenu(
|
|||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
fabExpanded = false
|
fabExpanded = false
|
||||||
item.onSelected?.invoke()
|
item.onSelected?.invoke()
|
||||||
},
|
},
|
||||||
|
@ -111,8 +111,8 @@ class InboxChatScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
|
@ -46,6 +46,7 @@ interface CommunityDetailMviModel :
|
|||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val currentUserId: Int? = null,
|
val currentUserId: Int? = null,
|
||||||
val swipeActionsEnabled: Boolean = true,
|
val swipeActionsEnabled: Boolean = true,
|
||||||
|
val doubleTapActionEnabled: Boolean = false,
|
||||||
val postLayout: PostLayout = PostLayout.Card,
|
val postLayout: PostLayout = PostLayout.Card,
|
||||||
val fullHeightImages: Boolean = true,
|
val fullHeightImages: Boolean = true,
|
||||||
val separateUpAndDownVotes: Boolean = false,
|
val separateUpAndDownVotes: Boolean = false,
|
||||||
|
@ -237,7 +237,7 @@ class CommunityDetailScreen(
|
|||||||
if (!isOnOtherInstance && uiState.isLogged) {
|
if (!isOnOtherInstance && uiState.isLogged) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
when (uiState.community.subscribed) {
|
when (uiState.community.subscribed) {
|
||||||
true -> model.reduce(CommunityDetailMviModel.Intent.Unsubscribe)
|
true -> model.reduce(CommunityDetailMviModel.Intent.Unsubscribe)
|
||||||
false -> model.reduce(CommunityDetailMviModel.Intent.Subscribe)
|
false -> model.reduce(CommunityDetailMviModel.Intent.Subscribe)
|
||||||
@ -259,11 +259,11 @@ class CommunityDetailScreen(
|
|||||||
// sort button
|
// sort button
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
expandTop = true,
|
expandTop = true,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = uiState.sortType.toIcon(),
|
||||||
@ -297,7 +297,7 @@ class CommunityDetailScreen(
|
|||||||
modifier = Modifier.onGloballyPositioned {
|
modifier = Modifier.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
}.padding(start = Spacing.s).onClick(
|
}.padding(start = Spacing.s).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = true
|
optionsExpanded = true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -321,7 +321,7 @@ class CommunityDetailScreen(
|
|||||||
horizontal = Spacing.m,
|
horizontal = Spacing.m,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = false
|
optionsExpanded = false
|
||||||
when (option.id) {
|
when (option.id) {
|
||||||
OptionId.BlockInstance -> model.reduce(
|
OptionId.BlockInstance -> model.reduce(
|
||||||
@ -333,8 +333,7 @@ class CommunityDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.InfoInstance -> {
|
OptionId.InfoInstance -> {
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(
|
|
||||||
InstanceInfoScreen(
|
InstanceInfoScreen(
|
||||||
url = uiState.community.instanceUrl,
|
url = uiState.community.instanceUrl,
|
||||||
),
|
),
|
||||||
@ -342,8 +341,7 @@ class CommunityDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Info -> {
|
OptionId.Info -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CommunityInfoScreen(uiState.community),
|
CommunityInfoScreen(uiState.community),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -359,12 +357,11 @@ class CommunityDetailScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
val navigator = navigationCoordinator.getRootNavigator()
|
if (navigationCoordinator.canPop) {
|
||||||
if (navigator?.canPop == true) {
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigator.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -437,7 +434,7 @@ class CommunityDetailScreen(
|
|||||||
val screen = CreatePostScreen(
|
val screen = CreatePostScreen(
|
||||||
communityId = uiState.community.id,
|
communityId = uiState.community.id,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -476,8 +473,7 @@ class CommunityDetailScreen(
|
|||||||
community = uiState.community,
|
community = uiState.community,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
onOpenImage = rememberCallbackArgs { url ->
|
onOpenImage = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||||
?.push(ZoomableImageScreen(url))
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(Spacing.m))
|
Spacer(modifier = Modifier.height(Spacing.m))
|
||||||
@ -559,15 +555,27 @@ class CommunityDetailScreen(
|
|||||||
post.id
|
post.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = post,
|
post = post,
|
||||||
otherInstance = otherInstanceName,
|
otherInstance = otherInstanceName,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled || !uiState.isLogged || isOnOtherInstance) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
CommunityDetailMviModel.Intent.UpVotePost(
|
||||||
|
id = post.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(
|
UserDetailScreen(
|
||||||
user = user,
|
user = user,
|
||||||
otherInstance = otherInstanceName,
|
otherInstance = otherInstanceName,
|
||||||
@ -609,8 +617,7 @@ class CommunityDetailScreen(
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = post,
|
originalPost = post,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
?.show(screen)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs(model) { url ->
|
onImageClick = rememberCallbackArgs(model) { url ->
|
||||||
@ -619,7 +626,7 @@ class CommunityDetailScreen(
|
|||||||
post.id
|
post.id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -680,22 +687,19 @@ class CommunityDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreatePostScreen(editedPost = post)
|
CreatePostScreen(editedPost = post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(postId = post.id)
|
CreateReportScreen(postId = post.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreatePostScreen(crossPost = post)
|
CreatePostScreen(crossPost = post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ class CommunityDetailViewModel(
|
|||||||
it.copy(
|
it.copy(
|
||||||
blurNsfw = settings.blurNsfw,
|
blurNsfw = settings.blurNsfw,
|
||||||
swipeActionsEnabled = settings.enableSwipeActions,
|
swipeActionsEnabled = settings.enableSwipeActions,
|
||||||
|
doubleTapActionEnabled = settings.enableDoubleTapAction,
|
||||||
sortType = settings.defaultPostSortType.toSortType(),
|
sortType = settings.defaultPostSortType.toSortType(),
|
||||||
fullHeightImages = settings.fullHeightImages,
|
fullHeightImages = settings.fullHeightImages,
|
||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
|
@ -21,7 +21,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepos
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
@ -42,6 +41,7 @@ fun CommentCard(
|
|||||||
autoLoadImages: Boolean = true,
|
autoLoadImages: Boolean = true,
|
||||||
options: List<Option> = emptyList(),
|
options: List<Option> = emptyList(),
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
onUpVote: (() -> Unit)? = null,
|
onUpVote: (() -> Unit)? = null,
|
||||||
onDownVote: (() -> Unit)? = null,
|
onDownVote: (() -> Unit)? = null,
|
||||||
onSave: (() -> Unit)? = null,
|
onSave: (() -> Unit)? = null,
|
||||||
@ -63,9 +63,10 @@ fun CommentCard(
|
|||||||
endColor = MaterialTheme.colorScheme.background,
|
endColor = MaterialTheme.colorScheme.background,
|
||||||
)
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.onClick(rememberCallback {
|
modifier = Modifier.onClick(
|
||||||
onClick?.invoke()
|
onClick = onClick ?: {},
|
||||||
}).padding(
|
onDoubleClick = onDoubleClick ?: {}
|
||||||
|
).padding(
|
||||||
start = if (hideIndent) 0.dp else (INDENT_AMOUNT * comment.depth).dp
|
start = if (hideIndent) 0.dp else (INDENT_AMOUNT * comment.depth).dp
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
@ -96,6 +97,7 @@ fun CommentCard(
|
|||||||
text = comment.text,
|
text = comment.text,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PostCardFooter(
|
PostCardFooter(
|
||||||
|
@ -38,6 +38,7 @@ fun CommunityAndCreatorInfo(
|
|||||||
onOpenCommunity: ((CommunityModel) -> Unit)? = null,
|
onOpenCommunity: ((CommunityModel) -> Unit)? = null,
|
||||||
onOpenCreator: ((UserModel) -> Unit)? = null,
|
onOpenCreator: ((UserModel) -> Unit)? = null,
|
||||||
onToggleExpanded: (() -> Unit)? = null,
|
onToggleExpanded: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val communityName = community?.name.orEmpty()
|
val communityName = community?.name.orEmpty()
|
||||||
val communityIcon = community?.icon.orEmpty()
|
val communityIcon = community?.icon.orEmpty()
|
||||||
@ -56,11 +57,12 @@ fun CommunityAndCreatorInfo(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
)
|
)
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
@ -73,11 +75,12 @@ fun CommunityAndCreatorInfo(
|
|||||||
} else {
|
} else {
|
||||||
PlaceholderImage(
|
PlaceholderImage(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
),
|
),
|
||||||
size = IconSize.l,
|
size = IconSize.l,
|
||||||
title = communityName,
|
title = communityName,
|
||||||
@ -88,11 +91,12 @@ fun CommunityAndCreatorInfo(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
)
|
)
|
||||||
.padding(Spacing.xxxs)
|
.padding(Spacing.xxxs)
|
||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
@ -105,11 +109,12 @@ fun CommunityAndCreatorInfo(
|
|||||||
} else {
|
} else {
|
||||||
PlaceholderImage(
|
PlaceholderImage(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
),
|
),
|
||||||
size = iconSize,
|
size = iconSize,
|
||||||
title = creatorName,
|
title = creatorName,
|
||||||
@ -123,9 +128,10 @@ fun CommunityAndCreatorInfo(
|
|||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
),
|
),
|
||||||
text = buildString {
|
text = buildString {
|
||||||
append(communityName)
|
append(communityName)
|
||||||
@ -141,9 +147,10 @@ fun CommunityAndCreatorInfo(
|
|||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
),
|
),
|
||||||
text = buildString {
|
text = buildString {
|
||||||
append(creatorName)
|
append(creatorName)
|
||||||
@ -161,7 +168,7 @@ fun CommunityAndCreatorInfo(
|
|||||||
val expandedModifier = Modifier
|
val expandedModifier = Modifier
|
||||||
.padding(end = Spacing.xs)
|
.padding(end = Spacing.xs)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onToggleExpanded?.invoke()
|
onToggleExpanded?.invoke()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -92,7 +92,7 @@ fun CommunityHeader(
|
|||||||
.size(IconSize.xxl)
|
.size(IconSize.xxl)
|
||||||
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenImage?.invoke(communityIcon)
|
onOpenImage?.invoke(communityIcon)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -34,11 +34,13 @@ fun InboxCard(
|
|||||||
autoLoadImages: Boolean = true,
|
autoLoadImages: Boolean = true,
|
||||||
separateUpAndDownVotes: Boolean = true,
|
separateUpAndDownVotes: Boolean = true,
|
||||||
postLayout: PostLayout = PostLayout.Card,
|
postLayout: PostLayout = PostLayout.Card,
|
||||||
|
options: List<Option> = emptyList(),
|
||||||
onOpenPost: (PostModel) -> Unit,
|
onOpenPost: (PostModel) -> Unit,
|
||||||
onOpenCreator: (UserModel) -> Unit,
|
onOpenCreator: (UserModel) -> Unit,
|
||||||
onOpenCommunity: (CommunityModel) -> Unit,
|
onOpenCommunity: (CommunityModel) -> Unit,
|
||||||
onUpVote: ((CommentModel) -> Unit)? = null,
|
onUpVote: ((CommentModel) -> Unit)? = null,
|
||||||
onDownVote: ((CommentModel) -> Unit)? = null,
|
onDownVote: ((CommentModel) -> Unit)? = null,
|
||||||
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.let {
|
modifier = Modifier.let {
|
||||||
@ -52,7 +54,7 @@ fun InboxCard(
|
|||||||
it.background(MaterialTheme.colorScheme.background)
|
it.background(MaterialTheme.colorScheme.background)
|
||||||
}
|
}
|
||||||
}.onClick(
|
}.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenPost(mention.post)
|
onOpenPost(mention.post)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -92,6 +94,7 @@ fun InboxCard(
|
|||||||
separateUpAndDownVotes = separateUpAndDownVotes,
|
separateUpAndDownVotes = separateUpAndDownVotes,
|
||||||
upVoted = mention.myVote > 0,
|
upVoted = mention.myVote > 0,
|
||||||
downVoted = mention.myVote < 0,
|
downVoted = mention.myVote < 0,
|
||||||
|
options = options,
|
||||||
onOpenCommunity = onOpenCommunity,
|
onOpenCommunity = onOpenCommunity,
|
||||||
onOpenCreator = { user ->
|
onOpenCreator = { user ->
|
||||||
onOpenCreator(user)
|
onOpenCreator(user)
|
||||||
@ -102,6 +105,7 @@ fun InboxCard(
|
|||||||
onDownVote = {
|
onDownVote = {
|
||||||
onDownVote?.invoke(mention.comment)
|
onDownVote?.invoke(mention.comment)
|
||||||
},
|
},
|
||||||
|
onOptionSelected = onOptionSelected,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
|||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
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
|
||||||
@ -11,6 +12,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowCircleDown
|
import androidx.compose.material.icons.filled.ArrowCircleDown
|
||||||
import androidx.compose.material.icons.filled.ArrowCircleUp
|
import androidx.compose.material.icons.filled.ArrowCircleUp
|
||||||
|
import androidx.compose.material.icons.filled.MoreHoriz
|
||||||
import androidx.compose.material.icons.filled.Schedule
|
import androidx.compose.material.icons.filled.Schedule
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
@ -18,17 +20,23 @@ import androidx.compose.material3.Text
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.graphics.FilterQuality
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.layout.positionInParent
|
||||||
import androidx.compose.ui.text.SpanStyle
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
||||||
@ -36,6 +44,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
|
||||||
@ -50,6 +59,7 @@ fun InboxReplySubtitle(
|
|||||||
score: Int = 0,
|
score: Int = 0,
|
||||||
upvotes: Int = 0,
|
upvotes: Int = 0,
|
||||||
downvotes: Int = 0,
|
downvotes: Int = 0,
|
||||||
|
options: List<Option> = emptyList(),
|
||||||
separateUpAndDownVotes: Boolean = false,
|
separateUpAndDownVotes: Boolean = false,
|
||||||
upVoted: Boolean = false,
|
upVoted: Boolean = false,
|
||||||
downVoted: Boolean = false,
|
downVoted: Boolean = false,
|
||||||
@ -57,13 +67,17 @@ fun InboxReplySubtitle(
|
|||||||
onOpenCreator: ((UserModel) -> Unit)? = null,
|
onOpenCreator: ((UserModel) -> Unit)? = null,
|
||||||
onUpVote: (() -> Unit)? = null,
|
onUpVote: (() -> Unit)? = null,
|
||||||
onDownVote: (() -> Unit)? = null,
|
onDownVote: (() -> Unit)? = null,
|
||||||
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val buttonModifier = Modifier.size(IconSize.m).padding(4.dp)
|
val buttonModifier = Modifier.size(IconSize.m).padding(3.5.dp)
|
||||||
val themeRepository = remember { getThemeRepository() }
|
val themeRepository = remember { getThemeRepository() }
|
||||||
val upvoteColor by themeRepository.upvoteColor.collectAsState()
|
val upvoteColor by themeRepository.upvoteColor.collectAsState()
|
||||||
val downvoteColor by themeRepository.downvoteColor.collectAsState()
|
val downvoteColor by themeRepository.downvoteColor.collectAsState()
|
||||||
val defaultUpvoteColor = MaterialTheme.colorScheme.primary
|
val defaultUpvoteColor = MaterialTheme.colorScheme.primary
|
||||||
val defaultDownVoteColor = MaterialTheme.colorScheme.tertiary
|
val defaultDownVoteColor = MaterialTheme.colorScheme.tertiary
|
||||||
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
|
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
) {
|
) {
|
||||||
@ -83,7 +97,7 @@ fun InboxReplySubtitle(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
onOpenCreator?.invoke(creator)
|
onOpenCreator?.invoke(creator)
|
||||||
}
|
}
|
||||||
@ -124,7 +138,7 @@ fun InboxReplySubtitle(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
onOpenCommunity?.invoke(community)
|
onOpenCommunity?.invoke(community)
|
||||||
}
|
}
|
||||||
@ -162,6 +176,7 @@ fun InboxReplySubtitle(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
@ -174,11 +189,27 @@ fun InboxReplySubtitle(
|
|||||||
Text(
|
Text(
|
||||||
text = date?.prettifyDate() ?: "",
|
text = date?.prettifyDate() ?: "",
|
||||||
)
|
)
|
||||||
|
if (options.isNotEmpty()) {
|
||||||
|
Icon(
|
||||||
|
modifier = buttonModifier
|
||||||
|
.padding(top = Spacing.xxs)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
optionsOffset = it.positionInParent()
|
||||||
|
}
|
||||||
|
.onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
optionsExpanded = true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
imageVector = Icons.Default.MoreHoriz,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier
|
modifier = buttonModifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onUpVote?.invoke()
|
onUpVote?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -209,7 +240,9 @@ fun InboxReplySubtitle(
|
|||||||
append(downvoteText)
|
append(downvoteText)
|
||||||
if (downVoted) {
|
if (downVoted) {
|
||||||
addStyle(
|
addStyle(
|
||||||
style = SpanStyle(color = downvoteColor ?: defaultDownVoteColor),
|
style = SpanStyle(
|
||||||
|
color = downvoteColor ?: defaultDownVoteColor
|
||||||
|
),
|
||||||
start = upvoteText.length + 3,
|
start = upvoteText.length + 3,
|
||||||
end = upvoteText.length + 3 + downvoteText.length
|
end = upvoteText.length + 3 + downvoteText.length
|
||||||
)
|
)
|
||||||
@ -225,7 +258,9 @@ fun InboxReplySubtitle(
|
|||||||
)
|
)
|
||||||
} else if (downVoted) {
|
} else if (downVoted) {
|
||||||
addStyle(
|
addStyle(
|
||||||
style = SpanStyle(color = downvoteColor ?: defaultDownVoteColor),
|
style = SpanStyle(
|
||||||
|
color = downvoteColor ?: defaultDownVoteColor
|
||||||
|
),
|
||||||
start = 0,
|
start = 0,
|
||||||
end = length
|
end = length
|
||||||
)
|
)
|
||||||
@ -238,7 +273,7 @@ fun InboxReplySubtitle(
|
|||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier
|
modifier = buttonModifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onDownVote?.invoke()
|
onDownVote?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -253,5 +288,31 @@ fun InboxReplySubtitle(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
CustomDropDown(
|
||||||
|
expanded = optionsExpanded,
|
||||||
|
onDismiss = {
|
||||||
|
optionsExpanded = false
|
||||||
|
},
|
||||||
|
offset = DpOffset(
|
||||||
|
x = optionsOffset.x.toLocalDp(),
|
||||||
|
y = optionsOffset.y.toLocalDp(),
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
horizontal = Spacing.m,
|
||||||
|
vertical = Spacing.s,
|
||||||
|
).onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
optionsExpanded = false
|
||||||
|
onOptionSelected?.invoke(option.id)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
text = option.text,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,4 +17,6 @@ sealed class OptionId(val value: Int) {
|
|||||||
data object InfoInstance : OptionId(8)
|
data object InfoInstance : OptionId(8)
|
||||||
data object Block : OptionId(9)
|
data object Block : OptionId(9)
|
||||||
data object BlockInstance : OptionId(10)
|
data object BlockInstance : OptionId(10)
|
||||||
|
data object MarkRead : OptionId(11)
|
||||||
|
data object MarkUnread : OptionId(12)
|
||||||
}
|
}
|
@ -26,14 +26,17 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.toSize
|
import androidx.compose.ui.unit.toSize
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.web.WebViewScreen
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.looksLikeAnImage
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalPixel
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalPixel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
@ -63,6 +66,7 @@ fun PostCard(
|
|||||||
onImageClick: ((String) -> Unit)? = null,
|
onImageClick: ((String) -> Unit)? = null,
|
||||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.let {
|
modifier = modifier.let {
|
||||||
@ -74,7 +78,10 @@ fun PostCard(
|
|||||||
} else {
|
} else {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
}.onClick(rememberCallback { onClick?.invoke() }),
|
}.onClick(
|
||||||
|
onClick = onClick ?: {},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
|
),
|
||||||
) {
|
) {
|
||||||
if (postLayout != PostLayout.Compact) {
|
if (postLayout != PostLayout.Compact) {
|
||||||
ExtendedPost(
|
ExtendedPost(
|
||||||
@ -101,6 +108,7 @@ fun PostCard(
|
|||||||
onImageClick = onImageClick,
|
onImageClick = onImageClick,
|
||||||
onOptionSelected = onOptionSelected,
|
onOptionSelected = onOptionSelected,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
CompactPost(
|
CompactPost(
|
||||||
@ -119,6 +127,7 @@ fun PostCard(
|
|||||||
onImageClick = onImageClick,
|
onImageClick = onImageClick,
|
||||||
onOptionSelected = onOptionSelected,
|
onOptionSelected = onOptionSelected,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,6 +151,7 @@ private fun CompactPost(
|
|||||||
onImageClick: ((String) -> Unit)? = null,
|
onImageClick: ((String) -> Unit)? = null,
|
||||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier.background(MaterialTheme.colorScheme.background),
|
modifier = modifier.background(MaterialTheme.colorScheme.background),
|
||||||
@ -153,6 +163,7 @@ private fun CompactPost(
|
|||||||
onOpenCommunity = onOpenCommunity,
|
onOpenCommunity = onOpenCommunity,
|
||||||
onOpenCreator = onOpenCreator,
|
onOpenCreator = onOpenCreator,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(horizontal = Spacing.s),
|
modifier = Modifier.padding(horizontal = Spacing.s),
|
||||||
@ -165,6 +176,7 @@ private fun CompactPost(
|
|||||||
text = post.title,
|
text = post.title,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PostCardImage(
|
PostCardImage(
|
||||||
@ -180,6 +192,7 @@ private fun CompactPost(
|
|||||||
},
|
},
|
||||||
blurred = blurNsfw && post.nsfw,
|
blurred = blurNsfw && post.nsfw,
|
||||||
onImageClick = onImageClick,
|
onImageClick = onImageClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
PostCardFooter(
|
PostCardFooter(
|
||||||
@ -225,6 +238,7 @@ private fun ExtendedPost(
|
|||||||
onImageClick: ((String) -> Unit)? = null,
|
onImageClick: ((String) -> Unit)? = null,
|
||||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier.background(backgroundColor),
|
modifier = modifier.background(backgroundColor),
|
||||||
@ -237,6 +251,7 @@ private fun ExtendedPost(
|
|||||||
onOpenCommunity = onOpenCommunity,
|
onOpenCommunity = onOpenCommunity,
|
||||||
onOpenCreator = onOpenCreator,
|
onOpenCreator = onOpenCreator,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
ScaledContent {
|
ScaledContent {
|
||||||
PostCardTitle(
|
PostCardTitle(
|
||||||
@ -247,6 +262,7 @@ private fun ExtendedPost(
|
|||||||
text = post.title,
|
text = post.title,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,6 +285,7 @@ private fun ExtendedPost(
|
|||||||
imageUrl = post.imageUrl,
|
imageUrl = post.imageUrl,
|
||||||
blurred = blurNsfw && post.nsfw,
|
blurred = blurNsfw && post.nsfw,
|
||||||
onImageClick = onImageClick,
|
onImageClick = onImageClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
)
|
)
|
||||||
if (showBody) {
|
if (showBody) {
|
||||||
@ -290,6 +307,7 @@ private fun ExtendedPost(
|
|||||||
text = post.text,
|
text = post.text,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
if (limitBodyHeight && textHeightPx >= maxHeightPx) {
|
if (limitBodyHeight && textHeightPx >= maxHeightPx) {
|
||||||
Box(
|
Box(
|
||||||
@ -307,9 +325,25 @@ private fun ExtendedPost(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (post.url != post.imageUrl) {
|
if (post.url != post.imageUrl && !post.url.isNullOrEmpty()) {
|
||||||
|
val url = post.url.orEmpty()
|
||||||
|
val settingsRepository = remember { getSettingsRepository() }
|
||||||
|
val uriHandler = LocalUriHandler.current
|
||||||
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
|
|
||||||
PostLinkBanner(
|
PostLinkBanner(
|
||||||
modifier = Modifier.padding(vertical = Spacing.xs),
|
modifier = Modifier
|
||||||
|
.padding(vertical = Spacing.xs)
|
||||||
|
.onClick(
|
||||||
|
onClick = {
|
||||||
|
if (settingsRepository.currentSettings.value.openUrlsInExternalBrowser) {
|
||||||
|
uriHandler.openUri(url)
|
||||||
|
} else {
|
||||||
|
navigationCoordinator.pushScreen(WebViewScreen(url))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
|
),
|
||||||
url = post.url?.takeIf { !it.looksLikeAnImage }.orEmpty(),
|
url = post.url?.takeIf { !it.looksLikeAnImage }.orEmpty(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ fun PostCardBody(
|
|||||||
text: String,
|
text: String,
|
||||||
autoLoadImages: Boolean = true,
|
autoLoadImages: Boolean = true,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
@ -27,17 +28,17 @@ fun PostCardBody(
|
|||||||
inlineImages = false,
|
inlineImages = false,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onOpenUrl = { url ->
|
onOpenUrl = { url ->
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = url,
|
url = url,
|
||||||
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator()
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenImage = { url ->
|
onOpenImage = { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(ZoomableImageScreen(url))
|
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||||
},
|
},
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ fun PostCardFooter(
|
|||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier.padding(1.dp)
|
modifier = buttonModifier.padding(1.dp)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onReply?.invoke()
|
onReply?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -110,11 +110,12 @@ fun PostCardFooter(
|
|||||||
if (options.isNotEmpty()) {
|
if (options.isNotEmpty()) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = buttonModifier
|
modifier = buttonModifier
|
||||||
|
.padding(top = Spacing.xxs)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
}
|
}
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = true
|
optionsExpanded = true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -125,7 +126,7 @@ fun PostCardFooter(
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier.onClick(
|
modifier = buttonModifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSave?.invoke()
|
onSave?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -146,7 +147,7 @@ fun PostCardFooter(
|
|||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier
|
modifier = buttonModifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onUpVote?.invoke()
|
onUpVote?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -206,7 +207,7 @@ fun PostCardFooter(
|
|||||||
Image(
|
Image(
|
||||||
modifier = buttonModifier
|
modifier = buttonModifier
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onDownVote?.invoke()
|
onDownVote?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -238,7 +239,7 @@ fun PostCardFooter(
|
|||||||
horizontal = Spacing.m,
|
horizontal = Spacing.m,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = false
|
optionsExpanded = false
|
||||||
onOptionSelected?.invoke(option.id)
|
onOptionSelected?.invoke(option.id)
|
||||||
},
|
},
|
||||||
|
@ -19,7 +19,6 @@ import androidx.compose.ui.text.style.TextAlign
|
|||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
|
|
||||||
@ -33,6 +32,7 @@ fun PostCardImage(
|
|||||||
maxHeight: Dp = Dp.Unspecified,
|
maxHeight: Dp = Dp.Unspecified,
|
||||||
blurred: Boolean = false,
|
blurred: Boolean = false,
|
||||||
onImageClick: ((String) -> Unit)? = null,
|
onImageClick: ((String) -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
if (imageUrl.isNotEmpty()) {
|
if (imageUrl.isNotEmpty()) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
@ -40,9 +40,8 @@ fun PostCardImage(
|
|||||||
.heightIn(min = minHeight, max = maxHeight)
|
.heightIn(min = minHeight, max = maxHeight)
|
||||||
.blur(radius = if (blurred) 60.dp else 0.dp)
|
.blur(radius = if (blurred) 60.dp else 0.dp)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = { onImageClick?.invoke(imageUrl) },
|
||||||
onImageClick?.invoke(imageUrl)
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
},
|
|
||||||
),
|
),
|
||||||
url = imageUrl,
|
url = imageUrl,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
|
@ -15,6 +15,7 @@ fun PostCardTitle(
|
|||||||
autoLoadImages: Boolean = true,
|
autoLoadImages: Boolean = true,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
val uriHandler = LocalUriHandler.current
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
@ -25,16 +26,16 @@ fun PostCardTitle(
|
|||||||
content = text,
|
content = text,
|
||||||
autoLoadImages = autoLoadImages,
|
autoLoadImages = autoLoadImages,
|
||||||
onOpenUrl = { url ->
|
onOpenUrl = { url ->
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = url,
|
url = url,
|
||||||
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator(),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenImage = { url ->
|
onOpenImage = { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(ZoomableImageScreen(url))
|
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||||
},
|
},
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
|
onDoubleClick = onDoubleClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -29,24 +29,12 @@ fun PostLinkBanner(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
url: String,
|
url: String,
|
||||||
) {
|
) {
|
||||||
val uriHandler = LocalUriHandler.current
|
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
|
||||||
val settingsRepository = remember { getSettingsRepository() }
|
|
||||||
|
|
||||||
if (url.isNotEmpty()) {
|
if (url.isNotEmpty()) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.background(
|
.background(
|
||||||
color = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f),
|
color = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f),
|
||||||
shape = RoundedCornerShape(CornerSize.l),
|
shape = RoundedCornerShape(CornerSize.l),
|
||||||
).onClick(
|
|
||||||
rememberCallback {
|
|
||||||
if (settingsRepository.currentSettings.value.openUrlsInExternalBrowser) {
|
|
||||||
uriHandler.openUri(url)
|
|
||||||
} else {
|
|
||||||
navigationCoordinator.getRootNavigator()?.push(WebViewScreen(url))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).padding(
|
).padding(
|
||||||
horizontal = Spacing.m,
|
horizontal = Spacing.m,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
|
@ -145,7 +145,7 @@ fun TextFormattingBar(
|
|||||||
)
|
)
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectImage()
|
onSelectImage()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
||||||
|
|
||||||
import androidx.compose.ui.platform.UriHandler
|
import androidx.compose.ui.platform.UriHandler
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation.NavigationCoordinator
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.userdetail.UserDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.userdetail.UserDetailScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.web.WebViewScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.web.WebViewScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||||
@ -39,18 +39,17 @@ fun getPostFromUrl(url: String?): Pair<PostModel, String>? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleUrl(
|
fun NavigationCoordinator.handleUrl(
|
||||||
url: String,
|
url: String,
|
||||||
openExternal: Boolean,
|
openExternal: Boolean,
|
||||||
uriHandler: UriHandler,
|
uriHandler: UriHandler,
|
||||||
navigator: Navigator? = null,
|
|
||||||
) {
|
) {
|
||||||
val community = getCommunityFromUrl(url)
|
val community = getCommunityFromUrl(url)
|
||||||
val user = getUserFromUrl(url)
|
val user = getUserFromUrl(url)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
community != null && navigator != null -> {
|
community != null -> {
|
||||||
navigator.push(
|
pushScreen(
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
community = community,
|
community = community,
|
||||||
otherInstance = community.host
|
otherInstance = community.host
|
||||||
@ -58,8 +57,8 @@ fun handleUrl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
user != null && navigator != null -> {
|
user != null -> {
|
||||||
navigator.push(
|
pushScreen(
|
||||||
UserDetailScreen(
|
UserDetailScreen(
|
||||||
user = user,
|
user = user,
|
||||||
otherInstance = user.host
|
otherInstance = user.host
|
||||||
@ -71,11 +70,7 @@ fun handleUrl(
|
|||||||
uriHandler.openUri(url)
|
uriHandler.openUri(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
navigator != null -> {
|
else -> pushScreen(WebViewScreen(url))
|
||||||
navigator.push(WebViewScreen(url))
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> Unit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ fun UserHeader(
|
|||||||
.size(IconSize.xxl)
|
.size(IconSize.xxl)
|
||||||
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
.clip(RoundedCornerShape(IconSize.xxl / 2))
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenImage?.invoke(userAvatar)
|
onOpenImage?.invoke(userAvatar)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -126,7 +126,7 @@ class CreateCommentScreen(
|
|||||||
CreateCommentMviModel.Effect.Success -> {
|
CreateCommentMviModel.Effect.Success -> {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.CommentCreated)
|
notificationCenter.getObserver(NotificationCenterContractKeys.CommentCreated)
|
||||||
?.also { o -> o.invoke(Unit) }
|
?.also { o -> o.invoke(Unit) }
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
|
|
||||||
is CreateCommentMviModel.Effect.AddImageToText -> {
|
is CreateCommentMviModel.Effect.AddImageToText -> {
|
||||||
|
@ -176,7 +176,7 @@ class CreatePostScreen(
|
|||||||
CreatePostMviModel.Effect.Success -> {
|
CreatePostMviModel.Effect.Success -> {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.PostCreated)
|
notificationCenter.getObserver(NotificationCenterContractKeys.PostCreated)
|
||||||
?.also { o -> o.invoke(Unit) }
|
?.also { o -> o.invoke(Unit) }
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
|
|
||||||
is CreatePostMviModel.Effect.AddImageToBody -> {
|
is CreatePostMviModel.Effect.AddImageToBody -> {
|
||||||
@ -190,7 +190,7 @@ class CreatePostScreen(
|
|||||||
DisposableEffect(key) {
|
DisposableEffect(key) {
|
||||||
notificationCenter.addObserver(
|
notificationCenter.addObserver(
|
||||||
{
|
{
|
||||||
(it as CommunityModel)?.also { community ->
|
(it as? CommunityModel)?.also { community ->
|
||||||
model.reduce(CreatePostMviModel.Intent.SetCommunity(community))
|
model.reduce(CreatePostMviModel.Intent.SetCommunity(community))
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ class CreatePostScreen(
|
|||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
openImagePicker = true
|
openImagePicker = true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -190,7 +190,7 @@ object ModalDrawerContent : Tab {
|
|||||||
items(uiState.multiCommunities) { community ->
|
items(uiState.multiCommunities) { community ->
|
||||||
MultiCommunityItem(
|
MultiCommunityItem(
|
||||||
modifier = Modifier.fillMaxWidth().onClick(
|
modifier = Modifier.fillMaxWidth().onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
coordinator.toggleDrawer()
|
coordinator.toggleDrawer()
|
||||||
coordinator.sendEvent(
|
coordinator.sendEvent(
|
||||||
@ -207,7 +207,7 @@ object ModalDrawerContent : Tab {
|
|||||||
items(uiState.communities) { community ->
|
items(uiState.communities) { community ->
|
||||||
CommunityItem(
|
CommunityItem(
|
||||||
modifier = Modifier.fillMaxWidth().onClick(
|
modifier = Modifier.fillMaxWidth().onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
coordinator.toggleDrawer()
|
coordinator.toggleDrawer()
|
||||||
coordinator.sendEvent(
|
coordinator.sendEvent(
|
||||||
@ -338,7 +338,7 @@ private fun DrawerHeader(
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpenChangeInstance?.invoke()
|
onOpenChangeInstance?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -362,7 +362,7 @@ private fun DrawerShortcut(
|
|||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.xs,
|
vertical = Spacing.xs,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelected?.invoke()
|
onSelected?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -443,7 +443,7 @@ private fun ChangeInstanceDialog(
|
|||||||
if (instanceName.isNotEmpty()) {
|
if (instanceName.isNotEmpty()) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onChangeInstanceName?.invoke("")
|
onChangeInstanceName?.invoke("")
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -81,8 +81,8 @@ class ZoomableImageScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -93,7 +93,7 @@ class ZoomableImageScreen(
|
|||||||
actions = {
|
actions = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(ZoomableImageMviModel.Intent.SaveToGallery(url))
|
model.reduce(ZoomableImageMviModel.Intent.SaveToGallery(url))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -104,7 +104,7 @@ class ZoomableImageScreen(
|
|||||||
Spacer(Modifier.width(Spacing.s))
|
Spacer(Modifier.width(Spacing.s))
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(ZoomableImageMviModel.Intent.Share(url))
|
model.reduce(ZoomableImageMviModel.Intent.Share(url))
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -114,8 +114,8 @@ class InstanceInfoScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -145,7 +145,7 @@ class InstanceInfoScreen(
|
|||||||
}
|
}
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
values = listOf(
|
values = listOf(
|
||||||
SortType.Active,
|
SortType.Active,
|
||||||
@ -158,7 +158,7 @@ class InstanceInfoScreen(
|
|||||||
),
|
),
|
||||||
expandTop = true,
|
expandTop = true,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = uiState.sortType.toIcon(),
|
||||||
@ -232,8 +232,8 @@ class InstanceInfoScreen(
|
|||||||
items(uiState.communities) {
|
items(uiState.communities) {
|
||||||
CommunityItem(
|
CommunityItem(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
community = it,
|
community = it,
|
||||||
otherInstance = instanceName,
|
otherInstance = instanceName,
|
||||||
|
@ -95,13 +95,13 @@ class ColorBottomSheet : Screen {
|
|||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).fillMaxWidth().onClick(
|
).fillMaxWidth().onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (!isChooseCustom) {
|
if (!isChooseCustom) {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeColor)
|
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeColor)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(value.first ?: Unit)
|
it.invoke(value.first ?: Unit)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
} else {
|
} else {
|
||||||
customPickerDialogOpened = true
|
customPickerDialogOpened = true
|
||||||
}
|
}
|
||||||
@ -149,7 +149,7 @@ class ColorBottomSheet : Screen {
|
|||||||
?.also {
|
?.also {
|
||||||
it.invoke(color)
|
it.invoke(color)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -73,13 +73,13 @@ class DurationBottomSheet(
|
|||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).fillMaxWidth().onClick(
|
).fillMaxWidth().onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(
|
notificationCenter.getObserver(
|
||||||
NotificationCenterContractKeys.ChangeZombieInterval
|
NotificationCenterContractKeys.ChangeZombieInterval
|
||||||
)?.also {
|
)?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -74,14 +74,14 @@ class FontFamilyBottomSheet(
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(
|
notificationCenter.getObserver(
|
||||||
NotificationCenterContractKeys.ChangeFontFamily
|
NotificationCenterContractKeys.ChangeFontFamily
|
||||||
)
|
)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -75,11 +75,11 @@ class FontScaleBottomSheet(
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(contract)?.also {
|
notificationCenter.getObserver(contract)?.also {
|
||||||
it.invoke(value.scaleFactor)
|
it.invoke(value.scaleFactor)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -61,12 +61,12 @@ class InboxTypeSheet : Screen {
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeInboxType)
|
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeInboxType)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(true)
|
it.invoke(true)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
@ -83,12 +83,12 @@ class InboxTypeSheet : Screen {
|
|||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.m,
|
vertical = Spacing.m,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeInboxType)
|
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeInboxType)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(false)
|
it.invoke(false)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -75,14 +75,14 @@ class LanguageBottomSheet : Screen {
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(
|
notificationCenter.getObserver(
|
||||||
NotificationCenterContractKeys.ChangeLanguage
|
NotificationCenterContractKeys.ChangeLanguage
|
||||||
)
|
)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -77,13 +77,13 @@ class ListingTypeBottomSheet(
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getAllObservers(
|
notificationCenter.getAllObservers(
|
||||||
NotificationCenterContractKeys.ChangeFeedType
|
NotificationCenterContractKeys.ChangeFeedType
|
||||||
).forEach {
|
).forEach {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -67,12 +67,12 @@ class PostLayoutBottomSheet : Screen {
|
|||||||
horizontal = Spacing.s,
|
horizontal = Spacing.s,
|
||||||
vertical = Spacing.m,
|
vertical = Spacing.m,
|
||||||
).fillMaxWidth().onClick(
|
).fillMaxWidth().onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.ChangePostLayout)
|
notificationCenter.getObserver(NotificationCenterContractKeys.ChangePostLayout)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -76,7 +76,7 @@ class SliderBottomSheet(
|
|||||||
?.also {
|
?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Text(text = stringResource(MR.strings.button_confirm))
|
Text(text = stringResource(MR.strings.button_confirm))
|
||||||
|
@ -109,14 +109,14 @@ internal class SortBottomSheetMain(
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (value == SortType.Top.Generic && expandTop) {
|
if (value == SortType.Top.Generic && expandTop) {
|
||||||
navigator.push(SortBottomSheetTop(contract = contract))
|
navigator.push(SortBottomSheetTop(contract = contract))
|
||||||
} else {
|
} else {
|
||||||
notificationCenter.getAllObservers(contract).forEach {
|
notificationCenter.getAllObservers(contract).forEach {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -172,7 +172,7 @@ internal class SortBottomSheetTop(
|
|||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigator.pop()
|
navigator.pop()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -199,13 +199,13 @@ internal class SortBottomSheetTop(
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getAllObservers(
|
notificationCenter.getAllObservers(
|
||||||
contract,
|
contract,
|
||||||
).forEach {
|
).forEach {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -75,12 +75,12 @@ class ThemeBottomSheet : Screen {
|
|||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeTheme)
|
notificationCenter.getObserver(NotificationCenterContractKeys.ChangeTheme)
|
||||||
?.also {
|
?.also {
|
||||||
it.invoke(value)
|
it.invoke(value)
|
||||||
}
|
}
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
@ -1,20 +1,31 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation
|
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation
|
||||||
|
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
||||||
import cafe.adriel.voyager.navigator.tab.Tab
|
import cafe.adriel.voyager.navigator.tab.Tab
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.ensureActive
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
private const val NAVIGATION_DELAY = 250L
|
||||||
|
private const val BOTTOM_NAVIGATION_DELAY = 150L
|
||||||
|
private const val DEEP_LINK_DELAY = 500L
|
||||||
|
|
||||||
internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
||||||
|
|
||||||
override val onDoubleTabSelection = MutableSharedFlow<Tab>()
|
override val onDoubleTabSelection = MutableSharedFlow<Tab>()
|
||||||
override val deepLinkUrl = MutableSharedFlow<String>()
|
override val deepLinkUrl = MutableSharedFlow<String>()
|
||||||
|
override val inboxUnread = MutableStateFlow(0)
|
||||||
|
override val canPop: Boolean
|
||||||
|
get() = navigator?.canPop == true
|
||||||
|
|
||||||
private var connection: NestedScrollConnection? = null
|
private var connection: NestedScrollConnection? = null
|
||||||
private var navigator: Navigator? = null
|
private var navigator: Navigator? = null
|
||||||
@ -22,14 +33,12 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
private var currentTab: Tab? = null
|
private var currentTab: Tab? = null
|
||||||
private val scope = CoroutineScope(SupervisorJob())
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
private var canGoBackCallback: (() -> Boolean)? = null
|
private var canGoBackCallback: (() -> Boolean)? = null
|
||||||
override val inboxUnread = MutableStateFlow(0)
|
private var job: Job? = null
|
||||||
|
|
||||||
override fun setRootNavigator(value: Navigator?) {
|
override fun setRootNavigator(value: Navigator?) {
|
||||||
navigator = value
|
navigator = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getRootNavigator(): Navigator? = navigator
|
|
||||||
|
|
||||||
override fun setBottomBarScrollConnection(value: NestedScrollConnection?) {
|
override fun setBottomBarScrollConnection(value: NestedScrollConnection?) {
|
||||||
connection = value
|
connection = value
|
||||||
}
|
}
|
||||||
@ -48,10 +57,13 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
|
|
||||||
override fun submitDeeplink(url: String) {
|
override fun submitDeeplink(url: String) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
delay(500)
|
delay(DEEP_LINK_DELAY)
|
||||||
|
runCatching {
|
||||||
|
ensureActive()
|
||||||
deepLinkUrl.emit(url)
|
deepLinkUrl.emit(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun setCanGoBackCallback(value: (() -> Boolean)?) {
|
override fun setCanGoBackCallback(value: (() -> Boolean)?) {
|
||||||
canGoBackCallback = value
|
canGoBackCallback = value
|
||||||
@ -67,7 +79,47 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
bottomNavigator = value
|
bottomNavigator = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBottomNavigator(): BottomSheetNavigator? {
|
override fun showBottomSheet(screen: Screen) {
|
||||||
return bottomNavigator
|
job?.cancel()
|
||||||
|
job = scope.launch {
|
||||||
|
delay(BOTTOM_NAVIGATION_DELAY)
|
||||||
|
runCatching {
|
||||||
|
ensureActive()
|
||||||
|
bottomNavigator?.show(screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pushScreen(screen: Screen) {
|
||||||
|
job?.cancel()
|
||||||
|
job = scope.launch {
|
||||||
|
delay(NAVIGATION_DELAY)
|
||||||
|
runCatching {
|
||||||
|
ensureActive()
|
||||||
|
navigator?.push(screen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hideBottomSheet() {
|
||||||
|
job?.cancel()
|
||||||
|
job = scope.launch {
|
||||||
|
delay(BOTTOM_NAVIGATION_DELAY)
|
||||||
|
runCatching {
|
||||||
|
ensureActive()
|
||||||
|
bottomNavigator?.hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun popScreen() {
|
||||||
|
job?.cancel()
|
||||||
|
job = scope.launch {
|
||||||
|
delay(NAVIGATION_DELAY)
|
||||||
|
runCatching {
|
||||||
|
ensureActive()
|
||||||
|
navigator?.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation
|
|||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
||||||
import cafe.adriel.voyager.navigator.tab.Tab
|
import cafe.adriel.voyager.navigator.tab.Tab
|
||||||
@ -14,26 +15,19 @@ interface NavigationCoordinator {
|
|||||||
val onDoubleTabSelection: Flow<Tab>
|
val onDoubleTabSelection: Flow<Tab>
|
||||||
val inboxUnread: StateFlow<Int>
|
val inboxUnread: StateFlow<Int>
|
||||||
val deepLinkUrl: Flow<String?>
|
val deepLinkUrl: Flow<String?>
|
||||||
|
val canPop: Boolean
|
||||||
|
|
||||||
fun setCurrentSection(tab: Tab)
|
fun setCurrentSection(tab: Tab)
|
||||||
|
|
||||||
fun submitDeeplink(url: String)
|
fun submitDeeplink(url: String)
|
||||||
|
|
||||||
fun setRootNavigator(value: Navigator?)
|
fun setRootNavigator(value: Navigator?)
|
||||||
|
|
||||||
fun setCanGoBackCallback(value: (() -> Boolean)?)
|
fun setCanGoBackCallback(value: (() -> Boolean)?)
|
||||||
|
|
||||||
fun getCanGoBackCallback(): (() -> Boolean)?
|
fun getCanGoBackCallback(): (() -> Boolean)?
|
||||||
|
|
||||||
fun getRootNavigator(): Navigator?
|
|
||||||
|
|
||||||
fun setBottomBarScrollConnection(value: NestedScrollConnection?)
|
fun setBottomBarScrollConnection(value: NestedScrollConnection?)
|
||||||
|
|
||||||
fun getBottomBarScrollConnection(): NestedScrollConnection?
|
fun getBottomBarScrollConnection(): NestedScrollConnection?
|
||||||
|
|
||||||
fun setInboxUnread(count: Int)
|
fun setInboxUnread(count: Int)
|
||||||
|
|
||||||
fun setBottomNavigator(value: BottomSheetNavigator?)
|
fun setBottomNavigator(value: BottomSheetNavigator?)
|
||||||
|
fun showBottomSheet(screen: Screen)
|
||||||
fun getBottomNavigator(): BottomSheetNavigator?
|
fun hideBottomSheet()
|
||||||
|
fun pushScreen(screen: Screen)
|
||||||
|
fun popScreen()
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ interface PostDetailMviModel :
|
|||||||
val comments: List<CommentModel> = emptyList(),
|
val comments: List<CommentModel> = emptyList(),
|
||||||
val currentUserId: Int? = null,
|
val currentUserId: Int? = null,
|
||||||
val swipeActionsEnabled: Boolean = true,
|
val swipeActionsEnabled: Boolean = true,
|
||||||
|
val doubleTapActionEnabled: Boolean = true,
|
||||||
val postLayout: PostLayout = PostLayout.Card,
|
val postLayout: PostLayout = PostLayout.Card,
|
||||||
val fullHeightImages: Boolean = true,
|
val fullHeightImages: Boolean = true,
|
||||||
val separateUpAndDownVotes: Boolean = false,
|
val separateUpAndDownVotes: Boolean = false,
|
||||||
|
@ -230,7 +230,7 @@ class PostDetailScreen(
|
|||||||
model.effects.onEach { evt ->
|
model.effects.onEach { evt ->
|
||||||
when (evt) {
|
when (evt) {
|
||||||
PostDetailMviModel.Effect.Close -> {
|
PostDetailMviModel.Effect.Close -> {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
is PostDetailMviModel.Effect.ScrollToComment -> {
|
is PostDetailMviModel.Effect.ScrollToComment -> {
|
||||||
@ -263,7 +263,7 @@ class PostDetailScreen(
|
|||||||
actions = {
|
actions = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
values = listOf(
|
values = listOf(
|
||||||
SortType.Hot,
|
SortType.Hot,
|
||||||
@ -273,7 +273,7 @@ class PostDetailScreen(
|
|||||||
SortType.Controversial,
|
SortType.Controversial,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = uiState.sortType.toIcon(),
|
||||||
@ -282,12 +282,11 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
val navigator = navigationCoordinator.getRootNavigator()
|
if (navigationCoordinator.canPop) {
|
||||||
if (navigator?.canPop == true) {
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigator.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -328,7 +327,7 @@ class PostDetailScreen(
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = uiState.post,
|
originalPost = uiState.post,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -365,12 +364,12 @@ class PostDetailScreen(
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
blurNsfw = false,
|
blurNsfw = false,
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community = community)
|
CommunityDetailScreen(community = community)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user = user)
|
UserDetailScreen(user = user)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -405,7 +404,7 @@ class PostDetailScreen(
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = uiState.post,
|
originalPost = uiState.post,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
options = buildList {
|
options = buildList {
|
||||||
@ -455,19 +454,19 @@ class PostDetailScreen(
|
|||||||
OptionId.Delete -> model.reduce(PostDetailMviModel.Intent.DeletePost)
|
OptionId.Delete -> model.reduce(PostDetailMviModel.Intent.DeletePost)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreatePostScreen(editedPost = uiState.post)
|
CreatePostScreen(editedPost = uiState.post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreateReportScreen(postId = uiState.post.id)
|
CreateReportScreen(postId = uiState.post.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreatePostScreen(crossPost = uiState.post)
|
CreatePostScreen(crossPost = uiState.post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -482,7 +481,7 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -523,13 +522,12 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val post = PostModel(
|
val post = PostModel(
|
||||||
id = crossPost.id,
|
id = crossPost.id,
|
||||||
community = community,
|
community = community,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(
|
|
||||||
PostDetailScreen(post)
|
PostDetailScreen(post)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -639,6 +637,18 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
PostDetailMviModel.Intent.UpVoteComment(
|
||||||
|
commentId = comment.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onUpVote = rememberCallback(model) {
|
onUpVote = rememberCallback(model) {
|
||||||
if (uiState.isLogged && !isOnOtherInstance) {
|
if (uiState.isLogged && !isOnOtherInstance) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -675,15 +685,15 @@ class PostDetailScreen(
|
|||||||
originalPost = uiState.post,
|
originalPost = uiState.post,
|
||||||
originalComment = comment,
|
originalComment = comment,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(screen)
|
screen
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs {
|
onOpenCreator = rememberCallbackArgs {
|
||||||
val user = comment.creator
|
val user = comment.creator
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(
|
|
||||||
UserDetailScreen(
|
UserDetailScreen(
|
||||||
user = user,
|
user = user,
|
||||||
otherInstance = otherInstanceName,
|
otherInstance = otherInstanceName,
|
||||||
@ -694,8 +704,7 @@ class PostDetailScreen(
|
|||||||
onOpenCommunity = rememberCallbackArgs {
|
onOpenCommunity = rememberCallbackArgs {
|
||||||
val community = comment.community
|
val community = comment.community
|
||||||
if (community != null) {
|
if (community != null) {
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(
|
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
community = community,
|
community = community,
|
||||||
otherInstance = otherInstanceName,
|
otherInstance = otherInstanceName,
|
||||||
@ -742,8 +751,7 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateCommentScreen(
|
CreateCommentScreen(
|
||||||
editedComment = comment,
|
editedComment = comment,
|
||||||
)
|
)
|
||||||
@ -751,8 +759,7 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
commentId = comment.id
|
commentId = comment.id
|
||||||
)
|
)
|
||||||
@ -815,14 +822,13 @@ class PostDetailScreen(
|
|||||||
originalPost = uiState.post,
|
originalPost = uiState.post,
|
||||||
originalComment = comment,
|
originalComment = comment,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
?.show(screen)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs {
|
onOpenCreator = rememberCallbackArgs {
|
||||||
val user = comment.creator
|
val user = comment.creator
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(
|
UserDetailScreen(
|
||||||
user = user,
|
user = user,
|
||||||
otherInstance = otherInstanceName,
|
otherInstance = otherInstanceName,
|
||||||
@ -867,8 +873,7 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateCommentScreen(
|
CreateCommentScreen(
|
||||||
editedComment = comment,
|
editedComment = comment,
|
||||||
)
|
)
|
||||||
@ -876,8 +881,7 @@ class PostDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
commentId = comment.id
|
commentId = comment.id
|
||||||
)
|
)
|
||||||
|
@ -70,6 +70,7 @@ class PostDetailViewModel(
|
|||||||
mvi.updateState {
|
mvi.updateState {
|
||||||
it.copy(
|
it.copy(
|
||||||
swipeActionsEnabled = settings.enableSwipeActions,
|
swipeActionsEnabled = settings.enableSwipeActions,
|
||||||
|
doubleTapActionEnabled = settings.enableDoubleTapAction,
|
||||||
sortType = settings.defaultCommentSortType.toSortType(),
|
sortType = settings.defaultCommentSortType.toSortType(),
|
||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
autoLoadImages = settings.autoLoadImages,
|
autoLoadImages = settings.autoLoadImages,
|
||||||
|
@ -73,7 +73,7 @@ class CreateReportScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CreateReportMviModel.Effect.Success -> {
|
CreateReportMviModel.Effect.Success -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
@ -138,7 +138,7 @@ class SavedItemsScreen : Screen {
|
|||||||
actions = {
|
actions = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
values = listOf(
|
values = listOf(
|
||||||
SortType.Hot,
|
SortType.Hot,
|
||||||
@ -146,7 +146,7 @@ class SavedItemsScreen : Screen {
|
|||||||
SortType.Old,
|
SortType.Old,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
navigatorCoordinator.getBottomNavigator()?.show(sheet)
|
navigatorCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = uiState.sortType.toIcon(),
|
||||||
@ -157,8 +157,8 @@ class SavedItemsScreen : Screen {
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.pop()
|
navigatorCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -250,19 +250,18 @@ class SavedItemsScreen : Screen {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
blurNsfw = uiState.blurNsfw,
|
blurNsfw = uiState.blurNsfw,
|
||||||
onClick = {
|
onClick = {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
PostDetailScreen(post),
|
PostDetailScreen(post),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCommunity = { community ->
|
onOpenCommunity = { community ->
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = { u ->
|
onOpenCreator = { u ->
|
||||||
if (u.id != uiState.user?.id) {
|
if (u.id != uiState.user?.id) {
|
||||||
navigatorCoordinator.getRootNavigator()
|
navigatorCoordinator.pushScreen(UserDetailScreen(u))
|
||||||
?.push(UserDetailScreen(u))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onUpVote = {
|
onUpVote = {
|
||||||
@ -293,10 +292,10 @@ class SavedItemsScreen : Screen {
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = post,
|
originalPost = post,
|
||||||
)
|
)
|
||||||
navigatorCoordinator.getBottomNavigator()?.show(screen)
|
navigatorCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
onImageClick = { url ->
|
onImageClick = { url ->
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -323,7 +322,7 @@ class SavedItemsScreen : Screen {
|
|||||||
onOptionSelected = { optionIndex ->
|
onOptionSelected = { optionIndex ->
|
||||||
when (optionIndex) {
|
when (optionIndex) {
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigatorCoordinator.getBottomNavigator()?.show(
|
navigatorCoordinator.showBottomSheet(
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
postId = post.id
|
postId = post.id
|
||||||
)
|
)
|
||||||
@ -373,7 +372,7 @@ class SavedItemsScreen : Screen {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
hideIndent = true,
|
hideIndent = true,
|
||||||
onClick = {
|
onClick = {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = PostModel(id = comment.postId),
|
post = PostModel(id = comment.postId),
|
||||||
highlightCommentId = comment.id,
|
highlightCommentId = comment.id,
|
||||||
@ -409,7 +408,7 @@ class SavedItemsScreen : Screen {
|
|||||||
originalPost = PostModel(id = comment.postId),
|
originalPost = PostModel(id = comment.postId),
|
||||||
originalComment = comment,
|
originalComment = comment,
|
||||||
)
|
)
|
||||||
navigatorCoordinator.getBottomNavigator()?.show(screen)
|
navigatorCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
options = buildList {
|
options = buildList {
|
||||||
add(
|
add(
|
||||||
@ -428,7 +427,7 @@ class SavedItemsScreen : Screen {
|
|||||||
onOptionSelected = { optionIndex ->
|
onOptionSelected = { optionIndex ->
|
||||||
when (optionIndex) {
|
when (optionIndex) {
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigatorCoordinator.getBottomNavigator()?.show(
|
navigatorCoordinator.showBottomSheet(
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
commentId = comment.id
|
commentId = comment.id
|
||||||
)
|
)
|
||||||
|
@ -97,7 +97,7 @@ class SelectCommunityDialog : Screen {
|
|||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (uiState.searchText.isNotEmpty()) {
|
if (uiState.searchText.isNotEmpty()) {
|
||||||
model.reduce(SelectCommunityMviModel.Intent.SetSearch(""))
|
model.reduce(SelectCommunityMviModel.Intent.SetSearch(""))
|
||||||
}
|
}
|
||||||
@ -127,7 +127,8 @@ class SelectCommunityDialog : Screen {
|
|||||||
CommunityItem(
|
CommunityItem(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.background)
|
.background(MaterialTheme.colorScheme.background)
|
||||||
.onClick(rememberCallback {
|
.onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
notificationCenter.getObserver(
|
notificationCenter.getObserver(
|
||||||
NotificationCenterContractKeys.SelectCommunity
|
NotificationCenterContractKeys.SelectCommunity
|
||||||
)
|
)
|
||||||
@ -136,7 +137,8 @@ class SelectCommunityDialog : Screen {
|
|||||||
NotificationCenterContractKeys.CloseDialog
|
NotificationCenterContractKeys.CloseDialog
|
||||||
)
|
)
|
||||||
?.invoke(Unit)
|
?.invoke(Unit)
|
||||||
}),
|
},
|
||||||
|
),
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
community = community,
|
community = community,
|
||||||
)
|
)
|
||||||
|
@ -46,6 +46,7 @@ interface UserDetailMviModel :
|
|||||||
val user: UserModel = UserModel(),
|
val user: UserModel = UserModel(),
|
||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val swipeActionsEnabled: Boolean = true,
|
val swipeActionsEnabled: Boolean = true,
|
||||||
|
val doubleTapActionEnabled: Boolean = true,
|
||||||
val postLayout: PostLayout = PostLayout.Card,
|
val postLayout: PostLayout = PostLayout.Card,
|
||||||
val fullHeightImages: Boolean = true,
|
val fullHeightImages: Boolean = true,
|
||||||
val separateUpAndDownVotes: Boolean = false,
|
val separateUpAndDownVotes: Boolean = false,
|
||||||
|
@ -227,11 +227,11 @@ class UserDetailScreen(
|
|||||||
// sort button
|
// sort button
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
expandTop = true,
|
expandTop = true,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = uiState.sortType.toIcon(),
|
imageVector = uiState.sortType.toIcon(),
|
||||||
@ -257,7 +257,7 @@ class UserDetailScreen(
|
|||||||
modifier = Modifier.onGloballyPositioned {
|
modifier = Modifier.onGloballyPositioned {
|
||||||
optionsOffset = it.positionInParent()
|
optionsOffset = it.positionInParent()
|
||||||
}.padding(start = Spacing.s).onClick(
|
}.padding(start = Spacing.s).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = true
|
optionsExpanded = true
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -281,7 +281,7 @@ class UserDetailScreen(
|
|||||||
horizontal = Spacing.m,
|
horizontal = Spacing.m,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
optionsExpanded = false
|
optionsExpanded = false
|
||||||
when (option.id) {
|
when (option.id) {
|
||||||
OptionId.BlockInstance -> model.reduce(
|
OptionId.BlockInstance -> model.reduce(
|
||||||
@ -303,12 +303,11 @@ class UserDetailScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
val navigator = navigationCoordinator.getRootNavigator()
|
if (navigationCoordinator.canPop) {
|
||||||
if (navigator?.canPop == true) {
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigator.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -348,7 +347,7 @@ class UserDetailScreen(
|
|||||||
text = stringResource(MR.strings.action_chat),
|
text = stringResource(MR.strings.action_chat),
|
||||||
onSelected = rememberCallback {
|
onSelected = rememberCallback {
|
||||||
val screen = InboxChatScreen(otherUserId = user.id)
|
val screen = InboxChatScreen(otherUserId = user.id)
|
||||||
navigationCoordinator.getRootNavigator()?.push(screen)
|
navigationCoordinator.pushScreen(screen)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -391,8 +390,7 @@ class UserDetailScreen(
|
|||||||
user = uiState.user,
|
user = uiState.user,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
onOpenImage = rememberCallbackArgs { url ->
|
onOpenImage = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||||
?.push(ZoomableImageScreen(url))
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
SectionSelector(
|
SectionSelector(
|
||||||
@ -486,8 +484,21 @@ class UserDetailScreen(
|
|||||||
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(PostDetailScreen(post = post))
|
PostDetailScreen(post = post),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
UserDetailMviModel.Intent.UpVotePost(
|
||||||
|
id = post.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onUpVote = if (!uiState.isLogged || isOnOtherInstance) {
|
onUpVote = if (!uiState.isLogged || isOnOtherInstance) {
|
||||||
null
|
null
|
||||||
@ -526,8 +537,9 @@ class UserDetailScreen(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(CommunityDetailScreen(community))
|
CommunityDetailScreen(community),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
onReply = if (!uiState.isLogged || isOnOtherInstance) {
|
onReply = if (!uiState.isLogged || isOnOtherInstance) {
|
||||||
null
|
null
|
||||||
@ -536,12 +548,11 @@ class UserDetailScreen(
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = post,
|
originalPost = post,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
?.show(screen)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -576,8 +587,7 @@ class UserDetailScreen(
|
|||||||
onOptionSelected = rememberCallbackArgs { optionId ->
|
onOptionSelected = rememberCallbackArgs { optionId ->
|
||||||
when (optionId) {
|
when (optionId) {
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
postId = post.id
|
postId = post.id
|
||||||
)
|
)
|
||||||
@ -585,8 +595,7 @@ class UserDetailScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreatePostScreen(crossPost = post)
|
CreatePostScreen(crossPost = post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -689,13 +698,25 @@ class UserDetailScreen(
|
|||||||
hideAuthor = true,
|
hideAuthor = true,
|
||||||
hideIndent = true,
|
hideIndent = true,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = PostModel(id = comment.postId),
|
post = PostModel(id = comment.postId),
|
||||||
highlightCommentId = comment.id,
|
highlightCommentId = comment.id,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
UserDetailMviModel.Intent.UpVoteComment(
|
||||||
|
id = comment.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onSave = if (!uiState.isLogged || isOnOtherInstance) {
|
onSave = if (!uiState.isLogged || isOnOtherInstance) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@ -740,13 +761,15 @@ class UserDetailScreen(
|
|||||||
originalPost = PostModel(id = comment.postId),
|
originalPost = PostModel(id = comment.postId),
|
||||||
originalComment = comment,
|
originalComment = comment,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
?.show(screen)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(
|
||||||
?.push(CommunityDetailScreen(community))
|
CommunityDetailScreen(
|
||||||
|
community
|
||||||
|
)
|
||||||
|
)
|
||||||
},
|
},
|
||||||
options = buildList {
|
options = buildList {
|
||||||
add(
|
add(
|
||||||
@ -767,11 +790,10 @@ class UserDetailScreen(
|
|||||||
onOptionSelected = rememberCallbackArgs { optionId ->
|
onOptionSelected = rememberCallbackArgs { optionId ->
|
||||||
when (optionId) {
|
when (optionId) {
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
commentId = comment.id
|
commentId = comment.id
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class UserDetailViewModel(
|
|||||||
it.copy(
|
it.copy(
|
||||||
blurNsfw = settings.blurNsfw,
|
blurNsfw = settings.blurNsfw,
|
||||||
swipeActionsEnabled = settings.enableSwipeActions,
|
swipeActionsEnabled = settings.enableSwipeActions,
|
||||||
|
doubleTapActionEnabled = settings.enableDoubleTapAction,
|
||||||
sortType = settings.defaultPostSortType.toSortType(),
|
sortType = settings.defaultPostSortType.toSortType(),
|
||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
autoLoadImages = settings.autoLoadImages,
|
autoLoadImages = settings.autoLoadImages,
|
||||||
|
@ -35,7 +35,7 @@ class WebViewScreen(
|
|||||||
override fun Content() {
|
override fun Content() {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||||
var shareHelper = remember { getShareHelper() }
|
val shareHelper = remember { getShareHelper() }
|
||||||
val drawerCoordinator = remember { getDrawerCoordinator() }
|
val drawerCoordinator = remember { getDrawerCoordinator() }
|
||||||
|
|
||||||
DisposableEffect(key) {
|
DisposableEffect(key) {
|
||||||
@ -53,8 +53,8 @@ class WebViewScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -65,7 +65,7 @@ class WebViewScreen(
|
|||||||
actions = {
|
actions = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
shareHelper.share(url, "text/plain")
|
shareHelper.share(url, "text/plain")
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -80,7 +80,6 @@ class WebViewScreen(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(paddingValues)
|
modifier = Modifier.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
|
||||||
val webNavigator = rememberWebViewNavigator()
|
val webNavigator = rememberWebViewNavigator()
|
||||||
|
|
||||||
DisposableEffect(key) {
|
DisposableEffect(key) {
|
||||||
|
@ -46,6 +46,7 @@ kotlin {
|
|||||||
|
|
||||||
api(libs.markdown)
|
api(libs.markdown)
|
||||||
implementation(projects.coreCommonui.components)
|
implementation(projects.coreCommonui.components)
|
||||||
|
implementation(projects.coreUtils)
|
||||||
implementation(projects.resources)
|
implementation(projects.resources)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,11 @@ package com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.IdRes
|
import androidx.annotation.IdRes
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
@ -30,6 +30,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownColo
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.DateTime
|
||||||
import io.noties.markwon.image.AsyncDrawableSpan
|
import io.noties.markwon.image.AsyncDrawableSpan
|
||||||
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
|
import org.intellij.markdown.flavours.MarkdownFlavourDescriptor
|
||||||
|
|
||||||
@ -50,6 +52,7 @@ actual fun CustomMarkdown(
|
|||||||
autoLoadImages: Boolean,
|
autoLoadImages: Boolean,
|
||||||
onOpenImage: ((String) -> Unit)?,
|
onOpenImage: ((String) -> Unit)?,
|
||||||
onClick: (() -> Unit)?,
|
onClick: (() -> Unit)?,
|
||||||
|
onDoubleClick: (() -> Unit)?,
|
||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalReferenceLinkHandler provides ReferenceLinkHandlerImpl(),
|
LocalReferenceLinkHandler provides ReferenceLinkHandlerImpl(),
|
||||||
@ -64,10 +67,10 @@ actual fun CustomMarkdown(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
BoxWithConstraints(
|
BoxWithConstraints(
|
||||||
modifier = modifier.clickable(
|
modifier = modifier.onClick(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
onClick = onClick ?: {},
|
||||||
indication = null
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
) { onClick?.invoke() }
|
)
|
||||||
) {
|
) {
|
||||||
val style = LocalMarkdownTypography.current.text
|
val style = LocalMarkdownTypography.current.text
|
||||||
val fontScale = LocalDensity.current.fontScale * 1.25f
|
val fontScale = LocalDensity.current.fontScale * 1.25f
|
||||||
@ -93,9 +96,35 @@ actual fun CustomMarkdown(
|
|||||||
typeface = typeface,
|
typeface = typeface,
|
||||||
fontSize = style.fontSize * fontScale,
|
fontSize = style.fontSize * fontScale,
|
||||||
).apply {
|
).apply {
|
||||||
setOnClickListener {
|
val gestureDetector =
|
||||||
|
GestureDetector(
|
||||||
|
ctx,
|
||||||
|
object : GestureDetector.SimpleOnGestureListener() {
|
||||||
|
|
||||||
|
private var lastClickTime = 0L
|
||||||
|
|
||||||
|
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||||
|
val currentTime = DateTime.epochMillis()
|
||||||
|
if ((currentTime - lastClickTime) < 300) return false
|
||||||
|
lastClickTime = currentTime
|
||||||
onClick?.invoke()
|
onClick?.invoke()
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDoubleTap(e: MotionEvent): Boolean {
|
||||||
|
val currentTime = DateTime.epochMillis()
|
||||||
|
if ((currentTime - lastClickTime) < 300) return false
|
||||||
|
lastClickTime = currentTime
|
||||||
|
onDoubleClick?.invoke()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDown(e: MotionEvent): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
setOnTouchListener { _, evt -> gestureDetector.onTouchEvent(evt) }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
update = { textView ->
|
update = { textView ->
|
||||||
|
@ -38,4 +38,5 @@ expect fun CustomMarkdown(
|
|||||||
autoLoadImages: Boolean = true,
|
autoLoadImages: Boolean = true,
|
||||||
onOpenImage: ((String) -> Unit)? = null,
|
onOpenImage: ((String) -> Unit)? = null,
|
||||||
onClick: (() -> Unit)? = null,
|
onClick: (() -> Unit)? = null,
|
||||||
|
onDoubleClick: (() -> Unit)? = null,
|
||||||
)
|
)
|
@ -4,9 +4,7 @@ import androidx.compose.animation.core.InfiniteRepeatableSpec
|
|||||||
import androidx.compose.animation.core.animateFloat
|
import androidx.compose.animation.core.animateFloat
|
||||||
import androidx.compose.animation.core.rememberInfiniteTransition
|
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
import androidx.compose.foundation.gestures.detectTapGestures
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.heightIn
|
import androidx.compose.foundation.layout.heightIn
|
||||||
@ -40,6 +38,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.LocalMarkd
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.LocalReferenceLinkHandler
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.LocalReferenceLinkHandler
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.utils.TAG_IMAGE_URL
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.utils.TAG_IMAGE_URL
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.utils.TAG_URL
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.utils.TAG_URL
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||||
import dev.icerock.moko.resources.compose.stringResource
|
import dev.icerock.moko.resources.compose.stringResource
|
||||||
|
|
||||||
@ -121,12 +120,9 @@ internal fun MarkdownText(
|
|||||||
CustomImage(
|
CustomImage(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable(
|
.onClick(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
onClick = { onOpenImage?.invoke(imageUrl) },
|
||||||
indication = null
|
),
|
||||||
) {
|
|
||||||
onOpenImage?.invoke(imageUrl)
|
|
||||||
},
|
|
||||||
url = link,
|
url = link,
|
||||||
autoload = autoLoadImages,
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
@ -175,12 +171,10 @@ internal fun MarkdownText(
|
|||||||
// TODO: improve fixed values
|
// TODO: improve fixed values
|
||||||
.heightIn(min = 200.dp, max = Dp.Unspecified)
|
.heightIn(min = 200.dp, max = Dp.Unspecified)
|
||||||
.clip(RoundedCornerShape(20.dp))
|
.clip(RoundedCornerShape(20.dp))
|
||||||
.clickable(
|
.onClick(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
onClick = { onOpenImage?.invoke(imageUrl) },
|
||||||
indication = null
|
onDoubleClick = {},
|
||||||
) {
|
),
|
||||||
onOpenImage?.invoke(imageUrl)
|
|
||||||
},
|
|
||||||
url = imageUrl,
|
url = imageUrl,
|
||||||
autoload = autoLoadImages,
|
autoload = autoLoadImages,
|
||||||
quality = FilterQuality.Low,
|
quality = FilterQuality.Low,
|
||||||
|
@ -44,3 +44,4 @@ internal fun List<ASTNode>.innerList(): List<ASTNode> = this.subList(1, this.siz
|
|||||||
internal fun List<ASTNode>.filterNonListTypes(): List<ASTNode> = this.filter { n ->
|
internal fun List<ASTNode>.filterNonListTypes(): List<ASTNode> = this.filter { n ->
|
||||||
n.type != MarkdownElementTypes.ORDERED_LIST && n.type != MarkdownElementTypes.UNORDERED_LIST && n.type != MarkdownTokenTypes.EOL
|
n.type != MarkdownElementTypes.ORDERED_LIST && n.type != MarkdownElementTypes.UNORDERED_LIST && n.type != MarkdownTokenTypes.EOL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose
|
package com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.elements.MarkdownBlockQuote
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.elements.MarkdownBlockQuote
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.elements.MarkdownBulletList
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.compose.elements.MarkdownBulletList
|
||||||
@ -22,6 +19,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownColo
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownPadding
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.MarkdownTypography
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
import com.github.diegoberaldin.raccoonforlemmy.core.markdown.model.ReferenceLinkHandlerImpl
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import org.intellij.markdown.MarkdownElementTypes
|
import org.intellij.markdown.MarkdownElementTypes
|
||||||
import org.intellij.markdown.MarkdownElementTypes.ATX_1
|
import org.intellij.markdown.MarkdownElementTypes.ATX_1
|
||||||
import org.intellij.markdown.MarkdownElementTypes.ATX_2
|
import org.intellij.markdown.MarkdownElementTypes.ATX_2
|
||||||
@ -62,6 +60,7 @@ actual fun CustomMarkdown(
|
|||||||
autoLoadImages: Boolean,
|
autoLoadImages: Boolean,
|
||||||
onOpenImage: ((String) -> Unit)?,
|
onOpenImage: ((String) -> Unit)?,
|
||||||
onClick: (() -> Unit)?,
|
onClick: (() -> Unit)?,
|
||||||
|
onDoubleClick: (() -> Unit)?,
|
||||||
) {
|
) {
|
||||||
val matches = Regex("::: spoiler (?<title>.*?)\\n(?<content>.*?)\\n:::\\n").findAll(content)
|
val matches = Regex("::: spoiler (?<title>.*?)\\n(?<content>.*?)\\n:::\\n").findAll(content)
|
||||||
val mangledContent = buildString {
|
val mangledContent = buildString {
|
||||||
@ -97,10 +96,12 @@ actual fun CustomMarkdown(
|
|||||||
LocalMarkdownColors provides colors,
|
LocalMarkdownColors provides colors,
|
||||||
LocalMarkdownTypography provides typography,
|
LocalMarkdownTypography provides typography,
|
||||||
) {
|
) {
|
||||||
Column(modifier.clickable(
|
Column(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
modifier = modifier.onClick(
|
||||||
indication = null
|
onClick = onClick ?: {},
|
||||||
) { onClick?.invoke() }) {
|
onDoubleClick = onDoubleClick ?: {},
|
||||||
|
)
|
||||||
|
) {
|
||||||
val parsedTree = MarkdownParser(flavour).buildMarkdownTreeFromString(mangledContent)
|
val parsedTree = MarkdownParser(flavour).buildMarkdownTreeFromString(mangledContent)
|
||||||
parsedTree.children.forEach { node ->
|
parsedTree.children.forEach { node ->
|
||||||
if (!node.handleElement(
|
if (!node.handleElement(
|
||||||
|
@ -20,6 +20,7 @@ data class SettingsModel(
|
|||||||
val dynamicColors: Boolean = false,
|
val dynamicColors: Boolean = false,
|
||||||
val openUrlsInExternalBrowser: Boolean = false,
|
val openUrlsInExternalBrowser: Boolean = false,
|
||||||
val enableSwipeActions: Boolean = true,
|
val enableSwipeActions: Boolean = true,
|
||||||
|
val enableDoubleTapAction: Boolean = false,
|
||||||
val customSeedColor: Int? = null,
|
val customSeedColor: Int? = null,
|
||||||
val upvoteColor: Int? = null,
|
val upvoteColor: Int? = null,
|
||||||
val downvoteColor: Int? = null,
|
val downvoteColor: Int? = null,
|
||||||
|
@ -25,6 +25,7 @@ private object KeyStoreKeys {
|
|||||||
const val DynamicColors = "dynamicColors"
|
const val DynamicColors = "dynamicColors"
|
||||||
const val OpenUrlsInExternalBrowser = "openUrlsInExternalBrowser"
|
const val OpenUrlsInExternalBrowser = "openUrlsInExternalBrowser"
|
||||||
const val EnableSwipeActions = "enableSwipeActions"
|
const val EnableSwipeActions = "enableSwipeActions"
|
||||||
|
const val EnableDoubleTapAction = "enableDoubleTapAction"
|
||||||
const val CustomSeedColor = "customPrimaryColor"
|
const val CustomSeedColor = "customPrimaryColor"
|
||||||
const val PostLayout = "postLayout"
|
const val PostLayout = "postLayout"
|
||||||
const val SeparateUpAndDownVotes = "separateUpAndDownVotes"
|
const val SeparateUpAndDownVotes = "separateUpAndDownVotes"
|
||||||
@ -64,6 +65,7 @@ internal class DefaultSettingsRepository(
|
|||||||
dynamicColors = if (settings.dynamicColors) 1L else 0L,
|
dynamicColors = if (settings.dynamicColors) 1L else 0L,
|
||||||
openUrlsInExternalBrowser = if (settings.openUrlsInExternalBrowser) 1L else 0L,
|
openUrlsInExternalBrowser = if (settings.openUrlsInExternalBrowser) 1L else 0L,
|
||||||
enableSwipeActions = if (settings.enableSwipeActions) 1L else 0L,
|
enableSwipeActions = if (settings.enableSwipeActions) 1L else 0L,
|
||||||
|
enableDoubleTapAction = if (settings.enableDoubleTapAction) 1L else 0L,
|
||||||
customSeedColor = settings.customSeedColor?.toLong(),
|
customSeedColor = settings.customSeedColor?.toLong(),
|
||||||
account_id = accountId,
|
account_id = accountId,
|
||||||
postLayout = settings.postLayout.toLong(),
|
postLayout = settings.postLayout.toLong(),
|
||||||
@ -100,6 +102,7 @@ internal class DefaultSettingsRepository(
|
|||||||
dynamicColors = keyStore[KeyStoreKeys.DynamicColors, false],
|
dynamicColors = keyStore[KeyStoreKeys.DynamicColors, false],
|
||||||
openUrlsInExternalBrowser = keyStore[KeyStoreKeys.OpenUrlsInExternalBrowser, false],
|
openUrlsInExternalBrowser = keyStore[KeyStoreKeys.OpenUrlsInExternalBrowser, false],
|
||||||
enableSwipeActions = keyStore[KeyStoreKeys.EnableSwipeActions, true],
|
enableSwipeActions = keyStore[KeyStoreKeys.EnableSwipeActions, true],
|
||||||
|
enableDoubleTapAction = keyStore[KeyStoreKeys.EnableDoubleTapAction, false],
|
||||||
customSeedColor = if (!keyStore.containsKey(KeyStoreKeys.CustomSeedColor)) null else keyStore[KeyStoreKeys.CustomSeedColor, 0],
|
customSeedColor = if (!keyStore.containsKey(KeyStoreKeys.CustomSeedColor)) null else keyStore[KeyStoreKeys.CustomSeedColor, 0],
|
||||||
postLayout = keyStore[KeyStoreKeys.PostLayout, 0],
|
postLayout = keyStore[KeyStoreKeys.PostLayout, 0],
|
||||||
separateUpAndDownVotes = keyStore[KeyStoreKeys.SeparateUpAndDownVotes, false],
|
separateUpAndDownVotes = keyStore[KeyStoreKeys.SeparateUpAndDownVotes, false],
|
||||||
@ -148,6 +151,7 @@ internal class DefaultSettingsRepository(
|
|||||||
value = settings.openUrlsInExternalBrowser
|
value = settings.openUrlsInExternalBrowser
|
||||||
)
|
)
|
||||||
keyStore.save(KeyStoreKeys.EnableSwipeActions, settings.enableSwipeActions)
|
keyStore.save(KeyStoreKeys.EnableSwipeActions, settings.enableSwipeActions)
|
||||||
|
keyStore.save(KeyStoreKeys.EnableDoubleTapAction, settings.enableDoubleTapAction)
|
||||||
if (settings.customSeedColor != null) {
|
if (settings.customSeedColor != null) {
|
||||||
keyStore.save(KeyStoreKeys.CustomSeedColor, settings.customSeedColor)
|
keyStore.save(KeyStoreKeys.CustomSeedColor, settings.customSeedColor)
|
||||||
} else {
|
} else {
|
||||||
@ -196,6 +200,7 @@ internal class DefaultSettingsRepository(
|
|||||||
dynamicColors = if (settings.dynamicColors) 1L else 0L,
|
dynamicColors = if (settings.dynamicColors) 1L else 0L,
|
||||||
openUrlsInExternalBrowser = if (settings.openUrlsInExternalBrowser) 1L else 0L,
|
openUrlsInExternalBrowser = if (settings.openUrlsInExternalBrowser) 1L else 0L,
|
||||||
enableSwipeActions = if (settings.enableSwipeActions) 1L else 0L,
|
enableSwipeActions = if (settings.enableSwipeActions) 1L else 0L,
|
||||||
|
enableDoubleTapAction = if (settings.enableDoubleTapAction) 1L else 0L,
|
||||||
customSeedColor = settings.customSeedColor?.toLong(),
|
customSeedColor = settings.customSeedColor?.toLong(),
|
||||||
postLayout = settings.postLayout.toLong(),
|
postLayout = settings.postLayout.toLong(),
|
||||||
separateUpAndDownVotes = if (settings.separateUpAndDownVotes) 1L else 0L,
|
separateUpAndDownVotes = if (settings.separateUpAndDownVotes) 1L else 0L,
|
||||||
@ -233,6 +238,7 @@ private fun GetBy.toModel() = SettingsModel(
|
|||||||
dynamicColors = dynamicColors != 0L,
|
dynamicColors = dynamicColors != 0L,
|
||||||
openUrlsInExternalBrowser = openUrlsInExternalBrowser != 0L,
|
openUrlsInExternalBrowser = openUrlsInExternalBrowser != 0L,
|
||||||
enableSwipeActions = enableSwipeActions != 0L,
|
enableSwipeActions = enableSwipeActions != 0L,
|
||||||
|
enableDoubleTapAction = enableDoubleTapAction != 0L,
|
||||||
customSeedColor = customSeedColor?.toInt(),
|
customSeedColor = customSeedColor?.toInt(),
|
||||||
postLayout = postLayout.toInt(),
|
postLayout = postLayout.toInt(),
|
||||||
separateUpAndDownVotes = separateUpAndDownVotes != 0L,
|
separateUpAndDownVotes = separateUpAndDownVotes != 0L,
|
||||||
|
@ -14,6 +14,7 @@ CREATE TABLE SettingsEntity (
|
|||||||
dynamicColors INTEGER NOT NULL DEFAULT 0,
|
dynamicColors INTEGER NOT NULL DEFAULT 0,
|
||||||
openUrlsInExternalBrowser INTEGER NOT NULL DEFAULT 0,
|
openUrlsInExternalBrowser INTEGER NOT NULL DEFAULT 0,
|
||||||
enableSwipeActions INTEGER NOT NULL DEFAULT 1,
|
enableSwipeActions INTEGER NOT NULL DEFAULT 1,
|
||||||
|
enableDoubleTapAction INTEGER NOT NULL DEFAULT 1,
|
||||||
customSeedColor INTEGER DEFAULT NULL,
|
customSeedColor INTEGER DEFAULT NULL,
|
||||||
postLayout INTEGER NOT NULL DEFAULT 0,
|
postLayout INTEGER NOT NULL DEFAULT 0,
|
||||||
separateUpAndDownVotes INTEGER NOT NULL DEFAULT 0,
|
separateUpAndDownVotes INTEGER NOT NULL DEFAULT 0,
|
||||||
@ -46,6 +47,7 @@ INSERT OR IGNORE INTO SettingsEntity (
|
|||||||
dynamicColors,
|
dynamicColors,
|
||||||
openUrlsInExternalBrowser,
|
openUrlsInExternalBrowser,
|
||||||
enableSwipeActions,
|
enableSwipeActions,
|
||||||
|
enableDoubleTapAction,
|
||||||
customSeedColor,
|
customSeedColor,
|
||||||
postLayout,
|
postLayout,
|
||||||
separateUpAndDownVotes,
|
separateUpAndDownVotes,
|
||||||
@ -84,6 +86,7 @@ INSERT OR IGNORE INTO SettingsEntity (
|
|||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
?,
|
?,
|
||||||
|
?,
|
||||||
?
|
?
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -103,6 +106,7 @@ SET theme = ?,
|
|||||||
dynamicColors = ?,
|
dynamicColors = ?,
|
||||||
openUrlsInExternalBrowser = ?,
|
openUrlsInExternalBrowser = ?,
|
||||||
enableSwipeActions = ?,
|
enableSwipeActions = ?,
|
||||||
|
enableDoubleTapAction = ?,
|
||||||
customSeedColor = ?,
|
customSeedColor = ?,
|
||||||
postLayout = ?,
|
postLayout = ?,
|
||||||
separateUpAndDownVotes = ?,
|
separateUpAndDownVotes = ?,
|
||||||
@ -133,6 +137,7 @@ SELECT
|
|||||||
dynamicColors,
|
dynamicColors,
|
||||||
openUrlsInExternalBrowser,
|
openUrlsInExternalBrowser,
|
||||||
enableSwipeActions,
|
enableSwipeActions,
|
||||||
|
enableDoubleTapAction,
|
||||||
customSeedColor,
|
customSeedColor,
|
||||||
postLayout,
|
postLayout,
|
||||||
separateUpAndDownVotes,
|
separateUpAndDownVotes,
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE SettingsEntity
|
||||||
|
ADD COLUMN enableDoubleTapAction INTEGER NOT NULL DEFAULT 1;
|
@ -1,16 +1,37 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.core.utils.compose
|
package com.github.diegoberaldin.raccoonforlemmy.core.utils.compose
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
import androidx.compose.ui.composed
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.DateTime
|
||||||
|
|
||||||
fun Modifier.onClick(onClick: () -> Unit): Modifier = composed {
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
clickable(
|
fun Modifier.onClick(
|
||||||
|
debounceInterval: Long = 300,
|
||||||
|
onClick: () -> Unit = {},
|
||||||
|
onDoubleClick: () -> Unit = {},
|
||||||
|
): Modifier = composed {
|
||||||
|
var lastClickTime by remember { mutableStateOf(0L) }
|
||||||
|
combinedClickable(
|
||||||
indication = null,
|
indication = null,
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
interactionSource = remember { MutableInteractionSource() },
|
||||||
) {
|
onClick = {
|
||||||
|
val currentTime = DateTime.epochMillis()
|
||||||
|
if ((currentTime - lastClickTime) < debounceInterval) return@combinedClickable
|
||||||
|
lastClickTime = currentTime
|
||||||
onClick()
|
onClick()
|
||||||
}
|
},
|
||||||
|
onDoubleClick = {
|
||||||
|
val currentTime = DateTime.epochMillis()
|
||||||
|
if ((currentTime - lastClickTime) < debounceInterval) return@combinedClickable
|
||||||
|
lastClickTime = currentTime
|
||||||
|
onDoubleClick()
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
@ -35,6 +35,6 @@ val PostModel.shareUrl: String
|
|||||||
}
|
}
|
||||||
|
|
||||||
val PostModel.imageUrl: String
|
val PostModel.imageUrl: String
|
||||||
get() = thumbnailUrl?.takeIf { it.isNotEmpty() } ?: run {
|
get() = url?.takeIf { it.looksLikeAnImage }?.takeIf { it.isNotEmpty() } ?: run {
|
||||||
url?.takeIf { it.looksLikeAnImage }
|
thumbnailUrl
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
|
@ -44,6 +44,7 @@ interface PostListMviModel :
|
|||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val currentUserId: Int? = null,
|
val currentUserId: Int? = null,
|
||||||
val swipeActionsEnabled: Boolean = true,
|
val swipeActionsEnabled: Boolean = true,
|
||||||
|
val doubleTapActionEnabled: Boolean = false,
|
||||||
val postLayout: PostLayout = PostLayout.Card,
|
val postLayout: PostLayout = PostLayout.Card,
|
||||||
val fullHeightImages: Boolean = true,
|
val fullHeightImages: Boolean = true,
|
||||||
val separateUpAndDownVotes: Boolean = false,
|
val separateUpAndDownVotes: Boolean = false,
|
||||||
|
@ -198,13 +198,13 @@ class PostListScreen : Screen {
|
|||||||
val sheet = ListingTypeBottomSheet(
|
val sheet = ListingTypeBottomSheet(
|
||||||
isLogged = uiState.isLogged,
|
isLogged = uiState.isLogged,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
onSelectSortType = rememberCallback {
|
onSelectSortType = rememberCallback {
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
expandTop = true,
|
expandTop = true,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -315,6 +315,14 @@ class PostListScreen : Screen {
|
|||||||
SwipeableCard(
|
SwipeableCard(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
enabled = uiState.swipeActionsEnabled,
|
enabled = uiState.swipeActionsEnabled,
|
||||||
|
directions = if (!uiState.isLogged) {
|
||||||
|
emptySet()
|
||||||
|
} else {
|
||||||
|
setOf(
|
||||||
|
DismissDirection.StartToEnd,
|
||||||
|
DismissDirection.EndToStart,
|
||||||
|
)
|
||||||
|
},
|
||||||
backgroundColor = rememberCallbackArgs {
|
backgroundColor = rememberCallbackArgs {
|
||||||
when (it) {
|
when (it) {
|
||||||
DismissValue.DismissedToStart -> upvoteColor
|
DismissValue.DismissedToStart -> upvoteColor
|
||||||
@ -356,51 +364,72 @@ class PostListScreen : Screen {
|
|||||||
blurNsfw = uiState.blurNsfw,
|
blurNsfw = uiState.blurNsfw,
|
||||||
onClick = rememberCallback(model) {
|
onClick = rememberCallback(model) {
|
||||||
model.reduce(PostListMviModel.Intent.MarkAsRead(post.id))
|
model.reduce(PostListMviModel.Intent.MarkAsRead(post.id))
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(post),
|
PostDetailScreen(post),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onDoubleClick = if (!uiState.doubleTapActionEnabled || !uiState.isLogged) {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
null
|
||||||
CommunityDetailScreen(community),
|
} else {
|
||||||
)
|
rememberCallback(model) {
|
||||||
},
|
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
|
||||||
UserDetailScreen(user),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onUpVote = rememberCallback(model) {
|
|
||||||
model.reduce(
|
model.reduce(
|
||||||
PostListMviModel.Intent.UpVotePost(
|
PostListMviModel.Intent.UpVotePost(
|
||||||
id = post.id,
|
id = post.id,
|
||||||
feedback = true,
|
feedback = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
|
navigationCoordinator.pushScreen(
|
||||||
|
CommunityDetailScreen(community),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
|
navigationCoordinator.pushScreen(
|
||||||
|
UserDetailScreen(user),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onUpVote = rememberCallback(model) {
|
||||||
|
if (uiState.isLogged) {
|
||||||
|
model.reduce(
|
||||||
|
PostListMviModel.Intent.UpVotePost(
|
||||||
|
id = post.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDownVote = rememberCallback(model) {
|
onDownVote = rememberCallback(model) {
|
||||||
|
if (uiState.isLogged) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
PostListMviModel.Intent.DownVotePost(
|
PostListMviModel.Intent.DownVotePost(
|
||||||
id = post.id,
|
id = post.id,
|
||||||
feedback = true,
|
feedback = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onSave = rememberCallback(model) {
|
onSave = rememberCallback(model) {
|
||||||
|
if (uiState.isLogged) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
PostListMviModel.Intent.SavePost(
|
PostListMviModel.Intent.SavePost(
|
||||||
id = post.id,
|
id = post.id,
|
||||||
feedback = true,
|
feedback = true,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onReply = rememberCallback(model) {
|
onReply = rememberCallback(model) {
|
||||||
val screen = CreateCommentScreen(originalPost = post)
|
if (uiState.isLogged) {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
val screen =
|
||||||
|
CreateCommentScreen(originalPost = post)
|
||||||
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs(model, post) { url ->
|
onImageClick = rememberCallbackArgs(model, post) { url ->
|
||||||
model.reduce(PostListMviModel.Intent.MarkAsRead(post.id))
|
model.reduce(PostListMviModel.Intent.MarkAsRead(post.id))
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url)
|
ZoomableImageScreen(url)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -411,7 +440,7 @@ class PostListScreen : Screen {
|
|||||||
stringResource(MR.strings.post_action_share)
|
stringResource(MR.strings.post_action_share)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (uiState.currentUserId != null) {
|
if (uiState.isLogged) {
|
||||||
add(
|
add(
|
||||||
Option(
|
Option(
|
||||||
OptionId.Hide,
|
OptionId.Hide,
|
||||||
@ -425,7 +454,7 @@ class PostListScreen : Screen {
|
|||||||
stringResource(MR.strings.post_action_see_raw)
|
stringResource(MR.strings.post_action_see_raw)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (uiState.currentUserId != null) {
|
if (uiState.isLogged) {
|
||||||
add(
|
add(
|
||||||
Option(
|
Option(
|
||||||
OptionId.CrossPost,
|
OptionId.CrossPost,
|
||||||
@ -461,22 +490,19 @@ class PostListScreen : Screen {
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreatePostScreen(editedPost = post)
|
CreatePostScreen(editedPost = post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreateReportScreen(postId = post.id)
|
CreateReportScreen(postId = post.id)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionId.CrossPost -> {
|
OptionId.CrossPost -> {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(
|
||||||
?.show(
|
|
||||||
CreatePostScreen(crossPost = post)
|
CreatePostScreen(crossPost = post)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,7 @@ class PostListViewModel(
|
|||||||
it.copy(
|
it.copy(
|
||||||
blurNsfw = settings.blurNsfw,
|
blurNsfw = settings.blurNsfw,
|
||||||
swipeActionsEnabled = settings.enableSwipeActions,
|
swipeActionsEnabled = settings.enableSwipeActions,
|
||||||
|
doubleTapActionEnabled = settings.enableDoubleTapAction,
|
||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
autoLoadImages = settings.autoLoadImages,
|
autoLoadImages = settings.autoLoadImages,
|
||||||
fullHeightImages = settings.fullHeightImages,
|
fullHeightImages = settings.fullHeightImages,
|
||||||
|
@ -47,7 +47,7 @@ internal fun PostsTopBar(
|
|||||||
onHamburgerTapped != null -> {
|
onHamburgerTapped != null -> {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onHamburgerTapped()
|
onHamburgerTapped()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -60,7 +60,7 @@ internal fun PostsTopBar(
|
|||||||
listingType != null -> {
|
listingType != null -> {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectListingType?.invoke()
|
onSelectListingType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -80,7 +80,7 @@ internal fun PostsTopBar(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = Spacing.s)
|
.padding(horizontal = Spacing.s)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectListingType?.invoke()
|
onSelectListingType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -115,7 +115,7 @@ internal fun PostsTopBar(
|
|||||||
if (sortType != null) {
|
if (sortType != null) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectSortType?.invoke()
|
onSelectSortType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -105,7 +105,7 @@ object InboxScreen : Tab {
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
drawerCoordinator.toggleDrawer()
|
drawerCoordinator.toggleDrawer()
|
||||||
}
|
}
|
||||||
@ -128,9 +128,9 @@ object InboxScreen : Tab {
|
|||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = InboxTypeSheet()
|
val sheet = InboxTypeSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
text = text,
|
text = text,
|
||||||
@ -142,7 +142,7 @@ object InboxScreen : Tab {
|
|||||||
if (uiState.isLogged == true) {
|
if (uiState.isLogged == true) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(InboxMviModel.Intent.ReadAll)
|
model.reduce(InboxMviModel.Intent.ReadAll)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -46,6 +46,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.Co
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.OptionId
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen
|
||||||
@ -181,7 +183,7 @@ class InboxMentionsScreen : Tab {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
||||||
onOpenPost = rememberCallbackArgs { post ->
|
onOpenPost = rememberCallbackArgs { post ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = post,
|
post = post,
|
||||||
highlightCommentId = mention.comment.id,
|
highlightCommentId = mention.comment.id,
|
||||||
@ -189,12 +191,12 @@ class InboxMentionsScreen : Tab {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user),
|
UserDetailScreen(user),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -208,6 +210,39 @@ class InboxMentionsScreen : Tab {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
options = buildList {
|
||||||
|
add(
|
||||||
|
Option(
|
||||||
|
OptionId.MarkRead,
|
||||||
|
stringResource(MR.strings.inbox_action_mark_read)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
add(
|
||||||
|
Option(
|
||||||
|
OptionId.MarkUnread,
|
||||||
|
stringResource(MR.strings.inbox_action_mark_unread)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onOptionSelected = rememberCallbackArgs(model) { optionId ->
|
||||||
|
when (optionId) {
|
||||||
|
OptionId.MarkRead -> model.reduce(
|
||||||
|
InboxMentionsMviModel.Intent.MarkAsRead(
|
||||||
|
read = true,
|
||||||
|
id = mention.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
OptionId.MarkUnread -> model.reduce(
|
||||||
|
InboxMentionsMviModel.Intent.MarkAsRead(
|
||||||
|
read = false,
|
||||||
|
id = mention.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -1,32 +1,47 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
|
package com.github.diegoberaldin.raccoonforlemmy.feature.inbox.messages
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.MoreHoriz
|
||||||
import androidx.compose.material.icons.filled.Schedule
|
import androidx.compose.material.icons.filled.Schedule
|
||||||
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
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.graphics.FilterQuality
|
import androidx.compose.ui.graphics.FilterQuality
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.layout.positionInParent
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.DpOffset
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomDropDown
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomImage
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.OptionId
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PlaceholderImage
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.ScaledContent
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.ScaledContent
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.prettifyDate
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -36,24 +51,30 @@ internal fun ChatCard(
|
|||||||
lastMessage: String,
|
lastMessage: String,
|
||||||
lastMessageDate: String? = null,
|
lastMessageDate: String? = null,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
options: List<Option> = emptyList(),
|
||||||
onOpenUser: ((UserModel) -> Unit)? = null,
|
onOpenUser: ((UserModel) -> Unit)? = null,
|
||||||
onOpen: (() -> Unit)? = null,
|
onOpen: (() -> Unit)? = null,
|
||||||
|
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
|
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
|
val creatorName = user?.name.orEmpty()
|
||||||
|
val creatorHost = user?.host.orEmpty()
|
||||||
|
val creatorAvatar = user?.avatar.orEmpty()
|
||||||
|
val iconSize = IconSize.xl
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(Spacing.xs)
|
.padding(Spacing.xs)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onOpen?.invoke()
|
onOpen?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.m),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.m),
|
||||||
) {
|
) {
|
||||||
val creatorName = user?.name.orEmpty()
|
|
||||||
val creatorHost = user?.host.orEmpty()
|
|
||||||
val creatorAvatar = user?.avatar.orEmpty()
|
|
||||||
val iconSize = 46.dp
|
|
||||||
|
|
||||||
if (creatorAvatar.isNotEmpty()) {
|
if (creatorAvatar.isNotEmpty()) {
|
||||||
CustomImage(
|
CustomImage(
|
||||||
@ -62,7 +83,7 @@ internal fun ChatCard(
|
|||||||
.size(iconSize)
|
.size(iconSize)
|
||||||
.clip(RoundedCornerShape(iconSize / 2))
|
.clip(RoundedCornerShape(iconSize / 2))
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
onOpenUser?.invoke(user)
|
onOpenUser?.invoke(user)
|
||||||
}
|
}
|
||||||
@ -77,7 +98,7 @@ internal fun ChatCard(
|
|||||||
} else {
|
} else {
|
||||||
PlaceholderImage(
|
PlaceholderImage(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
onOpenUser?.invoke(user)
|
onOpenUser?.invoke(user)
|
||||||
}
|
}
|
||||||
@ -115,11 +136,12 @@ internal fun ChatCard(
|
|||||||
|
|
||||||
// last message date
|
// last message date
|
||||||
if (lastMessageDate != null) {
|
if (lastMessageDate != null) {
|
||||||
|
Box {
|
||||||
Row(
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
horizontalArrangement = Arrangement.spacedBy(Spacing.xxs),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
val buttonModifier = Modifier.size(IconSize.m).padding(3.25.dp)
|
val buttonModifier = Modifier.size(IconSize.m).padding(3.5.dp)
|
||||||
Icon(
|
Icon(
|
||||||
modifier = buttonModifier.padding(1.dp),
|
modifier = buttonModifier.padding(1.dp),
|
||||||
imageVector = Icons.Default.Schedule,
|
imageVector = Icons.Default.Schedule,
|
||||||
@ -131,6 +153,50 @@ internal fun ChatCard(
|
|||||||
style = MaterialTheme.typography.labelMedium,
|
style = MaterialTheme.typography.labelMedium,
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface,
|
||||||
)
|
)
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
if (options.isNotEmpty()) {
|
||||||
|
Icon(
|
||||||
|
modifier = buttonModifier
|
||||||
|
.padding(top = Spacing.xxs)
|
||||||
|
.onGloballyPositioned {
|
||||||
|
optionsOffset = it.positionInParent()
|
||||||
|
}
|
||||||
|
.onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
optionsExpanded = true
|
||||||
|
},
|
||||||
|
),
|
||||||
|
imageVector = Icons.Default.MoreHoriz,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomDropDown(
|
||||||
|
expanded = optionsExpanded,
|
||||||
|
onDismiss = {
|
||||||
|
optionsExpanded = false
|
||||||
|
},
|
||||||
|
offset = DpOffset(
|
||||||
|
x = optionsOffset.x.toLocalDp(),
|
||||||
|
y = optionsOffset.y.toLocalDp(),
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
options.forEach { option ->
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
horizontal = Spacing.m,
|
||||||
|
vertical = Spacing.s,
|
||||||
|
).onClick(
|
||||||
|
onClick = rememberCallback {
|
||||||
|
optionsExpanded = false
|
||||||
|
onOptionSelected?.invoke(option.id)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
text = option.text,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,18 +118,18 @@ class InboxMessagesScreen : Tab {
|
|||||||
lastMessage = chat.content.orEmpty(),
|
lastMessage = chat.content.orEmpty(),
|
||||||
lastMessageDate = chat.publishDate,
|
lastMessageDate = chat.publishDate,
|
||||||
onOpenUser = rememberCallbackArgs { user ->
|
onOpenUser = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user)
|
UserDetailScreen(user)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpen = rememberCallback {
|
onOpen = rememberCallback {
|
||||||
val userId = otherUser?.id
|
val userId = otherUser?.id
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
InboxChatScreen(userId)
|
InboxChatScreen(userId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
item {
|
item {
|
||||||
|
@ -46,6 +46,8 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.Co
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardPlaceholder
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.InboxCardType
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.OptionId
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen
|
||||||
@ -180,7 +182,7 @@ class InboxRepliesScreen : Tab {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
||||||
onOpenPost = rememberCallbackArgs { post ->
|
onOpenPost = rememberCallbackArgs { post ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = post,
|
post = post,
|
||||||
highlightCommentId = reply.comment.id,
|
highlightCommentId = reply.comment.id,
|
||||||
@ -188,12 +190,12 @@ class InboxRepliesScreen : Tab {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user),
|
UserDetailScreen(user),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -203,6 +205,39 @@ class InboxRepliesScreen : Tab {
|
|||||||
onDownVote = rememberCallbackArgs(model) {
|
onDownVote = rememberCallbackArgs(model) {
|
||||||
model.reduce(InboxRepliesMviModel.Intent.DownVoteComment(reply.id))
|
model.reduce(InboxRepliesMviModel.Intent.DownVoteComment(reply.id))
|
||||||
},
|
},
|
||||||
|
options = buildList {
|
||||||
|
add(
|
||||||
|
Option(
|
||||||
|
OptionId.MarkRead,
|
||||||
|
stringResource(MR.strings.inbox_action_mark_read)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
add(
|
||||||
|
Option(
|
||||||
|
OptionId.MarkUnread,
|
||||||
|
stringResource(MR.strings.inbox_action_mark_unread)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onOptionSelected = rememberCallbackArgs(model) { optionId ->
|
||||||
|
when (optionId) {
|
||||||
|
OptionId.MarkRead -> model.reduce(
|
||||||
|
InboxRepliesMviModel.Intent.MarkAsRead(
|
||||||
|
read = true,
|
||||||
|
id = reply.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
OptionId.MarkUnread -> model.reduce(
|
||||||
|
InboxRepliesMviModel.Intent.MarkAsRead(
|
||||||
|
read = false,
|
||||||
|
id = reply.id,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -142,8 +142,7 @@ internal object ProfileLoggedScreen : Tab {
|
|||||||
user = user,
|
user = user,
|
||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
onOpenImage = rememberCallbackArgs { url ->
|
onOpenImage = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()
|
navigationCoordinator.pushScreen(ZoomableImageScreen(url))
|
||||||
?.push(ZoomableImageScreen(url))
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
SectionSelector(
|
SectionSelector(
|
||||||
@ -193,17 +192,17 @@ internal object ProfileLoggedScreen : Tab {
|
|||||||
hideAuthor = true,
|
hideAuthor = true,
|
||||||
blurNsfw = false,
|
blurNsfw = false,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(post),
|
PostDetailScreen(post),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -264,7 +263,7 @@ internal object ProfileLoggedScreen : Tab {
|
|||||||
)
|
)
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreatePostScreen(
|
CreatePostScreen(
|
||||||
editedPost = post,
|
editedPost = post,
|
||||||
)
|
)
|
||||||
@ -324,7 +323,7 @@ internal object ProfileLoggedScreen : Tab {
|
|||||||
hideAuthor = true,
|
hideAuthor = true,
|
||||||
hideIndent = true,
|
hideIndent = true,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = PostModel(id = comment.postId),
|
post = PostModel(id = comment.postId),
|
||||||
highlightCommentId = comment.id,
|
highlightCommentId = comment.id,
|
||||||
@ -386,7 +385,7 @@ internal object ProfileLoggedScreen : Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OptionId.Edit -> {
|
OptionId.Edit -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreateCommentScreen(editedComment = comment)
|
CreateCommentScreen(editedComment = comment)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ class LoginBottomSheet : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoginBottomSheetMviModel.Effect.LoginSuccess -> {
|
LoginBottomSheetMviModel.Effect.LoginSuccess -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -125,12 +125,11 @@ class LoginBottomSheet : Screen {
|
|||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.align(Alignment.TopEnd),
|
modifier = Modifier.align(Alignment.TopEnd),
|
||||||
onClick = {
|
onClick = {
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = HELP_URL,
|
url = HELP_URL,
|
||||||
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
openExternal = settingsRepository.currentSettings.value.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator(),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -181,7 +180,7 @@ class LoginBottomSheet : Screen {
|
|||||||
if (uiState.instanceName.isNotEmpty()) {
|
if (uiState.instanceName.isNotEmpty()) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback(model) {
|
onClick = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
LoginBottomSheetMviModel.Intent.SetInstanceName("")
|
LoginBottomSheetMviModel.Intent.SetInstanceName("")
|
||||||
)
|
)
|
||||||
@ -254,7 +253,7 @@ class LoginBottomSheet : Screen {
|
|||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
transformation =
|
transformation =
|
||||||
if (transformation == VisualTransformation.None) {
|
if (transformation == VisualTransformation.None) {
|
||||||
PasswordVisualTransformation()
|
PasswordVisualTransformation()
|
||||||
|
@ -86,7 +86,7 @@ internal object ProfileMainScreen : Tab {
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
drawerCoordinator.toggleDrawer()
|
drawerCoordinator.toggleDrawer()
|
||||||
}
|
}
|
||||||
@ -108,9 +108,8 @@ internal object ProfileMainScreen : Tab {
|
|||||||
if (uiState.logged == true) {
|
if (uiState.logged == true) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getBottomNavigator()
|
navigationCoordinator.showBottomSheet(ManageAccountsScreen())
|
||||||
?.show(ManageAccountsScreen())
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ManageAccounts,
|
imageVector = Icons.Default.ManageAccounts,
|
||||||
@ -122,7 +121,7 @@ internal object ProfileMainScreen : Tab {
|
|||||||
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(ProfileMainMviModel.Intent.Logout)
|
model.reduce(ProfileMainMviModel.Intent.Logout)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -64,7 +64,7 @@ class ManageAccountsScreen : Screen {
|
|||||||
model.effects.onEach { effect ->
|
model.effects.onEach { effect ->
|
||||||
when (effect) {
|
when (effect) {
|
||||||
ManageAccountsMviModel.Effect.Close -> {
|
ManageAccountsMviModel.Effect.Close -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.hide()
|
navigationCoordinator.hideBottomSheet()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -104,7 +104,7 @@ class ManageAccountsScreen : Screen {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(ManageAccountsMviModel.Intent.SwitchAccount(idx))
|
model.reduce(ManageAccountsMviModel.Intent.SwitchAccount(idx))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -151,7 +151,7 @@ class ManageAccountsScreen : Screen {
|
|||||||
Spacer(modifier = Modifier.height(Spacing.m))
|
Spacer(modifier = Modifier.height(Spacing.m))
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(LoginBottomSheet())
|
navigationCoordinator.showBottomSheet(LoginBottomSheet())
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
|
@ -42,7 +42,7 @@ internal object ProfileNotLoggedScreen : Tab {
|
|||||||
Button(
|
Button(
|
||||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||||
onClick = {
|
onClick = {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
LoginBottomSheet(),
|
LoginBottomSheet(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -18,6 +18,7 @@ interface ExploreMviModel :
|
|||||||
data class SetListingType(val value: ListingType) : Intent
|
data class SetListingType(val value: ListingType) : Intent
|
||||||
data class SetSortType(val value: SortType) : Intent
|
data class SetSortType(val value: SortType) : Intent
|
||||||
data class SetResultType(val value: SearchResultType) : Intent
|
data class SetResultType(val value: SearchResultType) : Intent
|
||||||
|
data object HapticIndication : Intent
|
||||||
data class UpVotePost(val id: Int, val feedback: Boolean = false) : Intent
|
data class UpVotePost(val id: Int, val feedback: Boolean = false) : Intent
|
||||||
data class DownVotePost(val id: Int, val feedback: Boolean = false) : Intent
|
data class DownVotePost(val id: Int, val feedback: Boolean = false) : Intent
|
||||||
data class SavePost(val id: Int, val feedback: Boolean = false) : Intent
|
data class SavePost(val id: Int, val feedback: Boolean = false) : Intent
|
||||||
@ -31,6 +32,8 @@ interface ExploreMviModel :
|
|||||||
val loading: Boolean = false,
|
val loading: Boolean = false,
|
||||||
val canFetchMore: Boolean = true,
|
val canFetchMore: Boolean = true,
|
||||||
val isLogged: Boolean = false,
|
val isLogged: Boolean = false,
|
||||||
|
val swipeActionsEnabled: Boolean = false,
|
||||||
|
val doubleTapActionEnabled: Boolean = false,
|
||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val instance: String = "",
|
val instance: String = "",
|
||||||
val searchText: String = "",
|
val searchText: String = "",
|
||||||
|
@ -15,12 +15,16 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
import androidx.compose.material.ExperimentalMaterialApi
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowCircleDown
|
||||||
|
import androidx.compose.material.icons.filled.ArrowCircleUp
|
||||||
import androidx.compose.material.icons.filled.Clear
|
import androidx.compose.material.icons.filled.Clear
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||||
import androidx.compose.material.pullrefresh.pullRefresh
|
import androidx.compose.material.pullrefresh.pullRefresh
|
||||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.DismissDirection
|
||||||
|
import androidx.compose.material3.DismissValue
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@ -42,6 +46,7 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
@ -52,6 +57,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.PostLayout
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
||||||
@ -59,6 +65,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Comment
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityItem
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityItem
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.PostCardPlaceholder
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.SwipeableCard
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.UserItem
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.UserItem
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.createcomment.CreateCommentScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
|
||||||
@ -114,6 +121,12 @@ class ExploreScreen : Screen {
|
|||||||
}
|
}
|
||||||
val settingsRepository = remember { getSettingsRepository() }
|
val settingsRepository = remember { getSettingsRepository() }
|
||||||
val settings by settingsRepository.currentSettings.collectAsState()
|
val settings by settingsRepository.currentSettings.collectAsState()
|
||||||
|
val themeRepository = remember { getThemeRepository() }
|
||||||
|
val upvoteColor by themeRepository.upvoteColor.collectAsState()
|
||||||
|
val downvoteColor by themeRepository.downvoteColor.collectAsState()
|
||||||
|
val defaultUpvoteColor = MaterialTheme.colorScheme.primary
|
||||||
|
val defaultDownVoteColor = MaterialTheme.colorScheme.tertiary
|
||||||
|
|
||||||
DisposableEffect(key) {
|
DisposableEffect(key) {
|
||||||
onDispose {
|
onDispose {
|
||||||
notificationCenter.removeObserver(key)
|
notificationCenter.removeObserver(key)
|
||||||
@ -176,14 +189,14 @@ class ExploreScreen : Screen {
|
|||||||
val sheet = ListingTypeBottomSheet(
|
val sheet = ListingTypeBottomSheet(
|
||||||
isLogged = uiState.isLogged,
|
isLogged = uiState.isLogged,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
onSelectSortType = rememberCallback {
|
onSelectSortType = rememberCallback {
|
||||||
focusManager.clearFocus()
|
focusManager.clearFocus()
|
||||||
val sheet = SortBottomSheet(
|
val sheet = SortBottomSheet(
|
||||||
expandTop = true,
|
expandTop = true,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
onHamburgerTapped = rememberCallback {
|
onHamburgerTapped = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@ -217,7 +230,7 @@ class ExploreScreen : Screen {
|
|||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (uiState.searchText.isNotEmpty()) {
|
if (uiState.searchText.isNotEmpty()) {
|
||||||
model.reduce(ExploreMviModel.Intent.SetSearch(""))
|
model.reduce(ExploreMviModel.Intent.SetSearch(""))
|
||||||
}
|
}
|
||||||
@ -308,8 +321,8 @@ class ExploreScreen : Screen {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(result),
|
CommunityDetailScreen(result),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -320,6 +333,41 @@ class ExploreScreen : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is PostModel -> {
|
is PostModel -> {
|
||||||
|
SwipeableCard(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
enabled = uiState.swipeActionsEnabled,
|
||||||
|
backgroundColor = rememberCallbackArgs {
|
||||||
|
when (it) {
|
||||||
|
DismissValue.DismissedToStart -> upvoteColor
|
||||||
|
?: defaultUpvoteColor
|
||||||
|
|
||||||
|
DismissValue.DismissedToEnd -> downvoteColor
|
||||||
|
?: defaultDownVoteColor
|
||||||
|
|
||||||
|
DismissValue.Default -> Color.Transparent
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onGestureBegin = {
|
||||||
|
model.reduce(ExploreMviModel.Intent.HapticIndication)
|
||||||
|
},
|
||||||
|
onDismissToStart = rememberCallback(model) {
|
||||||
|
model.reduce(ExploreMviModel.Intent.UpVotePost(result.id))
|
||||||
|
},
|
||||||
|
onDismissToEnd = rememberCallback(model) {
|
||||||
|
model.reduce(ExploreMviModel.Intent.DownVotePost(result.id))
|
||||||
|
},
|
||||||
|
swipeContent = { direction ->
|
||||||
|
val icon = when (direction) {
|
||||||
|
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||||
|
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||||
|
}
|
||||||
|
androidx.compose.material.Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = Color.White,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
content = {
|
||||||
PostCard(
|
PostCard(
|
||||||
post = result,
|
post = result,
|
||||||
postLayout = uiState.postLayout,
|
postLayout = uiState.postLayout,
|
||||||
@ -328,17 +376,29 @@ class ExploreScreen : Screen {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
blurNsfw = uiState.blurNsfw,
|
blurNsfw = uiState.blurNsfw,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(result),
|
PostDetailScreen(result),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
ExploreMviModel.Intent.UpVotePost(
|
||||||
|
id = result.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs { community ->
|
onOpenCommunity = rememberCallbackArgs { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs { user ->
|
onOpenCreator = rememberCallbackArgs { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user),
|
UserDetailScreen(user),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -370,14 +430,16 @@ class ExploreScreen : Screen {
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = result,
|
originalPost = result,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
onImageClick = rememberCallbackArgs { url ->
|
onImageClick = rememberCallbackArgs { url ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
if (uiState.postLayout != PostLayout.Card) {
|
if (uiState.postLayout != PostLayout.Card) {
|
||||||
Divider(modifier = Modifier.padding(vertical = Spacing.s))
|
Divider(modifier = Modifier.padding(vertical = Spacing.s))
|
||||||
} else {
|
} else {
|
||||||
@ -386,6 +448,57 @@ class ExploreScreen : Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is CommentModel -> {
|
is CommentModel -> {
|
||||||
|
SwipeableCard(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
enabled = uiState.swipeActionsEnabled,
|
||||||
|
directions = if (!uiState.isLogged) {
|
||||||
|
emptySet()
|
||||||
|
} else {
|
||||||
|
setOf(
|
||||||
|
DismissDirection.StartToEnd,
|
||||||
|
DismissDirection.EndToStart,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
backgroundColor = rememberCallbackArgs {
|
||||||
|
when (it) {
|
||||||
|
DismissValue.DismissedToStart -> upvoteColor
|
||||||
|
?: defaultUpvoteColor
|
||||||
|
|
||||||
|
DismissValue.DismissedToEnd -> downvoteColor
|
||||||
|
?: defaultDownVoteColor
|
||||||
|
|
||||||
|
DismissValue.Default -> Color.Transparent
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onGestureBegin = rememberCallback(model) {
|
||||||
|
model.reduce(ExploreMviModel.Intent.HapticIndication)
|
||||||
|
},
|
||||||
|
onDismissToStart = rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
ExploreMviModel.Intent.UpVoteComment(
|
||||||
|
id = result.id
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onDismissToEnd = rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
ExploreMviModel.Intent.DownVoteComment(
|
||||||
|
id = result.id
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
swipeContent = { direction ->
|
||||||
|
val icon = when (direction) {
|
||||||
|
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||||
|
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||||
|
}
|
||||||
|
androidx.compose.material.Icon(
|
||||||
|
imageVector = icon,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = Color.White,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
content = {
|
||||||
CommentCard(
|
CommentCard(
|
||||||
modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
modifier = Modifier.background(MaterialTheme.colorScheme.background),
|
||||||
comment = result,
|
comment = result,
|
||||||
@ -393,13 +506,25 @@ class ExploreScreen : Screen {
|
|||||||
autoLoadImages = uiState.autoLoadImages,
|
autoLoadImages = uiState.autoLoadImages,
|
||||||
hideIndent = true,
|
hideIndent = true,
|
||||||
onClick = rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = PostModel(id = result.postId),
|
post = PostModel(id = result.postId),
|
||||||
highlightCommentId = result.id,
|
highlightCommentId = result.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (!uiState.doubleTapActionEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
ExploreMviModel.Intent.UpVoteComment(
|
||||||
|
id = result.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onUpVote = rememberCallback(model) {
|
onUpVote = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
ExploreMviModel.Intent.UpVoteComment(
|
ExploreMviModel.Intent.UpVoteComment(
|
||||||
@ -429,19 +554,21 @@ class ExploreScreen : Screen {
|
|||||||
originalPost = PostModel(id = result.postId),
|
originalPost = PostModel(id = result.postId),
|
||||||
originalComment = result,
|
originalComment = result,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
onOpenCommunity = rememberCallbackArgs {
|
onOpenCommunity = rememberCallbackArgs {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(it)
|
CommunityDetailScreen(it)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = rememberCallbackArgs {
|
onOpenCreator = rememberCallbackArgs {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(it)
|
UserDetailScreen(it)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
Divider(
|
Divider(
|
||||||
modifier = Modifier.padding(vertical = Spacing.xxxs),
|
modifier = Modifier.padding(vertical = Spacing.xxxs),
|
||||||
thickness = 0.25.dp
|
thickness = 0.25.dp
|
||||||
@ -453,8 +580,8 @@ class ExploreScreen : Screen {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(result),
|
UserDetailScreen(result),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -46,7 +46,7 @@ internal fun ExploreTopBar(
|
|||||||
onHamburgerTapped != null -> {
|
onHamburgerTapped != null -> {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onHamburgerTapped()
|
onHamburgerTapped()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -59,7 +59,7 @@ internal fun ExploreTopBar(
|
|||||||
listingType != null -> {
|
listingType != null -> {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectListingType?.invoke()
|
onSelectListingType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -79,7 +79,7 @@ internal fun ExploreTopBar(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = Spacing.s)
|
.padding(horizontal = Spacing.s)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectListingType?.invoke()
|
onSelectListingType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -109,7 +109,7 @@ internal fun ExploreTopBar(
|
|||||||
|
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onSelectSortType?.invoke()
|
onSelectSortType?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -89,6 +89,8 @@ class ExploreViewModel(
|
|||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
autoLoadImages = settings.autoLoadImages,
|
autoLoadImages = settings.autoLoadImages,
|
||||||
fullHeightImages = settings.fullHeightImages,
|
fullHeightImages = settings.fullHeightImages,
|
||||||
|
swipeActionsEnabled = settings.enableSwipeActions,
|
||||||
|
doubleTapActionEnabled = settings.enableDoubleTapAction,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -126,6 +128,7 @@ class ExploreViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExploreMviModel.Intent.HapticIndication -> hapticFeedback.vibrate()
|
||||||
is ExploreMviModel.Intent.SetSearch -> setSearch(intent.value)
|
is ExploreMviModel.Intent.SetSearch -> setSearch(intent.value)
|
||||||
is ExploreMviModel.Intent.SetListingType -> changeListingType(intent.value)
|
is ExploreMviModel.Intent.SetListingType -> changeListingType(intent.value)
|
||||||
is ExploreMviModel.Intent.SetSortType -> changeSortType(intent.value)
|
is ExploreMviModel.Intent.SetSortType -> changeSortType(intent.value)
|
||||||
|
@ -108,8 +108,8 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.pop()
|
navigatorCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -178,8 +178,8 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
MultiCommunityEditorScreen()
|
MultiCommunityEditorScreen()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -206,7 +206,7 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
model.reduce(ManageSubscriptionsMviModel.Intent.HapticIndication)
|
model.reduce(ManageSubscriptionsMviModel.Intent.HapticIndication)
|
||||||
},
|
},
|
||||||
onDismissToStart = rememberCallback {
|
onDismissToStart = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
MultiCommunityEditorScreen(community),
|
MultiCommunityEditorScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -233,8 +233,8 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
MultiCommunityItem(
|
MultiCommunityItem(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.background).onClick(
|
.background(MaterialTheme.colorScheme.background).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
MultiCommunityScreen(community),
|
MultiCommunityScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -294,8 +294,8 @@ class ManageSubscriptionsScreen : Screen {
|
|||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.background)
|
.background(MaterialTheme.colorScheme.background)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigatorCoordinator.getRootNavigator()?.push(
|
navigatorCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -159,8 +159,8 @@ class MultiCommunityScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -184,9 +184,9 @@ class MultiCommunityScreen(
|
|||||||
if (sortType != null) {
|
if (sortType != null) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
val sheet = SortBottomSheet(expandTop = true)
|
val sheet = SortBottomSheet(expandTop = true)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = sortType.toIcon(),
|
imageVector = sortType.toIcon(),
|
||||||
@ -316,17 +316,29 @@ class MultiCommunityScreen(
|
|||||||
blurNsfw = uiState.blurNsfw,
|
blurNsfw = uiState.blurNsfw,
|
||||||
onClick = {
|
onClick = {
|
||||||
model.reduce(MultiCommunityMviModel.Intent.MarkAsRead(post.id))
|
model.reduce(MultiCommunityMviModel.Intent.MarkAsRead(post.id))
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
PostDetailScreen(post),
|
PostDetailScreen(post),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
onDoubleClick = if (uiState.swipeActionsEnabled) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
rememberCallback(model) {
|
||||||
|
model.reduce(
|
||||||
|
MultiCommunityMviModel.Intent.UpVotePost(
|
||||||
|
id = post.id,
|
||||||
|
feedback = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onOpenCommunity = { community ->
|
onOpenCommunity = { community ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(community),
|
CommunityDetailScreen(community),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onOpenCreator = { user ->
|
onOpenCreator = { user ->
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
UserDetailScreen(user),
|
UserDetailScreen(user),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -358,11 +370,11 @@ class MultiCommunityScreen(
|
|||||||
val screen = CreateCommentScreen(
|
val screen = CreateCommentScreen(
|
||||||
originalPost = post,
|
originalPost = post,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(screen)
|
navigationCoordinator.showBottomSheet(screen)
|
||||||
},
|
},
|
||||||
onImageClick = { url ->
|
onImageClick = { url ->
|
||||||
model.reduce(MultiCommunityMviModel.Intent.MarkAsRead(post.id))
|
model.reduce(MultiCommunityMviModel.Intent.MarkAsRead(post.id))
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
ZoomableImageScreen(url),
|
ZoomableImageScreen(url),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -391,7 +403,7 @@ class MultiCommunityScreen(
|
|||||||
onOptionSelected = { optionId ->
|
onOptionSelected = { optionId ->
|
||||||
when (optionId) {
|
when (optionId) {
|
||||||
OptionId.Report -> {
|
OptionId.Report -> {
|
||||||
navigationCoordinator.getBottomNavigator()?.show(
|
navigationCoordinator.showBottomSheet(
|
||||||
CreateReportScreen(
|
CreateReportScreen(
|
||||||
postId = post.id
|
postId = post.id
|
||||||
)
|
)
|
||||||
|
@ -88,7 +88,7 @@ class MultiCommunityEditorScreen(
|
|||||||
model.effects.onEach {
|
model.effects.onEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
MultiCommunityEditorMviModel.Effect.Close -> {
|
MultiCommunityEditorMviModel.Effect.Close -> {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
@ -114,8 +114,8 @@ class MultiCommunityEditorScreen(
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
navigationCoordinator.getRootNavigator()?.pop()
|
navigationCoordinator.popScreen()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
@ -219,7 +219,7 @@ class MultiCommunityEditorScreen(
|
|||||||
it
|
it
|
||||||
}
|
}
|
||||||
}.onClick(
|
}.onClick(
|
||||||
rememberCallback(model) {
|
onClick = rememberCallback(model) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
MultiCommunityEditorMviModel.Intent.SelectImage(
|
MultiCommunityEditorMviModel.Intent.SelectImage(
|
||||||
idx,
|
idx,
|
||||||
@ -260,7 +260,7 @@ class MultiCommunityEditorScreen(
|
|||||||
it
|
it
|
||||||
}
|
}
|
||||||
}.onClick(
|
}.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
MultiCommunityEditorMviModel.Intent.SelectImage(
|
MultiCommunityEditorMviModel.Intent.SelectImage(
|
||||||
null,
|
null,
|
||||||
@ -307,7 +307,7 @@ class MultiCommunityEditorScreen(
|
|||||||
trailingIcon = {
|
trailingIcon = {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
if (uiState.searchText.isNotEmpty()) {
|
if (uiState.searchText.isNotEmpty()) {
|
||||||
model.reduce(
|
model.reduce(
|
||||||
MultiCommunityEditorMviModel.Intent.SetSearch("")
|
MultiCommunityEditorMviModel.Intent.SetSearch("")
|
||||||
|
@ -75,7 +75,7 @@ class AboutDialog : Screen {
|
|||||||
viewModel.effects.onEach { effect ->
|
viewModel.effects.onEach { effect ->
|
||||||
when (effect) {
|
when (effect) {
|
||||||
is AboutDialogMviModel.Effect.OpenCommunity -> {
|
is AboutDialogMviModel.Effect.OpenCommunity -> {
|
||||||
navigationCoordinator.getRootNavigator()?.push(
|
navigationCoordinator.pushScreen(
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
community = effect.community,
|
community = effect.community,
|
||||||
otherInstance = effect.instance,
|
otherInstance = effect.instance,
|
||||||
@ -122,11 +122,10 @@ class AboutDialog : Screen {
|
|||||||
vector = Icons.Default.OpenInBrowser,
|
vector = Icons.Default.OpenInBrowser,
|
||||||
textDecoration = TextDecoration.Underline,
|
textDecoration = TextDecoration.Underline,
|
||||||
onClick = {
|
onClick = {
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = CHANGELOG_URL,
|
url = CHANGELOG_URL,
|
||||||
openExternal = settings.openUrlsInExternalBrowser,
|
openExternal = settings.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -134,11 +133,10 @@ class AboutDialog : Screen {
|
|||||||
item {
|
item {
|
||||||
Button(
|
Button(
|
||||||
onClick = {
|
onClick = {
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = REPORT_URL,
|
url = REPORT_URL,
|
||||||
openExternal = settings.openUrlsInExternalBrowser,
|
openExternal = settings.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator(),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
@ -166,11 +164,10 @@ class AboutDialog : Screen {
|
|||||||
text = stringResource(MR.strings.settings_about_view_github),
|
text = stringResource(MR.strings.settings_about_view_github),
|
||||||
textDecoration = TextDecoration.Underline,
|
textDecoration = TextDecoration.Underline,
|
||||||
onClick = {
|
onClick = {
|
||||||
handleUrl(
|
navigationCoordinator.handleUrl(
|
||||||
url = WEBSITE_URL,
|
url = WEBSITE_URL,
|
||||||
openExternal = settings.openUrlsInExternalBrowser,
|
openExternal = settings.openUrlsInExternalBrowser,
|
||||||
uriHandler = uriHandler,
|
uriHandler = uriHandler,
|
||||||
navigator = navigationCoordinator.getRootNavigator(),
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -212,7 +209,7 @@ class AboutDialog : Screen {
|
|||||||
horizontal = Spacing.xs,
|
horizontal = Spacing.xs,
|
||||||
vertical = Spacing.s,
|
vertical = Spacing.s,
|
||||||
).onClick(
|
).onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onClick?.invoke()
|
onClick?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -32,6 +32,7 @@ interface SettingsMviModel :
|
|||||||
data class ChangeBlurNsfw(val value: Boolean) : Intent
|
data class ChangeBlurNsfw(val value: Boolean) : Intent
|
||||||
data class ChangeOpenUrlsInExternalBrowser(val value: Boolean) : Intent
|
data class ChangeOpenUrlsInExternalBrowser(val value: Boolean) : Intent
|
||||||
data class ChangeEnableSwipeActions(val value: Boolean) : Intent
|
data class ChangeEnableSwipeActions(val value: Boolean) : Intent
|
||||||
|
data class ChangeEnableDoubleTapAction(val value: Boolean) : Intent
|
||||||
data class ChangeCustomSeedColor(val value: Color?) : Intent
|
data class ChangeCustomSeedColor(val value: Color?) : Intent
|
||||||
data class ChangeUpvoteColor(val value: Color?) : Intent
|
data class ChangeUpvoteColor(val value: Color?) : Intent
|
||||||
data class ChangeDownvoteColor(val value: Color?) : Intent
|
data class ChangeDownvoteColor(val value: Color?) : Intent
|
||||||
@ -66,6 +67,7 @@ interface SettingsMviModel :
|
|||||||
val blurNsfw: Boolean = true,
|
val blurNsfw: Boolean = true,
|
||||||
val openUrlsInExternalBrowser: Boolean = false,
|
val openUrlsInExternalBrowser: Boolean = false,
|
||||||
val enableSwipeActions: Boolean = true,
|
val enableSwipeActions: Boolean = true,
|
||||||
|
val enableDoubleTapAction: Boolean = true,
|
||||||
val crashReportEnabled: Boolean = false,
|
val crashReportEnabled: Boolean = false,
|
||||||
val separateUpAndDownVotes: Boolean = false,
|
val separateUpAndDownVotes: Boolean = false,
|
||||||
val autoLoadImages: Boolean = false,
|
val autoLoadImages: Boolean = false,
|
||||||
|
@ -65,10 +65,10 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.SortBottomS
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.ThemeBottomSheet
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.modals.ThemeBottomSheet
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterContractKeys
|
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.NotificationCenterContractKeys
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotificationCenter
|
import com.github.diegoberaldin.raccoonforlemmy.core.notifications.di.getNotificationCenter
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.getPrettyDuration
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.onClick
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallback
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.compose.rememberCallbackArgs
|
||||||
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.datetime.getPrettyDuration
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageName
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLanguageName
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.ListingType
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.ListingType
|
||||||
@ -278,7 +278,7 @@ class SettingsScreen : Screen {
|
|||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick(
|
modifier = Modifier.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
drawerCoordinator.toggleDrawer()
|
drawerCoordinator.toggleDrawer()
|
||||||
}
|
}
|
||||||
@ -318,7 +318,7 @@ class SettingsScreen : Screen {
|
|||||||
value = uiState.lang.toLanguageName(),
|
value = uiState.lang.toLanguageName(),
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = LanguageBottomSheet()
|
val sheet = LanguageBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -328,13 +328,14 @@ class SettingsScreen : Screen {
|
|||||||
value = uiState.uiTheme.toReadableName(),
|
value = uiState.uiTheme.toReadableName(),
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = ThemeBottomSheet()
|
val sheet = ThemeBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// dynamic colors
|
// dynamic colors
|
||||||
if (uiState.supportsDynamicColors) {
|
if (uiState.supportsDynamicColors) {
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_dynamic_colors),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_dynamic_colors),
|
||||||
value = uiState.dynamicColors,
|
value = uiState.dynamicColors,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -342,7 +343,8 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val colorSchemeProvider = remember { getColorSchemeProvider() }
|
val colorSchemeProvider = remember { getColorSchemeProvider() }
|
||||||
@ -355,7 +357,7 @@ class SettingsScreen : Screen {
|
|||||||
).primary,
|
).primary,
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = ColorBottomSheet()
|
val sheet = ColorBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// upvote and downvote colors
|
// upvote and downvote colors
|
||||||
@ -380,7 +382,7 @@ class SettingsScreen : Screen {
|
|||||||
value = uiState.uiFontFamily.toReadableName(),
|
value = uiState.uiFontFamily.toReadableName(),
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = FontFamilyBottomSheet()
|
val sheet = FontFamilyBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// font scale
|
// font scale
|
||||||
@ -396,7 +398,7 @@ class SettingsScreen : Screen {
|
|||||||
),
|
),
|
||||||
contract = NotificationCenterContractKeys.ChangeUiFontSize
|
contract = NotificationCenterContractKeys.ChangeUiFontSize
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
SettingsRow(
|
SettingsRow(
|
||||||
@ -406,7 +408,7 @@ class SettingsScreen : Screen {
|
|||||||
val sheet = FontScaleBottomSheet(
|
val sheet = FontScaleBottomSheet(
|
||||||
contract = NotificationCenterContractKeys.ChangeContentFontSize,
|
contract = NotificationCenterContractKeys.ChangeContentFontSize,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -416,12 +418,13 @@ class SettingsScreen : Screen {
|
|||||||
value = uiState.postLayout.toReadableName(),
|
value = uiState.postLayout.toReadableName(),
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = PostLayoutBottomSheet()
|
val sheet = PostLayoutBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// separate upvotes and downvotes
|
// separate upvotes and downvotes
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_separate_up_and_downvotes),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_separate_up_and_downvotes),
|
||||||
value = uiState.separateUpAndDownVotes,
|
value = uiState.separateUpAndDownVotes,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -429,10 +432,12 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// full height images
|
// full height images
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_full_height_images),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_full_height_images),
|
||||||
value = uiState.fullHeightImages,
|
value = uiState.fullHeightImages,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -440,10 +445,12 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// navigation bar titles
|
// navigation bar titles
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_navigation_bar_titles_visible),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_navigation_bar_titles_visible),
|
||||||
value = uiState.navBarTitlesVisible,
|
value = uiState.navBarTitlesVisible,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -451,7 +458,8 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
SettingsHeader(
|
SettingsHeader(
|
||||||
icon = Icons.Default.Tune,
|
icon = Icons.Default.Tune,
|
||||||
@ -466,7 +474,7 @@ class SettingsScreen : Screen {
|
|||||||
val sheet = ListingTypeBottomSheet(
|
val sheet = ListingTypeBottomSheet(
|
||||||
isLogged = uiState.isLogged,
|
isLogged = uiState.isLogged,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -479,7 +487,7 @@ class SettingsScreen : Screen {
|
|||||||
expandTop = true,
|
expandTop = true,
|
||||||
contract = NotificationCenterContractKeys.ChangeSortType,
|
contract = NotificationCenterContractKeys.ChangeSortType,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -498,7 +506,7 @@ class SettingsScreen : Screen {
|
|||||||
SortType.Controversial,
|
SortType.Controversial,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -517,7 +525,7 @@ class SettingsScreen : Screen {
|
|||||||
),
|
),
|
||||||
onTap = rememberCallback {
|
onTap = rememberCallback {
|
||||||
val sheet = DurationBottomSheet()
|
val sheet = DurationBottomSheet()
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -535,12 +543,13 @@ class SettingsScreen : Screen {
|
|||||||
max = screenWidth,
|
max = screenWidth,
|
||||||
initial = uiState.zombieModeScrollAmount,
|
initial = uiState.zombieModeScrollAmount,
|
||||||
)
|
)
|
||||||
navigationCoordinator.getBottomNavigator()?.show(sheet)
|
navigationCoordinator.showBottomSheet(sheet)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// swipe actions
|
// swipe actions
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_enable_swipe_actions),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_enable_swipe_actions),
|
||||||
value = uiState.enableSwipeActions,
|
value = uiState.enableSwipeActions,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -548,10 +557,25 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// double tap
|
||||||
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_enable_double_tap),
|
||||||
|
value = uiState.enableDoubleTapAction,
|
||||||
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
|
model.reduce(
|
||||||
|
SettingsMviModel.Intent.ChangeEnableDoubleTapAction(
|
||||||
|
value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// bottom navigation hiding
|
// bottom navigation hiding
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_hide_navigation_bar),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_hide_navigation_bar),
|
||||||
value = uiState.hideNavigationBarWhileScrolling,
|
value = uiState.hideNavigationBarWhileScrolling,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -559,10 +583,12 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// URL open
|
// URL open
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_open_url_external),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_open_url_external),
|
||||||
value = uiState.openUrlsInExternalBrowser,
|
value = uiState.openUrlsInExternalBrowser,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -570,10 +596,12 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// auto-expand comments
|
// auto-expand comments
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_auto_expand_comments),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_auto_expand_comments),
|
||||||
value = uiState.autoExpandComments,
|
value = uiState.autoExpandComments,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -581,10 +609,12 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// image loading
|
// image loading
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_auto_load_images),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_auto_load_images),
|
||||||
value = uiState.autoLoadImages,
|
value = uiState.autoLoadImages,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(
|
model.reduce(
|
||||||
@ -592,7 +622,8 @@ class SettingsScreen : Screen {
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
SettingsHeader(
|
SettingsHeader(
|
||||||
icon = Icons.Default.Shield,
|
icon = Icons.Default.Shield,
|
||||||
@ -600,16 +631,19 @@ class SettingsScreen : Screen {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NSFW options
|
// NSFW options
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_include_nsfw),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_include_nsfw),
|
||||||
value = uiState.includeNsfw,
|
value = uiState.includeNsfw,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(SettingsMviModel.Intent.ChangeIncludeNsfw(value))
|
model.reduce(SettingsMviModel.Intent.ChangeIncludeNsfw(value))
|
||||||
})
|
})
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_blur_nsfw),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_blur_nsfw),
|
||||||
value = uiState.blurNsfw,
|
value = uiState.blurNsfw,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(SettingsMviModel.Intent.ChangeBlurNsfw(value))
|
model.reduce(SettingsMviModel.Intent.ChangeBlurNsfw(value))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
SettingsHeader(
|
SettingsHeader(
|
||||||
icon = Icons.Default.BugReport,
|
icon = Icons.Default.BugReport,
|
||||||
@ -617,11 +651,13 @@ class SettingsScreen : Screen {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// enable crash report
|
// enable crash report
|
||||||
SettingsSwitchRow(title = stringResource(MR.strings.settings_enable_crash_report),
|
SettingsSwitchRow(
|
||||||
|
title = stringResource(MR.strings.settings_enable_crash_report),
|
||||||
value = uiState.crashReportEnabled,
|
value = uiState.crashReportEnabled,
|
||||||
onValueChanged = rememberCallbackArgs(model) { value ->
|
onValueChanged = rememberCallbackArgs(model) { value ->
|
||||||
model.reduce(SettingsMviModel.Intent.ChangeCrashReportEnabled(value))
|
model.reduce(SettingsMviModel.Intent.ChangeCrashReportEnabled(value))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// about
|
// about
|
||||||
SettingsRow(
|
SettingsRow(
|
||||||
|
@ -109,6 +109,7 @@ class SettingsViewModel(
|
|||||||
supportsDynamicColors = colorSchemeProvider.supportsDynamicColors,
|
supportsDynamicColors = colorSchemeProvider.supportsDynamicColors,
|
||||||
openUrlsInExternalBrowser = settings.openUrlsInExternalBrowser,
|
openUrlsInExternalBrowser = settings.openUrlsInExternalBrowser,
|
||||||
enableSwipeActions = settings.enableSwipeActions,
|
enableSwipeActions = settings.enableSwipeActions,
|
||||||
|
enableDoubleTapAction = settings.enableDoubleTapAction,
|
||||||
crashReportEnabled = crashReportConfiguration.isEnabled(),
|
crashReportEnabled = crashReportConfiguration.isEnabled(),
|
||||||
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
separateUpAndDownVotes = settings.separateUpAndDownVotes,
|
||||||
autoLoadImages = settings.autoLoadImages,
|
autoLoadImages = settings.autoLoadImages,
|
||||||
@ -179,6 +180,10 @@ class SettingsViewModel(
|
|||||||
changeEnableSwipeActions(intent.value)
|
changeEnableSwipeActions(intent.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is SettingsMviModel.Intent.ChangeEnableDoubleTapAction -> {
|
||||||
|
changeEnableDoubleTapAction(intent.value)
|
||||||
|
}
|
||||||
|
|
||||||
is SettingsMviModel.Intent.ChangeCustomSeedColor -> changeCustomSeedColor(
|
is SettingsMviModel.Intent.ChangeCustomSeedColor -> changeCustomSeedColor(
|
||||||
intent.value
|
intent.value
|
||||||
)
|
)
|
||||||
@ -389,6 +394,16 @@ class SettingsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun changeEnableDoubleTapAction(value: Boolean) {
|
||||||
|
mvi.updateState { it.copy(enableDoubleTapAction = value) }
|
||||||
|
mvi.scope?.launch {
|
||||||
|
val settings = settingsRepository.currentSettings.value.copy(
|
||||||
|
enableDoubleTapAction = value
|
||||||
|
)
|
||||||
|
saveSettings(settings)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun changePostLayout(value: PostLayout) {
|
private fun changePostLayout(value: PostLayout) {
|
||||||
themeRepository.changePostLayout(value)
|
themeRepository.changePostLayout(value)
|
||||||
mvi.scope?.launch {
|
mvi.scope?.launch {
|
||||||
|
@ -2,6 +2,7 @@ package com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.components
|
|||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -24,18 +25,20 @@ internal fun SettingsColorRow(
|
|||||||
title: String,
|
title: String,
|
||||||
value: Color,
|
value: Color,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
subtitle: String? = null,
|
||||||
onTap: (() -> Unit)? = null,
|
onTap: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(vertical = Spacing.s, horizontal = Spacing.m)
|
.padding(vertical = Spacing.s, horizontal = Spacing.m)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onTap?.invoke()
|
onTap?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
@ -43,6 +46,16 @@ internal fun SettingsColorRow(
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
if (subtitle != null) {
|
||||||
|
Text(
|
||||||
|
text = subtitle,
|
||||||
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.components
|
package com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.components
|
||||||
|
|
||||||
|
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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -18,18 +19,20 @@ internal fun SettingsRow(
|
|||||||
title: String,
|
title: String,
|
||||||
value: String,
|
value: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
subtitle: String? = null,
|
||||||
onTap: (() -> Unit)? = null,
|
onTap: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.padding(vertical = Spacing.s, horizontal = Spacing.m)
|
.padding(vertical = Spacing.s, horizontal = Spacing.m)
|
||||||
.onClick(
|
.onClick(
|
||||||
rememberCallback {
|
onClick = rememberCallback {
|
||||||
onTap?.invoke()
|
onTap?.invoke()
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
@ -37,6 +40,16 @@ internal fun SettingsRow(
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
if (subtitle != null) {
|
||||||
|
Text(
|
||||||
|
text = subtitle,
|
||||||
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Text(
|
Text(
|
||||||
text = value,
|
text = value,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.components
|
package com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.components
|
||||||
|
|
||||||
|
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.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -16,12 +17,14 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
|||||||
internal fun SettingsSwitchRow(
|
internal fun SettingsSwitchRow(
|
||||||
title: String,
|
title: String,
|
||||||
value: Boolean,
|
value: Boolean,
|
||||||
|
subtitle: String? = null,
|
||||||
onValueChanged: (Boolean) -> Unit,
|
onValueChanged: (Boolean) -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(horizontal = Spacing.m),
|
modifier = Modifier.padding(horizontal = Spacing.m),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
@ -29,6 +32,16 @@ internal fun SettingsSwitchRow(
|
|||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
|
if (subtitle != null) {
|
||||||
|
Text(
|
||||||
|
text = subtitle,
|
||||||
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
Switch(
|
Switch(
|
||||||
checked = value,
|
checked = value,
|
||||||
|
@ -80,6 +80,8 @@
|
|||||||
<string name="home_sort_type_top_week_short">week</string>
|
<string name="home_sort_type_top_week_short">week</string>
|
||||||
<string name="home_sort_type_top_year">Top year</string>
|
<string name="home_sort_type_top_year">Top year</string>
|
||||||
<string name="home_sort_type_top_year_short">year</string>
|
<string name="home_sort_type_top_year_short">year</string>
|
||||||
|
<string name="inbox_action_mark_read">Mark as read</string>
|
||||||
|
<string name="inbox_action_mark_unread">Mark as unread</string>
|
||||||
<string name="inbox_chat_message">Message</string>
|
<string name="inbox_chat_message">Message</string>
|
||||||
<string name="inbox_item_mention">mentioned you in</string>
|
<string name="inbox_item_mention">mentioned you in</string>
|
||||||
<string name="inbox_item_reply_comment">replied to your comment in</string>
|
<string name="inbox_item_reply_comment">replied to your comment in</string>
|
||||||
@ -200,6 +202,7 @@
|
|||||||
<string name="settings_downvote_color">Downvote color</string>
|
<string name="settings_downvote_color">Downvote color</string>
|
||||||
<string name="settings_dynamic_colors">Use dynamic colors</string>
|
<string name="settings_dynamic_colors">Use dynamic colors</string>
|
||||||
<string name="settings_enable_crash_report">Enable crash reporting</string>
|
<string name="settings_enable_crash_report">Enable crash reporting</string>
|
||||||
|
<string name="settings_enable_double_tap">Enable double tap action</string>
|
||||||
<string name="settings_enable_swipe_actions">Enable swipe actions</string>
|
<string name="settings_enable_swipe_actions">Enable swipe actions</string>
|
||||||
<string name="settings_full_height_images">Full height images</string>
|
<string name="settings_full_height_images">Full height images</string>
|
||||||
<string name="settings_include_nsfw">Include NSFW contents</string>
|
<string name="settings_include_nsfw">Include NSFW contents</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Alle</string>
|
<string name="inbox_listing_type_all">Alle</string>
|
||||||
<string name="inbox_listing_type_title">Posteingangstyp</string>
|
<string name="inbox_listing_type_title">Posteingangstyp</string>
|
||||||
<string name="inbox_listing_type_unread">Ungelesen</string>
|
<string name="inbox_listing_type_unread">Ungelesen</string>
|
||||||
|
<string name="inbox_action_mark_read">Als gelesen markieren</string>
|
||||||
|
<string name="inbox_action_mark_unread">Als ungelesen markieren</string>
|
||||||
<string name="inbox_not_logged_message">Sie sind derzeit nicht angemeldet.\nBitte fügen Sie über
|
<string name="inbox_not_logged_message">Sie sind derzeit nicht angemeldet.\nBitte fügen Sie über
|
||||||
den Profilbildschirm ein Konto hinzu, um Ihren Posteingang anzuzeigen.
|
den Profilbildschirm ein Konto hinzu, um Ihren Posteingang anzuzeigen.
|
||||||
</string>
|
</string>
|
||||||
@ -193,6 +195,7 @@
|
|||||||
<string name="settings_downvote_color">Farbe für Downvotes</string>
|
<string name="settings_downvote_color">Farbe für Downvotes</string>
|
||||||
<string name="settings_dynamic_colors">Verwenden Sie dynamische Farben</string>
|
<string name="settings_dynamic_colors">Verwenden Sie dynamische Farben</string>
|
||||||
<string name="settings_enable_crash_report">Absturzberichte aktivieren</string>
|
<string name="settings_enable_crash_report">Absturzberichte aktivieren</string>
|
||||||
|
<string name="settings_enable_double_tap">Doppeltipp-Aktion aktivieren</string>
|
||||||
<string name="settings_enable_swipe_actions">Wischaktionen aktivieren</string>
|
<string name="settings_enable_swipe_actions">Wischaktionen aktivieren</string>
|
||||||
<string name="settings_full_height_images">Bilder in voller Höhe</string>
|
<string name="settings_full_height_images">Bilder in voller Höhe</string>
|
||||||
<string name="settings_include_nsfw">NSFW-Inhalte einbeziehen</string>
|
<string name="settings_include_nsfw">NSFW-Inhalte einbeziehen</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Όλα</string>
|
<string name="inbox_listing_type_all">Όλα</string>
|
||||||
<string name="inbox_listing_type_title">Τύπος εισερχομένων</string>
|
<string name="inbox_listing_type_title">Τύπος εισερχομένων</string>
|
||||||
<string name="inbox_listing_type_unread">Μη αναγνωσμένα</string>
|
<string name="inbox_listing_type_unread">Μη αναγνωσμένα</string>
|
||||||
|
<string name="inbox_action_mark_read">Σημειώσε ως αναγνωσμένο</string>
|
||||||
|
<string name="inbox_action_mark_unread">Σημειώστε ως αδιάβαστο</string>
|
||||||
<string name="inbox_not_logged_message">Προς το παρόν, δεν έχετε συνδεθεί.\nΠαρακαλούμε
|
<string name="inbox_not_logged_message">Προς το παρόν, δεν έχετε συνδεθεί.\nΠαρακαλούμε
|
||||||
προσθέστε έναν λογαριασμό από την οθόνη προφίλ για να δείτε τα εισερχόμενά σας.
|
προσθέστε έναν λογαριασμό από την οθόνη προφίλ για να δείτε τα εισερχόμενά σας.
|
||||||
</string>
|
</string>
|
||||||
@ -194,6 +196,7 @@
|
|||||||
<string name="settings_downvote_color">Χρώμα ψήφου κατώτερου</string>
|
<string name="settings_downvote_color">Χρώμα ψήφου κατώτερου</string>
|
||||||
<string name="settings_dynamic_colors">Χρήση δυναμικών χρωμάτων</string>
|
<string name="settings_dynamic_colors">Χρήση δυναμικών χρωμάτων</string>
|
||||||
<string name="settings_enable_crash_report">Ενεργοποίηση αναφοράς καταρρεύσεων</string>
|
<string name="settings_enable_crash_report">Ενεργοποίηση αναφοράς καταρρεύσεων</string>
|
||||||
|
<string name="settings_enable_double_tap">Ενεργοποίηση της δράσης διπλού πατήματος</string>
|
||||||
<string name="settings_enable_swipe_actions">Ενεργοποίηση κινήσεων σαρώσεων</string>
|
<string name="settings_enable_swipe_actions">Ενεργοποίηση κινήσεων σαρώσεων</string>
|
||||||
<string name="settings_full_height_images">Εικόνες πλήρους ύψους</string>
|
<string name="settings_full_height_images">Εικόνες πλήρους ύψους</string>
|
||||||
<string name="settings_include_nsfw">Συμπερίληψη περιεχομένων NSFW</string>
|
<string name="settings_include_nsfw">Συμπερίληψη περιεχομένων NSFW</string>
|
||||||
|
@ -84,6 +84,8 @@
|
|||||||
<string name="inbox_item_mention">te ha mencionado en</string>
|
<string name="inbox_item_mention">te ha mencionado en</string>
|
||||||
<string name="inbox_item_reply_comment">ha contestado a tu comentario en</string>
|
<string name="inbox_item_reply_comment">ha contestado a tu comentario en</string>
|
||||||
<string name="inbox_item_reply_post">ha contestado a tu publicación en</string>
|
<string name="inbox_item_reply_post">ha contestado a tu publicación en</string>
|
||||||
|
<string name="inbox_action_mark_read">mMrcar como leído</string>
|
||||||
|
<string name="inbox_action_mark_unread">Marcar como no leído</string>
|
||||||
<string name="inbox_listing_type_all">Todos</string>
|
<string name="inbox_listing_type_all">Todos</string>
|
||||||
<string name="inbox_listing_type_title">Tipo de mensajes</string>
|
<string name="inbox_listing_type_title">Tipo de mensajes</string>
|
||||||
<string name="inbox_listing_type_unread">No leídos</string>
|
<string name="inbox_listing_type_unread">No leídos</string>
|
||||||
@ -192,6 +194,7 @@
|
|||||||
<string name="settings_downvote_color">Color votos negativos</string>
|
<string name="settings_downvote_color">Color votos negativos</string>
|
||||||
<string name="settings_dynamic_colors">Utilizar colores dinámicos</string>
|
<string name="settings_dynamic_colors">Utilizar colores dinámicos</string>
|
||||||
<string name="settings_enable_crash_report">Activar notificación de accidentes</string>
|
<string name="settings_enable_crash_report">Activar notificación de accidentes</string>
|
||||||
|
<string name="settings_enable_double_tap">Activar la acción de doble toque</string>
|
||||||
<string name="settings_enable_swipe_actions">Activar acciones de deslizamiento</string>
|
<string name="settings_enable_swipe_actions">Activar acciones de deslizamiento</string>
|
||||||
<string name="settings_full_height_images">Altura completa imágenes</string>
|
<string name="settings_full_height_images">Altura completa imágenes</string>
|
||||||
<string name="settings_include_nsfw">Incluir contenidos NSFW</string>
|
<string name="settings_include_nsfw">Incluir contenidos NSFW</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Tous</string>
|
<string name="inbox_listing_type_all">Tous</string>
|
||||||
<string name="inbox_listing_type_title">Type de boîte de réception</string>
|
<string name="inbox_listing_type_title">Type de boîte de réception</string>
|
||||||
<string name="inbox_listing_type_unread">Non lus</string>
|
<string name="inbox_listing_type_unread">Non lus</string>
|
||||||
|
<string name="inbox_action_mark_read">Marquer comme lu</string>
|
||||||
|
<string name="inbox_action_mark_unread">Marquer comme non lu</string>
|
||||||
<string name="inbox_not_logged_message">Vous n\'êtes pas connecté.\nVeuillez ajouter un compte à
|
<string name="inbox_not_logged_message">Vous n\'êtes pas connecté.\nVeuillez ajouter un compte à
|
||||||
partir de l\'écran de profil pour voir votre boîte de réception.
|
partir de l\'écran de profil pour voir votre boîte de réception.
|
||||||
</string>
|
</string>
|
||||||
@ -192,6 +194,7 @@
|
|||||||
<string name="settings_downvote_color">Couleur votes négatifs</string>
|
<string name="settings_downvote_color">Couleur votes négatifs</string>
|
||||||
<string name="settings_dynamic_colors">Utiliser couleur dynamique</string>
|
<string name="settings_dynamic_colors">Utiliser couleur dynamique</string>
|
||||||
<string name="settings_enable_crash_report">Activer les rapports d\'accidents</string>
|
<string name="settings_enable_crash_report">Activer les rapports d\'accidents</string>
|
||||||
|
<string name="settings_enable_double_tap">Activer l\'action double tap</string>
|
||||||
<string name="settings_enable_swipe_actions">Activer les actions de glissement</string>
|
<string name="settings_enable_swipe_actions">Activer les actions de glissement</string>
|
||||||
<string name="settings_full_height_images">Images en pleine hauteur</string>
|
<string name="settings_full_height_images">Images en pleine hauteur</string>
|
||||||
<string name="settings_include_nsfw">Inclure contenus NSFW</string>
|
<string name="settings_include_nsfw">Inclure contenus NSFW</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Tutti</string>
|
<string name="inbox_listing_type_all">Tutti</string>
|
||||||
<string name="inbox_listing_type_title">Tipo inbox</string>
|
<string name="inbox_listing_type_title">Tipo inbox</string>
|
||||||
<string name="inbox_listing_type_unread">Non letti</string>
|
<string name="inbox_listing_type_unread">Non letti</string>
|
||||||
|
<string name="inbox_action_mark_read">Segna come letto</string>
|
||||||
|
<string name="inbox_action_mark_unread">Segna come non letto</string>
|
||||||
<string name="inbox_not_logged_message">Login non effettuato.\nAggiungi un account dalla
|
<string name="inbox_not_logged_message">Login non effettuato.\nAggiungi un account dalla
|
||||||
schermata Profilo per accedere alla inbox.
|
schermata Profilo per accedere alla inbox.
|
||||||
</string>
|
</string>
|
||||||
@ -192,6 +194,7 @@
|
|||||||
<string name="settings_downvote_color">Colore voti negativi</string>
|
<string name="settings_downvote_color">Colore voti negativi</string>
|
||||||
<string name="settings_dynamic_colors">Usa colori dinamici</string>
|
<string name="settings_dynamic_colors">Usa colori dinamici</string>
|
||||||
<string name="settings_enable_crash_report">Abilitare segnalazioni di crash</string>
|
<string name="settings_enable_crash_report">Abilitare segnalazioni di crash</string>
|
||||||
|
<string name="settings_enable_double_tap">Abilita azione doppio tap</string>
|
||||||
<string name="settings_enable_swipe_actions">Consenti azioni allo swipe</string>
|
<string name="settings_enable_swipe_actions">Consenti azioni allo swipe</string>
|
||||||
<string name="settings_full_height_images">Altezza completa immagini</string>
|
<string name="settings_full_height_images">Altezza completa immagini</string>
|
||||||
<string name="settings_include_nsfw">Includi contenuti NSFW</string>
|
<string name="settings_include_nsfw">Includi contenuti NSFW</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Alle</string>
|
<string name="inbox_listing_type_all">Alle</string>
|
||||||
<string name="inbox_listing_type_title">Type inbox</string>
|
<string name="inbox_listing_type_title">Type inbox</string>
|
||||||
<string name="inbox_listing_type_unread">Ongelezen</string>
|
<string name="inbox_listing_type_unread">Ongelezen</string>
|
||||||
|
<string name="inbox_action_mark_read">Markeren als gelezen</string>
|
||||||
|
<string name="inbox_action_mark_unread">Markeren als ongelezen</string>
|
||||||
<string name="inbox_not_logged_message">U bent momenteel niet ingelogd.\nVoeg een account toe
|
<string name="inbox_not_logged_message">U bent momenteel niet ingelogd.\nVoeg een account toe
|
||||||
vanuit het profielscherm om je inbox te zien.
|
vanuit het profielscherm om je inbox te zien.
|
||||||
</string>
|
</string>
|
||||||
@ -200,6 +202,7 @@
|
|||||||
<string name="settings_downvote_color">Kleur voor downvote</string>
|
<string name="settings_downvote_color">Kleur voor downvote</string>
|
||||||
<string name="settings_dynamic_colors">Dynamische kleuren gebruiken</string>
|
<string name="settings_dynamic_colors">Dynamische kleuren gebruiken</string>
|
||||||
<string name="settings_enable_crash_report">Crashrapportage inschakelen</string>
|
<string name="settings_enable_crash_report">Crashrapportage inschakelen</string>
|
||||||
|
<string name="settings_enable_double_tap">Dubbele tik actie inschakelen</string>
|
||||||
<string name="settings_enable_swipe_actions">Veegacties inschakelen</string>
|
<string name="settings_enable_swipe_actions">Veegacties inschakelen</string>
|
||||||
<string name="settings_full_height_images">Afbeeldingen op volledige hoogte</string>
|
<string name="settings_full_height_images">Afbeeldingen op volledige hoogte</string>
|
||||||
<string name="settings_include_nsfw">NSFW-inhoud opnemen</string>
|
<string name="settings_include_nsfw">NSFW-inhoud opnemen</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Wszystkie</string>
|
<string name="inbox_listing_type_all">Wszystkie</string>
|
||||||
<string name="inbox_listing_type_title">Typ skrzynki</string>
|
<string name="inbox_listing_type_title">Typ skrzynki</string>
|
||||||
<string name="inbox_listing_type_unread">Nieprzeczytany</string>
|
<string name="inbox_listing_type_unread">Nieprzeczytany</string>
|
||||||
|
<string name="inbox_action_mark_read">Oznacz jako przeczytane</string>
|
||||||
|
<string name="inbox_action_mark_unread">Oznacz jako nieprzeczytane</string>
|
||||||
<string name="inbox_not_logged_message">Obecnie nie jesteś zalogowany.\nDodaj konto na ekranie
|
<string name="inbox_not_logged_message">Obecnie nie jesteś zalogowany.\nDodaj konto na ekranie
|
||||||
profilu, aby zobaczyć swoją skrzynkę odbiorczą."
|
profilu, aby zobaczyć swoją skrzynkę odbiorczą."
|
||||||
</string>
|
</string>
|
||||||
@ -191,6 +193,7 @@
|
|||||||
<string name="settings_downvote_color">Kolor głosów negatywnych</string>
|
<string name="settings_downvote_color">Kolor głosów negatywnych</string>
|
||||||
<string name="settings_dynamic_colors">Używaj dynamicznych kolorów</string>
|
<string name="settings_dynamic_colors">Używaj dynamicznych kolorów</string>
|
||||||
<string name="settings_enable_crash_report">Włącz raportowanie awarii</string>
|
<string name="settings_enable_crash_report">Włącz raportowanie awarii</string>
|
||||||
|
<string name="settings_enable_double_tap">Włącz akcje podwójnego dotknięcia</string>
|
||||||
<string name="settings_enable_swipe_actions">Włącz akcje przesuwania</string>
|
<string name="settings_enable_swipe_actions">Włącz akcje przesuwania</string>
|
||||||
<string name="settings_full_height_images">Obrazy o pełnej wysokości</string>
|
<string name="settings_full_height_images">Obrazy o pełnej wysokości</string>
|
||||||
<string name="settings_hide_navigation_bar">Ukryj pasek nawigacji podczas przewijania</string>
|
<string name="settings_hide_navigation_bar">Ukryj pasek nawigacji podczas przewijania</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Todas</string>
|
<string name="inbox_listing_type_all">Todas</string>
|
||||||
<string name="inbox_listing_type_title">Tipo de caixa</string>
|
<string name="inbox_listing_type_title">Tipo de caixa</string>
|
||||||
<string name="inbox_listing_type_unread">Não lidas</string>
|
<string name="inbox_listing_type_unread">Não lidas</string>
|
||||||
|
<string name="inbox_action_mark_read">Marcar como lido</string>
|
||||||
|
<string name="inbox_action_mark_unread">Marcar como não lido</string>
|
||||||
<string name="inbox_not_logged_message">Atualmente, não tem sessão iniciada.\nAdicione uma conta
|
<string name="inbox_not_logged_message">Atualmente, não tem sessão iniciada.\nAdicione uma conta
|
||||||
a partir do ecrã de perfil para ver a sua caixa de entrada.
|
a partir do ecrã de perfil para ver a sua caixa de entrada.
|
||||||
</string>
|
</string>
|
||||||
@ -190,6 +192,7 @@
|
|||||||
<string name="settings_downvote_color">Cor votos negativos</string>
|
<string name="settings_downvote_color">Cor votos negativos</string>
|
||||||
<string name="settings_dynamic_colors">Usar cores dinâmicas</string>
|
<string name="settings_dynamic_colors">Usar cores dinâmicas</string>
|
||||||
<string name="settings_enable_crash_report">Ativar relatórios de falhas</string>
|
<string name="settings_enable_crash_report">Ativar relatórios de falhas</string>
|
||||||
|
<string name="settings_enable_double_tap">Ativar a ação de duplo toque</string>
|
||||||
<string name="settings_enable_swipe_actions">Ativar ações de deslizar</string>
|
<string name="settings_enable_swipe_actions">Ativar ações de deslizar</string>
|
||||||
<string name="settings_full_height_images">Imagens de altura natural</string>
|
<string name="settings_full_height_images">Imagens de altura natural</string>
|
||||||
<string name="settings_include_nsfw">Incluir conteúdo NSFW</string>
|
<string name="settings_include_nsfw">Incluir conteúdo NSFW</string>
|
||||||
|
@ -87,6 +87,8 @@
|
|||||||
<string name="inbox_listing_type_all">Toate</string>
|
<string name="inbox_listing_type_all">Toate</string>
|
||||||
<string name="inbox_listing_type_title">Tip de inbox</string>
|
<string name="inbox_listing_type_title">Tip de inbox</string>
|
||||||
<string name="inbox_listing_type_unread">Necitit</string>
|
<string name="inbox_listing_type_unread">Necitit</string>
|
||||||
|
<string name="inbox_action_mark_read">Marchează ca citit</string>
|
||||||
|
<string name="inbox_action_mark_unread">Marchează ca necitit</string>
|
||||||
<string name="inbox_not_logged_message">Momentan nu sunteți autentificat.\nVă rugăm să adăugați
|
<string name="inbox_not_logged_message">Momentan nu sunteți autentificat.\nVă rugăm să adăugați
|
||||||
un cont din ecranul de profil pentru a vedea mesajele.
|
un cont din ecranul de profil pentru a vedea mesajele.
|
||||||
</string>
|
</string>
|
||||||
@ -191,6 +193,7 @@
|
|||||||
<string name="settings_downvote_color">Culoare voturilor negative</string>
|
<string name="settings_downvote_color">Culoare voturilor negative</string>
|
||||||
<string name="settings_dynamic_colors">Folosește culori dinamice</string>
|
<string name="settings_dynamic_colors">Folosește culori dinamice</string>
|
||||||
<string name="settings_enable_crash_report">Activează raporturi erorilor</string>
|
<string name="settings_enable_crash_report">Activează raporturi erorilor</string>
|
||||||
|
<string name="settings_enable_double_tap">Activează acțiunea de dublă atingere</string>
|
||||||
<string name="settings_enable_swipe_actions">Activează acțiunile de glisare</string>
|
<string name="settings_enable_swipe_actions">Activează acțiunile de glisare</string>
|
||||||
<string name="settings_full_height_images">Imagini pe toată înălțimea</string>
|
<string name="settings_full_height_images">Imagini pe toată înălțimea</string>
|
||||||
<string name="settings_include_nsfw">Include conținuturile NSFW</string>
|
<string name="settings_include_nsfw">Include conținuturile NSFW</string>
|
||||||
|
@ -172,7 +172,7 @@ fun App() {
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
if (newScreen != null) {
|
if (newScreen != null) {
|
||||||
navigationCoordinator.getRootNavigator()?.push(newScreen)
|
navigationCoordinator.pushScreen(newScreen)
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
@ -182,7 +182,6 @@ fun App() {
|
|||||||
val drawerGestureEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
val drawerGestureEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
||||||
LaunchedEffect(drawerCoordinator) {
|
LaunchedEffect(drawerCoordinator) {
|
||||||
drawerCoordinator.toggleEvents.onEach { evt ->
|
drawerCoordinator.toggleEvents.onEach { evt ->
|
||||||
val navigator = navigationCoordinator.getRootNavigator()
|
|
||||||
when (evt) {
|
when (evt) {
|
||||||
DrawerEvent.Toggled -> {
|
DrawerEvent.Toggled -> {
|
||||||
drawerState.apply {
|
drawerState.apply {
|
||||||
@ -197,19 +196,19 @@ fun App() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is DrawerEvent.OpenCommunity -> {
|
is DrawerEvent.OpenCommunity -> {
|
||||||
navigator?.push(CommunityDetailScreen(evt.community))
|
navigationCoordinator.pushScreen(CommunityDetailScreen(evt.community))
|
||||||
}
|
}
|
||||||
|
|
||||||
is DrawerEvent.OpenMultiCommunity -> {
|
is DrawerEvent.OpenMultiCommunity -> {
|
||||||
navigator?.push(MultiCommunityScreen(evt.community))
|
navigationCoordinator.pushScreen(MultiCommunityScreen(evt.community))
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerEvent.ManageSubscriptions -> {
|
DrawerEvent.ManageSubscriptions -> {
|
||||||
navigator?.push(ManageSubscriptionsScreen())
|
navigationCoordinator.pushScreen(ManageSubscriptionsScreen())
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerEvent.OpenBookmarks -> {
|
DrawerEvent.OpenBookmarks -> {
|
||||||
navigator?.push(SavedItemsScreen())
|
navigationCoordinator.pushScreen(SavedItemsScreen())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user