Skip to content

Commit

Permalink
feat: Make putRevealable() and removeRevealable() public (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
svenjacobs authored Jan 4, 2023
1 parent 5872d3b commit fa10788
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 68 deletions.
6 changes: 3 additions & 3 deletions reveal-core/src/main/kotlin/com/svenjacobs/reveal/Reveal.kt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public fun Reveal(
detectTapGestures(
onPress = { offset ->
rev?.key?.let(
if (rev?.revealArea?.contains(offset) == true) {
if (rev?.area?.contains(offset) == true) {
onRevealableClick
} else {
onOverlayClick
Expand All @@ -149,15 +149,15 @@ public fun Reveal(
}
}

private fun InternalRevealable.toActual(
private fun Revealable.toActual(
containerPositionInRoot: Offset,
density: Density,
layoutDirection: LayoutDirection,
): ActualRevealable = ActualRevealable(
key = key,
shape = shape,
padding = padding,
revealArea = getRevealArea(
area = computeArea(
containerPositionInRoot = containerPositionInRoot,
density = density,
layoutDirection = layoutDirection,
Expand Down
15 changes: 11 additions & 4 deletions reveal-core/src/main/kotlin/com/svenjacobs/reveal/RevealScope.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.toSize

/**
* Scope inside [Reveal]'s contents which provides [revealable] modifier.
Expand Down Expand Up @@ -48,10 +50,15 @@ internal class RevealScopeInstance(
Modifier
.onGloballyPositioned { layoutCoordinates ->
revealState.putRevealable(
key = key,
shape = shape,
padding = padding,
layoutCoordinates = layoutCoordinates,
Revealable(
key = key,
shape = shape,
padding = padding,
layout = Revealable.Layout(
offset = layoutCoordinates.positionInRoot(),
size = layoutCoordinates.size.toSize(),
),
),
)
}
.composed {
Expand Down
48 changes: 24 additions & 24 deletions reveal-core/src/main/kotlin/com/svenjacobs/reveal/RevealState.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.svenjacobs.reveal

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue
Expand All @@ -11,24 +10,23 @@ import androidx.compose.runtime.saveable.autoSaver
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.layout.LayoutCoordinates
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock

@Stable
@Suppress("MemberVisibilityCanBePrivate")
public class RevealState internal constructor(
visible: Boolean = false,
private val restoreRevealableKey: Key? = null,
private val restoreCurrentRevealableKey: Key? = null,
) {

private val mutex = Mutex()
private var didRestoreCurrentRevealable = false
private var visible by mutableStateOf(visible)
private val revealables = mutableStateMapOf<Key, InternalRevealable>()
internal var currentRevealable by mutableStateOf<InternalRevealable?>(null)
private val revealables = mutableStateMapOf<Key, Revealable>()
internal var currentRevealable by mutableStateOf<Revealable?>(null)
private set
internal var previousRevealable by mutableStateOf<InternalRevealable?>(null)
internal var previousRevealable by mutableStateOf<Revealable?>(null)
private set

/**
Expand Down Expand Up @@ -95,31 +93,31 @@ public class RevealState internal constructor(
previousRevealable = null
}

internal fun putRevealable(
key: Key,
shape: RevealShape,
padding: PaddingValues,
layoutCoordinates: LayoutCoordinates,
) {
val revealable = InternalRevealableInstance(
key = key,
shape = shape,
padding = padding,
layoutCoordinates = layoutCoordinates,
)

revealables[key] = revealable
/**
* Adds a [Revealable] to this state.
*
* Usually this should not be called manually but revealables registered via the
* [RevealScope.revealable] modifier. Only use this function when for instance you want to
* reveal legacy Android views.
*
* @see RevealScope.revealable
*/
public fun putRevealable(revealable: Revealable) {
revealables[revealable.key] = revealable

if (!didRestoreCurrentRevealable && restoreRevealableKey == key) {
if (!didRestoreCurrentRevealable && restoreCurrentRevealableKey == revealable.key) {
currentRevealable = revealable
didRestoreCurrentRevealable = true
}
}

/**
* Is called from [RevealScope.revealable] when the composable is disposed.
* Removes a [Revealable] from this state.
*
* Usually this must not be called manually. The [RevealScope.revealable] modifier takes care
* of removing revealables when the composable is disposed.
*/
internal fun removeRevealable(key: Key) {
public fun removeRevealable(key: Key) {
revealables.remove(key)

// Hide effect if the current revealable left the composition.
Expand All @@ -145,7 +143,9 @@ public class RevealState internal constructor(
restore = {
RevealState(
visible = it[0] as Boolean,
restoreRevealableKey = it[1]?.let { keySaveable -> keySaver.restore(keySaveable) },
restoreCurrentRevealableKey = it[1]?.let { keySaveable ->
keySaver.restore(keySaveable)
},
)
},
)
Expand Down
63 changes: 31 additions & 32 deletions reveal-core/src/main/kotlin/com/svenjacobs/reveal/Revealable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,31 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Immutable
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.LayoutDirection

public interface Revealable {
public val key: Key
public val shape: RevealShape
public val padding: PaddingValues
}

@Immutable
public class ActualRevealable(
override val key: Key,
override val shape: RevealShape,
override val padding: PaddingValues,
public val revealArea: Rect,
) : Revealable
public data class Revealable(
val key: Key,
val shape: RevealShape,
val padding: PaddingValues,
val layout: Layout,
) {

internal interface InternalRevealable : Revealable {
val layoutCoordinates: LayoutCoordinates
}

@Immutable
internal class InternalRevealableInstance(
override val key: Key,
override val shape: RevealShape,
override val padding: PaddingValues,
override val layoutCoordinates: LayoutCoordinates,
) : InternalRevealable {
/**
* @param offset Offset in pixels of revealable to root composable
* @param size Size in pixels of revealable
*/
@Immutable
public data class Layout(
val offset: Offset,
val size: Size,
)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is InternalRevealableInstance) return false
if (other !is Revealable) return false

if (key != other.key) return false

Expand All @@ -47,23 +38,31 @@ internal class InternalRevealableInstance(
override fun hashCode(): Int = key.hashCode()
}

@Immutable
public data class ActualRevealable(
val key: Key,
val shape: RevealShape,
val padding: PaddingValues,
val area: Rect,
)

/**
* Returns [Rect] in pixels of the reveal area including padding for this [Revealable].
*/
internal fun InternalRevealable.getRevealArea(
internal fun Revealable.computeArea(
containerPositionInRoot: Offset,
density: Density,
layoutDirection: LayoutDirection,
): Rect {
val pos = layoutCoordinates.positionInRoot() - containerPositionInRoot
val pos = layout.offset - containerPositionInRoot
return with(density) {
val rect = Rect(
left = pos.x - padding.calculateLeftPadding(layoutDirection).toPx(),
top = pos.y - padding.calculateTopPadding().toPx(),
right = pos.x + padding.calculateRightPadding(layoutDirection)
.toPx() + layoutCoordinates.size.width.toFloat(),
bottom = pos.y + padding.calculateBottomPadding()
.toPx() + layoutCoordinates.size.height.toFloat(),
right = pos.x + padding.calculateRightPadding(layoutDirection).toPx() +
layout.size.width,
bottom = pos.y + padding.calculateBottomPadding().toPx() +
layout.size.height,
)

if (shape == RevealShape.Circle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ private class DimItemHolder(
.alpha(contentAlpha.value),
content = {
RevealOverlayScopeInstance(
revealableRect = revealable.revealArea.toIntRect(),
revealableRect = revealable.area.toIntRect(),
).content(revealable.key)
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ internal fun ActualRevealable.createShapePath(
): Path = shape
.clip(
size = Size(
width = revealArea.width,
height = revealArea.height,
width = area.width,
height = area.height,
),
density = density,
layoutDirection = layoutDirection,
)
.apply {
translate(
Offset(
x = revealArea.left,
y = revealArea.top,
x = area.left,
y = area.top,
),
)
}

0 comments on commit fa10788

Please sign in to comment.