Skip to content

Commit

Permalink
Merge pull request #61 from anilibria/feature/TR-265-teams
Browse files Browse the repository at this point in the history
Feature/tr 265 teams
  • Loading branch information
RadiationX authored Oct 21, 2022
2 parents 7565d03 + af17d29 commit 232301d
Show file tree
Hide file tree
Showing 39 changed files with 971 additions and 22 deletions.
2 changes: 1 addition & 1 deletion app-mobile/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ android {
minSdkVersion 19
targetSdkVersion 29
versionCode 60
versionName "2.6.0"
versionName "2.7.0_RC1"
buildConfigField "String", 'BUILD_DATE', '"' + getDateTime() + '"'
vectorDrawables.useSupportLibrary = true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import ru.radiationx.anilibria.ui.fragments.page.PageFragment
import ru.radiationx.anilibria.ui.fragments.release.details.ReleaseFragment
import ru.radiationx.anilibria.ui.fragments.schedule.ScheduleFragment
import ru.radiationx.anilibria.ui.fragments.search.SearchCatalogFragment
import ru.radiationx.anilibria.ui.fragments.teams.TeamsFragment
import ru.radiationx.anilibria.ui.fragments.youtube.YoutubeFragment
import ru.radiationx.data.entity.app.release.ReleaseItem

Expand Down Expand Up @@ -124,4 +125,10 @@ object Screens {
return DonationDetailFragment()
}
}

