Collapse long lists of message reactions (#806)
--------- Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
parent
54c7e8bb57
commit
d8fcfc5844
72 changed files with 387 additions and 254 deletions
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.impl.timeline.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CornerSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AddReaction
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun MessagesMoreReactionsButton(modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||
val buttonColor = ElementTheme.colors.bgSubtleSecondary
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.background(Color.Transparent)
|
||||
// Outer border, same colour as background
|
||||
.border(
|
||||
BorderStroke(2.dp, MaterialTheme.colorScheme.background),
|
||||
shape = RoundedCornerShape(corner = CornerSize(14.dp))
|
||||
)
|
||||
.padding(vertical = 2.dp, horizontal = 2.dp)
|
||||
// Clip click indicator inside the outer border
|
||||
.clip(RoundedCornerShape(corner = CornerSize(12.dp)))
|
||||
.clickable(onClick = onClick)
|
||||
.background(buttonColor, RoundedCornerShape(corner = CornerSize(12.dp)))
|
||||
.padding(vertical = 4.dp, horizontal = 10.dp),
|
||||
color = buttonColor
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.AddReaction,
|
||||
contentDescription = "Add emoji",
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
modifier = Modifier
|
||||
// Same size as the line height of reaction emoji text
|
||||
.size(with(LocalDensity.current) { 20.sp.toDp() })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun MessagesMoreReactionsButtonLightPreview() =
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun MessagesMoreReactionsButtonDarkPreview() =
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
MessagesMoreReactionsButton(onClick = {})
|
||||
}
|
||||
|
|
@ -22,40 +22,55 @@ import androidx.compose.foundation.border
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CornerSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AddReaction
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.features.messages.impl.R
|
||||
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
|
||||
import io.element.android.features.messages.impl.timeline.model.AggregatedReactionProvider
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.ElementTextStyles
|
||||
import io.element.android.libraries.designsystem.preview.DayNightPreviews
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import io.element.android.libraries.designsystem.text.toDp
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.theme.ElementTheme
|
||||
|
||||
@Composable
|
||||
fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Modifier, onClick: () -> Unit) {
|
||||
val buttonColor = if (reaction.isHighlighted) {
|
||||
fun MessagesReactionButton(
|
||||
onClick: () -> Unit,
|
||||
content: MessagesReactionsButtonContent,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val buttonColor = if (content.isHighlighted) {
|
||||
ElementTheme.colors.bgSubtlePrimary
|
||||
} else {
|
||||
ElementTheme.colors.bgSubtleSecondary
|
||||
}
|
||||
val borderColor = if (reaction.isHighlighted) {
|
||||
|
||||
val borderColor = if (content.isHighlighted) {
|
||||
ElementTheme.colors.borderInteractivePrimary
|
||||
} else {
|
||||
buttonColor
|
||||
}
|
||||
|
||||
Surface(
|
||||
modifier = modifier
|
||||
.background(Color.Transparent)
|
||||
|
|
@ -74,35 +89,91 @@ fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Mo
|
|||
.padding(vertical = 4.dp, horizontal = 10.dp),
|
||||
color = buttonColor
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
text = reaction.key, fontSize = 15.sp, lineHeight = 20.sp
|
||||
)
|
||||
if (reaction.count > 1) {
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = reaction.count.toString(),
|
||||
color = if (reaction.isHighlighted) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
when (content) {
|
||||
is MessagesReactionsButtonContent.Icon -> IconContent(imageVector = content.imageVector)
|
||||
is MessagesReactionsButtonContent.Text -> TextContent(text = content.text)
|
||||
is MessagesReactionsButtonContent.Reaction -> ReactionContent(reaction = content.reaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun MessagesReactionButtonLightPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) =
|
||||
ElementPreviewLight { ContentToPreview(reaction) }
|
||||
sealed class MessagesReactionsButtonContent {
|
||||
data class Text(val text: String) : MessagesReactionsButtonContent()
|
||||
data class Icon(val imageVector: ImageVector) : MessagesReactionsButtonContent()
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun MessagesReactionButtonDarkPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) =
|
||||
ElementPreviewDark { ContentToPreview(reaction) }
|
||||
data class Reaction(val reaction: AggregatedReaction) : MessagesReactionsButtonContent()
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(reaction: AggregatedReaction) {
|
||||
MessagesReactionButton(reaction, onClick = { })
|
||||
val isHighlighted get() = this is Reaction && reaction.isHighlighted
|
||||
}
|
||||
|
||||
private val reactionEmojiLineHeight = 20.sp
|
||||
|
||||
@Composable
|
||||
private fun TextContent(
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
) = Text(
|
||||
modifier = modifier
|
||||
.height(reactionEmojiLineHeight.toDp()),
|
||||
text = text,
|
||||
style = ElementTextStyles.Regular.bodyMD
|
||||
)
|
||||
|
||||
@Composable
|
||||
private fun IconContent(
|
||||
imageVector: ImageVector,
|
||||
modifier: Modifier = Modifier
|
||||
) = Icon(
|
||||
imageVector = imageVector,
|
||||
contentDescription = stringResource(id = R.string.screen_room_timeline_add_reaction),
|
||||
tint = MaterialTheme.colorScheme.secondary,
|
||||
modifier = modifier
|
||||
.size(reactionEmojiLineHeight.toDp())
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun ReactionContent(
|
||||
reaction: AggregatedReaction,
|
||||
modifier: Modifier = Modifier,
|
||||
) = Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier,
|
||||
) {
|
||||
Text(
|
||||
text = reaction.key,
|
||||
fontSize = 15.sp, lineHeight = reactionEmojiLineHeight
|
||||
)
|
||||
if (reaction.count > 1) {
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
Text(
|
||||
text = reaction.count.toString(),
|
||||
color = if (reaction.isHighlighted) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
internal fun MessagesReactionButtonPreview(@PreviewParameter(AggregatedReactionProvider::class) reaction: AggregatedReaction) = ElementPreview {
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Reaction(reaction),
|
||||
onClick = {}
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
internal fun MessagesReactionExtraButtonsPreview() = ElementPreview {
|
||||
Row {
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
|
||||
onClick = {}
|
||||
)
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Text("12 more"),
|
||||
onClick = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ private fun TimelineItemEventRowContent(
|
|||
|
||||
// Reactions
|
||||
if (event.reactionsState.reactions.isNotEmpty()) {
|
||||
TimelineItemReactionsView(
|
||||
TimelineItemReactions(
|
||||
reactionsState = event.reactionsState,
|
||||
mainAxisAlignment = if (event.isMine) FlowMainAxisAlignment.End else FlowMainAxisAlignment.Start,
|
||||
onReactionClicked = onReactionClicked,
|
||||
|
|
|
|||
|
|
@ -16,59 +16,184 @@
|
|||
|
||||
package io.element.android.features.messages.impl.timeline.components
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.AddReaction
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.res.pluralStringResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.flowlayout.FlowMainAxisAlignment
|
||||
import com.google.accompanist.flowlayout.FlowRow
|
||||
import io.element.android.features.messages.impl.R
|
||||
import io.element.android.features.messages.impl.timeline.aTimelineItemReactions
|
||||
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemReactions
|
||||
import io.element.android.features.messages.impl.timeline.model.aTimelineItemReactions
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.preview.DayNightPreviews
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
/**
|
||||
* The maximum number of items that can be displayed before some items will be hidden
|
||||
*
|
||||
* TODO The threshold should be based on the number of rows, rather than items.
|
||||
* Once items would spill onto a third row, they should be hidden.
|
||||
* Note this could be particularly worthwhile to handle reactions that are
|
||||
* longer than a single character (as annotation keys are free text).
|
||||
*/
|
||||
private const val COLLAPSE_ITEMS_THRESHOLD = 8
|
||||
|
||||
@Composable
|
||||
fun TimelineItemReactionsView(
|
||||
fun TimelineItemReactions(
|
||||
reactionsState: TimelineItemReactions,
|
||||
mainAxisAlignment: FlowMainAxisAlignment,
|
||||
onReactionClicked: (emoji: String) -> Unit,
|
||||
onMoreReactionsClicked: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var expanded: Boolean by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
val reactions by remember(reactionsState, expanded) {
|
||||
derivedStateOf {
|
||||
val numToDisplay = if (expanded) {
|
||||
reactionsState.reactions.count()
|
||||
} else {
|
||||
COLLAPSE_ITEMS_THRESHOLD
|
||||
}
|
||||
reactionsState.reactions.take(numToDisplay).toPersistentList()
|
||||
}
|
||||
}
|
||||
|
||||
val expandableState by remember {
|
||||
derivedStateOf {
|
||||
if (expanded) {
|
||||
ExpandableState.Expanded
|
||||
} else {
|
||||
val hiddenItems = reactionsState.reactions.count() - reactions.count()
|
||||
if (hiddenItems > 0) {
|
||||
ExpandableState.Collapsed(hidden = hiddenItems)
|
||||
} else {
|
||||
ExpandableState.None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TimelineItemReactionsView(
|
||||
modifier = modifier,
|
||||
reactions = reactions,
|
||||
expandableState = expandableState,
|
||||
mainAxisAlignment = mainAxisAlignment,
|
||||
onReactionClick = onReactionClicked,
|
||||
onMoreReactionsClick = onMoreReactionsClicked,
|
||||
onExpandClick = { expanded = true },
|
||||
onCollapseClick = { expanded = false }
|
||||
)
|
||||
}
|
||||
|
||||
private sealed class ExpandableState {
|
||||
object None: ExpandableState()
|
||||
data class Collapsed(val hidden: Int): ExpandableState()
|
||||
object Expanded : ExpandableState()
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TimelineItemReactionsView(
|
||||
reactions: ImmutableList<AggregatedReaction>,
|
||||
expandableState: ExpandableState,
|
||||
mainAxisAlignment: FlowMainAxisAlignment,
|
||||
onReactionClick: (emoji: String) -> Unit,
|
||||
onMoreReactionsClick: () -> Unit,
|
||||
onExpandClick: () -> Unit,
|
||||
onCollapseClick: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) =
|
||||
FlowRow(
|
||||
modifier = modifier,
|
||||
mainAxisSpacing = 4.dp,
|
||||
crossAxisSpacing = 4.dp,
|
||||
mainAxisAlignment = mainAxisAlignment,
|
||||
) {
|
||||
reactionsState.reactions.forEach { reaction ->
|
||||
reactions.forEach { reaction ->
|
||||
MessagesReactionButton(
|
||||
reaction = reaction,
|
||||
onClick = { onReactionClicked(reaction.key) }
|
||||
content = MessagesReactionsButtonContent.Reaction(reaction = reaction),
|
||||
onClick = { onReactionClick(reaction.key) }
|
||||
)
|
||||
}
|
||||
MessagesMoreReactionsButton(
|
||||
onClick = onMoreReactionsClicked
|
||||
when (expandableState) {
|
||||
ExpandableState.Expanded ->
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Text(
|
||||
text = stringResource(id = R.string.screen_room_timeline_less_reactions)
|
||||
),
|
||||
onClick = onCollapseClick,
|
||||
)
|
||||
is ExpandableState.Collapsed -> {
|
||||
val hidden = expandableState.hidden
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Text(
|
||||
text = pluralStringResource(id = R.plurals.screen_room_timeline_more_reactions, hidden, hidden)
|
||||
),
|
||||
onClick = onExpandClick,
|
||||
)
|
||||
}
|
||||
ExpandableState.None -> {
|
||||
// No expand or collapse action available
|
||||
}
|
||||
}
|
||||
MessagesReactionButton(
|
||||
content = MessagesReactionsButtonContent.Icon(Icons.Outlined.AddReaction),
|
||||
onClick = onMoreReactionsClick
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
internal fun TimelineItemReactionsViewLightPreview() =
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun TimelineItemReactionsViewDarkPreview() =
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
TimelineItemReactionsView(
|
||||
reactionsState = aTimelineItemReactions(),
|
||||
mainAxisAlignment = FlowMainAxisAlignment.Center,
|
||||
onReactionClicked = {},
|
||||
onMoreReactionsClicked = {},
|
||||
fun TimelineItemReactionsViewPreview() = ElementPreview {
|
||||
ContentToPreview(
|
||||
reactions = aTimelineItemReactions(count = 1).reactions,
|
||||
expandableState = ExpandableState.None,
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
fun TimelineItemReactionsViewCollapsedPreview() = ElementPreview {
|
||||
ContentToPreview(
|
||||
reactions = aTimelineItemReactions(count = 3).reactions,
|
||||
expandableState = ExpandableState.Collapsed(hidden = 7),
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
fun TimelineItemReactionsViewExpandedPreview() = ElementPreview {
|
||||
ContentToPreview(
|
||||
reactions = aTimelineItemReactions(count = 10).reactions,
|
||||
expandableState = ExpandableState.Expanded,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(
|
||||
reactions: ImmutableList<AggregatedReaction>,
|
||||
expandableState: ExpandableState
|
||||
) {
|
||||
TimelineItemReactionsView(
|
||||
reactions = reactions,
|
||||
expandableState = expandableState,
|
||||
mainAxisAlignment = FlowMainAxisAlignment.Center,
|
||||
onReactionClick = {},
|
||||
onMoreReactionsClick = {},
|
||||
onExpandClick = {},
|
||||
onCollapseClick = {}
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
<item quantity="one">"%1$d room change"</item>
|
||||
<item quantity="other">"%1$d room changes"</item>
|
||||
</plurals>
|
||||
<string name="screen_room_timeline_less_reactions">"Show less"</string>
|
||||
<plurals name="screen_room_timeline_more_reactions">
|
||||
<item quantity="other">"%1$d more"</item>
|
||||
</plurals>
|
||||
<string name="screen_room_timeline_add_reaction">"Add emoji"</string>
|
||||
<string name="screen_room_attachment_source_camera">"Camera"</string>
|
||||
<string name="screen_room_attachment_source_camera_photo">"Take photo"</string>
|
||||
<string name="screen_room_attachment_source_camera_video">"Record a video"</string>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ import androidx.compose.ui.unit.TextUnit
|
|||
@Composable
|
||||
fun Dp.toSp(): TextUnit = with(LocalDensity.current) { toSp() }
|
||||
|
||||
/**
|
||||
* Convert Sp to Dp, regarding current density.
|
||||
* Can be used for instance to use Sp unit for size.
|
||||
*/
|
||||
@Composable
|
||||
fun TextUnit.toDp(): Dp = with(LocalDensity.current) { toDp() }
|
||||
|
||||
/**
|
||||
* Convert Px value to Dp, regarding current density.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c8527bc63aceac59916ca5dfe9c73e9fd1309b957b26945e261849cb1b658253
|
||||
size 6143
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:836fc6c1689c9be78cac4bcd0cfa4cb8fb5f8ed36ace9159889b2404feb8f52e
|
||||
size 6095
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:048cafa3f3d2aa0ec9122c84a6a6fe39d16549021bbbe286c436900c81fb8873
|
||||
size 6519
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5648d6a428f4b7fa20c9981c6e564555bc04ec6b0911028507e01f90a56a44cf
|
||||
size 7414
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d76cd06cf3b36aeb3de567605f6ebc33508cb074049ad854ccec5cf5b382ff36
|
||||
size 7263
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ab3023d14ccd579dc350bc019f94ea2ddc59ac55238d04f4a96c34a1036361df
|
||||
size 8185
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:211784ef45a8d357c2a9e9d8b4a16ea10be71d14613ab1e32119ed8fa584831a
|
||||
size 6365
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8e2085deec0b6096437c82204e8da30e143f3c669c9759dbf34c26d63bbf4442
|
||||
size 7232
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c01fa8074194cf65443f2f321d3ce6b313b7ade8aa7f41155acbfd2a1728e210
|
||||
size 7147
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:47ba3b562872e6078e48bd3168c3da54515ea7196fc5310e520a1876972bad16
|
||||
size 8020
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b024b20585c98eddb6032795e2a434bf675f7254d1f3a649ccccbe4fb2351c8f
|
||||
size 7844
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:cb3b2ccab39aa4cb7afde21d8a9b2c0d18f54d9f397e7020413281b3bfebaa2f
|
||||
size 7634
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6ac13d38a9aaf4341ff8845141dcbc90033f7105750e0ea212bb7b4387dd72ad
|
||||
size 141063
|
||||
oid sha256:b8ca3e1c8ce3c9476cdc7db46aebc8b6970486ff01e05b82c162256373c8957f
|
||||
size 141055
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:651535d566f1bf250b0856d3fd6d3726aa2f6714d44217701e08c805d3771347
|
||||
size 145406
|
||||
oid sha256:2bf89d0228a9771360eaad8a0bc514731153a351551df427cf7f7e44b886edfe
|
||||
size 145398
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7a1c0e5249236abdde5de337f2fe8c8f58bb2ad8bf31fe2f4214dbe35f327915
|
||||
size 129834
|
||||
oid sha256:82b4fb72cd3517b4eedeba3172cc428ba67199df816c686d998027ed021c1bb0
|
||||
size 84164
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1276ef584823b28330ee3facc4cbebdaf9bc6cb02f59af2c023a740677940f02
|
||||
size 133065
|
||||
oid sha256:7c95c7df9616dca071528f4185e63485e7e738e51e595d828f94b08205c6e33d
|
||||
size 87695
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:47760aad8040e34898f8d80d207a6fdb6255255f72bcc2f8cb99801bedebabd4
|
||||
size 119160
|
||||
oid sha256:02f2eb6e37f1022aa13cbcdfc34e7955b99ee4c3d6b35668b548afc94d33ae31
|
||||
size 119137
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5896cb2b9847d2f67bc6d7c39a2499286c59945b9e2c4961e191e547739f41e7
|
||||
size 123936
|
||||
oid sha256:d50e5ac4433e4a44091623f1813373884007506002cc0c657ca7231a6e309462
|
||||
size 123938
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6cc714b45529c63b455cd79fbec2057edf17eddc7352f01ed299115766894a33
|
||||
size 13729
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f1a633da75e5518aacf9b9be08afc27e0627cdebb86544f2de5b698103f1703c
|
||||
size 13533
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:61eda889828d68c309da1ca9879e6b6436fdedb5abea86abfb227caea866efdb
|
||||
size 15396
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a751a46c2aff2337d941442709910d442dd48496f8886e8dc510df17feea062c
|
||||
size 27180
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:71f688355e6a18472424c0958fe1c3baea7e53b4cc4d2d54806434174ff67e71
|
||||
size 27002
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e99b245b027b2610947863591f7593bf273cf328ff64344b575423635e03ac24
|
||||
size 15428
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:82550de45d39c52f34fca45f84b6e9eff53dfef6d2e9622dcaf49c707927d665
|
||||
size 7873
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fc39041ac035aa372640ca7b2e9af254564aa10ce7a7f4c55fbc4bca9f6dc6d9
|
||||
size 7844
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0b5e8b131784aa74261ebeef065f027c8ed4ab6188b390bc9849d3d4bac747e2
|
||||
size 51648
|
||||
oid sha256:6730052131679024056a86514c28639bd975277e46aefefa92b5b31a53a4037d
|
||||
size 51674
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8d26f0735eda30013ad31475347978d778e231e6b2ece7a3528a0b9a2f3743c5
|
||||
size 63185
|
||||
oid sha256:a9843fe657398792239c1058a0814e639072ebd6673bb2ecf8ff3ae309add40c
|
||||
size 63126
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9eba210c27876f999977e75874b4ed2d89f591e16734133ae140f5e82e7fe879
|
||||
size 49724
|
||||
oid sha256:43ee66a5472f660e9d0f1dfa3876406d5e05723b0c86f0adeb0e5f77bf0c1d27
|
||||
size 49740
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e88421b82ca846b94a0eba7a00d424dd077586ebdc28c5364cdb07e4f2d6e2ee
|
||||
size 66031
|
||||
oid sha256:b5dfdfdd9b5ffeee9d9af468c84144c85fcf16f145bfd9700825cf5bcb324cc2
|
||||
size 65969
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3e86e8491e170371cb229f2e58a1fda5efe5ac3dc3b87b4f928bfb74d9fd3ded
|
||||
size 56368
|
||||
oid sha256:cc84c10136a833f1f418de126535cccad09e6ea75f31ca7dd46f85e5eb1b272b
|
||||
size 56377
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:33e25642dd17c10bb39f576f33ebd673619b76c111fd4b5834cd51644cb57b8b
|
||||
size 229779
|
||||
oid sha256:14a299ad0ed6520f347d53206964d91691ce9e281001c93e3b5393d0a169d753
|
||||
size 229787
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7ae3b529f45c9a5c739193eee0dfd9c4ad73310deae8eb50e1b0f57205de84a6
|
||||
size 230761
|
||||
oid sha256:9f2c3a472d0aad53f531852343b572e0ad980fbd658a7b84779bfceb635e8569
|
||||
size 230768
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eece03c2cf471a428d6f383ab3ba2e763a333f10bedf6b4d7a86efd35ffb960d
|
||||
size 70996
|
||||
oid sha256:57cce1248b91028d53219b23d52c751a8ab9e85c475c11e60bb91f02b774c854
|
||||
size 70948
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:df108cf01c6ef1a061d7f84bdb283b9a7cea45ed3a6eea703c110a6981435733
|
||||
size 85260
|
||||
oid sha256:131801a6f63c5f0738ec5303a631161ef651da6a714ce60eec9fc693d1fbccae
|
||||
size 85282
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b0efa0cbf46ffc038bd7ff522b0f81587438f564dd9a7ed7b5b995ea9b3fda31
|
||||
size 174560
|
||||
oid sha256:dc88c24d4f5180ae3cfc1d936d901f3e31feaba8fabfcb8a67477f46ab10912e
|
||||
size 174514
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5ee5b3a256c3ebac9accb7a4361fd1e29c88e21d4c8b10be293bff368d3dd966
|
||||
size 165233
|
||||
oid sha256:7b8110ca00a0889ac02c1ec820f7e1750d57f84ec42b033d662898e5ba06bd79
|
||||
size 165223
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:538df93c96ec8d52f370607cb460c0c507cbf1d716cd8150979bc555e7c4dd92
|
||||
size 53061
|
||||
oid sha256:1075736c7eebc685290898a39d844cbd63984e031360a913904ace7ea8bd9a0e
|
||||
size 53065
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:09f899772bfd8fb4fcff729ba2b4236a842b6aba27a7c7efcbe15f60379ac067
|
||||
size 65090
|
||||
oid sha256:192ba37d34e3634559d25fcaf5c214fd53784bb304a1396a3e7704b498eeae44
|
||||
size 65018
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a9cf9fd968fe92c8e5f4402182689d400a554e423905a8d69a065e8ecf7461ba
|
||||
size 53294
|
||||
oid sha256:30fbb6bca73b70b5466a95c1e99e35a9b722e768e192cc00edf16782881d0d69
|
||||
size 53302
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3565ffe08fd9472a2a3298e0d1c65b2066bbf318f7c3564d3ca8022a22815750
|
||||
size 65710
|
||||
oid sha256:ae3cf36193474a4f2c057df5aa8d6caaca9cecf13abcd92998d8d6b46a054dc3
|
||||
size 65739
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85c2a8b9910c6f751902a40702fe605b5b50ee22b9d61d258500c0c9dfed07dd
|
||||
size 51179
|
||||
oid sha256:ce73d9459b8d41a9a47de3eef6627110990e3d077d81e240e227c7ad70d8f90e
|
||||
size 51200
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e07e00d3940bbc0f0cee49c76f82a1ad638616ecbab98599fb94c871628a8557
|
||||
size 68782
|
||||
oid sha256:2d437b4eb2aec598bdd2ef3c20ce186e18d61697fc6c4c53c8e6ed264dbdd377
|
||||
size 68813
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2858fb6aff4161239713634efe4040878a3e836173386c80675b962c9f87131f
|
||||
size 58413
|
||||
oid sha256:0317b3b8a387f168037a196e685d27fd89515048bf6f1cb28820bd4bcff5fb49
|
||||
size 58425
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9dff8dd2a36d8cb5521e7b7f4e395f87038dbd1c4886e92c94be122d18248f17
|
||||
size 230285
|
||||
oid sha256:65f1933991e74965f8f0848c88e54305d84dea3820ba75722e831ee5b9b44e75
|
||||
size 230252
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:873e746f40b06d4cfe2af496dd4bf2d6ad761412ae3c3e72b6184282b2225346
|
||||
size 231253
|
||||
oid sha256:df7c258ab50b5baeccf22434b343226d057b9127ce7a4a74489883e6aca98e94
|
||||
size 231221
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4d49e59b6ed1ccd2fbd22ed25ffd31619fda33b709a1af8546ceed2328fad6f0
|
||||
size 73767
|
||||
oid sha256:c80f71a5db4355418c4ade1e46536ff44e0f97bb0177a658e5bec0da367c13e6
|
||||
size 73764
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:db4b63cae9b106c125e53296875d3032ea1cd2a455c39c39bb8bd3bd514ab2ac
|
||||
size 89827
|
||||
oid sha256:50ee9e9ca2bf1eb8d0a01210a919eb8370a8125ff6d63c9934861296d781148a
|
||||
size 89841
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a1800f8b515a557d93f25ef1c2dae4f11b29de95f4ee9af649bb40bad1014966
|
||||
size 364477
|
||||
oid sha256:d077c1ca9d9f373b14e1cd657b8d112dd255b9956176cdc252155a53d433fa99
|
||||
size 364460
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:dc59dde6b5b1f0b894de2dc91516e2e9ae35d9b1d0d523b6a488b9366c57289d
|
||||
size 323483
|
||||
oid sha256:eeb039373b3898a42bbfd89c7bcb61b152cb45498f50994297a1f99ac13ae60b
|
||||
size 323473
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:eaa7b8ef747034fd29d383902436d491c4544e5a14f455fa29697120bbbcb204
|
||||
size 54917
|
||||
oid sha256:773ce37927e091ed7eb458e2c1260e08c947bb2d737f5977b3c1443962938a14
|
||||
size 54940
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:88788496a3be3ef0a464377869ef1ca2e7abe4eb8b96c5d69b819afed0470683
|
||||
size 67671
|
||||
oid sha256:af43a77aadb7fdf6e8fa2472836ecae4d1a764b2995a1dabff2f6c2ba9e35ccb
|
||||
size 67704
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:341ead0eb1a09351740738bd540bcf8c6c96862c3370b95b764617335e5b4f22
|
||||
size 52510
|
||||
oid sha256:cd827d099fae0d46cfed9f9beaa8c8ee4231d79b86e3d9e5a0db435a7a89adab
|
||||
size 52537
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:96b7a3cd0f79994d4195e4abe1ee07381f98c6c5c51760226a995efc09617a03
|
||||
size 54039
|
||||
oid sha256:da41884d88decec8e9fa742bd901916a74d6c5b321abc7f8bc6f0d03ec923409
|
||||
size 54062
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e8302d3b48c733500927ba7e5878f001bd7dced72ebd8386142931d557757028
|
||||
size 52706
|
||||
oid sha256:497a831673a4837a548d3cd5a83f8c2d5ff379c93b8080994c5c18470fa730a7
|
||||
size 52731
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2c6dbd33edb880fea91d290a24260c17573d4d36140f12a472c28c77441c8684
|
||||
size 55697
|
||||
oid sha256:beb5bf49b50d78bfa607190fee545d5664be56becf9cbb5ca930b0d3779c4c52
|
||||
size 55667
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:159b54d8c45229e37a3ca9748ab52a6ef448ad93aed209b4e770e94ff5196373
|
||||
size 50706
|
||||
oid sha256:204246b9d5913925f9d3899a74c97d602aeb81b262797f4fbef1a3c20b4cbee1
|
||||
size 50665
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f1ffe365eedfe6b054a268fb3a6a10599df9152d5008359ea95ab7b90b13a33e
|
||||
size 54389
|
||||
oid sha256:d8c430b4caaafe56526e2436238675156948032d0877d72330f2cac03d2d2568
|
||||
size 54405
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2ddcc0519e33b2f6a93d873d2e6aee000ca5a38d2dbd2122869e0befa0c78c7d
|
||||
size 55949
|
||||
oid sha256:cec94dbc2f0515af4bf3c79f9376e37a2f2b6e7b1227af36a20963ac528b766a
|
||||
size 55964
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:96fdf93ee3e67f4f575928a842ce309c4675d361526b9b2714ef2c3fe7167ff4
|
||||
size 54675
|
||||
oid sha256:21093f6d5209487fbc6218ad37a1daf62c946f38cefe8c1e82da8e9223335da7
|
||||
size 54696
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5694004acfac3f1c573dd7929897e01ea9b7e7927cc209e6f4b9bd5568c5ed96
|
||||
size 57714
|
||||
oid sha256:7a4c2a1d91f1ba87019ee9ddc254184e6d241284ff15ebf3cca2ad2eeddc3a78
|
||||
size 57666
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d2ff9337e57cecce1404c44b7b9eb7d6fce65a22fb94326429bd25041e59a588
|
||||
size 52250
|
||||
oid sha256:2f117563be9539efa9cc3790a3ca0ff8ff7718184a9a00eb2c540cfcb36f5d58
|
||||
size 52251
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue