Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement share monsters on folders and search #323

Merged
merged 2 commits into from
Aug 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ internal class MonsterFolderDaoImpl(
queries.getMonstersFromFolder(folderName).executeAsList().groupByMonsterFolder()
}

override suspend fun getMonstersFromFolders(
foldersName: List<String>
): List<MonsterEntity> {
return withContext(dispatcher) {
queries.getMonstersFromFolders(foldersName).executeAsList().map {
it.toMonsterEntity()
}
}
}

override suspend fun removeMonsterFromFolder(
folderName: String,
monsterIndexes: List<String>
Expand All @@ -76,28 +86,32 @@ internal class MonsterFolderDaoImpl(
folderName = it.folderName,
monsterIndex = it.monsterIndex,
createdAt = it.createdAt
) to MonsterEntity(
index = it.index,
type = it.type,
subtype = it.subtype,
group = it.subtitle,
challengeRating = it.challengeRating.toFloat(),
name = it.name,
subtitle = it.subtitle,
imageUrl = it.imageUrl,
backgroundColorLight = it.backgroundColorLight,
backgroundColorDark = it.backgroundColorDark,
isHorizontalImage = it.isHorizontalImage == 1L,
size = it.size,
alignment = it.alignment,
armorClass = it.armorClass.toInt(),
hitPoints = it.hitPoints.toInt(),
hitDice = it.hitDice,
senses = it.senses,
languages = it.languages,
sourceName = it.sourceName,
status = MonsterEntityStatus.entries[it.isClone.toInt()],
)
) to it.toMonsterEntity()
}.groupBy(keySelector = { it.first }, valueTransform = { it.second })
}

private fun MonsterFolderCompleteEntityView.toMonsterEntity(): MonsterEntity {
return MonsterEntity(
index = index,
type = type,
subtype = subtype,
group = subtitle,
challengeRating = challengeRating.toFloat(),
name = name,
subtitle = subtitle,
imageUrl = imageUrl,
backgroundColorLight = backgroundColorLight,
backgroundColorDark = backgroundColorDark,
isHorizontalImage = isHorizontalImage == 1L,
size = size,
alignment = alignment,
armorClass = armorClass.toInt(),
hitPoints = hitPoints.toInt(),
hitDice = hitDice,
senses = senses,
languages = languages,
sourceName = sourceName,
status = MonsterEntityStatus.entries[isClone.toInt()],
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ WHERE folderName == ?
ORDER BY createdAt DESC
;

getMonstersFromFolders:
SELECT * FROM MonsterFolderCompleteEntityView
WHERE folderName IN ?
ORDER BY createdAt DESC
;

removeMonsterFromFolder:
DELETE FROM MonsterFolderEntity
WHERE folderName == ? AND monsterIndex IN ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ class AddMonsterToTemporaryFolderUseCase(
private val addMonstersToFolder: AddMonstersToFolderUseCase,
) {

operator fun invoke(index: String): Flow<Unit> {
operator fun invoke(indexes: List<String>): Flow<Unit> {
return addMonstersToFolder(
folderName = TEMPORARY_FOLDER_NAME,
indexes = listOf(index)
indexes = indexes
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2022 Alexandre Gomes Pereira
*
* 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 br.alexandregpereira.hunter.domain.folder

import br.alexandregpereira.hunter.domain.folder.model.MonsterPreviewFolder
import kotlinx.coroutines.flow.Flow

class GetMonstersByFolders(
private val monsterFolderRepository: MonsterFolderRepository
) {

operator fun invoke(foldersName: List<String>): Flow<List<MonsterPreviewFolder>> {
return monsterFolderRepository.getMonstersFromFolders(
foldersName = foldersName
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package br.alexandregpereira.hunter.domain.folder

import br.alexandregpereira.hunter.domain.folder.model.MonsterFolder
import br.alexandregpereira.hunter.domain.folder.model.MonsterPreviewFolder
import kotlinx.coroutines.flow.Flow

interface MonsterFolderRepository {
Expand All @@ -25,5 +26,6 @@ interface MonsterFolderRepository {
fun removeMonsters(folderName: String, indexes: List<String>): Flow<Unit>
fun getMonsterFolders(): Flow<List<MonsterFolder>>
fun getMonstersFromFolder(folderName: String): Flow<MonsterFolder?>
fun getMonstersFromFolders(foldersName: List<String>): Flow<List<MonsterPreviewFolder>>
fun removeMonsterFolders(folderNames: List<String>): Flow<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import br.alexandregpereira.hunter.domain.folder.ClearTemporaryFolderUseCase
import br.alexandregpereira.hunter.domain.folder.GetFolderMonsterPreviewsByIdsUseCase
import br.alexandregpereira.hunter.domain.folder.GetMonsterFoldersUseCase
import br.alexandregpereira.hunter.domain.folder.GetMonstersByFolderUseCase
import br.alexandregpereira.hunter.domain.folder.GetMonstersByFolders
import br.alexandregpereira.hunter.domain.folder.GetMonstersByTemporaryFolderUseCase
import br.alexandregpereira.hunter.domain.folder.RemoveMonsterFoldersUseCase
import br.alexandregpereira.hunter.domain.folder.RemoveMonstersFromTemporaryFolderUseCase
Expand All @@ -37,4 +38,5 @@ val monsterFolderDomainModule = module {
factory { GetMonstersByTemporaryFolderUseCase(get()) }
factory { RemoveMonsterFoldersUseCase(get()) }
factory { RemoveMonstersFromTemporaryFolderUseCase(get()) }
factory { GetMonstersByFolders(get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ internal class DefaultFolderRepository(
return monsterFolderLocalDataSource.getMonstersFromFolder(folderName).map { it?.asDomain() }
}

override fun getMonstersFromFolders(foldersName: List<String>): Flow<List<MonsterPreviewFolder>> {
return monsterFolderLocalDataSource.getMonstersFromFolders(foldersName)
.map { it.asDomainMonsterPreviewFolderEntity() }
}

override fun removeMonsters(folderName: String, indexes: List<String>): Flow<Unit> {
return monsterFolderLocalDataSource.removeMonsters(folderName, monsterIndexes = indexes)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,8 @@ internal class DefaultMonsterFolderLocalDataSource(
override fun removeMonsterFolders(folderNames: List<String>): Flow<Unit> = flow {
emit(monsterFolderDao.removeMonsterFolders(folderNames))
}

override fun getMonstersFromFolders(foldersName: List<String>): Flow<List<MonsterEntity>> = flow {
emit(monsterFolderDao.getMonstersFromFolders(foldersName))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ internal interface MonsterFolderLocalDataSource {
fun getMonstersFromFolder(folderName: String): Flow<MonsterFolderCompleteEntity?>
fun getFolderMonsterPreviewsByIds(monsterIndexes: List<String>): Flow<List<MonsterEntity>>
fun removeMonsterFolders(folderNames: List<String>): Flow<Unit>
fun getMonstersFromFolders(foldersName: List<String>): Flow<List<MonsterEntity>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ interface MonsterFolderDao {
suspend fun removeMonsterFromFolder(folderName: String, monsterIndexes: List<String>)

suspend fun removeMonsterFolders(folderNames: List<String>)

suspend fun getMonstersFromFolders(foldersName: List<String>): List<MonsterEntity>
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fun FolderInsertFeature(
onFolderSelected = stateHolder::onFolderNameFieldChange,
onLongClick = stateHolder::onRemoveMonster,
onSave = stateHolder::onSave,
onClose = stateHolder::onClose
onClose = stateHolder::onClose,
onShare = stateHolder::onShare,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,38 +38,49 @@ internal fun FolderInsertScreen(
onLongClick: (String) -> Unit = {},
onSave: () -> Unit = {},
onClose: () -> Unit = {},
onShare: () -> Unit = {},
) = BottomSheet(
opened = state.isOpen,
contentPadding = contentPadding,
topSpaceHeight = 0.dp,
onClose = onClose
) {
BottomSheet(opened = state.isOpen, contentPadding = contentPadding, onClose = onClose) {
ScreenHeader(
title = state.strings.addToFolder,
modifier = Modifier.padding(16.dp)
)
ScreenHeader(
title = state.strings.addToFolder,
modifier = Modifier.padding(16.dp)
)

MonsterPreviewRow(
monsters = state.monsterPreviews,
onLongClick = onLongClick,
modifier = Modifier.padding(top = 8.dp)
)
MonsterPreviewRow(
monsters = state.monsterPreviews,
onLongClick = onLongClick,
modifier = Modifier.padding(top = 8.dp)
)

AppTextField(
text = state.folderName,
label = state.strings.folderNameLabel,
modifier = Modifier.padding(vertical = 16.dp, horizontal = 16.dp),
onValueChange = onFolderNameFieldChange
)
AppTextField(
text = state.folderName,
label = state.strings.folderNameLabel,
modifier = Modifier.padding(vertical = 16.dp, horizontal = 16.dp),
onValueChange = onFolderNameFieldChange
)

MonsterFolderGrid(
folders = state.folders,
onFolderSelected = onFolderSelected,
modifier = Modifier.padding(bottom = 16.dp)
)
MonsterFolderGrid(
folders = state.folders,
onFolderSelected = onFolderSelected,
modifier = Modifier.padding(bottom = 16.dp)
)

AppButton(
text = state.strings.save,
modifier = Modifier.padding(16.dp),
onClick = onSave
)
}
AppButton(
text = state.strings.share,
modifier = Modifier.padding(top = 16.dp, bottom = 8.dp).padding(horizontal = 16.dp),
isPrimary = false,
onClick = onShare
)

AppButton(
text = state.strings.save,
modifier = Modifier.padding(bottom = 16.dp, top = 8.dp).padding(horizontal = 16.dp),
onClick = onSave
)
}

@Preview
Expand Down
1 change: 1 addition & 0 deletions feature/folder-insert/state-holder/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ multiplatform {
api(project(":core:state-holder"))
api(project(":domain:monster-folder:core"))
implementation(project(":feature:folder-insert:event"))
implementation(project(":feature:share-content:event"))
implementation(libs.kotlin.coroutines.core)
implementation(libs.koin.core)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,10 @@ internal class FolderInsertAnalytics(
)
)
}

fun trackShared() {
analytics.track(
eventName = "Folder Insert - shared",
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package br.alexandregpereira.hunter.folder.insert

import br.alexadregpereira.hunter.shareContent.event.ShareContentEvent
import br.alexadregpereira.hunter.shareContent.event.ShareContentEventDispatcher
import br.alexandregpereira.hunter.domain.folder.AddMonstersToFolderUseCase
import br.alexandregpereira.hunter.domain.folder.GetFolderMonsterPreviewsByIdsUseCase
import br.alexandregpereira.hunter.domain.folder.GetMonsterFoldersUseCase
Expand All @@ -40,6 +42,7 @@ class FolderInsertStateHolder internal constructor(
private val dispatcher: CoroutineDispatcher,
private val analytics: FolderInsertAnalytics,
private val appLocalization: AppLocalization,
private val shareContentEventDispatcher: ShareContentEventDispatcher,
) : UiModel<FolderInsertState>(FolderInsertState()) {

private val strings: FolderInsertStrings
Expand Down Expand Up @@ -93,6 +96,14 @@ class FolderInsertStateHolder internal constructor(
setState { copy(isOpen = false) }
}

fun onShare() {
analytics.trackShared()
onClose()
shareContentEventDispatcher.dispatchEvent(
ShareContentEvent.Export.OnStart(state.value.monsterIndexes)
)
}

private fun load(monsterIndexes: List<String>, folderName: String = "") {
setState {
copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,28 @@ interface FolderInsertStrings {
val addToFolder: String
val folderNameLabel: String
val save: String
val share: String
}

internal data class FolderInsertEnStrings(
override val addToFolder: String = "Add to folder",
override val folderNameLabel: String = "Folder name",
override val save: String = "Save",
override val share: String = "Share",
) : FolderInsertStrings

internal data class FolderInsertPtStrings(
override val addToFolder: String = "Adicionar à pasta",
override val folderNameLabel: String = "Nome da pasta",
override val save: String = "Salvar",
override val share: String = "Compartilhar",
) : FolderInsertStrings

internal data class FolderInsertEmptyStrings(
override val addToFolder: String = "",
override val folderNameLabel: String = "",
override val save: String = "",
override val share: String = "",
) : FolderInsertStrings

internal fun getFolderInsertStrings(lang: Language): FolderInsertStrings {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ val folderInsertModule = module {
dispatcher = get(),
analytics = FolderInsertAnalytics(get()),
appLocalization = get(),
shareContentEventDispatcher = get(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ fun FolderListFeature(
onCLick = viewModel::onItemClick,
onLongCLick = viewModel::onItemSelect,
onItemSelectionClose = viewModel::onItemSelectionClose,
onItemSelectionDeleteClick = viewModel::onItemSelectionDeleteClick
onItemSelectionDeleteClick = viewModel::onItemSelectionDeleteClick,
onItemSelectionAddToPreviewClick = viewModel::onItemSelectionAddToPreviewClick,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ internal fun FolderListScreen(
onCLick: (String) -> Unit = {},
onLongCLick: (String) -> Unit = {},
onItemSelectionClose: () -> Unit = {},
onItemSelectionDeleteClick: () -> Unit = {}
onItemSelectionDeleteClick: () -> Unit = {},
onItemSelectionAddToPreviewClick: () -> Unit = {},
) {
Box(Modifier.fillMaxSize()) {
FolderCardGrid(
Expand All @@ -44,9 +45,11 @@ internal fun FolderListScreen(
ItemSelection(
itemSelectionText = state.strings.itemSelected(state.itemSelectionCount),
deleteText = state.strings.delete,
addToPreviewText = state.strings.addToPreview,
contentBottomPadding = contentPadding.calculateBottomPadding(),
onClose = onItemSelectionClose,
onDeleteClick = onItemSelectionDeleteClick,
onAddToPreviewClick = onItemSelectionAddToPreviewClick,
isOpen = state.isItemSelectionOpen,
)
}
Expand Down
Loading
Loading