class Teams(private val query: String? = null) : BaseAppScreen() {
override fun getFragment(): Fragment {
return TeamsFragment.newInstance(query)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class OtherPresenter @Inject constructor(
private val otherAnalytics: OtherAnalytics,
private val settingsAnalytics: SettingsAnalytics,
private val pageAnalytics: PageAnalytics,
private val donationDetailAnalytics: DonationDetailAnalytics
private val donationDetailAnalytics: DonationDetailAnalytics,
private val teamsAnalytics: TeamsAnalytics
) : BasePresenter<OtherView>(router) {

companion object {
Expand Down Expand Up @@ -78,7 +79,7 @@ class OtherPresenter @Inject constructor(
)

allMainMenu.add(OtherMenuItem(MENU_HISTORY, "История", R.drawable.ic_history))
allMainMenu.add(OtherMenuItem(MENU_TEAM, "Список команды", R.drawable.ic_account_multiple))
allMainMenu.add(OtherMenuItem(MENU_TEAM, "Команда проекта", R.drawable.ic_account_multiple))
allMainMenu.add(OtherMenuItem(MENU_DONATE, "Поддержать", R.drawable.ic_gift))

allSystemMenu.add(OtherMenuItem(MENU_SETTINGS, "Настройки", R.drawable.ic_settings))
Expand Down Expand Up @@ -131,8 +132,8 @@ class OtherPresenter @Inject constructor(
}
MENU_TEAM -> {
otherAnalytics.teamClick()
pageAnalytics.open(AnalyticsConstants.screen_other, PageApi.PAGE_PATH_TEAM)
router.navigateTo(Screens.StaticPage(PageApi.PAGE_PATH_TEAM))
teamsAnalytics.open(AnalyticsConstants.screen_other)
router.navigateTo(Screens.Teams())
}
MENU_DONATE -> {
otherAnalytics.donateClick()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ fun FavoriteInfo.toState() = ReleaseFavoriteState(

fun ReleaseFull.toInfoState(): ReleaseInfoState {
val seasonsHtml = "<b>Год:</b> " + seasons.joinToString(", ")
val voicesHtml = "<b>Голоса:</b> " + voices.joinToString(", ")
val voicesHtml = "<b>Голоса:</b> " + voices.joinToString(", ") {
val index = voices.indexOf(it)
"<a href=\"${ReleaseInfoState.TAG_VOICE}_$index\">${it}</a>"
}
val typesHtml = "<b>Тип:</b> " + types.joinToString(", ")
val releaseStatus = status ?: "Не указано"
val releaseStatusHtml = "<b>Состояние релиза:</b> $releaseStatus"
val genresHtml =
"<b>Жанр:</b> " + genres.joinToString(", ") { "<a href=\"$it\">${it.capitalize()}</a>" }
val genresHtml = "<b>Жанр:</b> " + genres.joinToString(", ") {
val index = genres.indexOf(it)
"<a href=\"${ReleaseInfoState.TAG_GENRE}_$index\">${it.capitalize()}</a>"
}
val arrHtml = arrayOf(
seasonsHtml,
voicesHtml,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ data class ReleaseInfoState(
val isOngoing: Boolean,
val announce: String?,
val favorite: ReleaseFavoriteState
)
){
companion object{
const val TAG_GENRE = "genre"
const val TAG_VOICE = "voice"
}
}

data class ReleaseFavoriteState(
val rating: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ru.radiationx.anilibria.presentation.release.details

import android.util.Log
import moxy.InjectViewState
import ru.radiationx.anilibria.model.DonationCardItemState
import ru.radiationx.anilibria.model.loading.StateController
Expand Down Expand Up @@ -44,7 +43,8 @@ class ReleaseInfoPresenter @Inject constructor(
private val webPlayerAnalytics: WebPlayerAnalytics,
private val releaseAnalytics: ReleaseAnalytics,
private val playerAnalytics: PlayerAnalytics,
private val donationDetailAnalytics: DonationDetailAnalytics
private val donationDetailAnalytics: DonationDetailAnalytics,
private val teamsAnalytics: TeamsAnalytics
) : BasePresenter<ReleaseInfoView>(router) {

private val remindText =
Expand Down Expand Up @@ -435,12 +435,22 @@ class ReleaseInfoPresenter @Inject constructor(
router.navigateTo(Screens.Auth())
}

fun openSearch(genre: String) {
currentData?.also {
releaseAnalytics.genreClick(it.id)
fun openSearch(tag: String, index: Int) {
val data = currentData ?: return
when (tag) {
ReleaseInfoState.TAG_GENRE -> {
val genre = data.genres.getOrNull(index) ?: return
releaseAnalytics.genreClick(data.id)
catalogAnalytics.open(AnalyticsConstants.screen_release)
router.navigateTo(Screens.ReleasesSearch(genre))
}
ReleaseInfoState.TAG_VOICE -> {
val voice = data.voices.getOrNull(index) ?: return
releaseAnalytics.voiceClick(data.id)
teamsAnalytics.open(AnalyticsConstants.screen_release)
router.navigateTo(Screens.Teams(voice))
}
}
catalogAnalytics.open(AnalyticsConstants.screen_release)
router.navigateTo(Screens.ReleasesSearch(genre))
}

fun onDownloadLinkSelected(url: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ru.radiationx.anilibria.presentation.teams

import ru.radiationx.data.entity.domain.team.TeamRole

data class TeamsState(
val hasQuery: Boolean = false,
val headerRoles: List<TeamRole>,
val teams: List<TeamState>
)

data class TeamState(
val section: TeamSectionState,
val users: List<TeamUserState>
)

data class TeamSectionState(
val title: String,
val description: String?
)

data class TeamUserState(
val nickname: String,
val color: Int?,
val roles: List<String>,
val tags: List<String>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package ru.radiationx.anilibria.presentation.teams

import com.jakewharton.rxrelay2.BehaviorRelay
import ru.radiationx.anilibria.presentation.common.BasePresenter
import ru.radiationx.anilibria.presentation.common.IErrorHandler
import ru.radiationx.data.analytics.features.TeamsAnalytics
import ru.radiationx.data.entity.common.DataWrapper
import ru.radiationx.data.entity.domain.team.Team
import ru.radiationx.data.entity.domain.team.Teams
import ru.radiationx.data.repository.TeamsRepository
import ru.radiationx.shared_app.common.SystemUtils
import ru.terrakok.cicerone.Router
import toothpick.InjectConstructor

@InjectConstructor
class TeamsPresenter(
router: Router,
private val repository: TeamsRepository,
private val errorHandler: IErrorHandler,
private val systemUtils: SystemUtils,
private val analytics: TeamsAnalytics
) : BasePresenter<TeamsView>(router) {

private val currentDataRelay =
BehaviorRelay.createDefault<DataWrapper<Teams>>(DataWrapper(null))

private val queryRelay = BehaviorRelay.createDefault(Query())

override fun onFirstViewAttach() {
super.onFirstViewAttach()
repository
.requestUpdate()
.subscribe({}, {
it.printStackTrace()
})
.addToDisposable()
repository
.observeTeams()
.doOnSubscribe { viewState.setLoading(true) }
.subscribe({
viewState.setLoading(false)
currentDataRelay.accept(DataWrapper(it))
}, {
viewState.setLoading(false)
errorHandler.handle(it)
})
.addToDisposable()

currentDataRelay
.filter { it.data != null }
.map { it.data!! }
.map { it.toState() }
.flatMap { teamStates ->
queryRelay.map { query ->
teamStates.filterBy(query)
}
}
.subscribe {
viewState.showData(it)
}
.addToDisposable()
}

fun setQueryText(text: String) {
queryRelay.accept(queryRelay.value!!.copy(text = text))
}

fun onHeaderActionClick() {
analytics.joinClick()
systemUtils.externalLink("https://t.me/joinlibria_bot")
}

private fun Teams.toState(): TeamsState = TeamsState(
false,
headerRoles,
teams.toState()
)

private fun List<Team>.toState(): List<TeamState> = map { team ->
val section = TeamSectionState(team.title, team.description)
val users = team.users.map { user ->
val tags = mutableListOf<String>().apply {
if (user.isIntern) {
add("Стажер")
}
if (user.isVacation) {
add("В отпуске")
}
}
TeamUserState(
user.nickname,
user.roles.find { it.color != null }?.color,
user.roles.map { it.title },
tags
)
}
TeamState(section, users)
}

private fun TeamsState.filterBy(query: Query): TeamsState {
val newTeams = teams.map { teamState ->
val newUsers = teamState.users
.filter { user ->
query.text.isEmpty()
|| user.nickname.contains(query.text, true)
|| user.roles.any { it.contains(query.text, true) }
|| user.tags.any { it.contains(query.text, true) }
}
teamState.copy(users = newUsers)
}.filter {
it.users.isNotEmpty()
}
return copy(teams = newTeams, hasQuery = query.text.isNotEmpty())
}

private data class Query(
val text: String = ""
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.radiationx.anilibria.presentation.teams

import moxy.MvpView
import moxy.viewstate.strategy.AddToEndSingleStrategy
import moxy.viewstate.strategy.StateStrategyType


interface TeamsView : MvpView {

@StateStrategyType(AddToEndSingleStrategy::class)
fun showData(data: TeamsState)

@StateStrategyType(AddToEndSingleStrategy::class)
fun setLoading(isLoading: Boolean)

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ class ReleaseHeadDelegate(
) : RecyclerView.ViewHolder(containerView), LayoutContainer {

init {
val tagsRegex = Regex("(\\w+)_(\\d+)")

full_fav_btn.setOnClickListener {
itemListener.onClickFav()
}
full_days_bar.clickListener = {
itemListener.onScheduleClick(it)
}
full_info.movementMethod = LinkMovementMethod {
itemListener.onClickTag(it)
val match = tagsRegex.find(it) ?: return@LinkMovementMethod true
val tag = match.groupValues[1]
val index = match.groupValues[2].toInt()
itemListener.onClickGenre(tag, index)
true
}
full_announce.movementMethod = LinkMovementMethod {
Expand Down Expand Up @@ -115,7 +120,7 @@ class ReleaseHeadDelegate(
interface Listener {
fun onClickSomeLink(url: String)

fun onClickTag(text: String)
fun onClickGenre(tag: String, index: Int)

fun onClickFav()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class PageFragment : BaseFragment(), PageView, ExtendedWebView.JsLifeCycleListen

toolbar.apply {
title = when (presenter.pagePath) {
PageApi.PAGE_PATH_TEAM -> "Список команды"
PageApi.PAGE_PATH_TEAM -> "Команда проекта"
PageApi.PAGE_PATH_DONATE -> "Поддержать"
else -> pageTitle ?: "Статическая страница"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand Down Expand Up @@ -480,8 +479,8 @@ class ReleaseInfoFragment : BaseFragment(), ReleaseInfoView {
presenter.onClickLink(url)
}

override fun onClickTag(text: String) {
presenter.openSearch(text)
override fun onClickGenre(tag: String, index: Int) {
presenter.openSearch(tag, index)
}

override fun onClickFav() {
Expand Down
Loading

0 comments on commit 232301d

Please sign in to comment.