mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 11:46:32 +00:00
linting fixes
This commit is contained in:
parent
deeed81e79
commit
ce28bf83f3
612 changed files with 40442 additions and 33570 deletions
|
|
@ -1,2 +1,14 @@
|
||||||
[*.{kt,kts}]
|
[*.{kt,kts}]
|
||||||
max_line_length=off
|
max_line_length=off
|
||||||
|
ktlint_function_naming_ignore_when_annotated_with=Composable
|
||||||
|
|
||||||
|
[*.gradle.kts]
|
||||||
|
property_naming=off
|
||||||
|
|
||||||
|
|
||||||
|
[shared/src/commonMain/kotlin/com/habitrpg/shared/habitica/models/responses/TaskDirectionData.kt]
|
||||||
|
ktlint_standard_backing-property-naming=disabled
|
||||||
|
|
||||||
|
[**/generated/**/*.kt]
|
||||||
|
ktlint_standard_property-naming=disabled
|
||||||
|
ktlint_standard_backing-property-naming=disabled
|
||||||
|
|
|
||||||
7
.github/workflows/android.yml
vendored
7
.github/workflows/android.yml
vendored
|
|
@ -25,6 +25,11 @@ jobs:
|
||||||
|
|
||||||
unit-test:
|
unit-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
module:
|
||||||
|
- "common"
|
||||||
|
- "Habitica"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: set up JDK 17
|
- name: set up JDK 17
|
||||||
|
|
@ -38,7 +43,7 @@ jobs:
|
||||||
- name: Run with Gradle
|
- name: Run with Gradle
|
||||||
uses: gradle/gradle-build-action@v2
|
uses: gradle/gradle-build-action@v2
|
||||||
with:
|
with:
|
||||||
arguments: testProdDebugUnitTest
|
arguments: ${{ matrix.module }}:testProdDebugUnitTest
|
||||||
|
|
||||||
# ui-test:
|
# ui-test:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources>
|
||||||
|
|
||||||
<!-- Application theme. -->
|
<!-- Application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.Material3.DayNight">
|
<style name="AppTheme" parent="Theme.Material3.DayNight">
|
||||||
<item name="android:listSeparatorTextViewStyle">@style/MyOwnListSeperatorTextViewStyle</item>
|
<item name="android:listSeparatorTextViewStyle">@style/MyOwnListSeperatorTextViewStyle
|
||||||
|
</item>
|
||||||
|
|
||||||
<item name="android:elevation">0dp</item>
|
<item name="android:elevation">0dp</item>
|
||||||
<item name="elevation">0dp</item>
|
<item name="elevation">0dp</item>
|
||||||
|
|
@ -69,8 +70,7 @@
|
||||||
<item name="headerTextColor">@color/text_title</item>
|
<item name="headerTextColor">@color/text_title</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="MainAppTheme" parent="AppTheme">
|
<style name="MainAppTheme" parent="AppTheme"></style>
|
||||||
</style>
|
|
||||||
|
|
||||||
<style name="MainAppTheme.Dark">
|
<style name="MainAppTheme.Dark">
|
||||||
<item name="colorPrimary">@color/brand_400</item>
|
<item name="colorPrimary">@color/brand_400</item>
|
||||||
|
|
@ -581,6 +581,7 @@
|
||||||
<style name="Pill.Content" parent="Pill">
|
<style name="Pill.Content" parent="Pill">
|
||||||
<item name="android:background">@drawable/pill_bg_content</item>
|
<item name="android:background">@drawable/pill_bg_content</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Pill.Purple">
|
<style name="Pill.Purple">
|
||||||
<item name="android:textColor">@color/white</item>
|
<item name="android:textColor">@color/white</item>
|
||||||
<item name="android:background">@drawable/pill_bg_purple_300</item>
|
<item name="android:background">@drawable/pill_bg_purple_300</item>
|
||||||
|
|
@ -881,12 +882,15 @@
|
||||||
<style name="RedTextLabel" parent="TextAppearance.AppCompat">
|
<style name="RedTextLabel" parent="TextAppearance.AppCompat">
|
||||||
<item name="android:textColor">@color/red_10</item>
|
<item name="android:textColor">@color/red_10</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="YellowTextLabel" parent="TextAppearance.AppCompat">
|
<style name="YellowTextLabel" parent="TextAppearance.AppCompat">
|
||||||
<item name="android:textColor">@color/yellow_5</item>
|
<item name="android:textColor">@color/yellow_5</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="BlueTextLabel" parent="TextAppearance.AppCompat">
|
<style name="BlueTextLabel" parent="TextAppearance.AppCompat">
|
||||||
<item name="android:textColor">@color/blue_10</item>
|
<item name="android:textColor">@color/blue_10</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="PurpleTextLabel" parent="TextAppearance.AppCompat">
|
<style name="PurpleTextLabel" parent="TextAppearance.AppCompat">
|
||||||
<item name="android:textColor">@color/brand_300</item>
|
<item name="android:textColor">@color/brand_300</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -919,7 +923,6 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style name="TaskFormTextInputLayoutAppearance" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
|
<style name="TaskFormTextInputLayoutAppearance" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
|
||||||
<!-- reference our hint & error styles -->
|
<!-- reference our hint & error styles -->
|
||||||
<item name="boxBackgroundColor">?colorTintedBackground</item>
|
<item name="boxBackgroundColor">?colorTintedBackground</item>
|
||||||
|
|
@ -1021,6 +1024,7 @@
|
||||||
<item name="android:textSize">12sp</item>
|
<item name="android:textSize">12sp</item>
|
||||||
<item name="android:textStyle">bold</item>
|
<item name="android:textStyle">bold</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ActiveLabel">
|
<style name="ActiveLabel">
|
||||||
<item name="android:background">@drawable/pill_bg_teal_100</item>
|
<item name="android:background">@drawable/pill_bg_teal_100</item>
|
||||||
<item name="android:paddingStart">4dp</item>
|
<item name="android:paddingStart">4dp</item>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
||||||
import com.habitrpg.android.habitica.data.TutorialRepository
|
import com.habitrpg.android.habitica.data.TutorialRepository
|
||||||
import com.habitrpg.android.habitica.data.UserRepository
|
import com.habitrpg.android.habitica.data.UserRepository
|
||||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||||
import com.habitrpg.common.habitica.helpers.MainNavigationController
|
|
||||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||||
import com.habitrpg.android.habitica.interactors.FeedPetUseCase
|
import com.habitrpg.android.habitica.interactors.FeedPetUseCase
|
||||||
|
|
@ -28,6 +27,7 @@ import com.habitrpg.android.habitica.models.user.User
|
||||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||||
import com.habitrpg.common.habitica.api.HostConfig
|
import com.habitrpg.common.habitica.api.HostConfig
|
||||||
import com.habitrpg.common.habitica.helpers.ExceptionHandler
|
import com.habitrpg.common.habitica.helpers.ExceptionHandler
|
||||||
|
import com.habitrpg.common.habitica.helpers.MainNavigationController
|
||||||
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
|
import com.kaspersky.kaspresso.testcases.api.testcase.TestCase
|
||||||
import io.mockk.clearAllMocks
|
import io.mockk.clearAllMocks
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
|
|
@ -104,7 +104,10 @@ open class HabiticaTestCase : TestCase() {
|
||||||
every { inventoryRepository.getItems(QuestContent::class.java, any()) } returns flowOf(content.quests)
|
every { inventoryRepository.getItems(QuestContent::class.java, any()) } returns flowOf(content.quests)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun <T> loadJsonFile(s: String, type: Type): T {
|
internal fun <T> loadJsonFile(
|
||||||
|
s: String,
|
||||||
|
type: Type,
|
||||||
|
): T {
|
||||||
val userStream = javaClass.classLoader?.getResourceAsStream("$s.json")
|
val userStream = javaClass.classLoader?.getResourceAsStream("$s.json")
|
||||||
return gson.fromJson(gson.newJsonReader(InputStreamReader(userStream)), type)
|
return gson.fromJson(gson.newJsonReader(InputStreamReader(userStream)), type)
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +135,11 @@ open class HabiticaTestCase : TestCase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private fun <P, C> assign(it: KCallable<*>, obj: C, value: P) {
|
private fun <P, C> assign(
|
||||||
|
it: KCallable<*>,
|
||||||
|
obj: C,
|
||||||
|
value: P,
|
||||||
|
) {
|
||||||
if ((it as KMutableProperty1<C, P>).javaField!!.get(obj) == null) {
|
if ((it as KMutableProperty1<C, P>).javaField!!.get(obj) == null) {
|
||||||
it.set(obj, value)
|
it.set(obj, value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ class IntroActivityScreen : Screen<IntroActivityScreen>() {
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class IntroActivityTest : ActivityTestCase() {
|
class IntroActivityTest : ActivityTestCase() {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@JvmField
|
@JvmField
|
||||||
var mActivityTestRule = ActivityScenarioRule(IntroActivity::class.java)
|
var mActivityTestRule = ActivityScenarioRule(IntroActivity::class.java)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ class MainActivityScreen : Screen<MainActivityScreen>() {
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class MainActivityTest : ActivityTestCase() {
|
class MainActivityTest : ActivityTestCase() {
|
||||||
|
|
||||||
val screen = MainActivityScreen()
|
val screen = MainActivityScreen()
|
||||||
|
|
||||||
lateinit var scenario: ActivityScenario<MainActivity>
|
lateinit var scenario: ActivityScenario<MainActivity>
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ class TaskFormScreen : Screen<TaskFormScreen>() {
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class TaskFormActivityTest : ActivityTestCase() {
|
class TaskFormActivityTest : ActivityTestCase() {
|
||||||
|
|
||||||
val screen = TaskFormScreen()
|
val screen = TaskFormScreen()
|
||||||
|
|
||||||
lateinit var scenario: ActivityScenario<TaskFormActivity>
|
lateinit var scenario: ActivityScenario<TaskFormActivity>
|
||||||
|
|
@ -297,7 +296,7 @@ class TaskFormActivityTest : ActivityTestCase() {
|
||||||
}
|
}
|
||||||
KSpinner(
|
KSpinner(
|
||||||
builder = { withId(R.id.repeats_every_spinner) },
|
builder = { withId(R.id.repeats_every_spinner) },
|
||||||
itemTypeBuilder = { itemType(::KSpinnerItem) }
|
itemTypeBuilder = { itemType(::KSpinnerItem) },
|
||||||
) perform {
|
) perform {
|
||||||
open()
|
open()
|
||||||
childAt<KSpinnerItem>(1) {
|
childAt<KSpinnerItem>(1) {
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,15 @@ import io.github.kakaocup.kakao.screen.Screen
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
|
||||||
abstract class FragmentTestCase<F : Fragment, VB : ViewBinding, S : Screen<S>>(
|
abstract class FragmentTestCase<F : Fragment, VB : ViewBinding, S : Screen<S>>(
|
||||||
val shouldLaunchFragment: Boolean = true
|
val shouldLaunchFragment: Boolean = true,
|
||||||
) : HabiticaTestCase() {
|
) : HabiticaTestCase() {
|
||||||
lateinit var scenario: FragmentScenario<F>
|
lateinit var scenario: FragmentScenario<F>
|
||||||
lateinit var fragment: F
|
lateinit var fragment: F
|
||||||
|
|
||||||
abstract fun makeFragment()
|
abstract fun makeFragment()
|
||||||
|
|
||||||
abstract fun launchFragment(args: Bundle? = null)
|
abstract fun launchFragment(args: Bundle? = null)
|
||||||
|
|
||||||
abstract val screen: S
|
abstract val screen: S
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ class MainItem(parent: Matcher<View>) : KRecyclerItem<MainItem>(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NavigationDrawerScreen : Screen<NavigationDrawerScreen>() {
|
class NavigationDrawerScreen : Screen<NavigationDrawerScreen>() {
|
||||||
val recycler: KRecyclerView = KRecyclerView({
|
val recycler: KRecyclerView =
|
||||||
|
KRecyclerView({
|
||||||
withId(R.id.recyclerView)
|
withId(R.id.recyclerView)
|
||||||
}, itemTypeBuilder = {
|
}, itemTypeBuilder = {
|
||||||
itemType(::SectionHeaderItem)
|
itemType(::SectionHeaderItem)
|
||||||
|
|
@ -38,7 +39,8 @@ internal class NavigationDrawerFragmentTest : FragmentTestCase<NavigationDrawerF
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,8 @@ class PartyDetailFragmentTest : FragmentTestCase<PartyDetailFragment, FragmentPa
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,22 +21,26 @@ import org.junit.runner.RunWith
|
||||||
|
|
||||||
class StatsScreen : Screen<StatsScreen>() {
|
class StatsScreen : Screen<StatsScreen>() {
|
||||||
val strengthStatsView = KView { withId(R.id.strengthStatsView) }
|
val strengthStatsView = KView { withId(R.id.strengthStatsView) }
|
||||||
val strengthAllocateButton = KButton {
|
val strengthAllocateButton =
|
||||||
|
KButton {
|
||||||
withId(R.id.allocateButton)
|
withId(R.id.allocateButton)
|
||||||
isDescendantOfA { withId(R.id.strengthStatsView) }
|
isDescendantOfA { withId(R.id.strengthStatsView) }
|
||||||
}
|
}
|
||||||
val intelligenceStatsView = KView { withId(R.id.intelligenceStatsView) }
|
val intelligenceStatsView = KView { withId(R.id.intelligenceStatsView) }
|
||||||
val intelligenceAllocateButton = KButton {
|
val intelligenceAllocateButton =
|
||||||
|
KButton {
|
||||||
withId(R.id.allocateButton)
|
withId(R.id.allocateButton)
|
||||||
isDescendantOfA { withId(R.id.intelligenceStatsView) }
|
isDescendantOfA { withId(R.id.intelligenceStatsView) }
|
||||||
}
|
}
|
||||||
val constitutionStatsView = KView { withId(R.id.constitutionStatsView) }
|
val constitutionStatsView = KView { withId(R.id.constitutionStatsView) }
|
||||||
val constitutionAllocateButton = KButton {
|
val constitutionAllocateButton =
|
||||||
|
KButton {
|
||||||
withId(R.id.allocateButton)
|
withId(R.id.allocateButton)
|
||||||
isDescendantOfA { withId(R.id.constitutionStatsView) }
|
isDescendantOfA { withId(R.id.constitutionStatsView) }
|
||||||
}
|
}
|
||||||
val perceptionStatsView = KView { withId(R.id.perceptionStatsView) }
|
val perceptionStatsView = KView { withId(R.id.perceptionStatsView) }
|
||||||
val perceptionAllocateButton = KButton {
|
val perceptionAllocateButton =
|
||||||
|
KButton {
|
||||||
withId(R.id.allocateButton)
|
withId(R.id.allocateButton)
|
||||||
isDescendantOfA { withId(R.id.perceptionStatsView) }
|
isDescendantOfA { withId(R.id.perceptionStatsView) }
|
||||||
}
|
}
|
||||||
|
|
@ -46,7 +50,6 @@ class StatsScreen : Screen<StatsScreen>() {
|
||||||
@LargeTest
|
@LargeTest
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
class StatsFragmentTest : FragmentTestCase<StatsFragment, FragmentStatsBinding, StatsScreen>() {
|
class StatsFragmentTest : FragmentTestCase<StatsFragment, FragmentStatsBinding, StatsScreen>() {
|
||||||
|
|
||||||
override val screen = StatsScreen()
|
override val screen = StatsScreen()
|
||||||
|
|
||||||
override fun makeFragment() {
|
override fun makeFragment() {
|
||||||
|
|
@ -55,7 +58,8 @@ class StatsFragmentTest : FragmentTestCase<StatsFragment, FragmentStatsBinding,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ private val KTextView.text: CharSequence?
|
||||||
get() {
|
get() {
|
||||||
var string: CharSequence? = null
|
var string: CharSequence? = null
|
||||||
(
|
(
|
||||||
this.view.perform(object : ViewAction {
|
this.view.perform(
|
||||||
|
object : ViewAction {
|
||||||
override fun getConstraints(): Matcher<View> {
|
override fun getConstraints(): Matcher<View> {
|
||||||
return isA(TextView::class.java)
|
return isA(TextView::class.java)
|
||||||
}
|
}
|
||||||
|
|
@ -43,11 +44,15 @@ private val KTextView.text: CharSequence?
|
||||||
return "getting text from a TextView"
|
return "getting text from a TextView"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun perform(uiController: UiController?, view: View?) {
|
override fun perform(
|
||||||
|
uiController: UiController?,
|
||||||
|
view: View?,
|
||||||
|
) {
|
||||||
val tv = view as TextView
|
val tv = view as TextView
|
||||||
string = tv.text
|
string = tv.text
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return string
|
return string
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +63,8 @@ class ItemItem(parent: Matcher<View>) : KRecyclerItem<ItemItem>(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemScreen : Screen<ItemScreen>() {
|
class ItemScreen : Screen<ItemScreen>() {
|
||||||
val recycler: KRecyclerView = KRecyclerView({
|
val recycler: KRecyclerView =
|
||||||
|
KRecyclerView({
|
||||||
withId(R.id.recyclerView)
|
withId(R.id.recyclerView)
|
||||||
}, itemTypeBuilder = {
|
}, itemTypeBuilder = {
|
||||||
itemType(::ItemItem)
|
itemType(::ItemItem)
|
||||||
|
|
@ -78,7 +84,8 @@ internal class ItemRecyclerFragmentTest : FragmentTestCase<ItemRecyclerFragment,
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ import kotlinx.coroutines.flow.flowOf
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
class PetDetailScreen : Screen<PetDetailScreen>() {
|
class PetDetailScreen : Screen<PetDetailScreen>() {
|
||||||
val recycler: KRecyclerView = KRecyclerView({
|
val recycler: KRecyclerView =
|
||||||
|
KRecyclerView({
|
||||||
withId(R.id.recyclerView)
|
withId(R.id.recyclerView)
|
||||||
}, itemTypeBuilder = {
|
}, itemTypeBuilder = {
|
||||||
itemType(::SectionItem)
|
itemType(::SectionItem)
|
||||||
|
|
@ -37,13 +38,14 @@ internal class PetDetailRecyclerFragmentTest :
|
||||||
every { inventoryRepository.getOwnedItems("food") } returns flowOf(user.items?.food!!.filter { it.numberOwned > 0 })
|
every { inventoryRepository.getOwnedItems("food") } returns flowOf(user.items?.food!!.filter { it.numberOwned > 0 })
|
||||||
val saddle = OwnedItem()
|
val saddle = OwnedItem()
|
||||||
saddle.numberOwned = 1
|
saddle.numberOwned = 1
|
||||||
every { inventoryRepository.getOwnedItems(true) } returns flowOf(
|
every { inventoryRepository.getOwnedItems(true) } returns
|
||||||
|
flowOf(
|
||||||
mapOf(
|
mapOf(
|
||||||
Pair(
|
Pair(
|
||||||
"Saddle-food",
|
"Saddle-food",
|
||||||
saddle
|
saddle,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
fragment = spyk()
|
fragment = spyk()
|
||||||
|
|
@ -51,7 +53,8 @@ internal class PetDetailRecyclerFragmentTest :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -66,18 +69,18 @@ internal class PetDetailRecyclerFragmentTest :
|
||||||
inventoryRepository.getPets(
|
inventoryRepository.getPets(
|
||||||
any(),
|
any(),
|
||||||
any(),
|
any(),
|
||||||
any()
|
any(),
|
||||||
)
|
)
|
||||||
} returns flowOf(content.pets.filter { it.animal == "Cactus" })
|
} returns flowOf(content.pets.filter { it.animal == "Cactus" })
|
||||||
every {
|
every {
|
||||||
inventoryRepository.getMounts(
|
inventoryRepository.getMounts(
|
||||||
any(),
|
any(),
|
||||||
any(),
|
any(),
|
||||||
any()
|
any(),
|
||||||
)
|
)
|
||||||
} returns flowOf(content.mounts.filter { it.animal == "Cactus" })
|
} returns flowOf(content.mounts.filter { it.animal == "Cactus" })
|
||||||
launchFragment(
|
launchFragment(
|
||||||
PetDetailRecyclerFragmentArgs.Builder("cactus", "drop", "").build().toBundle()
|
PetDetailRecyclerFragmentArgs.Builder("cactus", "drop", "").build().toBundle(),
|
||||||
)
|
)
|
||||||
screen {
|
screen {
|
||||||
recycler {
|
recycler {
|
||||||
|
|
@ -99,14 +102,14 @@ internal class PetDetailRecyclerFragmentTest :
|
||||||
inventoryRepository.getPets(
|
inventoryRepository.getPets(
|
||||||
any(),
|
any(),
|
||||||
any(),
|
any(),
|
||||||
any()
|
any(),
|
||||||
)
|
)
|
||||||
} returns flowOf(content.pets.filter { it.animal == "Fox" })
|
} returns flowOf(content.pets.filter { it.animal == "Fox" })
|
||||||
every {
|
every {
|
||||||
inventoryRepository.getMounts(
|
inventoryRepository.getMounts(
|
||||||
any(),
|
any(),
|
||||||
any(),
|
any(),
|
||||||
any()
|
any(),
|
||||||
)
|
)
|
||||||
} returns flowOf(content.mounts.filter { it.animal == "Fox" })
|
} returns flowOf(content.mounts.filter { it.animal == "Fox" })
|
||||||
launchFragment(PetDetailRecyclerFragmentArgs.Builder("fox", "drop", "").build().toBundle())
|
launchFragment(PetDetailRecyclerFragmentArgs.Builder("fox", "drop", "").build().toBundle())
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import android.view.View
|
||||||
import androidx.fragment.app.testing.launchFragmentInContainer
|
import androidx.fragment.app.testing.launchFragmentInContainer
|
||||||
import com.habitrpg.android.habitica.R
|
import com.habitrpg.android.habitica.R
|
||||||
import com.habitrpg.android.habitica.databinding.FragmentRecyclerviewBinding
|
import com.habitrpg.android.habitica.databinding.FragmentRecyclerviewBinding
|
||||||
import com.habitrpg.common.habitica.helpers.MainNavigationController
|
|
||||||
import com.habitrpg.android.habitica.ui.fragments.FragmentTestCase
|
import com.habitrpg.android.habitica.ui.fragments.FragmentTestCase
|
||||||
|
import com.habitrpg.common.habitica.helpers.MainNavigationController
|
||||||
import io.github.kakaocup.kakao.common.views.KView
|
import io.github.kakaocup.kakao.common.views.KView
|
||||||
import io.github.kakaocup.kakao.recycler.KRecyclerItem
|
import io.github.kakaocup.kakao.recycler.KRecyclerItem
|
||||||
import io.github.kakaocup.kakao.recycler.KRecyclerView
|
import io.github.kakaocup.kakao.recycler.KRecyclerView
|
||||||
|
|
@ -30,7 +30,8 @@ class SectionItem(parent: Matcher<View>) : KRecyclerItem<PetItem>(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class StableScreen : Screen<StableScreen>() {
|
class StableScreen : Screen<StableScreen>() {
|
||||||
val recycler: KRecyclerView = KRecyclerView({
|
val recycler: KRecyclerView =
|
||||||
|
KRecyclerView({
|
||||||
withId(R.id.recyclerView)
|
withId(R.id.recyclerView)
|
||||||
}, itemTypeBuilder = {
|
}, itemTypeBuilder = {
|
||||||
itemType(::SectionItem)
|
itemType(::SectionItem)
|
||||||
|
|
@ -48,7 +49,8 @@ internal class StableRecyclerFragmentTest : FragmentTestCase<StableRecyclerFragm
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
package com.habitrpg.android.habitica.ui.fragments.purchases
|
|
||||||
|
|
||||||
/*
|
|
||||||
class GemPurchaseScreen: Screen<GemPurchaseScreen>() {
|
|
||||||
val gems4View = KView { withId(R.id.gems_4_view) }
|
|
||||||
val gems4Button = KTextView {
|
|
||||||
withId(R.id.purchase_button)
|
|
||||||
isDescendantOfA { withId(R.id.gems_4_view) }
|
|
||||||
}
|
|
||||||
val gems21View = KView { withId(R.id.gems_21_view) }
|
|
||||||
val gems21Button = KTextView {
|
|
||||||
withId(R.id.purchase_button)
|
|
||||||
isDescendantOfA { withId(R.id.gems_21_view) }
|
|
||||||
}
|
|
||||||
val gems42View = KView { withId(R.id.gems_42_view) }
|
|
||||||
val gems42Button = KTextView {
|
|
||||||
withId(R.id.purchase_button)
|
|
||||||
isDescendantOfA { withId(R.id.gems_42_view) }
|
|
||||||
}
|
|
||||||
val gems84View = KView { withId(R.id.gems_84_view) }
|
|
||||||
val gems84Button = KTextView {
|
|
||||||
withId(R.id.purchase_button)
|
|
||||||
isDescendantOfA { withId(R.id.gems_84_view) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@LargeTest
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class GemsPurchaseFragmentTest :
|
|
||||||
FragmentTestCase<GemsPurchaseFragment, FragmentGemPurchaseBinding, GemPurchaseScreen>() {
|
|
||||||
|
|
||||||
private lateinit var gemSkuMock: MockKAdditionalAnswerScope<List<Sku>, List<Sku>>
|
|
||||||
private var purchaseHandler: PurchaseHandler = mockk(relaxed = true)
|
|
||||||
|
|
||||||
override val screen = GemPurchaseScreen()
|
|
||||||
|
|
||||||
private fun makeTestSKU(
|
|
||||||
product: String,
|
|
||||||
code: String,
|
|
||||||
price: Long,
|
|
||||||
title: String,
|
|
||||||
description: String
|
|
||||||
): Sku {
|
|
||||||
return Sku(
|
|
||||||
product,
|
|
||||||
code,
|
|
||||||
"$${price}",
|
|
||||||
Sku.Price(price, ""),
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
"",
|
|
||||||
Sku.Price(10L, ""),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun makeFragment() {
|
|
||||||
gemSkuMock = coEvery { purchaseHandler.getAllGemSKUs() } returns listOf(
|
|
||||||
makeTestSKU("4Gems", PurchaseTypes.Purchase4Gems, 99, "4 Gems", "smol amount of gems"),
|
|
||||||
makeTestSKU("21Gems", PurchaseTypes.Purchase21Gems, 499, "21 Gems", "medium amount of gems"),
|
|
||||||
makeTestSKU("42Gems", PurchaseTypes.Purchase42Gems, 999, "42 Gems", "lorge amount of gems"),
|
|
||||||
makeTestSKU("84Gems", PurchaseTypes.Purchase84Gems, 1999, "84 Gems", "huge amount of gems")
|
|
||||||
)
|
|
||||||
|
|
||||||
scenario = launchFragmentInContainer(null, R.style.MainAppTheme) {
|
|
||||||
fragment = spyk()
|
|
||||||
fragment.shouldInitializeComponent = false
|
|
||||||
fragment.userRepository = userRepository
|
|
||||||
fragment.tutorialRepository = tutorialRepository
|
|
||||||
fragment.appConfigManager = appConfigManager
|
|
||||||
fragment.setPurchaseHandler(purchaseHandler)
|
|
||||||
return@launchFragmentInContainer fragment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun displaysGemOptions() {
|
|
||||||
screen {
|
|
||||||
fragment.setupCheckout()
|
|
||||||
gems4View.hasDescendant { withText("4") }
|
|
||||||
gems4View.hasDescendant { withText("$99") }
|
|
||||||
gems21View.hasDescendant { withText("21") }
|
|
||||||
gems21View.hasDescendant { withText("$499") }
|
|
||||||
gems42View.hasDescendant { withText("42") }
|
|
||||||
gems42View.hasDescendant { withText("$999") }
|
|
||||||
gems84View.hasDescendant { withText("84") }
|
|
||||||
gems84View.hasDescendant { withText("$1999") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun callsCorrectPurchaseFunction() {
|
|
||||||
screen {
|
|
||||||
fragment.setupCheckout()
|
|
||||||
gems4Button.click()
|
|
||||||
verify(exactly = 1) { purchaseHandler.purchaseGems(PurchaseTypes.Purchase4Gems) }
|
|
||||||
|
|
||||||
gems21Button.click()
|
|
||||||
verify(exactly = 1) { purchaseHandler.purchaseGems(PurchaseTypes.Purchase21Gems) }
|
|
||||||
|
|
||||||
gems42Button.click()
|
|
||||||
verify(exactly = 1) { purchaseHandler.purchaseGems(PurchaseTypes.Purchase42Gems) }
|
|
||||||
|
|
||||||
gems84Button.click()
|
|
||||||
verify(exactly = 1) { purchaseHandler.purchaseGems(PurchaseTypes.Purchase84Gems) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun disablesButtonsWithoutData() {
|
|
||||||
gemSkuMock = coEvery { purchaseHandler.getAllGemSKUs() } returns emptyList()
|
|
||||||
screen {
|
|
||||||
fragment.setupCheckout()
|
|
||||||
gems4Button.click()
|
|
||||||
gems21Button.click()
|
|
||||||
gems42Button.click()
|
|
||||||
gems84Button.click()
|
|
||||||
verify(exactly = 0) { purchaseHandler.purchaseGems(any()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun displaysSubscriptionBannerForUnsubscribed() {
|
|
||||||
screen {
|
|
||||||
subscriptionPromo.isVisible()
|
|
||||||
subscriptionPromoButton.isClickable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun hidesSubscriptionBannerForSubscribed() {
|
|
||||||
user.purchased = Purchases()
|
|
||||||
user.purchased?.plan = SubscriptionPlan()
|
|
||||||
user.purchased?.plan?.customerId = "plan"
|
|
||||||
userSubject.onNext(user)
|
|
||||||
screen {
|
|
||||||
subscriptionPromo.isGone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
package com.habitrpg.android.habitica.ui.fragments.purchases
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
class SubscriptionScreen: Screen<SubscriptionScreen>() {
|
|
||||||
val sub1MonthView = KView { withId(R.id.subscription1month) }
|
|
||||||
val sub3MonthView = KView { withId(R.id.subscription3month) }
|
|
||||||
val sub6MonthView = KView { withId(R.id.subscription6month) }
|
|
||||||
val sub12MonthView = KView { withId(R.id.subscription12month) }
|
|
||||||
val subscribeButton = KView { withId(R.id.subscribeButton) }
|
|
||||||
val subscriptionDetails = KView { withId(R.id.subscriptionDetails) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@LargeTest
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class SubscriptionFragmentTest :
|
|
||||||
FragmentTestCase<SubscriptionFragment, FragmentSubscriptionBinding, SubscriptionScreen>() {
|
|
||||||
private lateinit var subSkuMock: MockKAdditionalAnswerScope<Inventory.Product?, Inventory.Product?>
|
|
||||||
private var purchaseHandler: PurchaseHandler = mockk(relaxed = true)
|
|
||||||
|
|
||||||
private fun makeTestSKU(
|
|
||||||
product: String,
|
|
||||||
code: String,
|
|
||||||
price: Long,
|
|
||||||
title: String,
|
|
||||||
description: String
|
|
||||||
): Sku {
|
|
||||||
return Sku(
|
|
||||||
product,
|
|
||||||
code,
|
|
||||||
"$${price}",
|
|
||||||
Sku.Price(price, ""),
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
"",
|
|
||||||
Sku.Price(10L, ""),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
0
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun makeFragment() {
|
|
||||||
subSkuMock = coEvery { purchaseHandler.getAllSubscriptionProducts() } answers {
|
|
||||||
val product = mockk<Inventory.Product>()
|
|
||||||
every { product.skus } returns listOf(
|
|
||||||
makeTestSKU("1Month", PurchaseTypes.Subscription1Month, 99, "1 Month", "smol amount of gems"),
|
|
||||||
makeTestSKU("3Month", PurchaseTypes.Subscription3Month, 499, "3 Months", "medium amount of gems"),
|
|
||||||
makeTestSKU("6Month", PurchaseTypes.Subscription6Month, 999, "6 Months", "lorge amount of gems"),
|
|
||||||
makeTestSKU("12Month", PurchaseTypes.Subscription12Month, 1999, "12 Months", "huge amount of gems")
|
|
||||||
)
|
|
||||||
product
|
|
||||||
}
|
|
||||||
|
|
||||||
scenario = launchFragmentInContainer(null, R.style.MainAppTheme) {
|
|
||||||
fragment = spyk()
|
|
||||||
fragment.shouldInitializeComponent = false
|
|
||||||
fragment.userRepository = userRepository
|
|
||||||
fragment.inventoryRepository = inventoryRepository
|
|
||||||
fragment.tutorialRepository = tutorialRepository
|
|
||||||
fragment.appConfigManager = appConfigManager
|
|
||||||
fragment.setPurchaseHandler(purchaseHandler)
|
|
||||||
return@launchFragmentInContainer fragment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val screen = SubscriptionScreen()
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun showsSubscriptionOptions() {
|
|
||||||
fragment.setupCheckout()
|
|
||||||
screen {
|
|
||||||
sub1MonthView.isVisible()
|
|
||||||
sub1MonthView.hasDescendant { withText("1 Month") }
|
|
||||||
sub3MonthView.isVisible()
|
|
||||||
sub3MonthView.hasDescendant { withText("3 Months") }
|
|
||||||
sub6MonthView.isVisible()
|
|
||||||
sub6MonthView.hasDescendant { withText("6 Months") }
|
|
||||||
sub12MonthView.isVisible()
|
|
||||||
sub12MonthView.hasDescendant { withText("12 Months") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
@ -28,7 +28,8 @@ open class TaskItem(val parent: Matcher<View>) : KRecyclerItem<TaskItem>(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TaskListScreen : Screen<TaskListScreen>() {
|
class TaskListScreen : Screen<TaskListScreen>() {
|
||||||
val recycler: KRecyclerView = KRecyclerView({
|
val recycler: KRecyclerView =
|
||||||
|
KRecyclerView({
|
||||||
withId(R.id.recyclerView)
|
withId(R.id.recyclerView)
|
||||||
}, itemTypeBuilder = {
|
}, itemTypeBuilder = {
|
||||||
itemType(::TaskItem)
|
itemType(::TaskItem)
|
||||||
|
|
@ -36,7 +37,6 @@ class TaskListScreen : Screen<TaskListScreen>() {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewFragment, FragmentRefreshRecyclerviewBinding, TaskListScreen>(false) {
|
internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewFragment, FragmentRefreshRecyclerviewBinding, TaskListScreen>(false) {
|
||||||
|
|
||||||
lateinit var tasks: MutableCollection<Task>
|
lateinit var tasks: MutableCollection<Task>
|
||||||
|
|
||||||
override fun makeFragment() {
|
override fun makeFragment() {
|
||||||
|
|
@ -46,7 +46,8 @@ internal class TaskRecyclerViewFragmentTest : FragmentTestCase<TaskRecyclerViewF
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun launchFragment(args: Bundle?) {
|
override fun launchFragment(args: Bundle?) {
|
||||||
scenario = launchFragmentInContainer(args, R.style.MainAppTheme) {
|
scenario =
|
||||||
|
launchFragmentInContainer(args, R.style.MainAppTheme) {
|
||||||
return@launchFragmentInContainer fragment
|
return@launchFragmentInContainer fragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,10 @@ import java.lang.ref.WeakReference
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ApplicationLifecycleTracker(private val sharedPreferences: SharedPreferences): DefaultLifecycleObserver {
|
class ApplicationLifecycleTracker(private val sharedPreferences: SharedPreferences) :
|
||||||
|
DefaultLifecycleObserver {
|
||||||
private var lastResumeTime = 0L
|
private var lastResumeTime = 0L
|
||||||
|
|
||||||
override fun onResume(owner: LifecycleOwner) {
|
override fun onResume(owner: LifecycleOwner) {
|
||||||
super.onResume(owner)
|
super.onResume(owner)
|
||||||
lastResumeTime = Date().time
|
lastResumeTime = Date().time
|
||||||
|
|
@ -107,9 +109,6 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
|
|
||||||
private lateinit var lifecycleTracker: ApplicationLifecycleTracker
|
private lateinit var lifecycleTracker: ApplicationLifecycleTracker
|
||||||
|
|
||||||
/**
|
|
||||||
* For better performance billing class should be used as singleton
|
|
||||||
*/
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
|
|
@ -148,7 +147,6 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
checkIfNewVersion()
|
checkIfNewVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun setupAdHandler() {
|
private fun setupAdHandler() {
|
||||||
AdHandler.setup(sharedPrefs)
|
AdHandler.setup(sharedPrefs)
|
||||||
}
|
}
|
||||||
|
|
@ -171,7 +169,8 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
|
|
||||||
protected open fun setupRealm() {
|
protected open fun setupRealm() {
|
||||||
Realm.init(this)
|
Realm.init(this)
|
||||||
val builder = RealmConfiguration.Builder()
|
val builder =
|
||||||
|
RealmConfiguration.Builder()
|
||||||
.schemaVersion(1)
|
.schemaVersion(1)
|
||||||
.deleteRealmIfMigrationNeeded()
|
.deleteRealmIfMigrationNeeded()
|
||||||
.allowWritesOnUiThread(true)
|
.allowWritesOnUiThread(true)
|
||||||
|
|
@ -212,7 +211,7 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
override fun openOrCreateDatabase(
|
override fun openOrCreateDatabase(
|
||||||
name: String,
|
name: String,
|
||||||
mode: Int,
|
mode: Int,
|
||||||
factory: SQLiteDatabase.CursorFactory?
|
factory: SQLiteDatabase.CursorFactory?,
|
||||||
): SQLiteDatabase {
|
): SQLiteDatabase {
|
||||||
return super.openOrCreateDatabase(getDatabasePath(name).absolutePath, mode, factory)
|
return super.openOrCreateDatabase(getDatabasePath(name).absolutePath, mode, factory)
|
||||||
}
|
}
|
||||||
|
|
@ -221,9 +220,14 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
name: String,
|
name: String,
|
||||||
mode: Int,
|
mode: Int,
|
||||||
factory: SQLiteDatabase.CursorFactory?,
|
factory: SQLiteDatabase.CursorFactory?,
|
||||||
errorHandler: DatabaseErrorHandler?
|
errorHandler: DatabaseErrorHandler?,
|
||||||
): SQLiteDatabase {
|
): SQLiteDatabase {
|
||||||
return super.openOrCreateDatabase(getDatabasePath(name).absolutePath, mode, factory, errorHandler)
|
return super.openOrCreateDatabase(
|
||||||
|
getDatabasePath(name).absolutePath,
|
||||||
|
mode,
|
||||||
|
factory,
|
||||||
|
errorHandler,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
@ -241,7 +245,8 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
|
|
||||||
private fun setupRemoteConfig() {
|
private fun setupRemoteConfig() {
|
||||||
val remoteConfig = FirebaseRemoteConfig.getInstance()
|
val remoteConfig = FirebaseRemoteConfig.getInstance()
|
||||||
val configSettings = FirebaseRemoteConfigSettings.Builder()
|
val configSettings =
|
||||||
|
FirebaseRemoteConfigSettings.Builder()
|
||||||
.setMinimumFetchIntervalInSeconds(if (BuildConfig.DEBUG) 0 else 3600)
|
.setMinimumFetchIntervalInSeconds(if (BuildConfig.DEBUG) 0 else 3600)
|
||||||
.build()
|
.build()
|
||||||
remoteConfig.setConfigSettingsAsync(configSettings)
|
remoteConfig.setConfigSettingsAsync(configSettings)
|
||||||
|
|
@ -278,13 +283,19 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityCreated(p0: Activity, p1: Bundle?) {
|
override fun onActivityCreated(
|
||||||
|
p0: Activity,
|
||||||
|
p1: Bundle?,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityDestroyed(p0: Activity) {
|
override fun onActivityDestroyed(p0: Activity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivitySaveInstanceState(p0: Activity, p1: Bundle) {
|
override fun onActivitySaveInstanceState(
|
||||||
|
p0: Activity,
|
||||||
|
p1: Bundle,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityStopped(p0: Activity) {
|
override fun onActivityStopped(p0: Activity) {
|
||||||
|
|
@ -319,7 +330,10 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startActivity(activityClass: Class<*>, context: Context) {
|
private fun startActivity(
|
||||||
|
activityClass: Class<*>,
|
||||||
|
context: Context,
|
||||||
|
) {
|
||||||
val intent = Intent(context, activityClass)
|
val intent = Intent(context, activityClass)
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
context.startActivity(intent)
|
context.startActivity(intent)
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,6 @@ import com.google.gson.reflect.TypeToken;
|
||||||
import com.habitrpg.android.habitica.models.Achievement;
|
import com.habitrpg.android.habitica.models.Achievement;
|
||||||
import com.habitrpg.android.habitica.models.ContentResult;
|
import com.habitrpg.android.habitica.models.ContentResult;
|
||||||
import com.habitrpg.android.habitica.models.FAQArticle;
|
import com.habitrpg.android.habitica.models.FAQArticle;
|
||||||
import com.habitrpg.android.habitica.models.tasks.GroupAssignedDetails;
|
|
||||||
import com.habitrpg.android.habitica.utils.AssignedDetailsDeserializer;
|
|
||||||
import com.habitrpg.common.habitica.models.Notification;
|
|
||||||
import com.habitrpg.android.habitica.models.Skill;
|
import com.habitrpg.android.habitica.models.Skill;
|
||||||
import com.habitrpg.android.habitica.models.Tag;
|
import com.habitrpg.android.habitica.models.Tag;
|
||||||
import com.habitrpg.android.habitica.models.TutorialStep;
|
import com.habitrpg.android.habitica.models.TutorialStep;
|
||||||
|
|
@ -19,11 +16,11 @@ import com.habitrpg.android.habitica.models.inventory.Quest;
|
||||||
import com.habitrpg.android.habitica.models.inventory.QuestCollect;
|
import com.habitrpg.android.habitica.models.inventory.QuestCollect;
|
||||||
import com.habitrpg.android.habitica.models.inventory.QuestDropItem;
|
import com.habitrpg.android.habitica.models.inventory.QuestDropItem;
|
||||||
import com.habitrpg.android.habitica.models.members.Member;
|
import com.habitrpg.android.habitica.models.members.Member;
|
||||||
import com.habitrpg.shared.habitica.models.responses.FeedResponse;
|
|
||||||
import com.habitrpg.android.habitica.models.social.Challenge;
|
import com.habitrpg.android.habitica.models.social.Challenge;
|
||||||
import com.habitrpg.android.habitica.models.social.ChatMessage;
|
import com.habitrpg.android.habitica.models.social.ChatMessage;
|
||||||
import com.habitrpg.android.habitica.models.social.FindUsernameResult;
|
import com.habitrpg.android.habitica.models.social.FindUsernameResult;
|
||||||
import com.habitrpg.android.habitica.models.social.Group;
|
import com.habitrpg.android.habitica.models.social.Group;
|
||||||
|
import com.habitrpg.android.habitica.models.tasks.GroupAssignedDetails;
|
||||||
import com.habitrpg.android.habitica.models.tasks.Task;
|
import com.habitrpg.android.habitica.models.tasks.Task;
|
||||||
import com.habitrpg.android.habitica.models.tasks.TaskList;
|
import com.habitrpg.android.habitica.models.tasks.TaskList;
|
||||||
import com.habitrpg.android.habitica.models.user.OwnedItem;
|
import com.habitrpg.android.habitica.models.user.OwnedItem;
|
||||||
|
|
@ -33,6 +30,7 @@ import com.habitrpg.android.habitica.models.user.Purchases;
|
||||||
import com.habitrpg.android.habitica.models.user.User;
|
import com.habitrpg.android.habitica.models.user.User;
|
||||||
import com.habitrpg.android.habitica.models.user.auth.SocialAuthentication;
|
import com.habitrpg.android.habitica.models.user.auth.SocialAuthentication;
|
||||||
import com.habitrpg.android.habitica.utils.AchievementListDeserializer;
|
import com.habitrpg.android.habitica.utils.AchievementListDeserializer;
|
||||||
|
import com.habitrpg.android.habitica.utils.AssignedDetailsDeserializer;
|
||||||
import com.habitrpg.android.habitica.utils.BooleanAsIntAdapter;
|
import com.habitrpg.android.habitica.utils.BooleanAsIntAdapter;
|
||||||
import com.habitrpg.android.habitica.utils.ChallengeDeserializer;
|
import com.habitrpg.android.habitica.utils.ChallengeDeserializer;
|
||||||
import com.habitrpg.android.habitica.utils.ChallengeListDeserializer;
|
import com.habitrpg.android.habitica.utils.ChallengeListDeserializer;
|
||||||
|
|
@ -62,6 +60,8 @@ import com.habitrpg.android.habitica.utils.TaskTagDeserializer;
|
||||||
import com.habitrpg.android.habitica.utils.TutorialStepListDeserializer;
|
import com.habitrpg.android.habitica.utils.TutorialStepListDeserializer;
|
||||||
import com.habitrpg.android.habitica.utils.UserDeserializer;
|
import com.habitrpg.android.habitica.utils.UserDeserializer;
|
||||||
import com.habitrpg.android.habitica.utils.WorldStateSerialization;
|
import com.habitrpg.android.habitica.utils.WorldStateSerialization;
|
||||||
|
import com.habitrpg.common.habitica.models.Notification;
|
||||||
|
import com.habitrpg.shared.habitica.models.responses.FeedResponse;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -145,6 +145,7 @@ public class GSonFactoryCreator {
|
||||||
.setLenient()
|
.setLenient()
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GsonConverterFactory create() {
|
public static GsonConverterFactory create() {
|
||||||
return GsonConverterFactory.create(createGson());
|
return GsonConverterFactory.create(createGson());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ package com.habitrpg.android.habitica.data
|
||||||
import com.habitrpg.android.habitica.models.BaseObject
|
import com.habitrpg.android.habitica.models.BaseObject
|
||||||
|
|
||||||
interface BaseRepository {
|
interface BaseRepository {
|
||||||
|
|
||||||
val isClosed: Boolean
|
val isClosed: Boolean
|
||||||
|
|
||||||
fun close()
|
fun close()
|
||||||
|
|
||||||
fun <T : BaseObject> getUnmanagedCopy(obj: T): T
|
fun <T : BaseObject> getUnmanagedCopy(obj: T): T
|
||||||
|
|
||||||
fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T>
|
fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,25 @@ import com.habitrpg.android.habitica.models.tasks.TaskList
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface ChallengeRepository : BaseRepository {
|
interface ChallengeRepository : BaseRepository {
|
||||||
|
suspend fun retrieveChallenges(
|
||||||
|
page: Int = 0,
|
||||||
|
memberOnly: Boolean,
|
||||||
|
): List<Challenge>?
|
||||||
|
|
||||||
suspend fun retrieveChallenges(page: Int = 0, memberOnly: Boolean): List<Challenge>?
|
|
||||||
fun getChallenges(): Flow<List<Challenge>>
|
fun getChallenges(): Flow<List<Challenge>>
|
||||||
|
|
||||||
fun getChallenge(challengeId: String): Flow<Challenge>
|
fun getChallenge(challengeId: String): Flow<Challenge>
|
||||||
|
|
||||||
fun getChallengeTasks(challengeId: String): Flow<List<Task>>
|
fun getChallengeTasks(challengeId: String): Flow<List<Task>>
|
||||||
|
|
||||||
suspend fun retrieveChallenge(challengeID: String): Challenge?
|
suspend fun retrieveChallenge(challengeID: String): Challenge?
|
||||||
|
|
||||||
suspend fun retrieveChallengeTasks(challengeID: String): TaskList?
|
suspend fun retrieveChallengeTasks(challengeID: String): TaskList?
|
||||||
suspend fun createChallenge(challenge: Challenge, taskList: List<Task>): Challenge?
|
|
||||||
|
suspend fun createChallenge(
|
||||||
|
challenge: Challenge,
|
||||||
|
taskList: List<Task>,
|
||||||
|
): Challenge?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
|
@ -31,18 +41,28 @@ interface ChallengeRepository : BaseRepository {
|
||||||
fullTaskList: List<Task>,
|
fullTaskList: List<Task>,
|
||||||
addedTaskList: List<Task>,
|
addedTaskList: List<Task>,
|
||||||
updatedTaskList: List<Task>,
|
updatedTaskList: List<Task>,
|
||||||
removedTaskList: List<String>
|
removedTaskList: List<String>,
|
||||||
): Challenge?
|
): Challenge?
|
||||||
|
|
||||||
suspend fun deleteChallenge(challengeId: String): Void?
|
suspend fun deleteChallenge(challengeId: String): Void?
|
||||||
|
|
||||||
fun getUserChallenges(userId: String? = null): Flow<List<Challenge>>
|
fun getUserChallenges(userId: String? = null): Flow<List<Challenge>>
|
||||||
|
|
||||||
suspend fun leaveChallenge(challenge: Challenge, keepTasks: String): Void?
|
suspend fun leaveChallenge(
|
||||||
|
challenge: Challenge,
|
||||||
|
keepTasks: String,
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun joinChallenge(challenge: Challenge): Challenge?
|
suspend fun joinChallenge(challenge: Challenge): Challenge?
|
||||||
|
|
||||||
fun getChallengepMembership(id: String): Flow<ChallengeMembership>
|
fun getChallengepMembership(id: String): Flow<ChallengeMembership>
|
||||||
|
|
||||||
fun getChallengeMemberships(): Flow<List<ChallengeMembership>>
|
fun getChallengeMemberships(): Flow<List<ChallengeMembership>>
|
||||||
|
|
||||||
fun isChallengeMember(challengeID: String): Flow<Boolean>
|
fun isChallengeMember(challengeID: String): Flow<Boolean>
|
||||||
suspend fun reportChallenge(challengeid: String, updateData: Map<String, String>): Void?
|
|
||||||
|
suspend fun reportChallenge(
|
||||||
|
challengeid: String,
|
||||||
|
updateData: Map<String, String>,
|
||||||
|
): Void?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,6 @@ interface ContentRepository : BaseRepository {
|
||||||
suspend fun retrieveContent(forced: Boolean = false): ContentResult?
|
suspend fun retrieveContent(forced: Boolean = false): ContentResult?
|
||||||
|
|
||||||
suspend fun retrieveWorldState(forced: Boolean = false): WorldState?
|
suspend fun retrieveWorldState(forced: Boolean = false): WorldState?
|
||||||
|
|
||||||
fun getWorldState(): Flow<WorldState>
|
fun getWorldState(): Flow<WorldState>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,9 @@ import com.habitrpg.android.habitica.models.inventory.Customization
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface CustomizationRepository : BaseRepository {
|
interface CustomizationRepository : BaseRepository {
|
||||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>>
|
fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
category: String?,
|
||||||
|
onlyAvailable: Boolean,
|
||||||
|
): Flow<List<Customization>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@ import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface FAQRepository : BaseRepository {
|
interface FAQRepository : BaseRepository {
|
||||||
fun getArticles(): Flow<List<FAQArticle>>
|
fun getArticles(): Flow<List<FAQArticle>>
|
||||||
|
|
||||||
fun getArticle(position: Int): Flow<FAQArticle>
|
fun getArticle(position: Int): Flow<FAQArticle>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ import com.habitrpg.shared.habitica.models.responses.FeedResponse
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface InventoryRepository : BaseRepository {
|
interface InventoryRepository : BaseRepository {
|
||||||
|
|
||||||
fun getArmoireRemainingCount(): Flow<Int>
|
fun getArmoireRemainingCount(): Flow<Int>
|
||||||
|
|
||||||
fun getInAppRewards(): Flow<List<ShopItem>>
|
fun getInAppRewards(): Flow<List<ShopItem>>
|
||||||
|
|
||||||
fun getInAppReward(key: String): Flow<ShopItem>
|
fun getInAppReward(key: String): Flow<ShopItem>
|
||||||
|
|
||||||
fun getOwnedEquipment(): Flow<List<Equipment>>
|
fun getOwnedEquipment(): Flow<List<Equipment>>
|
||||||
|
|
@ -36,16 +36,27 @@ interface InventoryRepository : BaseRepository {
|
||||||
fun getPets(): Flow<List<Pet>>
|
fun getPets(): Flow<List<Pet>>
|
||||||
|
|
||||||
fun getOwnedPets(): Flow<List<OwnedPet>>
|
fun getOwnedPets(): Flow<List<OwnedPet>>
|
||||||
|
|
||||||
fun getQuestContent(key: String): Flow<QuestContent?>
|
fun getQuestContent(key: String): Flow<QuestContent?>
|
||||||
|
|
||||||
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
||||||
|
|
||||||
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
||||||
|
|
||||||
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
suspend fun retrieveInAppRewards(): List<ShopItem>?
|
||||||
|
|
||||||
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
||||||
fun getEquipmentType(type: String, set: String): Flow<List<Equipment>>
|
|
||||||
|
|
||||||
fun getOwnedItems(itemType: String, includeZero: Boolean = false): Flow<List<OwnedItem>>
|
fun getEquipmentType(
|
||||||
|
type: String,
|
||||||
|
set: String,
|
||||||
|
): Flow<List<Equipment>>
|
||||||
|
|
||||||
|
fun getOwnedItems(
|
||||||
|
itemType: String,
|
||||||
|
includeZero: Boolean = false,
|
||||||
|
): Flow<List<OwnedItem>>
|
||||||
|
|
||||||
fun getOwnedItems(includeZero: Boolean = false): Flow<Map<String, OwnedItem>>
|
fun getOwnedItems(includeZero: Boolean = false): Flow<Map<String, OwnedItem>>
|
||||||
|
|
||||||
fun getEquipment(key: String): Flow<Equipment>
|
fun getEquipment(key: String): Flow<Equipment>
|
||||||
|
|
@ -53,43 +64,100 @@ interface InventoryRepository : BaseRepository {
|
||||||
suspend fun openMysteryItem(user: User?): Equipment?
|
suspend fun openMysteryItem(user: User?): Equipment?
|
||||||
|
|
||||||
fun saveEquipment(equipment: Equipment)
|
fun saveEquipment(equipment: Equipment)
|
||||||
fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>>
|
|
||||||
fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>>
|
fun getMounts(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Mount>>
|
||||||
|
|
||||||
|
fun getPets(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Pet>>
|
||||||
|
|
||||||
fun updateOwnedEquipment(user: User)
|
fun updateOwnedEquipment(user: User)
|
||||||
|
|
||||||
suspend fun changeOwnedCount(type: String, key: String, amountToAdd: Int)
|
suspend fun changeOwnedCount(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
amountToAdd: Int,
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun sellItem(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): User?
|
||||||
|
|
||||||
suspend fun sellItem(type: String, key: String): User?
|
|
||||||
suspend fun sellItem(item: OwnedItem): User?
|
suspend fun sellItem(item: OwnedItem): User?
|
||||||
|
|
||||||
suspend fun equipGear(equipment: String, asCostume: Boolean): Items?
|
suspend fun equipGear(
|
||||||
suspend fun equip(type: String, key: String): Items?
|
equipment: String,
|
||||||
|
asCostume: Boolean,
|
||||||
|
): Items?
|
||||||
|
|
||||||
suspend fun feedPet(pet: Pet, food: Food): FeedResponse?
|
suspend fun equip(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Items?
|
||||||
|
|
||||||
suspend fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Items?
|
suspend fun feedPet(
|
||||||
|
pet: Pet,
|
||||||
|
food: Food,
|
||||||
|
): FeedResponse?
|
||||||
|
|
||||||
|
suspend fun hatchPet(
|
||||||
|
egg: Egg,
|
||||||
|
hatchingPotion: HatchingPotion,
|
||||||
|
successFunction: () -> Unit,
|
||||||
|
): Items?
|
||||||
|
|
||||||
suspend fun inviteToQuest(quest: QuestContent): Quest?
|
suspend fun inviteToQuest(quest: QuestContent): Quest?
|
||||||
|
|
||||||
suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse?
|
suspend fun buyItem(
|
||||||
|
user: User?,
|
||||||
|
id: String,
|
||||||
|
value: Double,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): BuyResponse?
|
||||||
|
|
||||||
suspend fun retrieveShopInventory(identifier: String): Shop?
|
suspend fun retrieveShopInventory(identifier: String): Shop?
|
||||||
|
|
||||||
suspend fun retrieveMarketGear(): Shop?
|
suspend fun retrieveMarketGear(): Shop?
|
||||||
|
|
||||||
suspend fun purchaseMysterySet(categoryIdentifier: String): Void?
|
suspend fun purchaseMysterySet(categoryIdentifier: String): Void?
|
||||||
|
|
||||||
suspend fun purchaseHourglassItem(purchaseType: String, key: String): Void?
|
suspend fun purchaseHourglassItem(
|
||||||
|
purchaseType: String,
|
||||||
|
key: String,
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun purchaseQuest(key: String): Void?
|
suspend fun purchaseQuest(key: String): Void?
|
||||||
|
|
||||||
suspend fun purchaseSpecialSpell(key: String): Void?
|
suspend fun purchaseSpecialSpell(key: String): Void?
|
||||||
|
|
||||||
suspend fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Void?
|
suspend fun purchaseItem(
|
||||||
|
purchaseType: String,
|
||||||
|
key: String,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun togglePinnedItem(item: ShopItem): List<ShopItem>?
|
suspend fun togglePinnedItem(item: ShopItem): List<ShopItem>?
|
||||||
fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>>
|
|
||||||
|
fun getItems(
|
||||||
|
itemClass: Class<out Item>,
|
||||||
|
keys: Array<String>,
|
||||||
|
): Flow<List<Item>>
|
||||||
|
|
||||||
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
||||||
|
|
||||||
fun getLatestMysteryItem(): Flow<Equipment>
|
fun getLatestMysteryItem(): Flow<Equipment>
|
||||||
fun getItem(type: String, key: String): Flow<Item>
|
|
||||||
|
fun getItem(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Flow<Item>
|
||||||
|
|
||||||
fun getAvailableLimitedItems(): Flow<List<Item>>
|
fun getAvailableLimitedItems(): Flow<List<Item>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,16 @@ import com.habitrpg.android.habitica.models.SetupCustomization
|
||||||
import com.habitrpg.android.habitica.models.user.User
|
import com.habitrpg.android.habitica.models.user.User
|
||||||
|
|
||||||
interface SetupCustomizationRepository {
|
interface SetupCustomizationRepository {
|
||||||
|
fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
user: User,
|
||||||
|
): List<SetupCustomization>
|
||||||
|
|
||||||
fun getCustomizations(type: String, user: User): List<SetupCustomization>
|
fun getCustomizations(
|
||||||
fun getCustomizations(type: String, subtype: String?, user: User): List<SetupCustomization>
|
type: String,
|
||||||
|
subtype: String?,
|
||||||
|
user: User,
|
||||||
|
): List<SetupCustomization>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val CATEGORY_BODY = "body"
|
const val CATEGORY_BODY = "body"
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface SocialRepository : BaseRepository {
|
interface SocialRepository : BaseRepository {
|
||||||
fun getUserGroups(type: String?): Flow<List<Group>>
|
fun getUserGroups(type: String?): Flow<List<Group>>
|
||||||
|
|
||||||
suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>?
|
suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>?
|
||||||
|
|
||||||
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
||||||
|
|
||||||
suspend fun markMessagesSeen(seenGroupId: String)
|
suspend fun markMessagesSeen(seenGroupId: String)
|
||||||
|
|
@ -24,10 +26,13 @@ interface SocialRepository : BaseRepository {
|
||||||
suspend fun flagMessage(
|
suspend fun flagMessage(
|
||||||
chatMessageID: String,
|
chatMessageID: String,
|
||||||
additionalInfo: String,
|
additionalInfo: String,
|
||||||
groupID: String? = null
|
groupID: String? = null,
|
||||||
): Void?
|
): Void?
|
||||||
|
|
||||||
suspend fun reportMember(memberID: String, data: Map<String, String>): Void?
|
suspend fun reportMember(
|
||||||
|
memberID: String,
|
||||||
|
data: Map<String, String>,
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun likeMessage(chatMessage: ChatMessage): ChatMessage?
|
suspend fun likeMessage(chatMessage: ChatMessage): ChatMessage?
|
||||||
|
|
||||||
|
|
@ -35,15 +40,22 @@ interface SocialRepository : BaseRepository {
|
||||||
|
|
||||||
suspend fun postGroupChat(
|
suspend fun postGroupChat(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
messageObject: HashMap<String, String>
|
messageObject: HashMap<String, String>,
|
||||||
): PostChatMessageResult?
|
): PostChatMessageResult?
|
||||||
|
|
||||||
suspend fun postGroupChat(groupId: String, message: String): PostChatMessageResult?
|
suspend fun postGroupChat(
|
||||||
|
groupId: String,
|
||||||
|
message: String,
|
||||||
|
): PostChatMessageResult?
|
||||||
|
|
||||||
suspend fun retrieveGroup(id: String): Group?
|
suspend fun retrieveGroup(id: String): Group?
|
||||||
|
|
||||||
fun getGroup(id: String?): Flow<Group?>
|
fun getGroup(id: String?): Flow<Group?>
|
||||||
|
|
||||||
suspend fun leaveGroup(id: String?, keepChallenges: Boolean): Group?
|
suspend fun leaveGroup(
|
||||||
|
id: String?,
|
||||||
|
keepChallenges: Boolean,
|
||||||
|
): Group?
|
||||||
|
|
||||||
suspend fun joinGroup(id: String?): Group?
|
suspend fun joinGroup(id: String?): Group?
|
||||||
|
|
||||||
|
|
@ -53,7 +65,7 @@ interface SocialRepository : BaseRepository {
|
||||||
leader: String?,
|
leader: String?,
|
||||||
type: String?,
|
type: String?,
|
||||||
privacy: String?,
|
privacy: String?,
|
||||||
leaderCreateChallenge: Boolean?
|
leaderCreateChallenge: Boolean?,
|
||||||
): Group?
|
): Group?
|
||||||
|
|
||||||
suspend fun updateGroup(
|
suspend fun updateGroup(
|
||||||
|
|
@ -61,43 +73,81 @@ interface SocialRepository : BaseRepository {
|
||||||
name: String?,
|
name: String?,
|
||||||
description: String?,
|
description: String?,
|
||||||
leader: String?,
|
leader: String?,
|
||||||
leaderCreateChallenge: Boolean?
|
leaderCreateChallenge: Boolean?,
|
||||||
): Group?
|
): Group?
|
||||||
|
|
||||||
fun getInboxMessages(replyToUserID: String?): Flow<RealmResults<ChatMessage>>
|
fun getInboxMessages(replyToUserID: String?): Flow<RealmResults<ChatMessage>>
|
||||||
suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>?
|
|
||||||
suspend fun retrieveInboxConversations(): List<InboxConversation>?
|
suspend fun retrieveInboxMessages(
|
||||||
fun getInboxConversations(): Flow<RealmResults<InboxConversation>>
|
uuid: String,
|
||||||
suspend fun postPrivateMessage(
|
page: Int,
|
||||||
recipientId: String,
|
|
||||||
messageObject: HashMap<String, String>
|
|
||||||
): List<ChatMessage>?
|
): List<ChatMessage>?
|
||||||
|
|
||||||
suspend fun postPrivateMessage(recipientId: String, message: String): List<ChatMessage>?
|
suspend fun retrieveInboxConversations(): List<InboxConversation>?
|
||||||
|
|
||||||
|
fun getInboxConversations(): Flow<RealmResults<InboxConversation>>
|
||||||
|
|
||||||
|
suspend fun postPrivateMessage(
|
||||||
|
recipientId: String,
|
||||||
|
messageObject: HashMap<String, String>,
|
||||||
|
): List<ChatMessage>?
|
||||||
|
|
||||||
|
suspend fun postPrivateMessage(
|
||||||
|
recipientId: String,
|
||||||
|
message: String,
|
||||||
|
): List<ChatMessage>?
|
||||||
|
|
||||||
suspend fun getPartyMembers(id: String): Flow<List<Member>>
|
suspend fun getPartyMembers(id: String): Flow<List<Member>>
|
||||||
|
|
||||||
suspend fun getGroupMembers(id: String): Flow<List<Member>>
|
suspend fun getGroupMembers(id: String): Flow<List<Member>>
|
||||||
suspend fun retrievePartyMembers(id: String, includeAllPublicFields: Boolean): List<Member>?
|
|
||||||
|
|
||||||
suspend fun inviteToGroup(id: String, inviteData: Map<String, Any>): List<InviteResponse>?
|
suspend fun retrievePartyMembers(
|
||||||
|
id: String,
|
||||||
|
includeAllPublicFields: Boolean,
|
||||||
|
): List<Member>?
|
||||||
|
|
||||||
suspend fun retrieveMember(userId: String?, fromHall: Boolean = false): Member?
|
suspend fun inviteToGroup(
|
||||||
|
id: String,
|
||||||
|
inviteData: Map<String, Any>,
|
||||||
|
): List<InviteResponse>?
|
||||||
|
|
||||||
|
suspend fun retrieveMember(
|
||||||
|
userId: String?,
|
||||||
|
fromHall: Boolean = false,
|
||||||
|
): Member?
|
||||||
|
|
||||||
suspend fun findUsernames(
|
suspend fun findUsernames(
|
||||||
username: String,
|
username: String,
|
||||||
context: String? = null,
|
context: String? = null,
|
||||||
id: String? = null
|
id: String? = null,
|
||||||
): List<FindUsernameResult>?
|
): List<FindUsernameResult>?
|
||||||
|
|
||||||
suspend fun markPrivateMessagesRead(user: User?)
|
suspend fun markPrivateMessagesRead(user: User?)
|
||||||
|
|
||||||
fun markSomePrivateMessagesAsRead(user: User?, messages: List<ChatMessage>)
|
fun markSomePrivateMessagesAsRead(
|
||||||
|
user: User?,
|
||||||
|
messages: List<ChatMessage>,
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun transferGroupOwnership(groupID: String, userID: String): Group?
|
suspend fun transferGroupOwnership(
|
||||||
suspend fun removeMemberFromGroup(groupID: String, userID: String): List<Member>?
|
groupID: String,
|
||||||
|
userID: String,
|
||||||
|
): Group?
|
||||||
|
|
||||||
suspend fun acceptQuest(user: User?, partyId: String = "party"): Void?
|
suspend fun removeMemberFromGroup(
|
||||||
suspend fun rejectQuest(user: User?, partyId: String = "party"): Void?
|
groupID: String,
|
||||||
|
userID: String,
|
||||||
|
): List<Member>?
|
||||||
|
|
||||||
|
suspend fun acceptQuest(
|
||||||
|
user: User?,
|
||||||
|
partyId: String = "party",
|
||||||
|
): Void?
|
||||||
|
|
||||||
|
suspend fun rejectQuest(
|
||||||
|
user: User?,
|
||||||
|
partyId: String = "party",
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun leaveQuest(partyId: String): Void?
|
suspend fun leaveQuest(partyId: String): Void?
|
||||||
|
|
||||||
|
|
@ -111,13 +161,28 @@ interface SocialRepository : BaseRepository {
|
||||||
|
|
||||||
suspend fun getMemberAchievements(userId: String?): List<Achievement>?
|
suspend fun getMemberAchievements(userId: String?): List<Achievement>?
|
||||||
|
|
||||||
suspend fun transferGems(giftedID: String, amount: Int): Void?
|
suspend fun transferGems(
|
||||||
|
giftedID: String,
|
||||||
|
amount: Int,
|
||||||
|
): Void?
|
||||||
|
|
||||||
fun getGroupMembership(id: String): Flow<GroupMembership?>
|
fun getGroupMembership(id: String): Flow<GroupMembership?>
|
||||||
|
|
||||||
fun getGroupMemberships(): Flow<List<GroupMembership>>
|
fun getGroupMemberships(): Flow<List<GroupMembership>>
|
||||||
|
|
||||||
suspend fun blockMember(userID: String): List<String>?
|
suspend fun blockMember(userID: String): List<String>?
|
||||||
|
|
||||||
fun getMember(userID: String?): Flow<Member?>
|
fun getMember(userID: String?): Flow<Member?>
|
||||||
suspend fun updateMember(memberID: String, data: Map<String, Map<String, Boolean>>): Member?
|
|
||||||
|
suspend fun updateMember(
|
||||||
|
memberID: String,
|
||||||
|
data: Map<String, Map<String, Boolean>>,
|
||||||
|
): Member?
|
||||||
|
|
||||||
suspend fun retrievePartySeekingUsers(page: Int = 0): List<Member>?
|
suspend fun retrievePartySeekingUsers(page: Int = 0): List<Member>?
|
||||||
suspend fun retrievegroupInvites(id: String, includeAllPublicFields: Boolean): List<Member>?
|
|
||||||
|
suspend fun retrievegroupInvites(
|
||||||
|
id: String,
|
||||||
|
includeAllPublicFields: Boolean,
|
||||||
|
): List<Member>?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,19 @@ import com.habitrpg.android.habitica.models.Tag
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TagRepository : BaseRepository {
|
interface TagRepository : BaseRepository {
|
||||||
|
|
||||||
fun getTags(): Flow<List<Tag>>
|
fun getTags(): Flow<List<Tag>>
|
||||||
|
|
||||||
fun getTags(userId: String): Flow<List<Tag>>
|
fun getTags(userId: String): Flow<List<Tag>>
|
||||||
|
|
||||||
suspend fun createTag(tag: Tag): Tag?
|
suspend fun createTag(tag: Tag): Tag?
|
||||||
|
|
||||||
suspend fun updateTag(tag: Tag): Tag?
|
suspend fun updateTag(tag: Tag): Tag?
|
||||||
|
|
||||||
suspend fun deleteTag(id: String): Void?
|
suspend fun deleteTag(id: String): Void?
|
||||||
|
|
||||||
suspend fun createTags(tags: Collection<Tag>): List<Tag>
|
suspend fun createTags(tags: Collection<Tag>): List<Tag>
|
||||||
|
|
||||||
suspend fun updateTags(tags: Collection<Tag>): List<Tag>
|
suspend fun updateTags(tags: Collection<Tag>): List<Tag>
|
||||||
|
|
||||||
suspend fun deleteTags(tagIds: Collection<String>): List<Void>
|
suspend fun deleteTags(tagIds: Collection<String>): List<Void>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,59 +12,124 @@ import kotlinx.coroutines.flow.Flow
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
interface TaskRepository : BaseRepository {
|
interface TaskRepository : BaseRepository {
|
||||||
fun getTasks(taskType: TaskType, userID: String? = null, includedGroupIDs: Array<String>): Flow<List<Task>>
|
fun getTasks(
|
||||||
fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList)
|
taskType: TaskType,
|
||||||
|
userID: String? = null,
|
||||||
|
includedGroupIDs: Array<String>,
|
||||||
|
): Flow<List<Task>>
|
||||||
|
|
||||||
suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder): TaskList?
|
fun saveTasks(
|
||||||
suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): TaskList?
|
userId: String,
|
||||||
|
order: TasksOrder,
|
||||||
|
tasks: TaskList,
|
||||||
|
)
|
||||||
|
|
||||||
|
suspend fun retrieveTasks(
|
||||||
|
userId: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
): TaskList?
|
||||||
|
|
||||||
|
suspend fun retrieveTasks(
|
||||||
|
userId: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
dueDate: Date,
|
||||||
|
): TaskList?
|
||||||
|
|
||||||
suspend fun taskChecked(
|
suspend fun taskChecked(
|
||||||
user: User?,
|
user: User?,
|
||||||
task: Task,
|
task: Task,
|
||||||
up: Boolean,
|
up: Boolean,
|
||||||
force: Boolean,
|
force: Boolean,
|
||||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
notifyFunc: ((TaskScoringResult) -> Unit)?,
|
||||||
): TaskScoringResult?
|
): TaskScoringResult?
|
||||||
|
|
||||||
suspend fun taskChecked(
|
suspend fun taskChecked(
|
||||||
user: User?,
|
user: User?,
|
||||||
taskId: String,
|
taskId: String,
|
||||||
up: Boolean,
|
up: Boolean,
|
||||||
force: Boolean,
|
force: Boolean,
|
||||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
notifyFunc: ((TaskScoringResult) -> Unit)?,
|
||||||
): TaskScoringResult?
|
): TaskScoringResult?
|
||||||
suspend fun scoreChecklistItem(taskId: String, itemId: String): Task?
|
|
||||||
|
suspend fun scoreChecklistItem(
|
||||||
|
taskId: String,
|
||||||
|
itemId: String,
|
||||||
|
): Task?
|
||||||
|
|
||||||
fun getTask(taskId: String): Flow<Task>
|
fun getTask(taskId: String): Flow<Task>
|
||||||
|
|
||||||
fun getTaskCopy(taskId: String): Flow<Task>
|
fun getTaskCopy(taskId: String): Flow<Task>
|
||||||
suspend fun createTask(task: Task, force: Boolean = false): Task?
|
|
||||||
suspend fun updateTask(task: Task, force: Boolean = false): Task?
|
suspend fun createTask(
|
||||||
|
task: Task,
|
||||||
|
force: Boolean = false,
|
||||||
|
): Task?
|
||||||
|
|
||||||
|
suspend fun updateTask(
|
||||||
|
task: Task,
|
||||||
|
force: Boolean = false,
|
||||||
|
): Task?
|
||||||
|
|
||||||
suspend fun deleteTask(taskId: String): Void?
|
suspend fun deleteTask(taskId: String): Void?
|
||||||
|
|
||||||
fun saveTask(task: Task)
|
fun saveTask(task: Task)
|
||||||
|
|
||||||
suspend fun createTasks(newTasks: List<Task>): List<Task>?
|
suspend fun createTasks(newTasks: List<Task>): List<Task>?
|
||||||
|
|
||||||
fun markTaskCompleted(taskId: String, isCompleted: Boolean)
|
fun markTaskCompleted(
|
||||||
|
taskId: String,
|
||||||
|
isCompleted: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun <T : BaseMainObject> modify(obj: T, transaction: (T) -> Unit)
|
fun <T : BaseMainObject> modify(
|
||||||
|
obj: T,
|
||||||
|
transaction: (T) -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
fun swapTaskPosition(
|
||||||
|
firstPosition: Int,
|
||||||
|
secondPosition: Int,
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): List<String>?
|
suspend fun updateTaskPosition(
|
||||||
|
taskType: TaskType,
|
||||||
|
taskID: String,
|
||||||
|
newPosition: Int,
|
||||||
|
): List<String>?
|
||||||
|
|
||||||
fun getUnmanagedTask(taskid: String): Flow<Task>
|
fun getUnmanagedTask(taskid: String): Flow<Task>
|
||||||
|
|
||||||
fun updateTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>)
|
fun updateTaskInBackground(
|
||||||
|
task: Task,
|
||||||
|
assignChanges: Map<String, MutableList<String>>,
|
||||||
|
)
|
||||||
|
|
||||||
fun createTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>)
|
fun createTaskInBackground(
|
||||||
|
task: Task,
|
||||||
|
assignChanges: Map<String, MutableList<String>>,
|
||||||
|
)
|
||||||
|
|
||||||
fun getTaskCopies(): Flow<List<Task>>
|
fun getTaskCopies(): Flow<List<Task>>
|
||||||
|
|
||||||
fun getTaskCopies(tasks: List<Task>): List<Task>
|
fun getTaskCopies(tasks: List<Task>): List<Task>
|
||||||
|
|
||||||
suspend fun retrieveDailiesFromDate(date: Date): TaskList?
|
suspend fun retrieveDailiesFromDate(date: Date): TaskList?
|
||||||
|
|
||||||
suspend fun retrieveCompletedTodos(userId: String? = null): TaskList?
|
suspend fun retrieveCompletedTodos(userId: String? = null): TaskList?
|
||||||
|
|
||||||
suspend fun syncErroredTasks(): List<Task>?
|
suspend fun syncErroredTasks(): List<Task>?
|
||||||
suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void?
|
|
||||||
|
suspend fun unlinkAllTasks(
|
||||||
|
challengeID: String?,
|
||||||
|
keepOption: String,
|
||||||
|
): Void?
|
||||||
|
|
||||||
fun getTasksForChallenge(challengeID: String?): Flow<List<Task>>
|
fun getTasksForChallenge(challengeID: String?): Flow<List<Task>>
|
||||||
|
|
||||||
suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData?
|
suspend fun bulkScoreTasks(data: List<Map<String, String>>): BulkTaskScoringData?
|
||||||
suspend fun markTaskNeedsWork(task: Task, userID: String)
|
|
||||||
|
suspend fun markTaskNeedsWork(
|
||||||
|
task: Task,
|
||||||
|
userID: String,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import com.habitrpg.android.habitica.models.TutorialStep
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TutorialRepository : BaseRepository {
|
interface TutorialRepository : BaseRepository {
|
||||||
|
|
||||||
fun getTutorialStep(key: String): Flow<TutorialStep>
|
fun getTutorialStep(key: String): Flow<TutorialStep>
|
||||||
|
|
||||||
fun getTutorialSteps(keys: List<String>): Flow<out List<TutorialStep>>
|
fun getTutorialSteps(keys: List<String>): Flow<out List<TutorialStep>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,21 @@ import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface UserRepository : BaseRepository {
|
interface UserRepository : BaseRepository {
|
||||||
fun getUser(): Flow<User?>
|
fun getUser(): Flow<User?>
|
||||||
|
|
||||||
fun getUser(userID: String): Flow<User?>
|
fun getUser(userID: String): Flow<User?>
|
||||||
|
|
||||||
suspend fun updateUser(updateData: Map<String, Any?>): User?
|
suspend fun updateUser(updateData: Map<String, Any?>): User?
|
||||||
suspend fun updateUser(key: String, value: Any?): User?
|
|
||||||
|
|
||||||
suspend fun retrieveUser(withTasks: Boolean = false, forced: Boolean = false, overrideExisting: Boolean = false): User?
|
suspend fun updateUser(
|
||||||
|
key: String,
|
||||||
|
value: Any?,
|
||||||
|
): User?
|
||||||
|
|
||||||
|
suspend fun retrieveUser(
|
||||||
|
withTasks: Boolean = false,
|
||||||
|
forced: Boolean = false,
|
||||||
|
overrideExisting: Boolean = false,
|
||||||
|
): User?
|
||||||
|
|
||||||
suspend fun revive(): Equipment?
|
suspend fun revive(): Equipment?
|
||||||
|
|
||||||
|
|
@ -37,23 +46,40 @@ interface UserRepository : BaseRepository {
|
||||||
|
|
||||||
fun getSpecialItems(user: User): Flow<List<Skill>>
|
fun getSpecialItems(user: User): Flow<List<Skill>>
|
||||||
|
|
||||||
suspend fun useSkill(key: String, target: String?, taskId: String): SkillResponse?
|
suspend fun useSkill(
|
||||||
suspend fun useSkill(key: String, target: String?): SkillResponse?
|
key: String,
|
||||||
|
target: String?,
|
||||||
|
taskId: String,
|
||||||
|
): SkillResponse?
|
||||||
|
|
||||||
|
suspend fun useSkill(
|
||||||
|
key: String,
|
||||||
|
target: String?,
|
||||||
|
): SkillResponse?
|
||||||
|
|
||||||
suspend fun disableClasses(): User?
|
suspend fun disableClasses(): User?
|
||||||
|
|
||||||
suspend fun changeClass(selectedClass: String? = null): User?
|
suspend fun changeClass(selectedClass: String? = null): User?
|
||||||
|
|
||||||
suspend fun unlockPath(path: String, price: Int): UnlockResponse?
|
suspend fun unlockPath(
|
||||||
|
path: String,
|
||||||
|
price: Int,
|
||||||
|
): UnlockResponse?
|
||||||
|
|
||||||
suspend fun unlockPath(customization: Customization): UnlockResponse?
|
suspend fun unlockPath(customization: Customization): UnlockResponse?
|
||||||
|
|
||||||
suspend fun runCron(tasks: MutableList<Task>)
|
suspend fun runCron(tasks: MutableList<Task>)
|
||||||
|
|
||||||
suspend fun runCron()
|
suspend fun runCron()
|
||||||
|
|
||||||
suspend fun getNews(): List<Any>?
|
suspend fun getNews(): List<Any>?
|
||||||
|
|
||||||
suspend fun getNewsNotification(): Notification?
|
suspend fun getNewsNotification(): Notification?
|
||||||
|
|
||||||
suspend fun readNotification(id: String): List<Any>?
|
suspend fun readNotification(id: String): List<Any>?
|
||||||
|
|
||||||
suspend fun readNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
suspend fun readNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||||
|
|
||||||
suspend fun seeNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
suspend fun seeNotifications(notificationIds: Map<String, List<String>>): List<Any>?
|
||||||
|
|
||||||
suspend fun changeCustomDayStart(dayStartTime: Int): User?
|
suspend fun changeCustomDayStart(dayStartTime: Int): User?
|
||||||
|
|
@ -61,29 +87,61 @@ interface UserRepository : BaseRepository {
|
||||||
suspend fun updateLanguage(languageCode: String): User?
|
suspend fun updateLanguage(languageCode: String): User?
|
||||||
|
|
||||||
suspend fun resetAccount(password: String): User?
|
suspend fun resetAccount(password: String): User?
|
||||||
|
|
||||||
suspend fun deleteAccount(password: String): Void?
|
suspend fun deleteAccount(password: String): Void?
|
||||||
|
|
||||||
suspend fun sendPasswordResetEmail(email: String): Void?
|
suspend fun sendPasswordResetEmail(email: String): Void?
|
||||||
|
|
||||||
suspend fun updateLoginName(newLoginName: String, password: String? = null): User?
|
suspend fun updateLoginName(
|
||||||
suspend fun updateEmail(newEmail: String, password: String): Void?
|
newLoginName: String,
|
||||||
suspend fun updatePassword(oldPassword: String, newPassword: String, newPasswordConfirmation: String): Void?
|
password: String? = null,
|
||||||
|
): User?
|
||||||
|
|
||||||
|
suspend fun updateEmail(
|
||||||
|
newEmail: String,
|
||||||
|
password: String,
|
||||||
|
): Void?
|
||||||
|
|
||||||
|
suspend fun updatePassword(
|
||||||
|
oldPassword: String,
|
||||||
|
newPassword: String,
|
||||||
|
newPasswordConfirmation: String,
|
||||||
|
): Void?
|
||||||
|
|
||||||
suspend fun verifyUsername(username: String): VerifyUsernameResponse?
|
suspend fun verifyUsername(username: String): VerifyUsernameResponse?
|
||||||
|
|
||||||
suspend fun allocatePoint(stat: Attribute): Stats?
|
suspend fun allocatePoint(stat: Attribute): Stats?
|
||||||
suspend fun bulkAllocatePoints(strength: Int, intelligence: Int, constitution: Int, perception: Int): Stats?
|
|
||||||
|
|
||||||
suspend fun useCustomization(type: String, category: String?, identifier: String): User?
|
suspend fun bulkAllocatePoints(
|
||||||
|
strength: Int,
|
||||||
|
intelligence: Int,
|
||||||
|
constitution: Int,
|
||||||
|
perception: Int,
|
||||||
|
): Stats?
|
||||||
|
|
||||||
|
suspend fun useCustomization(
|
||||||
|
type: String,
|
||||||
|
category: String?,
|
||||||
|
identifier: String,
|
||||||
|
): User?
|
||||||
|
|
||||||
suspend fun retrieveAchievements(): List<Achievement>?
|
suspend fun retrieveAchievements(): List<Achievement>?
|
||||||
|
|
||||||
fun getAchievements(): Flow<List<Achievement>>
|
fun getAchievements(): Flow<List<Achievement>>
|
||||||
|
|
||||||
fun getQuestAchievements(): Flow<List<QuestAchievement>>
|
fun getQuestAchievements(): Flow<List<QuestAchievement>>
|
||||||
|
|
||||||
fun getUserQuestStatus(): Flow<UserQuestStatus>
|
fun getUserQuestStatus(): Flow<UserQuestStatus>
|
||||||
|
|
||||||
suspend fun reroll(): User?
|
suspend fun reroll(): User?
|
||||||
|
|
||||||
suspend fun retrieveTeamPlans(): List<TeamPlan>?
|
suspend fun retrieveTeamPlans(): List<TeamPlan>?
|
||||||
|
|
||||||
fun getTeamPlans(): Flow<List<TeamPlan>>
|
fun getTeamPlans(): Flow<List<TeamPlan>>
|
||||||
|
|
||||||
suspend fun retrieveTeamPlan(teamID: String): Group?
|
suspend fun retrieveTeamPlan(teamID: String): Group?
|
||||||
|
|
||||||
fun getTeamPlan(teamID: String): Flow<Group?>
|
fun getTeamPlan(teamID: String): Flow<Group?>
|
||||||
|
|
||||||
suspend fun syncUserStats(): User?
|
suspend fun syncUserStats(): User?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,8 @@ class ApiClientImpl(
|
||||||
private val converter: Converter.Factory,
|
private val converter: Converter.Factory,
|
||||||
override val hostConfig: HostConfig,
|
override val hostConfig: HostConfig,
|
||||||
private val notificationsManager: NotificationsManager,
|
private val notificationsManager: NotificationsManager,
|
||||||
private val context: Context
|
private val context: Context,
|
||||||
) : ApiClient {
|
) : ApiClient {
|
||||||
|
|
||||||
private lateinit var retrofitAdapter: Retrofit
|
private lateinit var retrofitAdapter: Retrofit
|
||||||
|
|
||||||
// I think we don't need the ApiClientImpl anymore we could just use ApiService
|
// I think we don't need the ApiClientImpl anymore we could just use ApiService
|
||||||
|
|
@ -114,26 +113,30 @@ class ApiClientImpl(
|
||||||
|
|
||||||
val calendar = GregorianCalendar()
|
val calendar = GregorianCalendar()
|
||||||
val timeZone = calendar.timeZone
|
val timeZone = calendar.timeZone
|
||||||
val timezoneOffset = -TimeUnit.MINUTES.convert(
|
val timezoneOffset =
|
||||||
|
-TimeUnit.MINUTES.convert(
|
||||||
timeZone.getOffset(calendar.timeInMillis).toLong(),
|
timeZone.getOffset(calendar.timeInMillis).toLong(),
|
||||||
TimeUnit.MILLISECONDS
|
TimeUnit.MILLISECONDS,
|
||||||
)
|
)
|
||||||
|
|
||||||
val cacheSize: Long = 10 * 1024 * 1024 // 10 MB
|
val cacheSize: Long = 10 * 1024 * 1024 // 10 MB
|
||||||
|
|
||||||
val cache = Cache(File(context.cacheDir, "http_cache"), cacheSize)
|
val cache = Cache(File(context.cacheDir, "http_cache"), cacheSize)
|
||||||
|
|
||||||
val client = OkHttpClient.Builder()
|
val client =
|
||||||
|
OkHttpClient.Builder()
|
||||||
.cache(cache)
|
.cache(cache)
|
||||||
.addNetworkInterceptor { chain ->
|
.addNetworkInterceptor { chain ->
|
||||||
val original = chain.request()
|
val original = chain.request()
|
||||||
var builder: Request.Builder = original.newBuilder()
|
var builder: Request.Builder = original.newBuilder()
|
||||||
if (this.hostConfig.hasAuthentication()) {
|
if (this.hostConfig.hasAuthentication()) {
|
||||||
builder = builder
|
builder =
|
||||||
|
builder
|
||||||
.header("x-api-key", this.hostConfig.apiKey)
|
.header("x-api-key", this.hostConfig.apiKey)
|
||||||
.header("x-api-user", this.hostConfig.userID)
|
.header("x-api-user", this.hostConfig.userID)
|
||||||
}
|
}
|
||||||
builder = builder.header("x-client", "habitica-android")
|
builder =
|
||||||
|
builder.header("x-client", "habitica-android")
|
||||||
.header("x-user-timezoneOffset", timezoneOffset.toString())
|
.header("x-user-timezoneOffset", timezoneOffset.toString())
|
||||||
if (userAgent != null) {
|
if (userAgent != null) {
|
||||||
builder = builder.header("user-agent", userAgent)
|
builder = builder.header("user-agent", userAgent)
|
||||||
|
|
@ -141,7 +144,8 @@ class ApiClientImpl(
|
||||||
if (BuildConfig.STAGING_KEY.isNotEmpty()) {
|
if (BuildConfig.STAGING_KEY.isNotEmpty()) {
|
||||||
builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY)
|
builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY)
|
||||||
}
|
}
|
||||||
val request = builder.method(original.method, original.body)
|
val request =
|
||||||
|
builder.method(original.method, original.body)
|
||||||
.build()
|
.build()
|
||||||
lastAPICallURL = original.url.toString()
|
lastAPICallURL = original.url.toString()
|
||||||
val response = chain.proceed(request)
|
val response = chain.proceed(request)
|
||||||
|
|
@ -175,7 +179,8 @@ class ApiClientImpl(
|
||||||
|
|
||||||
val server = Server(this.hostConfig.address)
|
val server = Server(this.hostConfig.address)
|
||||||
|
|
||||||
retrofitAdapter = Retrofit.Builder()
|
retrofitAdapter =
|
||||||
|
Retrofit.Builder()
|
||||||
.client(client)
|
.client(client)
|
||||||
.baseUrl(server.toString())
|
.baseUrl(server.toString())
|
||||||
.addConverterFactory(converter)
|
.addConverterFactory(converter)
|
||||||
|
|
@ -195,7 +200,7 @@ class ApiClientImpl(
|
||||||
username: String,
|
username: String,
|
||||||
email: String,
|
email: String,
|
||||||
password: String,
|
password: String,
|
||||||
confirmPassword: String
|
confirmPassword: String,
|
||||||
): UserAuthResponse? {
|
): UserAuthResponse? {
|
||||||
val auth = UserAuth()
|
val auth = UserAuth()
|
||||||
auth.username = username
|
auth.username = username
|
||||||
|
|
@ -205,7 +210,10 @@ class ApiClientImpl(
|
||||||
return process { this.apiService.registerUser(auth) }
|
return process { this.apiService.registerUser(auth) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun connectUser(username: String, password: String): UserAuthResponse? {
|
override suspend fun connectUser(
|
||||||
|
username: String,
|
||||||
|
password: String,
|
||||||
|
): UserAuthResponse? {
|
||||||
val auth = UserAuth()
|
val auth = UserAuth()
|
||||||
auth.username = username
|
auth.username = username
|
||||||
auth.password = password
|
auth.password = password
|
||||||
|
|
@ -215,7 +223,7 @@ class ApiClientImpl(
|
||||||
override suspend fun connectSocial(
|
override suspend fun connectSocial(
|
||||||
network: String,
|
network: String,
|
||||||
userId: String,
|
userId: String,
|
||||||
accessToken: String
|
accessToken: String,
|
||||||
): UserAuthResponse? {
|
): UserAuthResponse? {
|
||||||
val auth = UserAuthSocial()
|
val auth = UserAuthSocial()
|
||||||
auth.network = network
|
auth.network = network
|
||||||
|
|
@ -243,14 +251,14 @@ class ApiClientImpl(
|
||||||
|
|
||||||
var isUserInputCall = false
|
var isUserInputCall = false
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
if (SocketException::class.java.isAssignableFrom(throwableClass)
|
if (SocketException::class.java.isAssignableFrom(throwableClass) ||
|
||||||
|| SSLException::class.java.isAssignableFrom(throwableClass)
|
SSLException::class.java.isAssignableFrom(throwableClass)
|
||||||
) {
|
) {
|
||||||
this.showConnectionProblemDialog(R.string.internal_error_api, isUserInputCall)
|
this.showConnectionProblemDialog(R.string.internal_error_api, isUserInputCall)
|
||||||
} else if (throwableClass == SocketTimeoutException::class.java || UnknownHostException::class.java == throwableClass || IOException::class.java == throwableClass) {
|
} else if (throwableClass == SocketTimeoutException::class.java || UnknownHostException::class.java == throwableClass || IOException::class.java == throwableClass) {
|
||||||
this.showConnectionProblemDialog(
|
this.showConnectionProblemDialog(
|
||||||
R.string.network_error_no_network_body,
|
R.string.network_error_no_network_body,
|
||||||
isUserInputCall
|
isUserInputCall,
|
||||||
)
|
)
|
||||||
} else if (HttpException::class.java.isAssignableFrom(throwable.javaClass)) {
|
} else if (HttpException::class.java.isAssignableFrom(throwable.javaClass)) {
|
||||||
val error = throwable as HttpException
|
val error = throwable as HttpException
|
||||||
|
|
@ -258,7 +266,8 @@ class ApiClientImpl(
|
||||||
val status = error.code()
|
val status = error.code()
|
||||||
val requestUrl = error.response()?.raw()?.request?.url
|
val requestUrl = error.response()?.raw()?.request?.url
|
||||||
val path = requestUrl?.encodedPath?.removePrefix("/api/v4") ?: ""
|
val path = requestUrl?.encodedPath?.removePrefix("/api/v4") ?: ""
|
||||||
isUserInputCall = when {
|
isUserInputCall =
|
||||||
|
when {
|
||||||
path.startsWith("/groups") && path.endsWith("invite") -> true
|
path.startsWith("/groups") && path.endsWith("invite") -> true
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
@ -278,7 +287,7 @@ class ApiClientImpl(
|
||||||
showConnectionProblemDialog(
|
showConnectionProblemDialog(
|
||||||
R.string.authentication_error_title,
|
R.string.authentication_error_title,
|
||||||
R.string.authentication_error_body,
|
R.string.authentication_error_body,
|
||||||
isUserInputCall
|
isUserInputCall,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (status in 500..599) {
|
} else if (status in 500..599) {
|
||||||
|
|
@ -295,14 +304,15 @@ class ApiClientImpl(
|
||||||
|
|
||||||
override suspend fun updateMember(
|
override suspend fun updateMember(
|
||||||
memberID: String,
|
memberID: String,
|
||||||
updateData: Map<String, Map<String, Boolean>>
|
updateData: Map<String, Map<String, Boolean>>,
|
||||||
): Member? {
|
): Member? {
|
||||||
return process { apiService.updateUser(memberID, updateData) }
|
return process { apiService.updateUser(memberID, updateData) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getErrorResponse(throwable: HttpException): ErrorResponse {
|
override fun getErrorResponse(throwable: HttpException): ErrorResponse {
|
||||||
val errorResponse = throwable.response()?.errorBody() ?: return ErrorResponse()
|
val errorResponse = throwable.response()?.errorBody() ?: return ErrorResponse()
|
||||||
val errorConverter = converter
|
val errorConverter =
|
||||||
|
converter
|
||||||
.responseBodyConverter(ErrorResponse::class.java, arrayOfNulls(0), retrofitAdapter)
|
.responseBodyConverter(ErrorResponse::class.java, arrayOfNulls(0), retrofitAdapter)
|
||||||
return try {
|
return try {
|
||||||
errorConverter?.convert(errorResponse) as ErrorResponse
|
errorConverter?.convert(errorResponse) as ErrorResponse
|
||||||
|
|
@ -319,7 +329,10 @@ class ApiClientImpl(
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>? {
|
override suspend fun retrieveInboxMessages(
|
||||||
|
uuid: String,
|
||||||
|
page: Int,
|
||||||
|
): List<ChatMessage>? {
|
||||||
return process { apiService.getInboxMessages(uuid, page) }
|
return process { apiService.getInboxMessages(uuid, page) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,7 +346,7 @@ class ApiClientImpl(
|
||||||
|
|
||||||
private fun showConnectionProblemDialog(
|
private fun showConnectionProblemDialog(
|
||||||
resourceMessageString: Int,
|
resourceMessageString: Int,
|
||||||
isFromUserInput: Boolean
|
isFromUserInput: Boolean,
|
||||||
) {
|
) {
|
||||||
showConnectionProblemDialog(null, context.getString(resourceMessageString), isFromUserInput)
|
showConnectionProblemDialog(null, context.getString(resourceMessageString), isFromUserInput)
|
||||||
}
|
}
|
||||||
|
|
@ -341,37 +354,40 @@ class ApiClientImpl(
|
||||||
private fun showConnectionProblemDialog(
|
private fun showConnectionProblemDialog(
|
||||||
resourceTitleString: Int,
|
resourceTitleString: Int,
|
||||||
resourceMessageString: Int,
|
resourceMessageString: Int,
|
||||||
isFromUserInput: Boolean
|
isFromUserInput: Boolean,
|
||||||
) {
|
) {
|
||||||
showConnectionProblemDialog(
|
showConnectionProblemDialog(
|
||||||
context.getString(resourceTitleString),
|
context.getString(resourceTitleString),
|
||||||
context.getString(resourceMessageString),
|
context.getString(resourceMessageString),
|
||||||
isFromUserInput
|
isFromUserInput,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var erroredRequestCount = 0
|
private var erroredRequestCount = 0
|
||||||
|
|
||||||
private fun showConnectionProblemDialog(
|
private fun showConnectionProblemDialog(
|
||||||
resourceTitleString: String?,
|
resourceTitleString: String?,
|
||||||
resourceMessageString: String,
|
resourceMessageString: String,
|
||||||
isFromUserInput: Boolean
|
isFromUserInput: Boolean,
|
||||||
) {
|
) {
|
||||||
erroredRequestCount += 1
|
erroredRequestCount += 1
|
||||||
val application = (context as? HabiticaBaseApplication)
|
val application =
|
||||||
|
(context as? HabiticaBaseApplication)
|
||||||
?: (context.applicationContext as? HabiticaBaseApplication)
|
?: (context.applicationContext as? HabiticaBaseApplication)
|
||||||
application?.currentActivity?.get()
|
application?.currentActivity?.get()
|
||||||
?.showConnectionProblem(
|
?.showConnectionProblem(
|
||||||
erroredRequestCount,
|
erroredRequestCount,
|
||||||
resourceTitleString,
|
resourceTitleString,
|
||||||
resourceMessageString,
|
resourceMessageString,
|
||||||
isFromUserInput
|
isFromUserInput,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideConnectionProblemDialog() {
|
private fun hideConnectionProblemDialog() {
|
||||||
if (erroredRequestCount == 0) return
|
if (erroredRequestCount == 0) return
|
||||||
erroredRequestCount = 0
|
erroredRequestCount = 0
|
||||||
val application = (context as? HabiticaBaseApplication)
|
val application =
|
||||||
|
(context as? HabiticaBaseApplication)
|
||||||
?: (context.applicationContext as? HabiticaBaseApplication)
|
?: (context.applicationContext as? HabiticaBaseApplication)
|
||||||
application?.currentActivity?.get()
|
application?.currentActivity?.get()
|
||||||
?.hideConnectionProblem()
|
?.hideConnectionProblem()
|
||||||
|
|
@ -382,7 +398,10 @@ class ApiClientImpl(
|
||||||
See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/
|
See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
override fun updateAuthenticationCredentials(userID: String?, apiToken: String?) {
|
override fun updateAuthenticationCredentials(
|
||||||
|
userID: String?,
|
||||||
|
apiToken: String?,
|
||||||
|
) {
|
||||||
this.hostConfig.userID = userID ?: ""
|
this.hostConfig.userID = userID ?: ""
|
||||||
this.hostConfig.apiKey = apiToken ?: ""
|
this.hostConfig.apiKey = apiToken ?: ""
|
||||||
Analytics.setUserID(hostConfig.userID)
|
Analytics.setUserID(hostConfig.userID)
|
||||||
|
|
@ -391,9 +410,10 @@ class ApiClientImpl(
|
||||||
override suspend fun getStatus(): Status? = process { apiService.getStatus() }
|
override suspend fun getStatus(): Status? = process { apiService.getStatus() }
|
||||||
|
|
||||||
override suspend fun syncUserStats(): User? = process { apiService.syncUserStats() }
|
override suspend fun syncUserStats(): User? = process { apiService.syncUserStats() }
|
||||||
|
|
||||||
override suspend fun reportChallenge(
|
override suspend fun reportChallenge(
|
||||||
challengeid: String,
|
challengeid: String,
|
||||||
updateData: Map<String, String>
|
updateData: Map<String, String>,
|
||||||
): Void? {
|
): Void? {
|
||||||
return process { apiService.reportChallenge(challengeid, updateData) }
|
return process { apiService.reportChallenge(challengeid, updateData) }
|
||||||
}
|
}
|
||||||
|
|
@ -414,15 +434,24 @@ class ApiClientImpl(
|
||||||
return process { apiService.retrieveInAppRewards() }
|
return process { apiService.retrieveInAppRewards() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun equipItem(type: String, itemKey: String): Items? {
|
override suspend fun equipItem(
|
||||||
|
type: String,
|
||||||
|
itemKey: String,
|
||||||
|
): Items? {
|
||||||
return process { apiService.equipItem(type, itemKey) }
|
return process { apiService.equipItem(type, itemKey) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun buyItem(itemKey: String, purchaseQuantity: Int): BuyResponse? {
|
override suspend fun buyItem(
|
||||||
|
itemKey: String,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): BuyResponse? {
|
||||||
return process { apiService.buyItem(itemKey, mapOf(Pair("quantity", purchaseQuantity))) }
|
return process { apiService.buyItem(itemKey, mapOf(Pair("quantity", purchaseQuantity))) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void? {
|
override suspend fun unlinkAllTasks(
|
||||||
|
challengeID: String?,
|
||||||
|
keepOption: String,
|
||||||
|
): Void? {
|
||||||
return process { apiService.unlinkAllTasks(challengeID, keepOption) }
|
return process { apiService.unlinkAllTasks(challengeID, keepOption) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -430,17 +459,22 @@ class ApiClientImpl(
|
||||||
return process { apiService.blockMember(userID) }
|
return process { apiService.blockMember(userID) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun purchaseItem(type: String, itemKey: String, purchaseQuantity: Int): Void? {
|
override suspend fun purchaseItem(
|
||||||
|
type: String,
|
||||||
|
itemKey: String,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): Void? {
|
||||||
return process {
|
return process {
|
||||||
apiService.purchaseItem(
|
apiService.purchaseItem(
|
||||||
type,
|
type,
|
||||||
itemKey,
|
itemKey,
|
||||||
mapOf(Pair("quantity", purchaseQuantity))
|
mapOf(Pair("quantity", purchaseQuantity)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastSubscribeCall: Date? = null
|
val lastSubscribeCall: Date? = null
|
||||||
|
|
||||||
override suspend fun validateSubscription(request: PurchaseValidationRequest): Any? {
|
override suspend fun validateSubscription(request: PurchaseValidationRequest): Any? {
|
||||||
return if (lastSubscribeCall == null || Date().time - lastSubscribeCall.time > 60000) {
|
return if (lastSubscribeCall == null || Date().time - lastSubscribeCall.time > 60000) {
|
||||||
process { apiService.validateSubscription(request) }
|
process { apiService.validateSubscription(request) }
|
||||||
|
|
@ -461,7 +495,10 @@ class ApiClientImpl(
|
||||||
return processResponse(apiService.cancelSubscription())
|
return processResponse(apiService.cancelSubscription())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun purchaseHourglassItem(type: String, itemKey: String): Void? {
|
override suspend fun purchaseHourglassItem(
|
||||||
|
type: String,
|
||||||
|
itemKey: String,
|
||||||
|
): Void? {
|
||||||
return process { apiService.purchaseHourglassItem(type, itemKey) }
|
return process { apiService.purchaseHourglassItem(type, itemKey) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -477,17 +514,26 @@ class ApiClientImpl(
|
||||||
return process { apiService.purchaseSpecialSpell(key) }
|
return process { apiService.purchaseSpecialSpell(key) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sellItem(itemType: String, itemKey: String): User? {
|
override suspend fun sellItem(
|
||||||
|
itemType: String,
|
||||||
|
itemKey: String,
|
||||||
|
): User? {
|
||||||
return process { apiService.sellItem(itemType, itemKey) }
|
return process { apiService.sellItem(itemType, itemKey) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun feedPet(petKey: String, foodKey: String): FeedResponse? {
|
override suspend fun feedPet(
|
||||||
|
petKey: String,
|
||||||
|
foodKey: String,
|
||||||
|
): FeedResponse? {
|
||||||
val response = apiService.feedPet(petKey, foodKey)
|
val response = apiService.feedPet(petKey, foodKey)
|
||||||
response.data?.message = response.message
|
response.data?.message = response.message
|
||||||
return process { response }
|
return process { response }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun hatchPet(eggKey: String, hatchingPotionKey: String): Items? {
|
override suspend fun hatchPet(
|
||||||
|
eggKey: String,
|
||||||
|
hatchingPotionKey: String,
|
||||||
|
): Items? {
|
||||||
return process { apiService.hatchPet(eggKey, hatchingPotionKey) }
|
return process { apiService.hatchPet(eggKey, hatchingPotionKey) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -497,7 +543,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.getTasks(type) }
|
return process { apiService.getTasks(type) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getTasks(type: String, dueDate: String): TaskList? {
|
override suspend fun getTasks(
|
||||||
|
type: String,
|
||||||
|
dueDate: String,
|
||||||
|
): TaskList? {
|
||||||
return process { apiService.getTasks(type, dueDate) }
|
return process { apiService.getTasks(type, dueDate) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,7 +562,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.getTask(id) }
|
return process { apiService.getTask(id) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postTaskDirection(id: String, direction: String): TaskDirectionData? {
|
override suspend fun postTaskDirection(
|
||||||
|
id: String,
|
||||||
|
direction: String,
|
||||||
|
): TaskDirectionData? {
|
||||||
return process { apiService.postTaskDirection(id, direction) }
|
return process { apiService.postTaskDirection(id, direction) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -521,11 +573,17 @@ class ApiClientImpl(
|
||||||
return process { apiService.bulkScoreTasks(data) }
|
return process { apiService.bulkScoreTasks(data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postTaskNewPosition(id: String, position: Int): List<String>? {
|
override suspend fun postTaskNewPosition(
|
||||||
|
id: String,
|
||||||
|
position: Int,
|
||||||
|
): List<String>? {
|
||||||
return process { apiService.postTaskNewPosition(id, position) }
|
return process { apiService.postTaskNewPosition(id, position) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun scoreChecklistItem(taskId: String, itemId: String): Task? {
|
override suspend fun scoreChecklistItem(
|
||||||
|
taskId: String,
|
||||||
|
itemId: String,
|
||||||
|
): Task? {
|
||||||
return process { apiService.scoreChecklistItem(taskId, itemId) }
|
return process { apiService.scoreChecklistItem(taskId, itemId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,7 +591,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.createTask(item) }
|
return process { apiService.createTask(item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createGroupTask(groupId: String, item: Task): Task? {
|
override suspend fun createGroupTask(
|
||||||
|
groupId: String,
|
||||||
|
item: Task,
|
||||||
|
): Task? {
|
||||||
return process { apiService.createGroupTask(groupId, item) }
|
return process { apiService.createGroupTask(groupId, item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,7 +602,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.createTasks(tasks) }
|
return process { apiService.createTasks(tasks) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateTask(id: String, item: Task): Task? {
|
override suspend fun updateTask(
|
||||||
|
id: String,
|
||||||
|
item: Task,
|
||||||
|
): Task? {
|
||||||
return process { apiService.updateTask(id, item) }
|
return process { apiService.updateTask(id, item) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,7 +617,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.createTag(tag) }
|
return process { apiService.createTag(tag) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateTag(id: String, tag: Tag): Tag? {
|
override suspend fun updateTag(
|
||||||
|
id: String,
|
||||||
|
tag: Tag,
|
||||||
|
): Tag? {
|
||||||
return process { apiService.updateTag(id, tag) }
|
return process { apiService.updateTag(id, tag) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -568,12 +635,15 @@ class ApiClientImpl(
|
||||||
override suspend fun useSkill(
|
override suspend fun useSkill(
|
||||||
skillName: String,
|
skillName: String,
|
||||||
targetType: String,
|
targetType: String,
|
||||||
targetId: String
|
targetId: String,
|
||||||
): SkillResponse? {
|
): SkillResponse? {
|
||||||
return process { apiService.useSkill(skillName, targetType, targetId) }
|
return process { apiService.useSkill(skillName, targetType, targetId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun useSkill(skillName: String, targetType: String): SkillResponse? {
|
override suspend fun useSkill(
|
||||||
|
skillName: String,
|
||||||
|
targetType: String,
|
||||||
|
): SkillResponse? {
|
||||||
return process { apiService.useSkill(skillName, targetType) }
|
return process { apiService.useSkill(skillName, targetType) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,11 +675,17 @@ class ApiClientImpl(
|
||||||
return processResponse(apiService.createGroup(group))
|
return processResponse(apiService.createGroup(group))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateGroup(id: String, item: Group): Group? {
|
override suspend fun updateGroup(
|
||||||
|
id: String,
|
||||||
|
item: Group,
|
||||||
|
): Group? {
|
||||||
return processResponse(apiService.updateGroup(id, item))
|
return processResponse(apiService.updateGroup(id, item))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun removeMemberFromGroup(groupID: String, userID: String): Void? {
|
override suspend fun removeMemberFromGroup(
|
||||||
|
groupID: String,
|
||||||
|
userID: String,
|
||||||
|
): Void? {
|
||||||
return processResponse(apiService.removeMemberFromGroup(groupID, userID))
|
return processResponse(apiService.removeMemberFromGroup(groupID, userID))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -621,18 +697,24 @@ class ApiClientImpl(
|
||||||
return processResponse(apiService.joinGroup(groupId))
|
return processResponse(apiService.joinGroup(groupId))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun leaveGroup(groupId: String, keepChallenges: String): Void? {
|
override suspend fun leaveGroup(
|
||||||
|
groupId: String,
|
||||||
|
keepChallenges: String,
|
||||||
|
): Void? {
|
||||||
return processResponse(apiService.leaveGroup(groupId, keepChallenges))
|
return processResponse(apiService.leaveGroup(groupId, keepChallenges))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postGroupChat(
|
override suspend fun postGroupChat(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
message: Map<String, String>
|
message: Map<String, String>,
|
||||||
): PostChatMessageResult? {
|
): PostChatMessageResult? {
|
||||||
return process { apiService.postGroupChat(groupId, message) }
|
return process { apiService.postGroupChat(groupId, message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteMessage(groupId: String, messageId: String): Void? {
|
override suspend fun deleteMessage(
|
||||||
|
groupId: String,
|
||||||
|
messageId: String,
|
||||||
|
): Void? {
|
||||||
return process { apiService.deleteMessage(groupId, messageId) }
|
return process { apiService.deleteMessage(groupId, messageId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -642,7 +724,7 @@ class ApiClientImpl(
|
||||||
|
|
||||||
override suspend fun getGroupMembers(
|
override suspend fun getGroupMembers(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
includeAllPublicFields: Boolean?
|
includeAllPublicFields: Boolean?,
|
||||||
): List<Member>? {
|
): List<Member>? {
|
||||||
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields))
|
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields))
|
||||||
}
|
}
|
||||||
|
|
@ -650,28 +732,37 @@ class ApiClientImpl(
|
||||||
override suspend fun getGroupMembers(
|
override suspend fun getGroupMembers(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
includeAllPublicFields: Boolean?,
|
includeAllPublicFields: Boolean?,
|
||||||
lastId: String
|
lastId: String,
|
||||||
): List<Member>? {
|
): List<Member>? {
|
||||||
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields, lastId))
|
return processResponse(apiService.getGroupMembers(groupId, includeAllPublicFields, lastId))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun likeMessage(groupId: String, mid: String): ChatMessage? {
|
override suspend fun likeMessage(
|
||||||
|
groupId: String,
|
||||||
|
mid: String,
|
||||||
|
): ChatMessage? {
|
||||||
return process { apiService.likeMessage(groupId, mid) }
|
return process { apiService.likeMessage(groupId, mid) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun reportMember(mid: String, data: Map<String, String>): Void? {
|
override suspend fun reportMember(
|
||||||
|
mid: String,
|
||||||
|
data: Map<String, String>,
|
||||||
|
): Void? {
|
||||||
return process { apiService.reportMember(mid, data) }
|
return process { apiService.reportMember(mid, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun flagMessage(
|
override suspend fun flagMessage(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
mid: String,
|
mid: String,
|
||||||
data: MutableMap<String, String>
|
data: MutableMap<String, String>,
|
||||||
): Void? {
|
): Void? {
|
||||||
return process { apiService.flagMessage(groupId, mid, data) }
|
return process { apiService.flagMessage(groupId, mid, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun flagInboxMessage(mid: String, data: MutableMap<String, String>): Void? {
|
override suspend fun flagInboxMessage(
|
||||||
|
mid: String,
|
||||||
|
data: MutableMap<String, String>,
|
||||||
|
): Void? {
|
||||||
return process { apiService.flagInboxMessage(mid, data) }
|
return process { apiService.flagInboxMessage(mid, data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -681,7 +772,7 @@ class ApiClientImpl(
|
||||||
|
|
||||||
override suspend fun inviteToGroup(
|
override suspend fun inviteToGroup(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
inviteData: Map<String, Any>
|
inviteData: Map<String, Any>,
|
||||||
): List<InviteResponse>? {
|
): List<InviteResponse>? {
|
||||||
return process { apiService.inviteToGroup(groupId, inviteData) }
|
return process { apiService.inviteToGroup(groupId, inviteData) }
|
||||||
}
|
}
|
||||||
|
|
@ -692,7 +783,7 @@ class ApiClientImpl(
|
||||||
|
|
||||||
override suspend fun getGroupInvites(
|
override suspend fun getGroupInvites(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
includeAllPublicFields: Boolean?
|
includeAllPublicFields: Boolean?,
|
||||||
): List<Member>? {
|
): List<Member>? {
|
||||||
return process { apiService.getGroupInvites(groupId, includeAllPublicFields) }
|
return process { apiService.getGroupInvites(groupId, includeAllPublicFields) }
|
||||||
}
|
}
|
||||||
|
|
@ -709,11 +800,17 @@ class ApiClientImpl(
|
||||||
return process { apiService.cancelQuest(groupId) }
|
return process { apiService.cancelQuest(groupId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun forceStartQuest(groupId: String, group: Group): Quest? {
|
override suspend fun forceStartQuest(
|
||||||
|
groupId: String,
|
||||||
|
group: Group,
|
||||||
|
): Quest? {
|
||||||
return process { apiService.forceStartQuest(groupId, group) }
|
return process { apiService.forceStartQuest(groupId, group) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun inviteToQuest(groupId: String, questKey: String): Quest? {
|
override suspend fun inviteToQuest(
|
||||||
|
groupId: String,
|
||||||
|
questKey: String,
|
||||||
|
): Quest? {
|
||||||
return process { apiService.inviteToQuest(groupId, questKey) }
|
return process { apiService.inviteToQuest(groupId, questKey) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -726,6 +823,7 @@ class ApiClientImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
private val lastPurchaseValidation: Date? = null
|
private val lastPurchaseValidation: Date? = null
|
||||||
|
|
||||||
override suspend fun validatePurchase(request: PurchaseValidationRequest): PurchaseValidationResult? {
|
override suspend fun validatePurchase(request: PurchaseValidationRequest): PurchaseValidationResult? {
|
||||||
// make sure a purchase attempt doesn't happen
|
// make sure a purchase attempt doesn't happen
|
||||||
return if (lastPurchaseValidation == null || Date().time - lastPurchaseValidation.time > 5000) {
|
return if (lastPurchaseValidation == null || Date().time - lastPurchaseValidation.time > 5000) {
|
||||||
|
|
@ -739,7 +837,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.changeCustomDayStart(updateObject) }
|
return process { apiService.changeCustomDayStart(updateObject) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun markTaskNeedsWork(taskID: String, userID: String): Task? {
|
override suspend fun markTaskNeedsWork(
|
||||||
|
taskID: String,
|
||||||
|
userID: String,
|
||||||
|
): Task? {
|
||||||
return process { apiService.markTaskNeedsWork(taskID, userID) }
|
return process { apiService.markTaskNeedsWork(taskID, userID) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -760,7 +861,7 @@ class ApiClientImpl(
|
||||||
override suspend fun findUsernames(
|
override suspend fun findUsernames(
|
||||||
username: String,
|
username: String,
|
||||||
context: String?,
|
context: String?,
|
||||||
id: String?
|
id: String?,
|
||||||
): List<FindUsernameResult>? {
|
): List<FindUsernameResult>? {
|
||||||
return process { apiService.findUsernames(username, context, id) }
|
return process { apiService.findUsernames(username, context, id) }
|
||||||
}
|
}
|
||||||
|
|
@ -781,7 +882,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.deletePushDevice(regId) }
|
return process { apiService.deletePushDevice(regId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getUserChallenges(page: Int, memberOnly: Boolean): List<Challenge>? {
|
override suspend fun getUserChallenges(
|
||||||
|
page: Int,
|
||||||
|
memberOnly: Boolean,
|
||||||
|
): List<Challenge>? {
|
||||||
return if (memberOnly) {
|
return if (memberOnly) {
|
||||||
process { apiService.getUserChallenges(page, memberOnly) }
|
process { apiService.getUserChallenges(page, memberOnly) }
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -801,7 +905,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.joinChallenge(challengeId) }
|
return process { apiService.joinChallenge(challengeId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun leaveChallenge(challengeId: String, body: LeaveChallengeBody): Void? {
|
override suspend fun leaveChallenge(
|
||||||
|
challengeId: String,
|
||||||
|
body: LeaveChallengeBody,
|
||||||
|
): Void? {
|
||||||
return process { apiService.leaveChallenge(challengeId, body) }
|
return process { apiService.leaveChallenge(challengeId, body) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -809,11 +916,17 @@ class ApiClientImpl(
|
||||||
return process { apiService.createChallenge(challenge) }
|
return process { apiService.createChallenge(challenge) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createChallengeTasks(challengeId: String, tasks: List<Task>): List<Task>? {
|
override suspend fun createChallengeTasks(
|
||||||
|
challengeId: String,
|
||||||
|
tasks: List<Task>,
|
||||||
|
): List<Task>? {
|
||||||
return process { apiService.createChallengeTasks(challengeId, tasks) }
|
return process { apiService.createChallengeTasks(challengeId, tasks) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createChallengeTask(challengeId: String, task: Task): Task? {
|
override suspend fun createChallengeTask(
|
||||||
|
challengeId: String,
|
||||||
|
task: Task,
|
||||||
|
): Task? {
|
||||||
return process { apiService.createChallengeTask(challengeId, task) }
|
return process { apiService.createChallengeTask(challengeId, task) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -867,7 +980,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.deleteAccount(updateObject) }
|
return process { apiService.deleteAccount(updateObject) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun togglePinnedItem(pinType: String, path: String): Void? {
|
override suspend fun togglePinnedItem(
|
||||||
|
pinType: String,
|
||||||
|
path: String,
|
||||||
|
): Void? {
|
||||||
return process { apiService.togglePinnedItem(pinType, path) }
|
return process { apiService.togglePinnedItem(pinType, path) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -877,7 +993,10 @@ class ApiClientImpl(
|
||||||
return process { apiService.sendPasswordResetEmail(data) }
|
return process { apiService.sendPasswordResetEmail(data) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateLoginName(newLoginName: String, password: String): Void? {
|
override suspend fun updateLoginName(
|
||||||
|
newLoginName: String,
|
||||||
|
password: String,
|
||||||
|
): Void? {
|
||||||
val updateObject = HashMap<String, String>()
|
val updateObject = HashMap<String, String>()
|
||||||
updateObject["username"] = newLoginName
|
updateObject["username"] = newLoginName
|
||||||
updateObject["password"] = password
|
updateObject["password"] = password
|
||||||
|
|
@ -896,7 +1015,10 @@ class ApiClientImpl(
|
||||||
return process { this.apiService.verifyUsername(updateObject) }
|
return process { this.apiService.verifyUsername(updateObject) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateEmail(newEmail: String, password: String): Void? {
|
override suspend fun updateEmail(
|
||||||
|
newEmail: String,
|
||||||
|
password: String,
|
||||||
|
): Void? {
|
||||||
val updateObject = HashMap<String, String>()
|
val updateObject = HashMap<String, String>()
|
||||||
updateObject["newEmail"] = newEmail
|
updateObject["newEmail"] = newEmail
|
||||||
if (password.isNotBlank()) {
|
if (password.isNotBlank()) {
|
||||||
|
|
@ -908,7 +1030,7 @@ class ApiClientImpl(
|
||||||
override suspend fun updatePassword(
|
override suspend fun updatePassword(
|
||||||
oldPassword: String,
|
oldPassword: String,
|
||||||
newPassword: String,
|
newPassword: String,
|
||||||
newPasswordConfirmation: String
|
newPasswordConfirmation: String,
|
||||||
): Void? {
|
): Void? {
|
||||||
val updateObject = HashMap<String, String>()
|
val updateObject = HashMap<String, String>()
|
||||||
updateObject["password"] = oldPassword
|
updateObject["password"] = oldPassword
|
||||||
|
|
@ -921,13 +1043,16 @@ class ApiClientImpl(
|
||||||
return process { apiService.allocatePoint(stat) }
|
return process { apiService.allocatePoint(stat) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun transferGems(giftedID: String, amount: Int): Void? {
|
override suspend fun transferGems(
|
||||||
|
giftedID: String,
|
||||||
|
amount: Int,
|
||||||
|
): Void? {
|
||||||
return process {
|
return process {
|
||||||
apiService.transferGems(
|
apiService.transferGems(
|
||||||
mapOf(
|
mapOf(
|
||||||
Pair("toUserId", giftedID),
|
Pair("toUserId", giftedID),
|
||||||
Pair("gemAmount", amount)
|
Pair("gemAmount", amount),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -940,11 +1065,17 @@ class ApiClientImpl(
|
||||||
return processResponse(apiService.getTeamPlanTasks(teamID))
|
return processResponse(apiService.getTeamPlanTasks(teamID))
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun assignToTask(taskId: String, ids: List<String>): Task? {
|
override suspend fun assignToTask(
|
||||||
|
taskId: String,
|
||||||
|
ids: List<String>,
|
||||||
|
): Task? {
|
||||||
return process { apiService.assignToTask(taskId, ids) }
|
return process { apiService.assignToTask(taskId, ids) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun unassignFromTask(taskId: String, userID: String): Task? {
|
override suspend fun unassignFromTask(
|
||||||
|
taskId: String,
|
||||||
|
userID: String,
|
||||||
|
): Task? {
|
||||||
return process { apiService.unassignFromTask(taskId, userID) }
|
return process { apiService.unassignFromTask(taskId, userID) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -952,7 +1083,7 @@ class ApiClientImpl(
|
||||||
strength: Int,
|
strength: Int,
|
||||||
intelligence: Int,
|
intelligence: Int,
|
||||||
constitution: Int,
|
constitution: Int,
|
||||||
perception: Int
|
perception: Int,
|
||||||
): Stats? {
|
): Stats? {
|
||||||
val body = HashMap<String, Map<String, Int>>()
|
val body = HashMap<String, Map<String, Int>>()
|
||||||
val stats = HashMap<String, Int>()
|
val stats = HashMap<String, Int>()
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,8 @@ import com.habitrpg.android.habitica.modules.AuthenticationHandler
|
||||||
abstract class BaseRepositoryImpl<T : BaseLocalRepository>(
|
abstract class BaseRepositoryImpl<T : BaseLocalRepository>(
|
||||||
protected val localRepository: T,
|
protected val localRepository: T,
|
||||||
protected val apiClient: ApiClient,
|
protected val apiClient: ApiClient,
|
||||||
protected val authenticationHandler: AuthenticationHandler
|
protected val authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepository {
|
) : BaseRepository {
|
||||||
|
|
||||||
val currentUserID: String
|
val currentUserID: String
|
||||||
get() = authenticationHandler.currentUserID ?: ""
|
get() = authenticationHandler.currentUserID ?: ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,16 +16,16 @@ import kotlinx.coroutines.flow.Flow
|
||||||
class ChallengeRepositoryImpl(
|
class ChallengeRepositoryImpl(
|
||||||
localRepository: ChallengeLocalRepository,
|
localRepository: ChallengeLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<ChallengeLocalRepository>(localRepository, apiClient, authenticationHandler), ChallengeRepository {
|
) : BaseRepositoryImpl<ChallengeLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
|
ChallengeRepository {
|
||||||
override fun isChallengeMember(challengeID: String): Flow<Boolean> {
|
override fun isChallengeMember(challengeID: String): Flow<Boolean> {
|
||||||
return localRepository.isChallengeMember(currentUserID, challengeID)
|
return localRepository.isChallengeMember(currentUserID, challengeID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun reportChallenge(
|
override suspend fun reportChallenge(
|
||||||
challengeid: String,
|
challengeid: String,
|
||||||
updateData: Map<String, String>
|
updateData: Map<String, String>,
|
||||||
): Void? {
|
): Void? {
|
||||||
return apiClient.reportChallenge(challengeid, updateData)
|
return apiClient.reportChallenge(challengeid, updateData)
|
||||||
}
|
}
|
||||||
|
|
@ -83,14 +83,29 @@ class ChallengeRepositoryImpl(
|
||||||
return tasksOrder
|
return tasksOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun addChallengeTasks(challenge: Challenge, addedTaskList: List<Task>) {
|
private suspend fun addChallengeTasks(
|
||||||
|
challenge: Challenge,
|
||||||
|
addedTaskList: List<Task>,
|
||||||
|
) {
|
||||||
when {
|
when {
|
||||||
addedTaskList.count() == 1 -> apiClient.createChallengeTask(challenge.id ?: "", addedTaskList[0])
|
addedTaskList.count() == 1 ->
|
||||||
addedTaskList.count() > 1 -> apiClient.createChallengeTasks(challenge.id ?: "", addedTaskList)
|
apiClient.createChallengeTask(
|
||||||
|
challenge.id ?: "",
|
||||||
|
addedTaskList[0],
|
||||||
|
)
|
||||||
|
|
||||||
|
addedTaskList.count() > 1 ->
|
||||||
|
apiClient.createChallengeTasks(
|
||||||
|
challenge.id ?: "",
|
||||||
|
addedTaskList,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun createChallenge(challenge: Challenge, taskList: List<Task>): Challenge? {
|
override suspend fun createChallenge(
|
||||||
|
challenge: Challenge,
|
||||||
|
taskList: List<Task>,
|
||||||
|
): Challenge? {
|
||||||
challenge.tasksOrder = getTaskOrders(taskList)
|
challenge.tasksOrder = getTaskOrders(taskList)
|
||||||
|
|
||||||
val createdChallenge = apiClient.createChallenge(challenge)
|
val createdChallenge = apiClient.createChallenge(challenge)
|
||||||
|
|
@ -105,7 +120,7 @@ class ChallengeRepositoryImpl(
|
||||||
fullTaskList: List<Task>,
|
fullTaskList: List<Task>,
|
||||||
addedTaskList: List<Task>,
|
addedTaskList: List<Task>,
|
||||||
updatedTaskList: List<Task>,
|
updatedTaskList: List<Task>,
|
||||||
removedTaskList: List<String>
|
removedTaskList: List<String>,
|
||||||
): Challenge? {
|
): Challenge? {
|
||||||
updatedTaskList
|
updatedTaskList
|
||||||
.map { localRepository.getUnmanagedCopy(it) }
|
.map { localRepository.getUnmanagedCopy(it) }
|
||||||
|
|
@ -141,7 +156,10 @@ class ChallengeRepositoryImpl(
|
||||||
return localRepository.getUserChallenges(userId ?: currentUserID)
|
return localRepository.getUserChallenges(userId ?: currentUserID)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrieveChallenges(page: Int, memberOnly: Boolean): List<Challenge>? {
|
override suspend fun retrieveChallenges(
|
||||||
|
page: Int,
|
||||||
|
memberOnly: Boolean,
|
||||||
|
): List<Challenge>? {
|
||||||
val challenges = apiClient.getUserChallenges(page, memberOnly)
|
val challenges = apiClient.getUserChallenges(page, memberOnly)
|
||||||
if (challenges != null) {
|
if (challenges != null) {
|
||||||
localRepository.saveChallenges(challenges, page == 0, memberOnly, currentUserID)
|
localRepository.saveChallenges(challenges, page == 0, memberOnly, currentUserID)
|
||||||
|
|
@ -149,7 +167,10 @@ class ChallengeRepositoryImpl(
|
||||||
return challenges
|
return challenges
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun leaveChallenge(challenge: Challenge, keepTasks: String): Void? {
|
override suspend fun leaveChallenge(
|
||||||
|
challenge: Challenge,
|
||||||
|
keepTasks: String,
|
||||||
|
): Void? {
|
||||||
apiClient.leaveChallenge(challenge.id ?: "", LeaveChallengeBody(keepTasks))
|
apiClient.leaveChallenge(challenge.id ?: "", LeaveChallengeBody(keepTasks))
|
||||||
localRepository.setParticipating(currentUserID, challenge.id ?: "", false)
|
localRepository.setParticipating(currentUserID, challenge.id ?: "", false)
|
||||||
return null
|
return null
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,8 @@ class ContentRepositoryImpl<T : ContentLocalRepository>(
|
||||||
localRepository: T,
|
localRepository: T,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
context: Context,
|
context: Context,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<T>(localRepository, apiClient, authenticationHandler), ContentRepository {
|
) : BaseRepositoryImpl<T>(localRepository, apiClient, authenticationHandler), ContentRepository {
|
||||||
|
|
||||||
private val mysteryItem = SpecialItem.makeMysteryItem(context)
|
private val mysteryItem = SpecialItem.makeMysteryItem(context)
|
||||||
|
|
||||||
private var lastContentSync = 0L
|
private var lastContentSync = 0L
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,18 @@ import kotlinx.coroutines.flow.Flow
|
||||||
class CustomizationRepositoryImpl(
|
class CustomizationRepositoryImpl(
|
||||||
localRepository: CustomizationLocalRepository,
|
localRepository: CustomizationLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<CustomizationLocalRepository>(localRepository, apiClient, authenticationHandler), CustomizationRepository {
|
) : BaseRepositoryImpl<CustomizationLocalRepository>(
|
||||||
|
localRepository,
|
||||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>> {
|
apiClient,
|
||||||
|
authenticationHandler,
|
||||||
|
),
|
||||||
|
CustomizationRepository {
|
||||||
|
override fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
category: String?,
|
||||||
|
onlyAvailable: Boolean,
|
||||||
|
): Flow<List<Customization>> {
|
||||||
return localRepository.getCustomizations(type, category, onlyAvailable)
|
return localRepository.getCustomizations(type, category, onlyAvailable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import kotlinx.coroutines.flow.Flow
|
||||||
class FAQRepositoryImpl(
|
class FAQRepositoryImpl(
|
||||||
localRepository: FAQLocalRepository,
|
localRepository: FAQLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<FAQLocalRepository>(localRepository, apiClient, authenticationHandler),
|
) : BaseRepositoryImpl<FAQLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
FAQRepository {
|
FAQRepository {
|
||||||
override fun getArticle(position: Int): Flow<FAQArticle> {
|
override fun getArticle(position: Int): Flow<FAQArticle> {
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,9 @@ class InventoryRepositoryImpl(
|
||||||
localRepository: InventoryLocalRepository,
|
localRepository: InventoryLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler,
|
authenticationHandler: AuthenticationHandler,
|
||||||
var appConfigManager: AppConfigManager
|
var appConfigManager: AppConfigManager,
|
||||||
) : BaseRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient, authenticationHandler), InventoryRepository {
|
) : BaseRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
|
InventoryRepository {
|
||||||
override fun getQuestContent(keys: List<String>) = localRepository.getQuestContent(keys)
|
override fun getQuestContent(keys: List<String>) = localRepository.getQuestContent(keys)
|
||||||
|
|
||||||
override fun getQuestContent(key: String) = localRepository.getQuestContent(key)
|
override fun getQuestContent(key: String) = localRepository.getQuestContent(key)
|
||||||
|
|
@ -72,19 +73,39 @@ class InventoryRepositoryImpl(
|
||||||
return localRepository.getOwnedEquipment()
|
return localRepository.getOwnedEquipment()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEquipmentType(type: String, set: String): Flow<List<Equipment>> {
|
override fun getEquipmentType(
|
||||||
|
type: String,
|
||||||
|
set: String,
|
||||||
|
): Flow<List<Equipment>> {
|
||||||
return localRepository.getEquipmentType(type, set)
|
return localRepository.getEquipmentType(type, set)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOwnedItems(itemType: String, includeZero: Boolean): Flow<List<OwnedItem>> {
|
override fun getOwnedItems(
|
||||||
return authenticationHandler.userIDFlow.flatMapLatest { localRepository.getOwnedItems(itemType, it, includeZero) }
|
itemType: String,
|
||||||
|
includeZero: Boolean,
|
||||||
|
): Flow<List<OwnedItem>> {
|
||||||
|
return authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
|
localRepository.getOwnedItems(
|
||||||
|
itemType,
|
||||||
|
it,
|
||||||
|
includeZero,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOwnedItems(includeZero: Boolean): Flow<Map<String, OwnedItem>> {
|
override fun getOwnedItems(includeZero: Boolean): Flow<Map<String, OwnedItem>> {
|
||||||
return authenticationHandler.userIDFlow.flatMapLatest { localRepository.getOwnedItems(it, includeZero) }
|
return authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
|
localRepository.getOwnedItems(
|
||||||
|
it,
|
||||||
|
includeZero,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>> {
|
override fun getItems(
|
||||||
|
itemClass: Class<out Item>,
|
||||||
|
keys: Array<String>,
|
||||||
|
): Flow<List<Item>> {
|
||||||
return localRepository.getItems(itemClass, keys)
|
return localRepository.getItems(itemClass, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,7 +136,11 @@ class InventoryRepositoryImpl(
|
||||||
return localRepository.getMounts()
|
return localRepository.getMounts()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>> {
|
override fun getMounts(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Mount>> {
|
||||||
return localRepository.getMounts(type, group, color)
|
return localRepository.getMounts(type, group, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +152,11 @@ class InventoryRepositoryImpl(
|
||||||
return localRepository.getPets()
|
return localRepository.getPets()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>> {
|
override fun getPets(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Pet>> {
|
||||||
return localRepository.getPets(type, group, color)
|
return localRepository.getPets(type, group, color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,17 +168,28 @@ class InventoryRepositoryImpl(
|
||||||
localRepository.updateOwnedEquipment(user)
|
localRepository.updateOwnedEquipment(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun changeOwnedCount(type: String, key: String, amountToAdd: Int) {
|
override suspend fun changeOwnedCount(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
amountToAdd: Int,
|
||||||
|
) {
|
||||||
localRepository.changeOwnedCount(type, key, currentUserID, amountToAdd)
|
localRepository.changeOwnedCount(type, key, currentUserID, amountToAdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sellItem(type: String, key: String): User? {
|
override suspend fun sellItem(
|
||||||
val item = localRepository.getOwnedItem(currentUserID, type, key, true).firstOrNull() ?: return null
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): User? {
|
||||||
|
val item =
|
||||||
|
localRepository.getOwnedItem(currentUserID, type, key, true).firstOrNull()
|
||||||
|
?: return null
|
||||||
return sellItem(item)
|
return sellItem(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sellItem(item: OwnedItem): User? {
|
override suspend fun sellItem(item: OwnedItem): User? {
|
||||||
val itemData = localRepository.getItem(item.itemType ?: "", item.key ?: "").firstOrNull() ?: return null
|
val itemData =
|
||||||
|
localRepository.getItem(item.itemType ?: "", item.key ?: "").firstOrNull()
|
||||||
|
?: return null
|
||||||
return sellItem(itemData, item)
|
return sellItem(itemData, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -157,11 +197,17 @@ class InventoryRepositoryImpl(
|
||||||
return localRepository.getLatestMysteryItem()
|
return localRepository.getLatestMysteryItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItem(type: String, key: String): Flow<Item> {
|
override fun getItem(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Flow<Item> {
|
||||||
return localRepository.getItem(type, key)
|
return localRepository.getItem(type, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun sellItem(item: Item, ownedItem: OwnedItem): User? {
|
private suspend fun sellItem(
|
||||||
|
item: Item,
|
||||||
|
ownedItem: OwnedItem,
|
||||||
|
): User? {
|
||||||
localRepository.executeTransaction {
|
localRepository.executeTransaction {
|
||||||
val liveItem = localRepository.getLiveObject(ownedItem)
|
val liveItem = localRepository.getLiveObject(ownedItem)
|
||||||
liveItem?.numberOwned = (liveItem?.numberOwned ?: 0) - 1
|
liveItem?.numberOwned = (liveItem?.numberOwned ?: 0) - 1
|
||||||
|
|
@ -170,11 +216,17 @@ class InventoryRepositoryImpl(
|
||||||
return localRepository.soldItem(currentUserID, user)
|
return localRepository.soldItem(currentUserID, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun equipGear(equipment: String, asCostume: Boolean): Items? {
|
override suspend fun equipGear(
|
||||||
|
equipment: String,
|
||||||
|
asCostume: Boolean,
|
||||||
|
): Items? {
|
||||||
return equip(if (asCostume) "costume" else "equipped", equipment)
|
return equip(if (asCostume) "costume" else "equipped", equipment)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun equip(type: String, key: String): Items? {
|
override suspend fun equip(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Items? {
|
||||||
val liveUser = localRepository.getLiveUser(currentUserID)
|
val liveUser = localRepository.getLiveUser(currentUserID)
|
||||||
|
|
||||||
if (liveUser != null) {
|
if (liveUser != null) {
|
||||||
|
|
@ -184,7 +236,8 @@ class InventoryRepositoryImpl(
|
||||||
} else if (type == "pet") {
|
} else if (type == "pet") {
|
||||||
user.items?.currentPet = key
|
user.items?.currentPet = key
|
||||||
}
|
}
|
||||||
val outfit = if (type == "costume") {
|
val outfit =
|
||||||
|
if (type == "costume") {
|
||||||
user.items?.gear?.costume
|
user.items?.gear?.costume
|
||||||
} else {
|
} else {
|
||||||
user.items?.gear?.equipped
|
user.items?.gear?.equipped
|
||||||
|
|
@ -217,13 +270,20 @@ class InventoryRepositoryImpl(
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun feedPet(pet: Pet, food: Food): FeedResponse? {
|
override suspend fun feedPet(
|
||||||
|
pet: Pet,
|
||||||
|
food: Food,
|
||||||
|
): FeedResponse? {
|
||||||
val feedResponse = apiClient.feedPet(pet.key, food.key) ?: return null
|
val feedResponse = apiClient.feedPet(pet.key, food.key) ?: return null
|
||||||
localRepository.feedPet(food.key, pet.key, feedResponse.value ?: 0, currentUserID)
|
localRepository.feedPet(food.key, pet.key, feedResponse.value ?: 0, currentUserID)
|
||||||
return feedResponse
|
return feedResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun hatchPet(egg: Egg, hatchingPotion: HatchingPotion, successFunction: () -> Unit): Items? {
|
override suspend fun hatchPet(
|
||||||
|
egg: Egg,
|
||||||
|
hatchingPotion: HatchingPotion,
|
||||||
|
successFunction: () -> Unit,
|
||||||
|
): Items? {
|
||||||
if (appConfigManager.enableLocalChanges()) {
|
if (appConfigManager.enableLocalChanges()) {
|
||||||
localRepository.hatchPet(egg.key, hatchingPotion.key, currentUserID)
|
localRepository.hatchPet(egg.key, hatchingPotion.key, currentUserID)
|
||||||
successFunction()
|
successFunction()
|
||||||
|
|
@ -242,7 +302,12 @@ class InventoryRepositoryImpl(
|
||||||
return newQuest
|
return newQuest
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun buyItem(user: User?, id: String, value: Double, purchaseQuantity: Int): BuyResponse? {
|
override suspend fun buyItem(
|
||||||
|
user: User?,
|
||||||
|
id: String,
|
||||||
|
value: Double,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): BuyResponse? {
|
||||||
val buyResponse = apiClient.buyItem(id, purchaseQuantity) ?: return null
|
val buyResponse = apiClient.buyItem(id, purchaseQuantity) ?: return null
|
||||||
val foundUser = user ?: localRepository.getLiveUser(currentUserID) ?: return buyResponse
|
val foundUser = user ?: localRepository.getLiveUser(currentUserID) ?: return buyResponse
|
||||||
val copiedUser = localRepository.getUnmanagedCopy(foundUser)
|
val copiedUser = localRepository.getUnmanagedCopy(foundUser)
|
||||||
|
|
@ -286,7 +351,10 @@ class InventoryRepositoryImpl(
|
||||||
return apiClient.purchaseMysterySet(categoryIdentifier)
|
return apiClient.purchaseMysterySet(categoryIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun purchaseHourglassItem(purchaseType: String, key: String): Void? {
|
override suspend fun purchaseHourglassItem(
|
||||||
|
purchaseType: String,
|
||||||
|
key: String,
|
||||||
|
): Void? {
|
||||||
return apiClient.purchaseHourglassItem(purchaseType, key)
|
return apiClient.purchaseHourglassItem(purchaseType, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,12 +366,17 @@ class InventoryRepositoryImpl(
|
||||||
return apiClient.purchaseSpecialSpell(key)
|
return apiClient.purchaseSpecialSpell(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun purchaseItem(purchaseType: String, key: String, purchaseQuantity: Int): Void? {
|
override suspend fun purchaseItem(
|
||||||
|
purchaseType: String,
|
||||||
|
key: String,
|
||||||
|
purchaseQuantity: Int,
|
||||||
|
): Void? {
|
||||||
val response = apiClient.purchaseItem(purchaseType, key, purchaseQuantity)
|
val response = apiClient.purchaseItem(purchaseType, key, purchaseQuantity)
|
||||||
if (key == "gem") {
|
if (key == "gem") {
|
||||||
val user = localRepository.getLiveUser(currentUserID)
|
val user = localRepository.getLiveUser(currentUserID)
|
||||||
localRepository.executeTransaction {
|
localRepository.executeTransaction {
|
||||||
user?.purchased?.plan?.gemsBought = purchaseQuantity + (user?.purchased?.plan?.gemsBought ?: 0)
|
user?.purchased?.plan?.gemsBought =
|
||||||
|
purchaseQuantity + (user?.purchased?.plan?.gemsBought ?: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|
|
||||||
|
|
@ -8,49 +8,148 @@ import com.habitrpg.android.habitica.models.user.User
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("StringLiteralDuplication")
|
@Suppress("StringLiteralDuplication")
|
||||||
class SetupCustomizationRepositoryImpl @Inject
|
class SetupCustomizationRepositoryImpl
|
||||||
|
@Inject
|
||||||
constructor(private val context: Context) : SetupCustomizationRepository {
|
constructor(private val context: Context) : SetupCustomizationRepository {
|
||||||
|
|
||||||
private val wheelchairs: List<SetupCustomization>
|
private val wheelchairs: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createWheelchair("none", 0), SetupCustomization.createWheelchair("black", R.drawable.creator_chair_black), SetupCustomization.createWheelchair("blue", R.drawable.creator_chair_blue), SetupCustomization.createWheelchair("green", R.drawable.creator_chair_green), SetupCustomization.createWheelchair("pink", R.drawable.creator_chair_pink), SetupCustomization.createWheelchair("red", R.drawable.creator_chair_red), SetupCustomization.createWheelchair("yellow", R.drawable.creator_chair_yellow))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createWheelchair("none", 0),
|
||||||
|
SetupCustomization.createWheelchair("black", R.drawable.creator_chair_black),
|
||||||
|
SetupCustomization.createWheelchair("blue", R.drawable.creator_chair_blue),
|
||||||
|
SetupCustomization.createWheelchair("green", R.drawable.creator_chair_green),
|
||||||
|
SetupCustomization.createWheelchair("pink", R.drawable.creator_chair_pink),
|
||||||
|
SetupCustomization.createWheelchair("red", R.drawable.creator_chair_red),
|
||||||
|
SetupCustomization.createWheelchair("yellow", R.drawable.creator_chair_yellow),
|
||||||
|
)
|
||||||
|
|
||||||
private val glasses: List<SetupCustomization>
|
private val glasses: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createGlasses("", R.drawable.creator_blank_face), SetupCustomization.createGlasses("eyewear_special_blackTopFrame", R.drawable.creator_eyewear_special_blacktopframe), SetupCustomization.createGlasses("eyewear_special_blueTopFrame", R.drawable.creator_eyewear_special_bluetopframe), SetupCustomization.createGlasses("eyewear_special_greenTopFrame", R.drawable.creator_eyewear_special_greentopframe), SetupCustomization.createGlasses("eyewear_special_pinkTopFrame", R.drawable.creator_eyewear_special_pinktopframe), SetupCustomization.createGlasses("eyewear_special_redTopFrame", R.drawable.creator_eyewear_special_redtopframe), SetupCustomization.createGlasses("eyewear_special_yellowTopFrame", R.drawable.creator_eyewear_special_yellowtopframe), SetupCustomization.createGlasses("eyewear_special_whiteTopFrame", R.drawable.creator_eyewear_special_whitetopframe))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createGlasses("", R.drawable.creator_blank_face),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_blackTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_blacktopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_blueTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_bluetopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_greenTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_greentopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_pinkTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_pinktopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_redTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_redtopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_yellowTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_yellowtopframe,
|
||||||
|
),
|
||||||
|
SetupCustomization.createGlasses(
|
||||||
|
"eyewear_special_whiteTopFrame",
|
||||||
|
R.drawable.creator_eyewear_special_whitetopframe,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
private val flowers: List<SetupCustomization>
|
private val flowers: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createFlower("0", R.drawable.creator_blank_face), SetupCustomization.createFlower("1", R.drawable.creator_hair_flower_1), SetupCustomization.createFlower("2", R.drawable.creator_hair_flower_2), SetupCustomization.createFlower("3", R.drawable.creator_hair_flower_3), SetupCustomization.createFlower("4", R.drawable.creator_hair_flower_4), SetupCustomization.createFlower("5", R.drawable.creator_hair_flower_5), SetupCustomization.createFlower("6", R.drawable.creator_hair_flower_6))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createFlower("0", R.drawable.creator_blank_face),
|
||||||
|
SetupCustomization.createFlower("1", R.drawable.creator_hair_flower_1),
|
||||||
|
SetupCustomization.createFlower("2", R.drawable.creator_hair_flower_2),
|
||||||
|
SetupCustomization.createFlower("3", R.drawable.creator_hair_flower_3),
|
||||||
|
SetupCustomization.createFlower("4", R.drawable.creator_hair_flower_4),
|
||||||
|
SetupCustomization.createFlower("5", R.drawable.creator_hair_flower_5),
|
||||||
|
SetupCustomization.createFlower("6", R.drawable.creator_hair_flower_6),
|
||||||
|
)
|
||||||
|
|
||||||
private val hairColors: List<SetupCustomization>
|
private val hairColors: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createHairColor("white", R.color.hair_white), SetupCustomization.createHairColor("brown", R.color.hair_brown), SetupCustomization.createHairColor("blond", R.color.hair_blond), SetupCustomization.createHairColor("red", R.color.hair_red), SetupCustomization.createHairColor("black", R.color.hair_black))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createHairColor("white", R.color.hair_white),
|
||||||
|
SetupCustomization.createHairColor("brown", R.color.hair_brown),
|
||||||
|
SetupCustomization.createHairColor("blond", R.color.hair_blond),
|
||||||
|
SetupCustomization.createHairColor("red", R.color.hair_red),
|
||||||
|
SetupCustomization.createHairColor("black", R.color.hair_black),
|
||||||
|
)
|
||||||
|
|
||||||
private val sizes: List<SetupCustomization>
|
private val sizes: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createSize("slim", R.drawable.creator_slim_shirt_black, context.getString(R.string.avatar_size_slim)), SetupCustomization.createSize("broad", R.drawable.creator_broad_shirt_black, context.getString(R.string.avatar_size_broad)))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createSize(
|
||||||
|
"slim",
|
||||||
|
R.drawable.creator_slim_shirt_black,
|
||||||
|
context.getString(R.string.avatar_size_slim),
|
||||||
|
),
|
||||||
|
SetupCustomization.createSize(
|
||||||
|
"broad",
|
||||||
|
R.drawable.creator_broad_shirt_black,
|
||||||
|
context.getString(R.string.avatar_size_broad),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
private val skins: List<SetupCustomization>
|
private val skins: List<SetupCustomization>
|
||||||
get() = listOf(SetupCustomization.createSkin("ddc994", R.color.skin_ddc994), SetupCustomization.createSkin("f5a76e", R.color.skin_f5a76e), SetupCustomization.createSkin("ea8349", R.color.skin_ea8349), SetupCustomization.createSkin("c06534", R.color.skin_c06534), SetupCustomization.createSkin("98461a", R.color.skin_98461a), SetupCustomization.createSkin("915533", R.color.skin_915533), SetupCustomization.createSkin("c3e1dc", R.color.skin_c3e1dc), SetupCustomization.createSkin("6bd049", R.color.skin_6bd049))
|
get() =
|
||||||
|
listOf(
|
||||||
|
SetupCustomization.createSkin("ddc994", R.color.skin_ddc994),
|
||||||
|
SetupCustomization.createSkin("f5a76e", R.color.skin_f5a76e),
|
||||||
|
SetupCustomization.createSkin("ea8349", R.color.skin_ea8349),
|
||||||
|
SetupCustomization.createSkin("c06534", R.color.skin_c06534),
|
||||||
|
SetupCustomization.createSkin("98461a", R.color.skin_98461a),
|
||||||
|
SetupCustomization.createSkin("915533", R.color.skin_915533),
|
||||||
|
SetupCustomization.createSkin("c3e1dc", R.color.skin_c3e1dc),
|
||||||
|
SetupCustomization.createSkin("6bd049", R.color.skin_6bd049),
|
||||||
|
)
|
||||||
|
|
||||||
override fun getCustomizations(type: String, user: User): List<SetupCustomization> {
|
override fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
user: User,
|
||||||
|
): List<SetupCustomization> {
|
||||||
return getCustomizations(type, null, user)
|
return getCustomizations(type, null, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCustomizations(type: String, subtype: String?, user: User): List<SetupCustomization> {
|
override fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
subtype: String?,
|
||||||
|
user: User,
|
||||||
|
): List<SetupCustomization> {
|
||||||
return when (type) {
|
return when (type) {
|
||||||
SetupCustomizationRepository.CATEGORY_BODY -> {
|
SetupCustomizationRepository.CATEGORY_BODY -> {
|
||||||
when (subtype) {
|
when (subtype) {
|
||||||
SetupCustomizationRepository.SUBCATEGORY_SIZE -> sizes
|
SetupCustomizationRepository.SUBCATEGORY_SIZE -> sizes
|
||||||
SetupCustomizationRepository.SUBCATEGORY_SHIRT -> getShirts(user.preferences?.size ?: "slim")
|
SetupCustomizationRepository.SUBCATEGORY_SHIRT ->
|
||||||
|
getShirts(
|
||||||
|
user.preferences?.size ?: "slim",
|
||||||
|
)
|
||||||
|
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupCustomizationRepository.CATEGORY_SKIN -> skins
|
SetupCustomizationRepository.CATEGORY_SKIN -> skins
|
||||||
SetupCustomizationRepository.CATEGORY_HAIR -> {
|
SetupCustomizationRepository.CATEGORY_HAIR -> {
|
||||||
when (subtype) {
|
when (subtype) {
|
||||||
SetupCustomizationRepository.SUBCATEGORY_BANGS -> getBangs(user.preferences?.hair?.color ?: "")
|
SetupCustomizationRepository.SUBCATEGORY_BANGS ->
|
||||||
SetupCustomizationRepository.SUBCATEGORY_PONYTAIL -> getHairBases(user.preferences?.hair?.color ?: "")
|
getBangs(
|
||||||
|
user.preferences?.hair?.color ?: "",
|
||||||
|
)
|
||||||
|
|
||||||
|
SetupCustomizationRepository.SUBCATEGORY_PONYTAIL ->
|
||||||
|
getHairBases(
|
||||||
|
user.preferences?.hair?.color ?: "",
|
||||||
|
)
|
||||||
|
|
||||||
SetupCustomizationRepository.SUBCATEGORY_COLOR -> hairColors
|
SetupCustomizationRepository.SUBCATEGORY_COLOR -> hairColors
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetupCustomizationRepository.CATEGORY_EXTRAS -> {
|
SetupCustomizationRepository.CATEGORY_EXTRAS -> {
|
||||||
when (subtype) {
|
when (subtype) {
|
||||||
SetupCustomizationRepository.SUBCATEGORY_FLOWER -> flowers
|
SetupCustomizationRepository.SUBCATEGORY_FLOWER -> flowers
|
||||||
|
|
@ -59,23 +158,47 @@ constructor(private val context: Context) : SetupCustomizationRepository {
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getHairBases(color: String): List<SetupCustomization> {
|
private fun getHairBases(color: String): List<SetupCustomization> {
|
||||||
return listOf(SetupCustomization.createHairPonytail("0", R.drawable.creator_blank_face), SetupCustomization.createHairPonytail("1", getResId("creator_hair_base_1_$color")), SetupCustomization.createHairPonytail("3", getResId("creator_hair_base_3_$color")))
|
return listOf(
|
||||||
|
SetupCustomization.createHairPonytail("0", R.drawable.creator_blank_face),
|
||||||
|
SetupCustomization.createHairPonytail("1", getResId("creator_hair_base_1_$color")),
|
||||||
|
SetupCustomization.createHairPonytail("3", getResId("creator_hair_base_3_$color")),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBangs(color: String): List<SetupCustomization> {
|
private fun getBangs(color: String): List<SetupCustomization> {
|
||||||
return listOf(SetupCustomization.createHairBangs("0", R.drawable.creator_blank_face), SetupCustomization.createHairBangs("1", getResId("creator_hair_bangs_1_$color")), SetupCustomization.createHairBangs("2", getResId("creator_hair_bangs_2_$color")), SetupCustomization.createHairBangs("3", getResId("creator_hair_bangs_3_$color")))
|
return listOf(
|
||||||
|
SetupCustomization.createHairBangs("0", R.drawable.creator_blank_face),
|
||||||
|
SetupCustomization.createHairBangs("1", getResId("creator_hair_bangs_1_$color")),
|
||||||
|
SetupCustomization.createHairBangs("2", getResId("creator_hair_bangs_2_$color")),
|
||||||
|
SetupCustomization.createHairBangs("3", getResId("creator_hair_bangs_3_$color")),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getShirts(size: String): List<SetupCustomization> {
|
private fun getShirts(size: String): List<SetupCustomization> {
|
||||||
return if (size == "broad") {
|
return if (size == "broad") {
|
||||||
listOf(SetupCustomization.createShirt("black", R.drawable.creator_broad_shirt_black), SetupCustomization.createShirt("blue", R.drawable.creator_broad_shirt_blue), SetupCustomization.createShirt("green", R.drawable.creator_broad_shirt_green), SetupCustomization.createShirt("pink", R.drawable.creator_broad_shirt_pink), SetupCustomization.createShirt("white", R.drawable.creator_broad_shirt_white), SetupCustomization.createShirt("yellow", R.drawable.creator_broad_shirt_yellow))
|
listOf(
|
||||||
|
SetupCustomization.createShirt("black", R.drawable.creator_broad_shirt_black),
|
||||||
|
SetupCustomization.createShirt("blue", R.drawable.creator_broad_shirt_blue),
|
||||||
|
SetupCustomization.createShirt("green", R.drawable.creator_broad_shirt_green),
|
||||||
|
SetupCustomization.createShirt("pink", R.drawable.creator_broad_shirt_pink),
|
||||||
|
SetupCustomization.createShirt("white", R.drawable.creator_broad_shirt_white),
|
||||||
|
SetupCustomization.createShirt("yellow", R.drawable.creator_broad_shirt_yellow),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
listOf(SetupCustomization.createShirt("black", R.drawable.creator_slim_shirt_black), SetupCustomization.createShirt("blue", R.drawable.creator_slim_shirt_blue), SetupCustomization.createShirt("green", R.drawable.creator_slim_shirt_green), SetupCustomization.createShirt("pink", R.drawable.creator_slim_shirt_pink), SetupCustomization.createShirt("white", R.drawable.creator_slim_shirt_white), SetupCustomization.createShirt("yellow", R.drawable.creator_slim_shirt_yellow))
|
listOf(
|
||||||
|
SetupCustomization.createShirt("black", R.drawable.creator_slim_shirt_black),
|
||||||
|
SetupCustomization.createShirt("blue", R.drawable.creator_slim_shirt_blue),
|
||||||
|
SetupCustomization.createShirt("green", R.drawable.creator_slim_shirt_green),
|
||||||
|
SetupCustomization.createShirt("pink", R.drawable.creator_slim_shirt_pink),
|
||||||
|
SetupCustomization.createShirt("white", R.drawable.creator_slim_shirt_white),
|
||||||
|
SetupCustomization.createShirt("yellow", R.drawable.creator_slim_shirt_yellow),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,23 @@ import java.util.UUID
|
||||||
class SocialRepositoryImpl(
|
class SocialRepositoryImpl(
|
||||||
localRepository: SocialLocalRepository,
|
localRepository: SocialLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<SocialLocalRepository>(localRepository, apiClient, authenticationHandler), SocialRepository {
|
) : BaseRepositoryImpl<SocialLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
override suspend fun transferGroupOwnership(groupID: String, userID: String): Group? {
|
SocialRepository {
|
||||||
val group = localRepository.getGroup(groupID).first()?.let { localRepository.getUnmanagedCopy(it) }
|
override suspend fun transferGroupOwnership(
|
||||||
|
groupID: String,
|
||||||
|
userID: String,
|
||||||
|
): Group? {
|
||||||
|
val group =
|
||||||
|
localRepository.getGroup(groupID).first()?.let { localRepository.getUnmanagedCopy(it) }
|
||||||
group?.leaderID = userID
|
group?.leaderID = userID
|
||||||
return group?.let { apiClient.updateGroup(groupID, it) }
|
return group?.let { apiClient.updateGroup(groupID, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun removeMemberFromGroup(groupID: String, userID: String): List<Member>? {
|
override suspend fun removeMemberFromGroup(
|
||||||
|
groupID: String,
|
||||||
|
userID: String,
|
||||||
|
): List<Member>? {
|
||||||
apiClient.removeMemberFromGroup(groupID, userID)
|
apiClient.removeMemberFromGroup(groupID, userID)
|
||||||
return retrievePartyMembers(groupID, true)
|
return retrievePartyMembers(groupID, true)
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +59,7 @@ class SocialRepositoryImpl(
|
||||||
|
|
||||||
override suspend fun updateMember(
|
override suspend fun updateMember(
|
||||||
memberID: String,
|
memberID: String,
|
||||||
data: Map<String, Map<String, Boolean>>
|
data: Map<String, Map<String, Boolean>>,
|
||||||
): Member? {
|
): Member? {
|
||||||
return apiClient.updateMember(memberID, data)
|
return apiClient.updateMember(memberID, data)
|
||||||
}
|
}
|
||||||
|
|
@ -60,10 +68,20 @@ class SocialRepositoryImpl(
|
||||||
return apiClient.retrievePartySeekingUsers(page)
|
return apiClient.retrievePartySeekingUsers(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getGroupMembership(id: String) = authenticationHandler.userIDFlow.flatMapLatest { localRepository.getGroupMembership(it, id) }
|
override fun getGroupMembership(id: String) =
|
||||||
|
authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
|
localRepository.getGroupMembership(
|
||||||
|
it,
|
||||||
|
id,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getGroupMemberships(): Flow<List<GroupMembership>> {
|
override fun getGroupMemberships(): Flow<List<GroupMembership>> {
|
||||||
return authenticationHandler.userIDFlow.flatMapLatest { localRepository.getGroupMemberships(it) }
|
return authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
|
localRepository.getGroupMemberships(
|
||||||
|
it,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>? {
|
override suspend fun retrieveGroupChat(groupId: String): List<ChatMessage>? {
|
||||||
|
|
@ -80,7 +98,11 @@ class SocialRepositoryImpl(
|
||||||
apiClient.seenMessages(seenGroupId)
|
apiClient.seenMessages(seenGroupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun flagMessage(chatMessageID: String, additionalInfo: String, groupID: String?): Void? {
|
override suspend fun flagMessage(
|
||||||
|
chatMessageID: String,
|
||||||
|
additionalInfo: String,
|
||||||
|
groupID: String?,
|
||||||
|
): Void? {
|
||||||
return when {
|
return when {
|
||||||
chatMessageID.isBlank() -> return null
|
chatMessageID.isBlank() -> return null
|
||||||
currentUserID == BuildConfig.ANDROID_TESTING_UUID -> return null
|
currentUserID == BuildConfig.ANDROID_TESTING_UUID -> return null
|
||||||
|
|
@ -96,7 +118,10 @@ class SocialRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun reportMember(memberID: String, data: Map<String, String>): Void? {
|
override suspend fun reportMember(
|
||||||
|
memberID: String,
|
||||||
|
data: Map<String, String>,
|
||||||
|
): Void? {
|
||||||
return apiClient.reportMember(memberID, data)
|
return apiClient.reportMember(memberID, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,13 +145,19 @@ class SocialRepositoryImpl(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postGroupChat(groupId: String, messageObject: HashMap<String, String>): PostChatMessageResult? {
|
override suspend fun postGroupChat(
|
||||||
|
groupId: String,
|
||||||
|
messageObject: HashMap<String, String>,
|
||||||
|
): PostChatMessageResult? {
|
||||||
val result = apiClient.postGroupChat(groupId, messageObject)
|
val result = apiClient.postGroupChat(groupId, messageObject)
|
||||||
result?.message?.groupId = groupId
|
result?.message?.groupId = groupId
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postGroupChat(groupId: String, message: String): PostChatMessageResult? {
|
override suspend fun postGroupChat(
|
||||||
|
groupId: String,
|
||||||
|
message: String,
|
||||||
|
): PostChatMessageResult? {
|
||||||
val messageObject = HashMap<String, String>()
|
val messageObject = HashMap<String, String>()
|
||||||
messageObject["message"] = message
|
messageObject["message"] = message
|
||||||
return postGroupChat(groupId, messageObject)
|
return postGroupChat(groupId, messageObject)
|
||||||
|
|
@ -146,7 +177,10 @@ class SocialRepositoryImpl(
|
||||||
return localRepository.getGroup(id)
|
return localRepository.getGroup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun leaveGroup(id: String?, keepChallenges: Boolean): Group? {
|
override suspend fun leaveGroup(
|
||||||
|
id: String?,
|
||||||
|
keepChallenges: Boolean,
|
||||||
|
): Group? {
|
||||||
if (id?.isNotBlank() != true) {
|
if (id?.isNotBlank() != true) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
@ -174,7 +208,7 @@ class SocialRepositoryImpl(
|
||||||
leader: String?,
|
leader: String?,
|
||||||
type: String?,
|
type: String?,
|
||||||
privacy: String?,
|
privacy: String?,
|
||||||
leaderCreateChallenge: Boolean?
|
leaderCreateChallenge: Boolean?,
|
||||||
): Group? {
|
): Group? {
|
||||||
val group = Group()
|
val group = Group()
|
||||||
group.name = name
|
group.name = name
|
||||||
|
|
@ -192,7 +226,7 @@ class SocialRepositoryImpl(
|
||||||
name: String?,
|
name: String?,
|
||||||
description: String?,
|
description: String?,
|
||||||
leader: String?,
|
leader: String?,
|
||||||
leaderCreateChallenge: Boolean?
|
leaderCreateChallenge: Boolean?,
|
||||||
): Group? {
|
): Group? {
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
return null
|
return null
|
||||||
|
|
@ -206,11 +240,21 @@ class SocialRepositoryImpl(
|
||||||
return apiClient.updateGroup(copiedGroup.id, copiedGroup)
|
return apiClient.updateGroup(copiedGroup.id, copiedGroup)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getInboxConversations() = authenticationHandler.userIDFlow.flatMapLatest { localRepository.getInboxConversation(it) }
|
override fun getInboxConversations() =
|
||||||
|
authenticationHandler.userIDFlow.flatMapLatest { localRepository.getInboxConversation(it) }
|
||||||
|
|
||||||
override fun getInboxMessages(replyToUserID: String?) = authenticationHandler.userIDFlow.flatMapLatest { localRepository.getInboxMessages(it, replyToUserID) }
|
override fun getInboxMessages(replyToUserID: String?) =
|
||||||
|
authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
|
localRepository.getInboxMessages(
|
||||||
|
it,
|
||||||
|
replyToUserID,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun retrieveInboxMessages(uuid: String, page: Int): List<ChatMessage>? {
|
override suspend fun retrieveInboxMessages(
|
||||||
|
uuid: String,
|
||||||
|
page: Int,
|
||||||
|
): List<ChatMessage>? {
|
||||||
val messages = apiClient.retrieveInboxMessages(uuid, page) ?: return null
|
val messages = apiClient.retrieveInboxMessages(uuid, page) ?: return null
|
||||||
messages.forEach {
|
messages.forEach {
|
||||||
it.isInboxMessage = true
|
it.isInboxMessage = true
|
||||||
|
|
@ -225,12 +269,18 @@ class SocialRepositoryImpl(
|
||||||
return conversations
|
return conversations
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postPrivateMessage(recipientId: String, messageObject: HashMap<String, String>): List<ChatMessage>? {
|
override suspend fun postPrivateMessage(
|
||||||
|
recipientId: String,
|
||||||
|
messageObject: HashMap<String, String>,
|
||||||
|
): List<ChatMessage>? {
|
||||||
apiClient.postPrivateMessage(messageObject)
|
apiClient.postPrivateMessage(messageObject)
|
||||||
return retrieveInboxMessages(recipientId, 0)
|
return retrieveInboxMessages(recipientId, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun postPrivateMessage(recipientId: String, message: String): List<ChatMessage>? {
|
override suspend fun postPrivateMessage(
|
||||||
|
recipientId: String,
|
||||||
|
message: String,
|
||||||
|
): List<ChatMessage>? {
|
||||||
val messageObject = HashMap<String, String>()
|
val messageObject = HashMap<String, String>()
|
||||||
messageObject["message"] = message
|
messageObject["message"] = message
|
||||||
messageObject["toUserId"] = recipientId
|
messageObject["toUserId"] = recipientId
|
||||||
|
|
@ -238,17 +288,28 @@ class SocialRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getPartyMembers(id: String) = localRepository.getPartyMembers(id)
|
override suspend fun getPartyMembers(id: String) = localRepository.getPartyMembers(id)
|
||||||
|
|
||||||
override suspend fun getGroupMembers(id: String) = localRepository.getGroupMembers(id)
|
override suspend fun getGroupMembers(id: String) = localRepository.getGroupMembers(id)
|
||||||
|
|
||||||
override suspend fun retrievePartyMembers(id: String, includeAllPublicFields: Boolean): List<Member>? {
|
override suspend fun retrievePartyMembers(
|
||||||
|
id: String,
|
||||||
|
includeAllPublicFields: Boolean,
|
||||||
|
): List<Member>? {
|
||||||
val members = apiClient.getGroupMembers(id, includeAllPublicFields)
|
val members = apiClient.getGroupMembers(id, includeAllPublicFields)
|
||||||
members?.let { localRepository.savePartyMembers(id, it) }
|
members?.let { localRepository.savePartyMembers(id, it) }
|
||||||
return members
|
return members
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun inviteToGroup(id: String, inviteData: Map<String, Any>) = apiClient.inviteToGroup(id, inviteData)
|
override suspend fun inviteToGroup(
|
||||||
|
id: String,
|
||||||
|
inviteData: Map<String, Any>,
|
||||||
|
) =
|
||||||
|
apiClient.inviteToGroup(id, inviteData)
|
||||||
|
|
||||||
override suspend fun retrieveMember(userId: String?, fromHall: Boolean): Member? {
|
override suspend fun retrieveMember(
|
||||||
|
userId: String?,
|
||||||
|
fromHall: Boolean,
|
||||||
|
): Member? {
|
||||||
return if (userId == null) {
|
return if (userId == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -265,9 +326,17 @@ class SocialRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrievegroupInvites(id: String, includeAllPublicFields: Boolean) = apiClient.getGroupInvites(id, includeAllPublicFields)
|
override suspend fun retrievegroupInvites(
|
||||||
|
id: String,
|
||||||
|
includeAllPublicFields: Boolean,
|
||||||
|
) =
|
||||||
|
apiClient.getGroupInvites(id, includeAllPublicFields)
|
||||||
|
|
||||||
override suspend fun findUsernames(username: String, context: String?, id: String?): List<FindUsernameResult>? {
|
override suspend fun findUsernames(
|
||||||
|
username: String,
|
||||||
|
context: String?,
|
||||||
|
id: String?,
|
||||||
|
): List<FindUsernameResult>? {
|
||||||
return apiClient.findUsernames(username, context, id)
|
return apiClient.findUsernames(username, context, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -280,7 +349,10 @@ class SocialRepositoryImpl(
|
||||||
return apiClient.markPrivateMessagesRead()
|
return apiClient.markPrivateMessagesRead()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markSomePrivateMessagesAsRead(user: User?, messages: List<ChatMessage>) {
|
override fun markSomePrivateMessagesAsRead(
|
||||||
|
user: User?,
|
||||||
|
messages: List<ChatMessage>,
|
||||||
|
) {
|
||||||
if (user?.isManaged == true) {
|
if (user?.isManaged == true) {
|
||||||
val numOfUnseenMessages = messages.count { !it.isSeen }
|
val numOfUnseenMessages = messages.count { !it.isSeen }
|
||||||
localRepository.modify(user) {
|
localRepository.modify(user) {
|
||||||
|
|
@ -299,9 +371,13 @@ class SocialRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUserGroups(type: String?) = authenticationHandler.userIDFlow.flatMapLatest { localRepository.getUserGroups(it, type) }
|
override fun getUserGroups(type: String?) =
|
||||||
|
authenticationHandler.userIDFlow.flatMapLatest { localRepository.getUserGroups(it, type) }
|
||||||
|
|
||||||
override suspend fun acceptQuest(user: User?, partyId: String): Void? {
|
override suspend fun acceptQuest(
|
||||||
|
user: User?,
|
||||||
|
partyId: String,
|
||||||
|
): Void? {
|
||||||
apiClient.acceptQuest(partyId)
|
apiClient.acceptQuest(partyId)
|
||||||
user?.let {
|
user?.let {
|
||||||
localRepository.updateRSVPNeeded(it, false)
|
localRepository.updateRSVPNeeded(it, false)
|
||||||
|
|
@ -309,7 +385,10 @@ class SocialRepositoryImpl(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun rejectQuest(user: User?, partyId: String): Void? {
|
override suspend fun rejectQuest(
|
||||||
|
user: User?,
|
||||||
|
partyId: String,
|
||||||
|
): Void? {
|
||||||
apiClient.rejectQuest(partyId)
|
apiClient.rejectQuest(partyId)
|
||||||
user?.let {
|
user?.let {
|
||||||
localRepository.updateRSVPNeeded(it, false)
|
localRepository.updateRSVPNeeded(it, false)
|
||||||
|
|
@ -353,7 +432,10 @@ class SocialRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun transferGems(giftedID: String, amount: Int): Void? {
|
override suspend fun transferGems(
|
||||||
|
giftedID: String,
|
||||||
|
amount: Int,
|
||||||
|
): Void? {
|
||||||
return apiClient.transferGems(giftedID, amount)
|
return apiClient.transferGems(giftedID, amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||||
class TagRepositoryImpl(
|
class TagRepositoryImpl(
|
||||||
localRepository: TagLocalRepository,
|
localRepository: TagLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<TagLocalRepository>(localRepository, apiClient, authenticationHandler),
|
) : BaseRepositoryImpl<TagLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
TagRepository {
|
TagRepository {
|
||||||
|
|
||||||
override fun getTags() = authenticationHandler.userIDFlow.flatMapLatest { getTags(it) }
|
override fun getTags() = authenticationHandler.userIDFlow.flatMapLatest { getTags(it) }
|
||||||
|
|
||||||
override fun getTags(userId: String): Flow<List<Tag>> {
|
override fun getTags(userId: String): Flow<List<Tag>> {
|
||||||
|
|
|
||||||
|
|
@ -39,17 +39,33 @@ class TaskRepositoryImpl(
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler,
|
authenticationHandler: AuthenticationHandler,
|
||||||
val appConfigManager: AppConfigManager,
|
val appConfigManager: AppConfigManager,
|
||||||
) : BaseRepositoryImpl<TaskLocalRepository>(localRepository, apiClient, authenticationHandler), TaskRepository {
|
) : BaseRepositoryImpl<TaskLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
|
TaskRepository {
|
||||||
private var lastTaskAction: Long = 0
|
private var lastTaskAction: Long = 0
|
||||||
|
|
||||||
override fun getTasks(taskType: TaskType, userID: String?, includedGroupIDs: Array<String>): Flow<List<Task>> =
|
override fun getTasks(
|
||||||
this.localRepository.getTasks(taskType, userID ?: authenticationHandler.currentUserID ?: "", includedGroupIDs)
|
taskType: TaskType,
|
||||||
|
userID: String?,
|
||||||
|
includedGroupIDs: Array<String>,
|
||||||
|
): Flow<List<Task>> =
|
||||||
|
this.localRepository.getTasks(
|
||||||
|
taskType,
|
||||||
|
userID ?: authenticationHandler.currentUserID ?: "",
|
||||||
|
includedGroupIDs,
|
||||||
|
)
|
||||||
|
|
||||||
override fun saveTasks(userId: String, order: TasksOrder, tasks: TaskList) {
|
override fun saveTasks(
|
||||||
|
userId: String,
|
||||||
|
order: TasksOrder,
|
||||||
|
tasks: TaskList,
|
||||||
|
) {
|
||||||
localRepository.saveTasks(userId, order, tasks)
|
localRepository.saveTasks(userId, order, tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder): TaskList? {
|
override suspend fun retrieveTasks(
|
||||||
|
userId: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
): TaskList? {
|
||||||
val tasks = apiClient.getTasks() ?: return null
|
val tasks = apiClient.getTasks() ?: return null
|
||||||
this.localRepository.saveTasks(userId, tasksOrder, tasks)
|
this.localRepository.saveTasks(userId, tasksOrder, tasks)
|
||||||
return tasks
|
return tasks
|
||||||
|
|
@ -58,11 +74,18 @@ class TaskRepositoryImpl(
|
||||||
override suspend fun retrieveCompletedTodos(userId: String?): TaskList? {
|
override suspend fun retrieveCompletedTodos(userId: String?): TaskList? {
|
||||||
val taskList = this.apiClient.getTasks("completedTodos") ?: return null
|
val taskList = this.apiClient.getTasks("completedTodos") ?: return null
|
||||||
val tasks = taskList.tasks
|
val tasks = taskList.tasks
|
||||||
this.localRepository.saveCompletedTodos(userId ?: authenticationHandler.currentUserID ?: "", tasks.values)
|
this.localRepository.saveCompletedTodos(
|
||||||
|
userId ?: authenticationHandler.currentUserID ?: "",
|
||||||
|
tasks.values,
|
||||||
|
)
|
||||||
return taskList
|
return taskList
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun retrieveTasks(userId: String, tasksOrder: TasksOrder, dueDate: Date): TaskList? {
|
override suspend fun retrieveTasks(
|
||||||
|
userId: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
dueDate: Date,
|
||||||
|
): TaskList? {
|
||||||
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
||||||
val taskList = this.apiClient.getTasks("dailys", formatter.format(dueDate)) ?: return null
|
val taskList = this.apiClient.getTasks("dailys", formatter.format(dueDate)) ?: return null
|
||||||
this.localRepository.saveTasks(userId, tasksOrder, taskList)
|
this.localRepository.saveTasks(userId, tasksOrder, taskList)
|
||||||
|
|
@ -75,10 +98,15 @@ class TaskRepositoryImpl(
|
||||||
task: Task,
|
task: Task,
|
||||||
up: Boolean,
|
up: Boolean,
|
||||||
force: Boolean,
|
force: Boolean,
|
||||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
notifyFunc: ((TaskScoringResult) -> Unit)?,
|
||||||
): TaskScoringResult? {
|
): TaskScoringResult? {
|
||||||
val localData = if (user != null && appConfigManager.enableLocalTaskScoring()) {
|
val localData =
|
||||||
ScoreTaskLocallyInteractor.score(user, task, if (up) TaskDirection.UP else TaskDirection.DOWN)
|
if (user != null && appConfigManager.enableLocalTaskScoring()) {
|
||||||
|
ScoreTaskLocallyInteractor.score(
|
||||||
|
user,
|
||||||
|
task,
|
||||||
|
if (up) TaskDirection.UP else TaskDirection.DOWN,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
@ -96,9 +124,15 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTaskAction = now
|
lastTaskAction = now
|
||||||
val res = this.apiClient.postTaskDirection(id, (if (up) TaskDirection.UP else TaskDirection.DOWN).text) ?: return null
|
val res =
|
||||||
|
this.apiClient.postTaskDirection(
|
||||||
|
id,
|
||||||
|
(if (up) TaskDirection.UP else TaskDirection.DOWN).text,
|
||||||
|
) ?: return null
|
||||||
// There are cases where the user object is not set correctly. So the app refetches it as a fallback
|
// There are cases where the user object is not set correctly. So the app refetches it as a fallback
|
||||||
val thisUser = user ?: localRepository.getUser(authenticationHandler.currentUserID ?: "").firstOrNull() ?: return null
|
val thisUser =
|
||||||
|
user ?: localRepository.getUser(authenticationHandler.currentUserID ?: "").firstOrNull()
|
||||||
|
?: return null
|
||||||
// save local task changes
|
// save local task changes
|
||||||
|
|
||||||
Analytics.sendEvent(
|
Analytics.sendEvent(
|
||||||
|
|
@ -108,8 +142,8 @@ class TaskRepositoryImpl(
|
||||||
mapOf(
|
mapOf(
|
||||||
"type" to (task.type ?: ""),
|
"type" to (task.type ?: ""),
|
||||||
"scored_up" to up,
|
"scored_up" to up,
|
||||||
"value" to task.value
|
"value" to task.value,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
if (res.lvl == 0) {
|
if (res.lvl == 0) {
|
||||||
// Team tasks that require approval have weird data that we should just ignore.
|
// Team tasks that require approval have weird data that we should just ignore.
|
||||||
|
|
@ -132,7 +166,7 @@ class TaskRepositoryImpl(
|
||||||
res: TaskDirectionData,
|
res: TaskDirectionData,
|
||||||
task: Task,
|
task: Task,
|
||||||
up: Boolean,
|
up: Boolean,
|
||||||
localDelta: Float
|
localDelta: Float,
|
||||||
) {
|
) {
|
||||||
this.localRepository.executeTransaction {
|
this.localRepository.executeTransaction {
|
||||||
val bgTask = localRepository.getLiveObject(task) ?: return@executeTransaction
|
val bgTask = localRepository.getLiveObject(task) ?: return@executeTransaction
|
||||||
|
|
@ -157,7 +191,8 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bgTask.isGroupTask) {
|
if (bgTask.isGroupTask) {
|
||||||
val entry = bgTask.group?.assignedUsersDetail?.firstOrNull { it.assignedUserID == user.id }
|
val entry =
|
||||||
|
bgTask.group?.assignedUsersDetail?.firstOrNull { it.assignedUserID == user.id }
|
||||||
entry?.completed = up
|
entry?.completed = up
|
||||||
if (up) {
|
if (up) {
|
||||||
entry?.completedDate = Date()
|
entry?.completedDate = Date()
|
||||||
|
|
@ -167,12 +202,15 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res._tmp?.drop?.key?.let { key ->
|
res._tmp?.drop?.key?.let { key ->
|
||||||
val type = when (res._tmp?.drop?.type?.lowercase(Locale.US)) {
|
val type =
|
||||||
|
when (res._tmp?.drop?.type?.lowercase(Locale.US)) {
|
||||||
"hatchingpotion" -> "hatchingPotions"
|
"hatchingpotion" -> "hatchingPotions"
|
||||||
"egg" -> "eggs"
|
"egg" -> "eggs"
|
||||||
else -> res._tmp?.drop?.type?.lowercase(Locale.US)
|
else -> res._tmp?.drop?.type?.lowercase(Locale.US)
|
||||||
}
|
}
|
||||||
var item = it.where(OwnedItem::class.java).equalTo("itemType", type).equalTo("key", key).findFirst()
|
var item =
|
||||||
|
it.where(OwnedItem::class.java).equalTo("itemType", type).equalTo("key", key)
|
||||||
|
.findFirst()
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
item = OwnedItem()
|
item = OwnedItem()
|
||||||
item.key = key
|
item.key = key
|
||||||
|
|
@ -201,7 +239,10 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun markTaskNeedsWork(task: Task, userID: String) {
|
override suspend fun markTaskNeedsWork(
|
||||||
|
task: Task,
|
||||||
|
userID: String,
|
||||||
|
) {
|
||||||
val savedTask = apiClient.markTaskNeedsWork(task.id ?: "", userID)
|
val savedTask = apiClient.markTaskNeedsWork(task.id ?: "", userID)
|
||||||
if (savedTask != null) {
|
if (savedTask != null) {
|
||||||
savedTask.id = task.id
|
savedTask.id = task.id
|
||||||
|
|
@ -219,13 +260,16 @@ class TaskRepositoryImpl(
|
||||||
taskId: String,
|
taskId: String,
|
||||||
up: Boolean,
|
up: Boolean,
|
||||||
force: Boolean,
|
force: Boolean,
|
||||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
notifyFunc: ((TaskScoringResult) -> Unit)?,
|
||||||
): TaskScoringResult? {
|
): TaskScoringResult? {
|
||||||
val task = localRepository.getTask(taskId).firstOrNull() ?: return null
|
val task = localRepository.getTask(taskId).firstOrNull() ?: return null
|
||||||
return taskChecked(user, task, up, force, notifyFunc)
|
return taskChecked(user, task, up, force, notifyFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun scoreChecklistItem(taskId: String, itemId: String): Task? {
|
override suspend fun scoreChecklistItem(
|
||||||
|
taskId: String,
|
||||||
|
itemId: String,
|
||||||
|
): Task? {
|
||||||
val task = apiClient.scoreChecklistItem(taskId, itemId)
|
val task = apiClient.scoreChecklistItem(taskId, itemId)
|
||||||
val updatedItem: ChecklistItem? = task?.checklist?.lastOrNull { itemId == it.id }
|
val updatedItem: ChecklistItem? = task?.checklist?.lastOrNull { itemId == it.id }
|
||||||
if (updatedItem != null) {
|
if (updatedItem != null) {
|
||||||
|
|
@ -238,7 +282,10 @@ class TaskRepositoryImpl(
|
||||||
|
|
||||||
override fun getTaskCopy(taskId: String) = localRepository.getTaskCopy(taskId)
|
override fun getTaskCopy(taskId: String) = localRepository.getTaskCopy(taskId)
|
||||||
|
|
||||||
override suspend fun createTask(task: Task, force: Boolean): Task? {
|
override suspend fun createTask(
|
||||||
|
task: Task,
|
||||||
|
force: Boolean,
|
||||||
|
): Task? {
|
||||||
val now = Date().time
|
val now = Date().time
|
||||||
if (lastTaskAction > now - 500 && !force) {
|
if (lastTaskAction > now - 500 && !force) {
|
||||||
return null
|
return null
|
||||||
|
|
@ -248,7 +295,8 @@ class TaskRepositoryImpl(
|
||||||
task.isSaving = true
|
task.isSaving = true
|
||||||
task.isCreating = true
|
task.isCreating = true
|
||||||
task.hasErrored = false
|
task.hasErrored = false
|
||||||
task.ownerID = if (task.isGroupTask) {
|
task.ownerID =
|
||||||
|
if (task.isGroupTask) {
|
||||||
task.group?.groupID ?: ""
|
task.group?.groupID ?: ""
|
||||||
} else {
|
} else {
|
||||||
authenticationHandler.currentUserID ?: ""
|
authenticationHandler.currentUserID ?: ""
|
||||||
|
|
@ -258,7 +306,8 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
localRepository.save(task)
|
localRepository.save(task)
|
||||||
|
|
||||||
val savedTask = if (task.isGroupTask) {
|
val savedTask =
|
||||||
|
if (task.isGroupTask) {
|
||||||
apiClient.createGroupTask(task.group?.groupID ?: "", task)
|
apiClient.createGroupTask(task.group?.groupID ?: "", task)
|
||||||
} else {
|
} else {
|
||||||
apiClient.createTask(task)
|
apiClient.createTask(task)
|
||||||
|
|
@ -276,7 +325,10 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("ReturnCount")
|
@Suppress("ReturnCount")
|
||||||
override suspend fun updateTask(task: Task, force: Boolean): Task? {
|
override suspend fun updateTask(
|
||||||
|
task: Task,
|
||||||
|
force: Boolean,
|
||||||
|
): Task? {
|
||||||
val now = Date().time
|
val now = Date().time
|
||||||
if ((lastTaskAction > now - 500 && !force) || !task.isValid) {
|
if ((lastTaskAction > now - 500 && !force) || !task.isValid) {
|
||||||
return task
|
return task
|
||||||
|
|
@ -314,41 +366,64 @@ class TaskRepositoryImpl(
|
||||||
|
|
||||||
override suspend fun createTasks(newTasks: List<Task>) = apiClient.createTasks(newTasks)
|
override suspend fun createTasks(newTasks: List<Task>) = apiClient.createTasks(newTasks)
|
||||||
|
|
||||||
override fun markTaskCompleted(taskId: String, isCompleted: Boolean) {
|
override fun markTaskCompleted(
|
||||||
|
taskId: String,
|
||||||
|
isCompleted: Boolean,
|
||||||
|
) {
|
||||||
localRepository.markTaskCompleted(taskId, isCompleted)
|
localRepository.markTaskCompleted(taskId, isCompleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : BaseMainObject> modify(obj: T, transaction: (T) -> Unit) {
|
override fun <T : BaseMainObject> modify(
|
||||||
|
obj: T,
|
||||||
|
transaction: (T) -> Unit,
|
||||||
|
) {
|
||||||
localRepository.modify(obj, transaction)
|
localRepository.modify(obj, transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun swapTaskPosition(firstPosition: Int, secondPosition: Int) {
|
override fun swapTaskPosition(
|
||||||
|
firstPosition: Int,
|
||||||
|
secondPosition: Int,
|
||||||
|
) {
|
||||||
localRepository.swapTaskPosition(firstPosition, secondPosition)
|
localRepository.swapTaskPosition(firstPosition, secondPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateTaskPosition(taskType: TaskType, taskID: String, newPosition: Int): List<String>? {
|
override suspend fun updateTaskPosition(
|
||||||
|
taskType: TaskType,
|
||||||
|
taskID: String,
|
||||||
|
newPosition: Int,
|
||||||
|
): List<String>? {
|
||||||
val positions = apiClient.postTaskNewPosition(taskID, newPosition) ?: return null
|
val positions = apiClient.postTaskNewPosition(taskID, newPosition) ?: return null
|
||||||
localRepository.updateTaskPositions(positions)
|
localRepository.updateTaskPositions(positions)
|
||||||
return positions
|
return positions
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUnmanagedTask(taskid: String) = getTask(taskid).map { localRepository.getUnmanagedCopy(it) }
|
override fun getUnmanagedTask(taskid: String) =
|
||||||
|
getTask(taskid).map { localRepository.getUnmanagedCopy(it) }
|
||||||
|
|
||||||
override fun updateTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
override fun updateTaskInBackground(
|
||||||
|
task: Task,
|
||||||
|
assignChanges: Map<String, MutableList<String>>,
|
||||||
|
) {
|
||||||
MainScope().launchCatching {
|
MainScope().launchCatching {
|
||||||
val updatedTask = updateTask(task) ?: return@launchCatching
|
val updatedTask = updateTask(task) ?: return@launchCatching
|
||||||
handleAssignmentChanges(updatedTask, assignChanges)
|
handleAssignmentChanges(updatedTask, assignChanges)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createTaskInBackground(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
override fun createTaskInBackground(
|
||||||
|
task: Task,
|
||||||
|
assignChanges: Map<String, MutableList<String>>,
|
||||||
|
) {
|
||||||
MainScope().launchCatching {
|
MainScope().launchCatching {
|
||||||
val createdTask = createTask(task) ?: return@launchCatching
|
val createdTask = createTask(task) ?: return@launchCatching
|
||||||
handleAssignmentChanges(createdTask, assignChanges)
|
handleAssignmentChanges(createdTask, assignChanges)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun handleAssignmentChanges(task: Task, assignChanges: Map<String, MutableList<String>>) {
|
private suspend fun handleAssignmentChanges(
|
||||||
|
task: Task,
|
||||||
|
assignChanges: Map<String, MutableList<String>>,
|
||||||
|
) {
|
||||||
val taskID = task.id ?: return
|
val taskID = task.id ?: return
|
||||||
assignChanges["assign"]?.let { assignments ->
|
assignChanges["assign"]?.let { assignments ->
|
||||||
if (assignments.isEmpty()) return@let
|
if (assignments.isEmpty()) return@let
|
||||||
|
|
@ -373,11 +448,13 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTaskCopies(): Flow<List<Task>> = authenticationHandler.userIDFlow.flatMapLatest {
|
override fun getTaskCopies(): Flow<List<Task>> =
|
||||||
|
authenticationHandler.userIDFlow.flatMapLatest {
|
||||||
localRepository.getTasks(it)
|
localRepository.getTasks(it)
|
||||||
}.map { localRepository.getUnmanagedCopy(it) }
|
}.map { localRepository.getUnmanagedCopy(it) }
|
||||||
|
|
||||||
override fun getTaskCopies(tasks: List<Task>): List<Task> = localRepository.getUnmanagedCopy(tasks)
|
override fun getTaskCopies(tasks: List<Task>): List<Task> =
|
||||||
|
localRepository.getUnmanagedCopy(tasks)
|
||||||
|
|
||||||
override suspend fun retrieveDailiesFromDate(date: Date): TaskList? {
|
override suspend fun retrieveDailiesFromDate(date: Date): TaskList? {
|
||||||
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ", Locale.US)
|
||||||
|
|
@ -385,7 +462,7 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun syncErroredTasks(): List<Task>? {
|
override suspend fun syncErroredTasks(): List<Task>? {
|
||||||
val tasks = localRepository.getErroredTasks(currentUserID ?: "").firstOrNull()
|
val tasks = localRepository.getErroredTasks(currentUserID).firstOrNull()
|
||||||
return tasks?.map { localRepository.getUnmanagedCopy(it) }?.mapNotNull {
|
return tasks?.map { localRepository.getUnmanagedCopy(it) }?.mapNotNull {
|
||||||
if (it.isCreating) {
|
if (it.isCreating) {
|
||||||
createTask(it, true)
|
createTask(it, true)
|
||||||
|
|
@ -395,11 +472,14 @@ class TaskRepositoryImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun unlinkAllTasks(challengeID: String?, keepOption: String): Void? {
|
override suspend fun unlinkAllTasks(
|
||||||
|
challengeID: String?,
|
||||||
|
keepOption: String,
|
||||||
|
): Void? {
|
||||||
return apiClient.unlinkAllTasks(challengeID, keepOption)
|
return apiClient.unlinkAllTasks(challengeID, keepOption)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTasksForChallenge(challengeID: String?): Flow<List<Task>> {
|
override fun getTasksForChallenge(challengeID: String?): Flow<List<Task>> {
|
||||||
return localRepository.getTasksForChallenge(challengeID, currentUserID ?: "")
|
return localRepository.getTasksForChallenge(challengeID, currentUserID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@ import kotlinx.coroutines.flow.Flow
|
||||||
class TutorialRepositoryImpl(
|
class TutorialRepositoryImpl(
|
||||||
localRepository: TutorialLocalRepository,
|
localRepository: TutorialLocalRepository,
|
||||||
apiClient: ApiClient,
|
apiClient: ApiClient,
|
||||||
authenticationHandler: AuthenticationHandler
|
authenticationHandler: AuthenticationHandler,
|
||||||
) : BaseRepositoryImpl<TutorialLocalRepository>(localRepository, apiClient, authenticationHandler), TutorialRepository {
|
) : BaseRepositoryImpl<TutorialLocalRepository>(localRepository, apiClient, authenticationHandler),
|
||||||
|
TutorialRepository {
|
||||||
override fun getTutorialStep(key: String): Flow<TutorialStep> =
|
override fun getTutorialStep(key: String): Flow<TutorialStep> =
|
||||||
localRepository.getTutorialStep(key)
|
localRepository.getTutorialStep(key)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,21 +6,28 @@ import com.habitrpg.android.habitica.models.user.User
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
|
|
||||||
interface BaseLocalRepository {
|
interface BaseLocalRepository {
|
||||||
|
|
||||||
val isClosed: Boolean
|
val isClosed: Boolean
|
||||||
var realm: Realm
|
var realm: Realm
|
||||||
|
|
||||||
fun close()
|
fun close()
|
||||||
|
|
||||||
fun executeTransaction(transaction: (Realm) -> Unit)
|
fun executeTransaction(transaction: (Realm) -> Unit)
|
||||||
fun <T : BaseMainObject> modify(obj: T, transaction: (T) -> Unit)
|
|
||||||
|
fun <T : BaseMainObject> modify(
|
||||||
|
obj: T,
|
||||||
|
transaction: (T) -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
fun <T : BaseObject> getLiveObject(obj: T): T?
|
fun <T : BaseObject> getLiveObject(obj: T): T?
|
||||||
|
|
||||||
fun <T : BaseObject> getUnmanagedCopy(managedObject: T): T
|
fun <T : BaseObject> getUnmanagedCopy(managedObject: T): T
|
||||||
|
|
||||||
fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T>
|
fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T>
|
||||||
|
|
||||||
fun <T : BaseObject> save(objects: List<T>)
|
fun <T : BaseObject> save(objects: List<T>)
|
||||||
|
|
||||||
fun <T : BaseObject> save(`object`: T)
|
fun <T : BaseObject> save(`object`: T)
|
||||||
|
|
||||||
fun <T : BaseMainObject> delete(obj: T)
|
fun <T : BaseMainObject> delete(obj: T)
|
||||||
|
|
||||||
fun getLiveUser(id: String): User?
|
fun getLiveUser(id: String): User?
|
||||||
|
|
|
||||||
|
|
@ -6,22 +6,36 @@ import com.habitrpg.android.habitica.models.tasks.Task
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface ChallengeLocalRepository : BaseLocalRepository {
|
interface ChallengeLocalRepository : BaseLocalRepository {
|
||||||
|
|
||||||
val challenges: Flow<List<Challenge>>
|
val challenges: Flow<List<Challenge>>
|
||||||
|
|
||||||
fun getChallenge(id: String): Flow<Challenge>
|
fun getChallenge(id: String): Flow<Challenge>
|
||||||
|
|
||||||
fun getTasks(challengeID: String): Flow<List<Task>>
|
fun getTasks(challengeID: String): Flow<List<Task>>
|
||||||
|
|
||||||
fun getUserChallenges(userId: String): Flow<List<Challenge>>
|
fun getUserChallenges(userId: String): Flow<List<Challenge>>
|
||||||
|
|
||||||
fun setParticipating(userID: String, challengeID: String, isParticipating: Boolean)
|
fun setParticipating(
|
||||||
|
userID: String,
|
||||||
|
challengeID: String,
|
||||||
|
isParticipating: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun saveChallenges(
|
fun saveChallenges(
|
||||||
challenges: List<Challenge>,
|
challenges: List<Challenge>,
|
||||||
clearChallenges: Boolean,
|
clearChallenges: Boolean,
|
||||||
memberOnly: Boolean,
|
memberOnly: Boolean,
|
||||||
userID: String
|
userID: String,
|
||||||
)
|
)
|
||||||
fun getChallengeMembership(userId: String, id: String): Flow<ChallengeMembership>
|
|
||||||
|
fun getChallengeMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
): Flow<ChallengeMembership>
|
||||||
|
|
||||||
fun getChallengeMemberships(userId: String): Flow<List<ChallengeMembership>>
|
fun getChallengeMemberships(userId: String): Flow<List<ChallengeMembership>>
|
||||||
fun isChallengeMember(userID: String, challengeID: String): Flow<Boolean>
|
|
||||||
|
fun isChallengeMember(
|
||||||
|
userID: String,
|
||||||
|
challengeID: String,
|
||||||
|
): Flow<Boolean>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface ContentLocalRepository : BaseLocalRepository {
|
interface ContentLocalRepository : BaseLocalRepository {
|
||||||
fun saveContent(contentResult: ContentResult)
|
fun saveContent(contentResult: ContentResult)
|
||||||
|
|
||||||
fun saveWorldState(worldState: WorldState)
|
fun saveWorldState(worldState: WorldState)
|
||||||
|
|
||||||
fun getWorldState(): Flow<WorldState>
|
fun getWorldState(): Flow<WorldState>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,9 @@ import com.habitrpg.android.habitica.models.inventory.Customization
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface CustomizationLocalRepository : ContentLocalRepository {
|
interface CustomizationLocalRepository : ContentLocalRepository {
|
||||||
fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>>
|
fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
category: String?,
|
||||||
|
onlyAvailable: Boolean,
|
||||||
|
): Flow<List<Customization>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import com.habitrpg.android.habitica.models.user.User
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface InventoryLocalRepository : ContentLocalRepository {
|
interface InventoryLocalRepository : ContentLocalRepository {
|
||||||
|
|
||||||
fun getArmoireRemainingCount(): Flow<Int>
|
fun getArmoireRemainingCount(): Flow<Int>
|
||||||
|
|
||||||
fun getOwnedEquipment(): Flow<List<Equipment>>
|
fun getOwnedEquipment(): Flow<List<Equipment>>
|
||||||
|
|
||||||
fun getMounts(): Flow<List<Mount>>
|
fun getMounts(): Flow<List<Mount>>
|
||||||
|
|
@ -27,44 +27,116 @@ interface InventoryLocalRepository : ContentLocalRepository {
|
||||||
fun getOwnedPets(userID: String): Flow<List<OwnedPet>>
|
fun getOwnedPets(userID: String): Flow<List<OwnedPet>>
|
||||||
|
|
||||||
fun getInAppRewards(): Flow<List<ShopItem>>
|
fun getInAppRewards(): Flow<List<ShopItem>>
|
||||||
|
|
||||||
fun getInAppReward(key: String): Flow<ShopItem>
|
fun getInAppReward(key: String): Flow<ShopItem>
|
||||||
|
|
||||||
fun getQuestContent(key: String): Flow<QuestContent?>
|
fun getQuestContent(key: String): Flow<QuestContent?>
|
||||||
|
|
||||||
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
fun getQuestContent(keys: List<String>): Flow<List<QuestContent>>
|
||||||
|
|
||||||
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
fun getEquipment(searchedKeys: List<String>): Flow<List<Equipment>>
|
||||||
|
|
||||||
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
fun getOwnedEquipment(type: String): Flow<List<Equipment>>
|
||||||
|
|
||||||
fun getOwnedItems(itemType: String, userID: String, includeZero: Boolean): Flow<List<OwnedItem>>
|
fun getOwnedItems(
|
||||||
fun getOwnedItems(userID: String, includeZero: Boolean): Flow<Map<String, OwnedItem>>
|
itemType: String,
|
||||||
fun getEquipmentType(type: String, set: String): Flow<List<Equipment>>
|
userID: String,
|
||||||
|
includeZero: Boolean,
|
||||||
|
): Flow<List<OwnedItem>>
|
||||||
|
|
||||||
|
fun getOwnedItems(
|
||||||
|
userID: String,
|
||||||
|
includeZero: Boolean,
|
||||||
|
): Flow<Map<String, OwnedItem>>
|
||||||
|
|
||||||
|
fun getEquipmentType(
|
||||||
|
type: String,
|
||||||
|
set: String,
|
||||||
|
): Flow<List<Equipment>>
|
||||||
|
|
||||||
fun getEquipment(key: String): Flow<Equipment>
|
fun getEquipment(key: String): Flow<Equipment>
|
||||||
fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>>
|
|
||||||
fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>>
|
fun getMounts(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Mount>>
|
||||||
|
|
||||||
|
fun getPets(
|
||||||
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Pet>>
|
||||||
|
|
||||||
fun updateOwnedEquipment(user: User)
|
fun updateOwnedEquipment(user: User)
|
||||||
|
|
||||||
suspend fun changeOwnedCount(type: String, key: String, userID: String, amountToAdd: Int)
|
suspend fun changeOwnedCount(
|
||||||
fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?)
|
type: String,
|
||||||
|
key: String,
|
||||||
|
userID: String,
|
||||||
|
amountToAdd: Int,
|
||||||
|
)
|
||||||
|
|
||||||
fun getItem(type: String, key: String): Flow<Item>
|
fun changeOwnedCount(
|
||||||
fun getOwnedItem(userID: String, type: String, key: String, includeZero: Boolean): Flow<OwnedItem>
|
item: OwnedItem,
|
||||||
|
amountToAdd: Int?,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getItem(
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Flow<Item>
|
||||||
|
|
||||||
|
fun getOwnedItem(
|
||||||
|
userID: String,
|
||||||
|
type: String,
|
||||||
|
key: String,
|
||||||
|
includeZero: Boolean,
|
||||||
|
): Flow<OwnedItem>
|
||||||
|
|
||||||
fun decrementMysteryItemCount(user: User?)
|
fun decrementMysteryItemCount(user: User?)
|
||||||
|
|
||||||
fun saveInAppRewards(onlineItems: List<ShopItem>)
|
fun saveInAppRewards(onlineItems: List<ShopItem>)
|
||||||
|
|
||||||
fun hatchPet(eggKey: String, potionKey: String, userID: String)
|
fun hatchPet(
|
||||||
fun unhatchPet(eggKey: String, potionKey: String, userID: String)
|
eggKey: String,
|
||||||
fun feedPet(foodKey: String, petKey: String, feedValue: Int, userID: String)
|
potionKey: String,
|
||||||
|
userID: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun unhatchPet(
|
||||||
|
eggKey: String,
|
||||||
|
potionKey: String,
|
||||||
|
userID: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun feedPet(
|
||||||
|
foodKey: String,
|
||||||
|
petKey: String,
|
||||||
|
feedValue: Int,
|
||||||
|
userID: String,
|
||||||
|
)
|
||||||
|
|
||||||
fun getLatestMysteryItem(): Flow<Equipment>
|
fun getLatestMysteryItem(): Flow<Equipment>
|
||||||
fun soldItem(userID: String, updatedUser: User): User
|
|
||||||
|
fun soldItem(
|
||||||
|
userID: String,
|
||||||
|
updatedUser: User,
|
||||||
|
): User
|
||||||
|
|
||||||
fun getAvailableLimitedItems(): Flow<List<Item>>
|
fun getAvailableLimitedItems(): Flow<List<Item>>
|
||||||
|
|
||||||
fun save(items: Items, userID: String)
|
fun save(
|
||||||
|
items: Items,
|
||||||
|
userID: String,
|
||||||
|
)
|
||||||
|
|
||||||
fun getLiveObject(obj: OwnedItem): OwnedItem?
|
fun getLiveObject(obj: OwnedItem): OwnedItem?
|
||||||
|
|
||||||
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
fun getItems(itemClass: Class<out Item>): Flow<List<Item>>
|
||||||
fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>>
|
|
||||||
|
fun getItems(
|
||||||
|
itemClass: Class<out Item>,
|
||||||
|
keys: Array<String>,
|
||||||
|
): Flow<List<Item>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,13 @@ import io.realm.RealmResults
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface SocialLocalRepository : BaseLocalRepository {
|
interface SocialLocalRepository : BaseLocalRepository {
|
||||||
fun getUserGroups(userID: String, type: String?): Flow<List<Group>>
|
fun getUserGroups(
|
||||||
|
userID: String,
|
||||||
|
type: String?,
|
||||||
|
): Flow<List<Group>>
|
||||||
|
|
||||||
fun getGroup(id: String): Flow<Group?>
|
fun getGroup(id: String): Flow<Group?>
|
||||||
|
|
||||||
fun saveGroup(group: Group)
|
fun saveGroup(group: Group)
|
||||||
|
|
||||||
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
fun getGroupChat(groupId: String): Flow<List<ChatMessage>>
|
||||||
|
|
@ -20,36 +24,80 @@ interface SocialLocalRepository : BaseLocalRepository {
|
||||||
fun deleteMessage(id: String)
|
fun deleteMessage(id: String)
|
||||||
|
|
||||||
fun getPartyMembers(partyId: String): Flow<List<Member>>
|
fun getPartyMembers(partyId: String): Flow<List<Member>>
|
||||||
|
|
||||||
fun getGroupMembers(groupID: String): Flow<List<Member>>
|
fun getGroupMembers(groupID: String): Flow<List<Member>>
|
||||||
|
|
||||||
fun updateRSVPNeeded(user: User?, newValue: Boolean)
|
fun updateRSVPNeeded(
|
||||||
|
user: User?,
|
||||||
|
newValue: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun likeMessage(chatMessage: ChatMessage, userId: String, liked: Boolean)
|
fun likeMessage(
|
||||||
|
chatMessage: ChatMessage,
|
||||||
|
userId: String,
|
||||||
|
liked: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun savePartyMembers(groupId: String?, members: List<Member>)
|
fun savePartyMembers(
|
||||||
|
groupId: String?,
|
||||||
|
members: List<Member>,
|
||||||
|
)
|
||||||
|
|
||||||
fun removeQuest(partyId: String)
|
fun removeQuest(partyId: String)
|
||||||
|
|
||||||
fun setQuestActivity(party: Group?, active: Boolean)
|
fun setQuestActivity(
|
||||||
|
party: Group?,
|
||||||
|
active: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun saveChatMessages(groupId: String?, chatMessages: List<ChatMessage>)
|
fun saveChatMessages(
|
||||||
|
groupId: String?,
|
||||||
|
chatMessages: List<ChatMessage>,
|
||||||
|
)
|
||||||
|
|
||||||
fun doesGroupExist(id: String): Boolean
|
fun doesGroupExist(id: String): Boolean
|
||||||
fun updateMembership(userId: String, id: String, isMember: Boolean)
|
|
||||||
fun getGroupMembership(userId: String, id: String): Flow<GroupMembership?>
|
|
||||||
fun getGroupMemberships(userId: String): Flow<List<GroupMembership>>
|
|
||||||
fun rejectGroupInvitation(userID: String, groupID: String)
|
|
||||||
|
|
||||||
fun getInboxMessages(userId: String, replyToUserID: String?): Flow<RealmResults<ChatMessage>>
|
fun updateMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
isMember: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getGroupMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
): Flow<GroupMembership?>
|
||||||
|
|
||||||
|
fun getGroupMemberships(userId: String): Flow<List<GroupMembership>>
|
||||||
|
|
||||||
|
fun rejectGroupInvitation(
|
||||||
|
userID: String,
|
||||||
|
groupID: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun getInboxMessages(
|
||||||
|
userId: String,
|
||||||
|
replyToUserID: String?,
|
||||||
|
): Flow<RealmResults<ChatMessage>>
|
||||||
|
|
||||||
fun getInboxConversation(userId: String): Flow<RealmResults<InboxConversation>>
|
fun getInboxConversation(userId: String): Flow<RealmResults<InboxConversation>>
|
||||||
fun saveGroupMemberships(userID: String?, memberships: List<GroupMembership>)
|
|
||||||
|
fun saveGroupMemberships(
|
||||||
|
userID: String?,
|
||||||
|
memberships: List<GroupMembership>,
|
||||||
|
)
|
||||||
|
|
||||||
fun saveInboxMessages(
|
fun saveInboxMessages(
|
||||||
userID: String,
|
userID: String,
|
||||||
recipientID: String,
|
recipientID: String,
|
||||||
messages: List<ChatMessage>,
|
messages: List<ChatMessage>,
|
||||||
page: Int
|
page: Int,
|
||||||
)
|
)
|
||||||
fun saveInboxConversations(userID: String, conversations: List<InboxConversation>)
|
|
||||||
|
fun saveInboxConversations(
|
||||||
|
userID: String,
|
||||||
|
conversations: List<InboxConversation>,
|
||||||
|
)
|
||||||
|
|
||||||
fun getMember(userID: String?): Flow<Member?>
|
fun getMember(userID: String?): Flow<Member?>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,56 @@ import com.habitrpg.shared.habitica.models.tasks.TasksOrder
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TaskLocalRepository : BaseLocalRepository {
|
interface TaskLocalRepository : BaseLocalRepository {
|
||||||
|
fun getTasks(
|
||||||
|
taskType: TaskType,
|
||||||
|
userID: String,
|
||||||
|
includedGroupIDs: Array<String>,
|
||||||
|
): Flow<List<Task>>
|
||||||
|
|
||||||
fun getTasks(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flow<List<Task>>
|
|
||||||
fun getTasks(userId: String): Flow<List<Task>>
|
fun getTasks(userId: String): Flow<List<Task>>
|
||||||
|
|
||||||
fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList)
|
fun saveTasks(
|
||||||
|
ownerID: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
tasks: TaskList,
|
||||||
|
)
|
||||||
|
|
||||||
fun deleteTask(taskID: String)
|
fun deleteTask(taskID: String)
|
||||||
|
|
||||||
fun getTask(taskId: String): Flow<Task>
|
fun getTask(taskId: String): Flow<Task>
|
||||||
|
|
||||||
fun getTaskCopy(taskId: String): Flow<Task>
|
fun getTaskCopy(taskId: String): Flow<Task>
|
||||||
|
|
||||||
fun markTaskCompleted(taskId: String, isCompleted: Boolean)
|
fun markTaskCompleted(
|
||||||
|
taskId: String,
|
||||||
|
isCompleted: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
fun swapTaskPosition(firstPosition: Int, secondPosition: Int)
|
fun swapTaskPosition(
|
||||||
|
firstPosition: Int,
|
||||||
|
secondPosition: Int,
|
||||||
|
)
|
||||||
|
|
||||||
fun getTaskAtPosition(taskType: String, position: Int): Flow<Task>
|
fun getTaskAtPosition(
|
||||||
|
taskType: String,
|
||||||
|
position: Int,
|
||||||
|
): Flow<Task>
|
||||||
|
|
||||||
fun updateIsdue(daily: TaskList): TaskList
|
fun updateIsdue(daily: TaskList): TaskList
|
||||||
|
|
||||||
fun updateTaskPositions(taskOrder: List<String>)
|
fun updateTaskPositions(taskOrder: List<String>)
|
||||||
fun saveCompletedTodos(userId: String, tasks: MutableCollection<Task>)
|
|
||||||
|
fun saveCompletedTodos(
|
||||||
|
userId: String,
|
||||||
|
tasks: MutableCollection<Task>,
|
||||||
|
)
|
||||||
|
|
||||||
fun getErroredTasks(userID: String): Flow<List<Task>>
|
fun getErroredTasks(userID: String): Flow<List<Task>>
|
||||||
|
|
||||||
fun getUser(userID: String): Flow<User>
|
fun getUser(userID: String): Flow<User>
|
||||||
fun getTasksForChallenge(challengeID: String?, userID: String?): Flow<List<Task>>
|
|
||||||
|
fun getTasksForChallenge(
|
||||||
|
challengeID: String?,
|
||||||
|
userID: String?,
|
||||||
|
): Flow<List<Task>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import com.habitrpg.android.habitica.models.TutorialStep
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface TutorialLocalRepository : BaseLocalRepository {
|
interface TutorialLocalRepository : BaseLocalRepository {
|
||||||
|
|
||||||
fun getTutorialStep(key: String): Flow<TutorialStep>
|
fun getTutorialStep(key: String): Flow<TutorialStep>
|
||||||
|
|
||||||
fun getTutorialSteps(keys: List<String>): Flow<List<TutorialStep>>
|
fun getTutorialSteps(keys: List<String>): Flow<List<TutorialStep>>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,28 @@ import io.realm.RealmResults
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface UserLocalRepository : BaseLocalRepository {
|
interface UserLocalRepository : BaseLocalRepository {
|
||||||
|
|
||||||
suspend fun getTutorialSteps(): Flow<RealmResults<TutorialStep>>
|
suspend fun getTutorialSteps(): Flow<RealmResults<TutorialStep>>
|
||||||
|
|
||||||
fun getUser(userID: String): Flow<User?>
|
fun getUser(userID: String): Flow<User?>
|
||||||
fun saveUser(user: User, overrideExisting: Boolean = true)
|
|
||||||
|
fun saveUser(
|
||||||
|
user: User,
|
||||||
|
overrideExisting: Boolean = true,
|
||||||
|
)
|
||||||
|
|
||||||
fun saveMessages(messages: List<ChatMessage>)
|
fun saveMessages(messages: List<ChatMessage>)
|
||||||
|
|
||||||
fun getSkills(user: User): Flow<List<Skill>>
|
fun getSkills(user: User): Flow<List<Skill>>
|
||||||
|
|
||||||
fun getSpecialItems(user: User): Flow<List<Skill>>
|
fun getSpecialItems(user: User): Flow<List<Skill>>
|
||||||
|
|
||||||
fun getAchievements(): Flow<List<Achievement>>
|
fun getAchievements(): Flow<List<Achievement>>
|
||||||
|
|
||||||
fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>>
|
fun getQuestAchievements(userID: String): Flow<List<QuestAchievement>>
|
||||||
|
|
||||||
fun getUserQuestStatus(userID: String): Flow<UserQuestStatus>
|
fun getUserQuestStatus(userID: String): Flow<UserQuestStatus>
|
||||||
|
|
||||||
fun getTeamPlans(userID: String): Flow<List<TeamPlan>>
|
fun getTeamPlans(userID: String): Flow<List<TeamPlan>>
|
||||||
|
|
||||||
fun getTeamPlan(teamID: String): Flow<Group?>
|
fun getTeamPlan(teamID: String): Flow<Group?>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
abstract class RealmBaseLocalRepository internal constructor(override var realm: Realm) : BaseLocalRepository {
|
abstract class RealmBaseLocalRepository internal constructor(override var realm: Realm) :
|
||||||
|
BaseLocalRepository {
|
||||||
override val isClosed: Boolean
|
override val isClosed: Boolean
|
||||||
get() = realm.isClosed
|
get() = realm.isClosed
|
||||||
|
|
||||||
|
|
@ -39,7 +39,9 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T> {
|
override fun <T : BaseObject> getUnmanagedCopy(list: List<T>): List<T> {
|
||||||
if (isClosed) { return emptyList() }
|
if (isClosed) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
return realm.copyFromRealm(list)
|
return realm.copyFromRealm(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +50,10 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
private var pendingSaves = mutableListOf<Any>()
|
private var pendingSaves = mutableListOf<Any>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : RealmModel> copy(realm: Realm, obj: T) {
|
private fun <T : RealmModel> copy(
|
||||||
|
realm: Realm,
|
||||||
|
obj: T,
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
realm.insertOrUpdate(obj)
|
realm.insertOrUpdate(obj)
|
||||||
} catch (_: java.lang.IllegalArgumentException) {
|
} catch (_: java.lang.IllegalArgumentException) {
|
||||||
|
|
@ -56,7 +61,9 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun process() {
|
private fun process() {
|
||||||
if (isClosed) { return }
|
if (isClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
realm.executeTransaction {
|
realm.executeTransaction {
|
||||||
while (pendingSaves.isNotEmpty()) {
|
while (pendingSaves.isNotEmpty()) {
|
||||||
val pending = pendingSaves.removeFirst()
|
val pending = pendingSaves.removeFirst()
|
||||||
|
|
@ -89,8 +96,13 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : BaseMainObject> modify(obj: T, transaction: (T) -> Unit) {
|
override fun <T : BaseMainObject> modify(
|
||||||
if (isClosed) { return }
|
obj: T,
|
||||||
|
transaction: (T) -> Unit,
|
||||||
|
) {
|
||||||
|
if (isClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val liveObject = getLiveObject(obj) ?: return
|
val liveObject = getLiveObject(obj) ?: return
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
transaction(liveObject)
|
transaction(liveObject)
|
||||||
|
|
@ -98,7 +110,9 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : BaseMainObject> delete(obj: T) {
|
override fun <T : BaseMainObject> delete(obj: T) {
|
||||||
if (isClosed) { return }
|
if (isClosed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val liveObject = getLiveObject(obj) ?: return
|
val liveObject = getLiveObject(obj) ?: return
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
liveObject.deleteFromRealm()
|
liveObject.deleteFromRealm()
|
||||||
|
|
@ -114,7 +128,9 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
||||||
if (obj !is RealmObject || !obj.isManaged) return obj
|
if (obj !is RealmObject || !obj.isManaged) return obj
|
||||||
val baseObject = obj as? BaseMainObject ?: return null
|
val baseObject = obj as? BaseMainObject ?: return null
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
return realm.where(baseObject.realmClass).equalTo(baseObject.primaryIdentifierName, baseObject.primaryIdentifier).findFirst() as? T
|
return realm.where(baseObject.realmClass)
|
||||||
|
.equalTo(baseObject.primaryIdentifierName, baseObject.primaryIdentifier)
|
||||||
|
.findFirst() as? T
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryUser(userID: String): Flow<User?> {
|
fun queryUser(userID: String): Flow<User?> {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,14 @@ import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ChallengeLocalRepository {
|
class RealmChallengeLocalRepository(realm: Realm) :
|
||||||
|
RealmBaseLocalRepository(realm),
|
||||||
override fun isChallengeMember(userID: String, challengeID: String): Flow<Boolean> = realm.where(ChallengeMembership::class.java)
|
ChallengeLocalRepository {
|
||||||
|
override fun isChallengeMember(
|
||||||
|
userID: String,
|
||||||
|
challengeID: String,
|
||||||
|
): Flow<Boolean> =
|
||||||
|
realm.where(ChallengeMembership::class.java)
|
||||||
.equalTo("userID", userID)
|
.equalTo("userID", userID)
|
||||||
.equalTo("challengeID", challengeID)
|
.equalTo("challengeID", challengeID)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
@ -25,7 +30,11 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
.map { it.count() > 0 }
|
.map { it.count() > 0 }
|
||||||
|
|
||||||
override fun getChallengeMembership(userId: String, id: String) = realm.where(ChallengeMembership::class.java)
|
override fun getChallengeMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
) =
|
||||||
|
realm.where(ChallengeMembership::class.java)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
.equalTo("challengeID", id)
|
.equalTo("challengeID", id)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
@ -34,7 +43,8 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
.map { it.first() }
|
.map { it.first() }
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
|
|
||||||
override fun getChallengeMemberships(userId: String) = realm.where(ChallengeMembership::class.java)
|
override fun getChallengeMemberships(userId: String) =
|
||||||
|
realm.where(ChallengeMembership::class.java)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
|
|
@ -59,7 +69,8 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
}
|
}
|
||||||
|
|
||||||
override val challenges: Flow<List<Challenge>>
|
override val challenges: Flow<List<Challenge>>
|
||||||
get() = realm.where(Challenge::class.java)
|
get() =
|
||||||
|
realm.where(Challenge::class.java)
|
||||||
.isNotNull("name")
|
.isNotNull("name")
|
||||||
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
.sort("official", Sort.DESCENDING, "createdAt", Sort.DESCENDING)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
@ -74,7 +85,8 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
.flatMapLatest { it ->
|
.flatMapLatest { it ->
|
||||||
val ids = it.map {
|
val ids =
|
||||||
|
it.map {
|
||||||
return@map it.challengeID
|
return@map it.challengeID
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
realm.where(Challenge::class.java)
|
realm.where(Challenge::class.java)
|
||||||
|
|
@ -91,13 +103,19 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setParticipating(userID: String, challengeID: String, isParticipating: Boolean) {
|
override fun setParticipating(
|
||||||
|
userID: String,
|
||||||
|
challengeID: String,
|
||||||
|
isParticipating: Boolean,
|
||||||
|
) {
|
||||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
if (isParticipating) {
|
if (isParticipating) {
|
||||||
user.challenges?.add(ChallengeMembership(userID, challengeID))
|
user.challenges?.add(ChallengeMembership(userID, challengeID))
|
||||||
} else {
|
} else {
|
||||||
val membership = user.challenges?.firstOrNull { it.challengeID == challengeID } ?: return@executeTransaction
|
val membership =
|
||||||
|
user.challenges?.firstOrNull { it.challengeID == challengeID }
|
||||||
|
?: return@executeTransaction
|
||||||
user.challenges?.remove(membership)
|
user.challenges?.remove(membership)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +125,7 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
||||||
challenges: List<Challenge>,
|
challenges: List<Challenge>,
|
||||||
clearChallenges: Boolean,
|
clearChallenges: Boolean,
|
||||||
memberOnly: Boolean,
|
memberOnly: Boolean,
|
||||||
userID: String
|
userID: String,
|
||||||
) {
|
) {
|
||||||
if (clearChallenges || memberOnly) {
|
if (clearChallenges || memberOnly) {
|
||||||
val localChallenges = realm.where(Challenge::class.java).findAll().createSnapshot()
|
val localChallenges = realm.where(Challenge::class.java).findAll().createSnapshot()
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ContentLocalRepository {
|
open class RealmContentLocalRepository(realm: Realm) :
|
||||||
|
RealmBaseLocalRepository(realm),
|
||||||
|
ContentLocalRepository {
|
||||||
override fun saveContent(contentResult: ContentResult) {
|
override fun saveContent(contentResult: ContentResult) {
|
||||||
executeTransaction { realm1 ->
|
executeTransaction { realm1 ->
|
||||||
contentResult.potion?.let { realm1.insertOrUpdate(it) }
|
contentResult.potion?.let { realm1.insertOrUpdate(it) }
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,22 @@ import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class RealmCustomizationLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), CustomizationLocalRepository {
|
class RealmCustomizationLocalRepository(realm: Realm) :
|
||||||
|
RealmContentLocalRepository(realm),
|
||||||
override fun getCustomizations(type: String, category: String?, onlyAvailable: Boolean): Flow<List<Customization>> {
|
CustomizationLocalRepository {
|
||||||
var query = realm.where(Customization::class.java)
|
override fun getCustomizations(
|
||||||
|
type: String,
|
||||||
|
category: String?,
|
||||||
|
onlyAvailable: Boolean,
|
||||||
|
): Flow<List<Customization>> {
|
||||||
|
var query =
|
||||||
|
realm.where(Customization::class.java)
|
||||||
.equalTo("type", type)
|
.equalTo("type", type)
|
||||||
.equalTo("category", category)
|
.equalTo("category", category)
|
||||||
if (onlyAvailable) {
|
if (onlyAvailable) {
|
||||||
val today = Date()
|
val today = Date()
|
||||||
query = query
|
query =
|
||||||
|
query
|
||||||
.beginGroup()
|
.beginGroup()
|
||||||
.beginGroup()
|
.beginGroup()
|
||||||
.lessThanOrEqualTo("availableFrom", today)
|
.lessThanOrEqualTo("availableFrom", today)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,9 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class RealmFAQLocalRepository(realm: Realm) : RealmContentLocalRepository(realm), FAQLocalRepository {
|
class RealmFAQLocalRepository(realm: Realm) :
|
||||||
|
RealmContentLocalRepository(realm),
|
||||||
|
FAQLocalRepository {
|
||||||
override fun getArticle(position: Int): Flow<FAQArticle> {
|
override fun getArticle(position: Int): Flow<FAQArticle> {
|
||||||
return realm.where(FAQArticle::class.java)
|
return realm.where(FAQArticle::class.java)
|
||||||
.equalTo("position", position)
|
.equalTo("position", position)
|
||||||
|
|
@ -21,7 +23,8 @@ class RealmFAQLocalRepository(realm: Realm) : RealmContentLocalRepository(realm)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val articles: Flow<List<FAQArticle>>
|
override val articles: Flow<List<FAQArticle>>
|
||||||
get() = realm.where(FAQArticle::class.java)
|
get() =
|
||||||
|
realm.where(FAQArticle::class.java)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,10 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getEquipmentType(type: String, set: String): Flow<out List<Equipment>> {
|
override fun getEquipmentType(
|
||||||
|
type: String,
|
||||||
|
set: String,
|
||||||
|
): Flow<out List<Equipment>> {
|
||||||
return realm.where(Equipment::class.java)
|
return realm.where(Equipment::class.java)
|
||||||
.equalTo("type", type)
|
.equalTo("type", type)
|
||||||
.equalTo("gearSet", set)
|
.equalTo("gearSet", set)
|
||||||
|
|
@ -104,10 +107,11 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
override fun getOwnedItems(
|
override fun getOwnedItems(
|
||||||
itemType: String,
|
itemType: String,
|
||||||
userID: String,
|
userID: String,
|
||||||
includeZero: Boolean
|
includeZero: Boolean,
|
||||||
): Flow<List<OwnedItem>> {
|
): Flow<List<OwnedItem>> {
|
||||||
return queryUser(userID).map {
|
return queryUser(userID).map {
|
||||||
val items = when (itemType) {
|
val items =
|
||||||
|
when (itemType) {
|
||||||
"eggs" -> it?.items?.eggs
|
"eggs" -> it?.items?.eggs
|
||||||
"hatchingPotions" -> it?.items?.hatchingPotions
|
"hatchingPotions" -> it?.items?.hatchingPotions
|
||||||
"food" -> it?.items?.food
|
"food" -> it?.items?.food
|
||||||
|
|
@ -128,12 +132,18 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItems(itemClass: Class<out Item>, keys: Array<String>): Flow<List<Item>> {
|
override fun getItems(
|
||||||
|
itemClass: Class<out Item>,
|
||||||
|
keys: Array<String>,
|
||||||
|
): Flow<List<Item>> {
|
||||||
return realm.where(itemClass).`in`("key", keys).findAll().toFlow()
|
return realm.where(itemClass).`in`("key", keys).findAll().toFlow()
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getOwnedItems(userID: String, includeZero: Boolean): Flow<Map<String, OwnedItem>> {
|
override fun getOwnedItems(
|
||||||
|
userID: String,
|
||||||
|
includeZero: Boolean,
|
||||||
|
): Flow<Map<String, OwnedItem>> {
|
||||||
return queryUser(userID)
|
return queryUser(userID)
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
.map {
|
.map {
|
||||||
|
|
@ -168,8 +178,13 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMounts(type: String?, group: String?, color: String?): Flow<List<Mount>> {
|
override fun getMounts(
|
||||||
var query = realm.where(Mount::class.java)
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Mount>> {
|
||||||
|
var query =
|
||||||
|
realm.where(Mount::class.java)
|
||||||
.sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING)
|
.sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING)
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
query = query.equalTo("animal", type)
|
query = query.equalTo("animal", type)
|
||||||
|
|
@ -202,8 +217,13 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPets(type: String?, group: String?, color: String?): Flow<List<Pet>> {
|
override fun getPets(
|
||||||
var query = realm.where(Pet::class.java)
|
type: String?,
|
||||||
|
group: String?,
|
||||||
|
color: String?,
|
||||||
|
): Flow<List<Pet>> {
|
||||||
|
var query =
|
||||||
|
realm.where(Pet::class.java)
|
||||||
.sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING)
|
.sort("type", Sort.ASCENDING, if (color == null) "color" else "animal", Sort.ASCENDING)
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
query = query.equalTo("animal", type)
|
query = query.equalTo("animal", type)
|
||||||
|
|
@ -239,7 +259,7 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
type: String,
|
type: String,
|
||||||
key: String,
|
key: String,
|
||||||
userID: String,
|
userID: String,
|
||||||
amountToAdd: Int
|
amountToAdd: Int,
|
||||||
) {
|
) {
|
||||||
val item = getOwnedItem(userID, type, key, true).firstOrNull()
|
val item = getOwnedItem(userID, type, key, true).firstOrNull()
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
|
|
@ -247,7 +267,10 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun changeOwnedCount(item: OwnedItem, amountToAdd: Int?) {
|
override fun changeOwnedCount(
|
||||||
|
item: OwnedItem,
|
||||||
|
amountToAdd: Int?,
|
||||||
|
) {
|
||||||
val liveItem = getLiveObject(item) ?: return
|
val liveItem = getLiveObject(item) ?: return
|
||||||
amountToAdd?.let { amount ->
|
amountToAdd?.let { amount ->
|
||||||
executeTransaction { liveItem.numberOwned = liveItem.numberOwned + amount }
|
executeTransaction { liveItem.numberOwned = liveItem.numberOwned + amount }
|
||||||
|
|
@ -258,7 +281,7 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
userID: String,
|
userID: String,
|
||||||
type: String,
|
type: String,
|
||||||
key: String,
|
key: String,
|
||||||
includeZero: Boolean
|
includeZero: Boolean,
|
||||||
): Flow<OwnedItem> {
|
): Flow<OwnedItem> {
|
||||||
return queryUser(userID)
|
return queryUser(userID)
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
|
|
@ -283,8 +306,12 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.map { it.first() }
|
.map { it.first() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItem(type: String, key: String): Flow<Item> {
|
override fun getItem(
|
||||||
val itemClass: Class<out RealmObject> = when (type) {
|
type: String,
|
||||||
|
key: String,
|
||||||
|
): Flow<Item> {
|
||||||
|
val itemClass: Class<out RealmObject> =
|
||||||
|
when (type) {
|
||||||
"eggs" -> Egg::class.java
|
"eggs" -> Egg::class.java
|
||||||
"hatchingPotions" -> HatchingPotion::class.java
|
"hatchingPotions" -> HatchingPotion::class.java
|
||||||
"food" -> Food::class.java
|
"food" -> Food::class.java
|
||||||
|
|
@ -347,7 +374,11 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hatchPet(eggKey: String, potionKey: String, userID: String) {
|
override fun hatchPet(
|
||||||
|
eggKey: String,
|
||||||
|
potionKey: String,
|
||||||
|
userID: String,
|
||||||
|
) {
|
||||||
val newPet = OwnedPet()
|
val newPet = OwnedPet()
|
||||||
newPet.key = "$eggKey-$potionKey"
|
newPet.key = "$eggKey-$potionKey"
|
||||||
newPet.trained = 5
|
newPet.trained = 5
|
||||||
|
|
@ -369,7 +400,10 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
.equalTo("itemType", obj.itemType).findFirst()
|
.equalTo("itemType", obj.itemType).findFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun save(items: Items, userID: String) {
|
override fun save(
|
||||||
|
items: Items,
|
||||||
|
userID: String,
|
||||||
|
) {
|
||||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||||
items.setItemTypes()
|
items.setItemTypes()
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
|
|
@ -377,7 +411,11 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unhatchPet(eggKey: String, potionKey: String, userID: String) {
|
override fun unhatchPet(
|
||||||
|
eggKey: String,
|
||||||
|
potionKey: String,
|
||||||
|
userID: String,
|
||||||
|
) {
|
||||||
val pet = realm.where(OwnedPet::class.java).equalTo("key", "$eggKey-$potionKey").findFirst()
|
val pet = realm.where(OwnedPet::class.java).equalTo("key", "$eggKey-$potionKey").findFirst()
|
||||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||||
val egg = user.items?.eggs?.firstOrNull { it.key == eggKey } ?: return
|
val egg = user.items?.eggs?.firstOrNull { it.key == eggKey } ?: return
|
||||||
|
|
@ -390,7 +428,12 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun feedPet(foodKey: String, petKey: String, feedValue: Int, userID: String) {
|
override fun feedPet(
|
||||||
|
foodKey: String,
|
||||||
|
petKey: String,
|
||||||
|
feedValue: Int,
|
||||||
|
userID: String,
|
||||||
|
) {
|
||||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
val user = realm.where(User::class.java).equalTo("id", userID).findFirst() ?: return
|
||||||
val pet = user.items?.pets?.firstOrNull { it.key == petKey } ?: return
|
val pet = user.items?.pets?.firstOrNull { it.key == petKey } ?: return
|
||||||
val food = user.items?.food?.firstOrNull { it.key == foodKey } ?: return
|
val food = user.items?.food?.firstOrNull { it.key == foodKey } ?: return
|
||||||
|
|
@ -422,8 +465,12 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun soldItem(userID: String, updatedUser: User): User {
|
override fun soldItem(
|
||||||
val user = realm.where(User::class.java)
|
userID: String,
|
||||||
|
updatedUser: User,
|
||||||
|
): User {
|
||||||
|
val user =
|
||||||
|
realm.where(User::class.java)
|
||||||
.equalTo("id", userID)
|
.equalTo("id", userID)
|
||||||
.findFirst() ?: return updatedUser
|
.findFirst() ?: return updatedUser
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
|
|
@ -453,7 +500,7 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
realm.where(Food::class.java)
|
realm.where(Food::class.java)
|
||||||
.lessThan("event.start", Date())
|
.lessThan("event.start", Date())
|
||||||
.greaterThan("event.end", Date())
|
.greaterThan("event.end", Date())
|
||||||
.findAll().toFlow()
|
.findAll().toFlow(),
|
||||||
) { items, food ->
|
) { items, food ->
|
||||||
items.addAll(food)
|
items.addAll(food)
|
||||||
items
|
items
|
||||||
|
|
@ -462,7 +509,7 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
realm.where(HatchingPotion::class.java)
|
realm.where(HatchingPotion::class.java)
|
||||||
.lessThan("event.start", Date())
|
.lessThan("event.start", Date())
|
||||||
.greaterThan("event.end", Date())
|
.greaterThan("event.end", Date())
|
||||||
.findAll().toFlow()
|
.findAll().toFlow(),
|
||||||
) { items, food ->
|
) { items, food ->
|
||||||
items.addAll(food)
|
items.addAll(food)
|
||||||
items
|
items
|
||||||
|
|
@ -471,7 +518,7 @@ class RealmInventoryLocalRepository(realm: Realm) :
|
||||||
realm.where(QuestContent::class.java)
|
realm.where(QuestContent::class.java)
|
||||||
.lessThan("event.start", Date())
|
.lessThan("event.start", Date())
|
||||||
.greaterThan("event.end", Date())
|
.greaterThan("event.end", Date())
|
||||||
.findAll().toFlow()
|
.findAll().toFlow(),
|
||||||
) { items, food ->
|
) { items, food ->
|
||||||
items.addAll(food)
|
items.addAll(food)
|
||||||
items
|
items
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,14 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.flatMapLatest
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), SocialLocalRepository {
|
class RealmSocialLocalRepository(realm: Realm) :
|
||||||
|
RealmBaseLocalRepository(realm),
|
||||||
override fun getGroupMembership(userId: String, id: String) = realm.where(GroupMembership::class.java)
|
SocialLocalRepository {
|
||||||
|
override fun getGroupMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
) =
|
||||||
|
realm.where(GroupMembership::class.java)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
.equalTo("groupID", id)
|
.equalTo("groupID", id)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
@ -28,17 +33,24 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
.filter { it.isLoaded && it.isNotEmpty() }
|
.filter { it.isLoaded && it.isNotEmpty() }
|
||||||
.map { it.first() }
|
.map { it.first() }
|
||||||
|
|
||||||
override fun getGroupMemberships(userId: String): Flow<List<GroupMembership>> = realm.where(GroupMembership::class.java)
|
override fun getGroupMemberships(userId: String): Flow<List<GroupMembership>> =
|
||||||
|
realm.where(GroupMembership::class.java)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
|
|
||||||
override fun updateMembership(userId: String, id: String, isMember: Boolean) {
|
override fun updateMembership(
|
||||||
|
userId: String,
|
||||||
|
id: String,
|
||||||
|
isMember: Boolean,
|
||||||
|
) {
|
||||||
if (isMember) {
|
if (isMember) {
|
||||||
save(GroupMembership(userId, id))
|
save(GroupMembership(userId, id))
|
||||||
} else {
|
} else {
|
||||||
val membership = realm.where(GroupMembership::class.java).equalTo("userID", userId).equalTo("groupID", id).findFirst()
|
val membership =
|
||||||
|
realm.where(GroupMembership::class.java).equalTo("userID", userId)
|
||||||
|
.equalTo("groupID", id).findFirst()
|
||||||
if (membership != null) {
|
if (membership != null) {
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
membership.deleteFromRealm()
|
membership.deleteFromRealm()
|
||||||
|
|
@ -61,11 +73,12 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
userID: String,
|
userID: String,
|
||||||
recipientID: String,
|
recipientID: String,
|
||||||
messages: List<ChatMessage>,
|
messages: List<ChatMessage>,
|
||||||
page: Int
|
page: Int,
|
||||||
) {
|
) {
|
||||||
messages.forEach { it.userID = userID }
|
messages.forEach { it.userID = userID }
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
val existingMessage = realm.where(ChatMessage::class.java)
|
val existingMessage =
|
||||||
|
realm.where(ChatMessage::class.java)
|
||||||
.equalTo("id", message.id)
|
.equalTo("id", message.id)
|
||||||
.findAll()
|
.findAll()
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
|
|
@ -73,7 +86,9 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
save(messages)
|
save(messages)
|
||||||
if (page != 0) return
|
if (page != 0) return
|
||||||
val existingMessages = realm.where(ChatMessage::class.java).equalTo("isInboxMessage", true).equalTo("uuid", recipientID).findAll()
|
val existingMessages =
|
||||||
|
realm.where(ChatMessage::class.java).equalTo("isInboxMessage", true)
|
||||||
|
.equalTo("uuid", recipientID).findAll()
|
||||||
val messagesToRemove = ArrayList<ChatMessage>()
|
val messagesToRemove = ArrayList<ChatMessage>()
|
||||||
for (existingMessage in existingMessages) {
|
for (existingMessage in existingMessages) {
|
||||||
val isStillMember = messages.any { existingMessage.id == it.id }
|
val isStillMember = messages.any { existingMessage.id == it.id }
|
||||||
|
|
@ -86,7 +101,10 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveInboxConversations(userID: String, conversations: List<InboxConversation>) {
|
override fun saveInboxConversations(
|
||||||
|
userID: String,
|
||||||
|
conversations: List<InboxConversation>,
|
||||||
|
) {
|
||||||
conversations.forEach { it.userID = userID }
|
conversations.forEach { it.userID = userID }
|
||||||
save(conversations)
|
save(conversations)
|
||||||
val existingConversations = realm.where(InboxConversation::class.java).findAll()
|
val existingConversations = realm.where(InboxConversation::class.java).findAll()
|
||||||
|
|
@ -111,10 +129,14 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
.map { member -> member.firstOrNull() }
|
.map { member -> member.firstOrNull() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveGroupMemberships(userID: String?, memberships: List<GroupMembership>) {
|
override fun saveGroupMemberships(
|
||||||
|
userID: String?,
|
||||||
|
memberships: List<GroupMembership>,
|
||||||
|
) {
|
||||||
save(memberships)
|
save(memberships)
|
||||||
if (userID != null) {
|
if (userID != null) {
|
||||||
val existingMemberships = realm.where(GroupMembership::class.java).equalTo("userID", userID).findAll()
|
val existingMemberships =
|
||||||
|
realm.where(GroupMembership::class.java).equalTo("userID", userID).findAll()
|
||||||
val membersToRemove = ArrayList<GroupMembership>()
|
val membersToRemove = ArrayList<GroupMembership>()
|
||||||
for (existingMembership in existingMemberships) {
|
for (existingMembership in existingMemberships) {
|
||||||
val isStillMember = memberships.any { existingMembership.groupID == it.groupID }
|
val isStillMember = memberships.any { existingMembership.groupID == it.groupID }
|
||||||
|
|
@ -129,7 +151,11 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
override fun getUserGroups(userID: String, type: String?) = realm.where(GroupMembership::class.java)
|
override fun getUserGroups(
|
||||||
|
userID: String,
|
||||||
|
type: String?,
|
||||||
|
) =
|
||||||
|
realm.where(GroupMembership::class.java)
|
||||||
.equalTo("userID", userID)
|
.equalTo("userID", userID)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
|
|
@ -141,7 +167,7 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
"id",
|
"id",
|
||||||
memberships.map {
|
memberships.map {
|
||||||
return@map it.groupID
|
return@map it.groupID
|
||||||
}.toTypedArray()
|
}.toTypedArray(),
|
||||||
)
|
)
|
||||||
.sort("memberCount", Sort.DESCENDING)
|
.sort("memberCount", Sort.DESCENDING)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
@ -171,23 +197,32 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
executeTransaction { chatMessage?.deleteFromRealm() }
|
executeTransaction { chatMessage?.deleteFromRealm() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPartyMembers(partyId: String) = realm.where(Member::class.java)
|
override fun getPartyMembers(partyId: String) =
|
||||||
|
realm.where(Member::class.java)
|
||||||
.equalTo("party.id", partyId)
|
.equalTo("party.id", partyId)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
|
|
||||||
override fun getGroupMembers(groupID: String) = realm.where(GroupMembership::class.java)
|
override fun getGroupMembers(groupID: String) =
|
||||||
|
realm.where(GroupMembership::class.java)
|
||||||
.equalTo("groupID", groupID)
|
.equalTo("groupID", groupID)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.map { memberships -> memberships.map { it.userID }.toTypedArray() }
|
.map { memberships -> memberships.map { it.userID }.toTypedArray() }
|
||||||
.flatMapLatest { realm.where(Member::class.java).`in`("id", it).findAll().toFlow() }
|
.flatMapLatest { realm.where(Member::class.java).`in`("id", it).findAll().toFlow() }
|
||||||
|
|
||||||
override fun updateRSVPNeeded(user: User?, newValue: Boolean) {
|
override fun updateRSVPNeeded(
|
||||||
|
user: User?,
|
||||||
|
newValue: Boolean,
|
||||||
|
) {
|
||||||
executeTransaction { user?.party?.quest?.RSVPNeeded = newValue }
|
executeTransaction { user?.party?.quest?.RSVPNeeded = newValue }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun likeMessage(chatMessage: ChatMessage, userId: String, liked: Boolean) {
|
override fun likeMessage(
|
||||||
|
chatMessage: ChatMessage,
|
||||||
|
userId: String,
|
||||||
|
liked: Boolean,
|
||||||
|
) {
|
||||||
val liveMessage = getLiveObject(chatMessage)
|
val liveMessage = getLiveObject(chatMessage)
|
||||||
if (liveMessage == null) {
|
if (liveMessage == null) {
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
|
|
@ -216,13 +251,18 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun savePartyMembers(groupId: String?, members: List<Member>) {
|
override fun savePartyMembers(
|
||||||
|
groupId: String?,
|
||||||
|
members: List<Member>,
|
||||||
|
) {
|
||||||
save(members)
|
save(members)
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
val existingMembers = realm.where(Member::class.java).equalTo("party.id", groupId).findAll()
|
val existingMembers =
|
||||||
|
realm.where(Member::class.java).equalTo("party.id", groupId).findAll()
|
||||||
val membersToRemove = ArrayList<Member>()
|
val membersToRemove = ArrayList<Member>()
|
||||||
for (existingMember in existingMembers) {
|
for (existingMember in existingMembers) {
|
||||||
val isStillMember = members.any { existingMember.id != null && existingMember.id == it.id }
|
val isStillMember =
|
||||||
|
members.any { existingMember.id != null && existingMember.id == it.id }
|
||||||
if (!isStillMember) {
|
if (!isStillMember) {
|
||||||
membersToRemove.add(existingMember)
|
membersToRemove.add(existingMember)
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +273,10 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun rejectGroupInvitation(userID: String, groupID: String) {
|
override fun rejectGroupInvitation(
|
||||||
|
userID: String,
|
||||||
|
groupID: String,
|
||||||
|
) {
|
||||||
val user = realm.where(User::class.java).equalTo("id", userID).findFirst()
|
val user = realm.where(User::class.java).equalTo("id", userID).findFirst()
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
user?.invitations?.removeInvitation(groupID)
|
user?.invitations?.removeInvitation(groupID)
|
||||||
|
|
@ -247,7 +290,10 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setQuestActivity(party: Group?, active: Boolean) {
|
override fun setQuestActivity(
|
||||||
|
party: Group?,
|
||||||
|
active: Boolean,
|
||||||
|
) {
|
||||||
if (party == null) return
|
if (party == null) return
|
||||||
val liveParty = getLiveObject(party)
|
val liveParty = getLiveObject(party)
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
|
|
@ -255,10 +301,14 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveChatMessages(groupId: String?, chatMessages: List<ChatMessage>) {
|
override fun saveChatMessages(
|
||||||
|
groupId: String?,
|
||||||
|
chatMessages: List<ChatMessage>,
|
||||||
|
) {
|
||||||
save(chatMessages)
|
save(chatMessages)
|
||||||
if (groupId != null) {
|
if (groupId != null) {
|
||||||
val existingMessages = realm.where(ChatMessage::class.java).equalTo("groupId", groupId).findAll()
|
val existingMessages =
|
||||||
|
realm.where(ChatMessage::class.java).equalTo("groupId", groupId).findAll()
|
||||||
val messagesToRemove = ArrayList<ChatMessage>()
|
val messagesToRemove = ArrayList<ChatMessage>()
|
||||||
for (existingMessage in existingMessages) {
|
for (existingMessage in existingMessages) {
|
||||||
val isStillMember = chatMessages.any { existingMessage.id == it.id }
|
val isStillMember = chatMessages.any { existingMessage.id == it.id }
|
||||||
|
|
@ -279,7 +329,11 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
return party != null && party.isValid
|
return party != null && party.isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getInboxMessages(userId: String, replyToUserID: String?) = realm.where(ChatMessage::class.java)
|
override fun getInboxMessages(
|
||||||
|
userId: String,
|
||||||
|
replyToUserID: String?,
|
||||||
|
) =
|
||||||
|
realm.where(ChatMessage::class.java)
|
||||||
.equalTo("isInboxMessage", true)
|
.equalTo("isInboxMessage", true)
|
||||||
.equalTo("uuid", replyToUserID)
|
.equalTo("uuid", replyToUserID)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
|
|
@ -288,7 +342,8 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
|
|
||||||
override fun getInboxConversation(userId: String) = realm.where(InboxConversation::class.java)
|
override fun getInboxConversation(userId: String) =
|
||||||
|
realm.where(InboxConversation::class.java)
|
||||||
.equalTo("userID", userId)
|
.equalTo("userID", userId)
|
||||||
.sort("timestamp", Sort.DESCENDING)
|
.sort("timestamp", Sort.DESCENDING)
|
||||||
.findAll()
|
.findAll()
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,14 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TaskLocalRepository {
|
class RealmTaskLocalRepository(realm: Realm) :
|
||||||
|
RealmBaseLocalRepository(realm),
|
||||||
override fun getTasks(taskType: TaskType, userID: String, includedGroupIDs: Array<String>): Flow<List<Task>> {
|
TaskLocalRepository {
|
||||||
|
override fun getTasks(
|
||||||
|
taskType: TaskType,
|
||||||
|
userID: String,
|
||||||
|
includedGroupIDs: Array<String>,
|
||||||
|
): Flow<List<Task>> {
|
||||||
if (realm.isClosed) return emptyFlow()
|
if (realm.isClosed) return emptyFlow()
|
||||||
return findTasks(taskType, userID)
|
return findTasks(taskType, userID)
|
||||||
.toFlow()
|
.toFlow()
|
||||||
|
|
@ -29,7 +34,7 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
|
|
||||||
private fun findTasks(
|
private fun findTasks(
|
||||||
taskType: TaskType,
|
taskType: TaskType,
|
||||||
ownerID: String
|
ownerID: String,
|
||||||
): RealmResults<Task> {
|
): RealmResults<Task> {
|
||||||
return realm.where(Task::class.java)
|
return realm.where(Task::class.java)
|
||||||
.equalTo("typeValue", taskType.value)
|
.equalTo("typeValue", taskType.value)
|
||||||
|
|
@ -47,7 +52,11 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
.filter { it.isLoaded }
|
.filter { it.isLoaded }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList) {
|
override fun saveTasks(
|
||||||
|
ownerID: String,
|
||||||
|
tasksOrder: TasksOrder,
|
||||||
|
tasks: TaskList,
|
||||||
|
) {
|
||||||
val sortedTasks = mutableListOf<Task>()
|
val sortedTasks = mutableListOf<Task>()
|
||||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.habits))
|
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.habits))
|
||||||
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.dailys))
|
sortedTasks.addAll(sortTasks(tasks.tasks, tasksOrder.dailys))
|
||||||
|
|
@ -74,7 +83,10 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
executeTransaction { realm1 -> realm1.insertOrUpdate(sortedTasks) }
|
executeTransaction { realm1 -> realm1.insertOrUpdate(sortedTasks) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveCompletedTodos(userId: String, tasks: MutableCollection<Task>) {
|
override fun saveCompletedTodos(
|
||||||
|
userId: String,
|
||||||
|
tasks: MutableCollection<Task>,
|
||||||
|
) {
|
||||||
removeCompletedTodos(userId, tasks)
|
removeCompletedTodos(userId, tasks)
|
||||||
executeTransaction { realm1 -> realm1.insertOrUpdate(tasks) }
|
executeTransaction { realm1 -> realm1.insertOrUpdate(tasks) }
|
||||||
}
|
}
|
||||||
|
|
@ -99,7 +111,10 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sortTasks(taskMap: MutableMap<String, Task>, taskOrder: List<String>): List<Task> {
|
private fun sortTasks(
|
||||||
|
taskMap: MutableMap<String, Task>,
|
||||||
|
taskOrder: List<String>,
|
||||||
|
): List<Task> {
|
||||||
val taskList = ArrayList<Task>()
|
val taskList = ArrayList<Task>()
|
||||||
var position = 0
|
var position = 0
|
||||||
for (taskId in taskOrder) {
|
for (taskId in taskOrder) {
|
||||||
|
|
@ -114,9 +129,13 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
return taskList
|
return taskList
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeOldTasks(ownerID: String, onlineTaskList: List<Task>) {
|
private fun removeOldTasks(
|
||||||
|
ownerID: String,
|
||||||
|
onlineTaskList: List<Task>,
|
||||||
|
) {
|
||||||
if (realm.isClosed) return
|
if (realm.isClosed) return
|
||||||
val localTasks = realm.where(Task::class.java)
|
val localTasks =
|
||||||
|
realm.where(Task::class.java)
|
||||||
.equalTo("ownerID", ownerID)
|
.equalTo("ownerID", ownerID)
|
||||||
.beginGroup()
|
.beginGroup()
|
||||||
.beginGroup()
|
.beginGroup()
|
||||||
|
|
@ -136,8 +155,12 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeCompletedTodos(userID: String, onlineTaskList: MutableCollection<Task>) {
|
private fun removeCompletedTodos(
|
||||||
val localTasks = realm.where(Task::class.java)
|
userID: String,
|
||||||
|
onlineTaskList: MutableCollection<Task>,
|
||||||
|
) {
|
||||||
|
val localTasks =
|
||||||
|
realm.where(Task::class.java)
|
||||||
.equalTo("ownerID", userID)
|
.equalTo("ownerID", userID)
|
||||||
.equalTo("typeValue", TaskType.TODO.value)
|
.equalTo("typeValue", TaskType.TODO.value)
|
||||||
.equalTo("completed", true)
|
.equalTo("completed", true)
|
||||||
|
|
@ -181,14 +204,21 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markTaskCompleted(taskId: String, isCompleted: Boolean) {
|
override fun markTaskCompleted(
|
||||||
|
taskId: String,
|
||||||
|
isCompleted: Boolean,
|
||||||
|
) {
|
||||||
val task = realm.where(Task::class.java).equalTo("id", taskId).findFirst()
|
val task = realm.where(Task::class.java).equalTo("id", taskId).findFirst()
|
||||||
executeTransaction { task?.completed = true }
|
executeTransaction { task?.completed = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun swapTaskPosition(firstPosition: Int, secondPosition: Int) {
|
override fun swapTaskPosition(
|
||||||
|
firstPosition: Int,
|
||||||
|
secondPosition: Int,
|
||||||
|
) {
|
||||||
val firstTask = realm.where(Task::class.java).equalTo("position", firstPosition).findFirst()
|
val firstTask = realm.where(Task::class.java).equalTo("position", firstPosition).findFirst()
|
||||||
val secondTask = realm.where(Task::class.java).equalTo("position", secondPosition).findFirst()
|
val secondTask =
|
||||||
|
realm.where(Task::class.java).equalTo("position", secondPosition).findFirst()
|
||||||
if (firstTask != null && secondTask != null && firstTask.isValid && secondTask.isValid) {
|
if (firstTask != null && secondTask != null && firstTask.isValid && secondTask.isValid) {
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
firstTask.position = secondPosition
|
firstTask.position = secondPosition
|
||||||
|
|
@ -197,8 +227,12 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTaskAtPosition(taskType: String, position: Int): Flow<Task> {
|
override fun getTaskAtPosition(
|
||||||
return realm.where(Task::class.java).equalTo("typeValue", taskType).equalTo("position", position)
|
taskType: String,
|
||||||
|
position: Int,
|
||||||
|
): Flow<Task> {
|
||||||
|
return realm.where(Task::class.java).equalTo("typeValue", taskType)
|
||||||
|
.equalTo("position", position)
|
||||||
.findAll()
|
.findAll()
|
||||||
.toFlow()
|
.toFlow()
|
||||||
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
.filter { realmObject -> realmObject.isLoaded && realmObject.isNotEmpty() }
|
||||||
|
|
@ -207,9 +241,11 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateIsdue(daily: TaskList): TaskList {
|
override fun updateIsdue(daily: TaskList): TaskList {
|
||||||
val tasks = realm.where(Task::class.java).equalTo("typeValue", TaskType.DAILY.value).findAll()
|
val tasks =
|
||||||
|
realm.where(Task::class.java).equalTo("typeValue", TaskType.DAILY.value).findAll()
|
||||||
realm.beginTransaction()
|
realm.beginTransaction()
|
||||||
tasks.filter { daily.tasks.containsKey(it.id) }.forEach { it.isDue = daily.tasks[it.id]?.isDue }
|
tasks.filter { daily.tasks.containsKey(it.id) }
|
||||||
|
.forEach { it.isDue = daily.tasks[it.id]?.isDue }
|
||||||
realm.commitTransaction()
|
realm.commitTransaction()
|
||||||
return daily
|
return daily
|
||||||
}
|
}
|
||||||
|
|
@ -218,7 +254,8 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
if (taskOrder.isNotEmpty()) {
|
if (taskOrder.isNotEmpty()) {
|
||||||
val tasks = realm.where(Task::class.java).`in`("id", taskOrder.toTypedArray()).findAll()
|
val tasks = realm.where(Task::class.java).`in`("id", taskOrder.toTypedArray()).findAll()
|
||||||
executeTransaction { _ ->
|
executeTransaction { _ ->
|
||||||
tasks.filter { taskOrder.contains(it.id) }.forEach { it.position = taskOrder.indexOf(it.id) }
|
tasks.filter { taskOrder.contains(it.id) }
|
||||||
|
.forEach { it.position = taskOrder.indexOf(it.id) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -243,7 +280,10 @@ class RealmTaskLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTasksForChallenge(challengeID: String?, userID: String?): Flow<List<Task>> {
|
override fun getTasksForChallenge(
|
||||||
|
challengeID: String?,
|
||||||
|
userID: String?,
|
||||||
|
): Flow<List<Task>> {
|
||||||
return realm.where(Task::class.java)
|
return realm.where(Task::class.java)
|
||||||
.equalTo("challengeID", challengeID)
|
.equalTo("challengeID", challengeID)
|
||||||
.equalTo("ownerID", userID)
|
.equalTo("ownerID", userID)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.filterNotNull
|
import kotlinx.coroutines.flow.filterNotNull
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TutorialLocalRepository {
|
class RealmTutorialLocalRepository(realm: Realm) :
|
||||||
|
RealmBaseLocalRepository(realm),
|
||||||
|
TutorialLocalRepository {
|
||||||
override fun getTutorialStep(key: String): Flow<TutorialStep> {
|
override fun getTutorialStep(key: String): Flow<TutorialStep> {
|
||||||
if (realm.isClosed) return emptyFlow()
|
if (realm.isClosed) return emptyFlow()
|
||||||
return realm.where(TutorialStep::class.java).equalTo("identifier", key)
|
return realm.where(TutorialStep::class.java).equalTo("identifier", key)
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ class RealmUserLocalRepository(realm: Realm) :
|
||||||
it.quest?.members?.find { questMember -> questMember.key == userID } === null -> UserQuestStatus.NO_QUEST
|
it.quest?.members?.find { questMember -> questMember.key == userID } === null -> UserQuestStatus.NO_QUEST
|
||||||
it.quest?.progress?.collect?.isNotEmpty()
|
it.quest?.progress?.collect?.isNotEmpty()
|
||||||
?: false -> UserQuestStatus.QUEST_COLLECT
|
?: false -> UserQuestStatus.QUEST_COLLECT
|
||||||
|
|
||||||
(it.quest?.progress?.hp ?: 0.0) > 0.0 -> UserQuestStatus.QUEST_BOSS
|
(it.quest?.progress?.hp ?: 0.0) > 0.0 -> UserQuestStatus.QUEST_BOSS
|
||||||
else -> UserQuestStatus.QUEST_UNKNOWN
|
else -> UserQuestStatus.QUEST_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
@ -81,9 +82,13 @@ class RealmUserLocalRepository(realm: Realm) :
|
||||||
.map { users -> users.first() }
|
.map { users -> users.first() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveUser(user: User, overrideExisting: Boolean) {
|
override fun saveUser(
|
||||||
|
user: User,
|
||||||
|
overrideExisting: Boolean,
|
||||||
|
) {
|
||||||
if (realm.isClosed) return
|
if (realm.isClosed) return
|
||||||
val oldUser = realm.where(User::class.java)
|
val oldUser =
|
||||||
|
realm.where(User::class.java)
|
||||||
.equalTo("id", user.id)
|
.equalTo("id", user.id)
|
||||||
.findFirst()
|
.findFirst()
|
||||||
if (oldUser != null && oldUser.isValid) {
|
if (oldUser != null && oldUser.isValid) {
|
||||||
|
|
@ -101,7 +106,10 @@ class RealmUserLocalRepository(realm: Realm) :
|
||||||
removeOldTags(user.id ?: "", user.tags)
|
removeOldTags(user.id ?: "", user.tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeOldTags(userId: String, onlineTags: List<Tag>) {
|
private fun removeOldTags(
|
||||||
|
userId: String,
|
||||||
|
onlineTags: List<Tag>,
|
||||||
|
) {
|
||||||
val tags = realm.where(Tag::class.java).equalTo("userId", userId).findAll().createSnapshot()
|
val tags = realm.where(Tag::class.java).equalTo("userId", userId).findAll().createSnapshot()
|
||||||
val tagsToDelete = tags.filterNot { onlineTags.contains(it) }
|
val tagsToDelete = tags.filterNot { onlineTags.contains(it) }
|
||||||
executeTransaction {
|
executeTransaction {
|
||||||
|
|
|
||||||
|
|
@ -5,21 +5,21 @@ import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||||
|
|
||||||
fun HabiticaAlertDialog.addOkButton(
|
fun HabiticaAlertDialog.addOkButton(
|
||||||
isPrimary: Boolean = true,
|
isPrimary: Boolean = true,
|
||||||
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null
|
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
this.addButton(R.string.ok, isPrimary, false, true, listener)
|
this.addButton(R.string.ok, isPrimary, false, true, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun HabiticaAlertDialog.addCloseButton(
|
fun HabiticaAlertDialog.addCloseButton(
|
||||||
isPrimary: Boolean = false,
|
isPrimary: Boolean = false,
|
||||||
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null
|
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
this.addButton(R.string.close, isPrimary, false, true, listener)
|
this.addButton(R.string.close, isPrimary, false, true, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun HabiticaAlertDialog.addCancelButton(
|
fun HabiticaAlertDialog.addCancelButton(
|
||||||
isPrimary: Boolean = false,
|
isPrimary: Boolean = false,
|
||||||
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null
|
listener: ((HabiticaAlertDialog, Int) -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
this.addButton(R.string.cancel, isPrimary, false, true, listener)
|
this.addButton(R.string.cancel, isPrimary, false, true, listener)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ fun Animal.getTranslatedType(c: Context?): String? {
|
||||||
return getTranslatedAnimalType(c, type)
|
return getTranslatedAnimalType(c, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTranslatedAnimalType(c: Context?, type: String?): String? {
|
fun getTranslatedAnimalType(
|
||||||
|
c: Context?,
|
||||||
|
type: String?,
|
||||||
|
): String? {
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
return type
|
return type
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,8 @@ import android.content.Context
|
||||||
import android.content.res.TypedArray
|
import android.content.res.TypedArray
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
|
||||||
fun AttributeSet.styledAttributes(context: Context?, style: IntArray): TypedArray? =
|
fun AttributeSet.styledAttributes(
|
||||||
|
context: Context?,
|
||||||
|
style: IntArray,
|
||||||
|
): TypedArray? =
|
||||||
context?.theme?.obtainStyledAttributes(this, style, 0, 0)
|
context?.theme?.obtainStyledAttributes(this, style, 0, 0)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,11 @@ import kotlin.time.toDuration
|
||||||
|
|
||||||
class DateUtils {
|
class DateUtils {
|
||||||
companion object {
|
companion object {
|
||||||
fun createDate(year: Int, month: Int, day: Int): Date {
|
fun createDate(
|
||||||
|
year: Int,
|
||||||
|
month: Int,
|
||||||
|
day: Int,
|
||||||
|
): Date {
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.set(Calendar.YEAR, year)
|
cal.set(Calendar.YEAR, year)
|
||||||
cal.set(Calendar.MONTH, month)
|
cal.set(Calendar.MONTH, month)
|
||||||
|
|
@ -25,7 +29,10 @@ class DateUtils {
|
||||||
return cal.time
|
return cal.time
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSameDay(date1 : Date, date2 : Date) : Boolean {
|
fun isSameDay(
|
||||||
|
date1: Date,
|
||||||
|
date2: Date,
|
||||||
|
): Boolean {
|
||||||
val cal1 = Calendar.getInstance()
|
val cal1 = Calendar.getInstance()
|
||||||
val cal2 = Calendar.getInstance()
|
val cal2 = Calendar.getInstance()
|
||||||
cal1.time = date1
|
cal1.time = date1
|
||||||
|
|
@ -50,26 +57,34 @@ fun Long.getAgoString(res: Resources): String {
|
||||||
val diffMonths = diffDays / 30
|
val diffMonths = diffDays / 30
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
diffMonths != 0L -> if (diffMonths == 1L) {
|
diffMonths != 0L ->
|
||||||
|
if (diffMonths == 1L) {
|
||||||
res.getString(R.string.ago_1month)
|
res.getString(R.string.ago_1month)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.ago_months, diffMonths)
|
res.getString(R.string.ago_months, diffMonths)
|
||||||
}
|
}
|
||||||
diffWeeks != 0L -> if (diffWeeks == 1L) {
|
|
||||||
|
diffWeeks != 0L ->
|
||||||
|
if (diffWeeks == 1L) {
|
||||||
res.getString(R.string.ago_1week)
|
res.getString(R.string.ago_1week)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.ago_weeks, diffWeeks)
|
res.getString(R.string.ago_weeks, diffWeeks)
|
||||||
}
|
}
|
||||||
diffDays != 0L -> if (diffDays == 1L) {
|
|
||||||
|
diffDays != 0L ->
|
||||||
|
if (diffDays == 1L) {
|
||||||
res.getString(R.string.ago_1day)
|
res.getString(R.string.ago_1day)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.ago_days, diffDays)
|
res.getString(R.string.ago_days, diffDays)
|
||||||
}
|
}
|
||||||
diffHours != 0L -> if (diffHours == 1L) {
|
|
||||||
|
diffHours != 0L ->
|
||||||
|
if (diffHours == 1L) {
|
||||||
res.getString(R.string.ago_1hour)
|
res.getString(R.string.ago_1hour)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.ago_hours, diffHours)
|
res.getString(R.string.ago_hours, diffHours)
|
||||||
}
|
}
|
||||||
|
|
||||||
diffMinutes == 1L -> res.getString(R.string.ago_1Minute)
|
diffMinutes == 1L -> res.getString(R.string.ago_1Minute)
|
||||||
else -> res.getString(R.string.ago_minutes, diffMinutes)
|
else -> res.getString(R.string.ago_minutes, diffMinutes)
|
||||||
}
|
}
|
||||||
|
|
@ -89,26 +104,34 @@ fun Long.getRemainingString(res: Resources): String {
|
||||||
val diffMonths = diffDays / 30
|
val diffMonths = diffDays / 30
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
diffMonths != 0L -> if (diffMonths == 1L) {
|
diffMonths != 0L ->
|
||||||
|
if (diffMonths == 1L) {
|
||||||
res.getString(R.string.remaining_1month)
|
res.getString(R.string.remaining_1month)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.remaining_months, diffMonths)
|
res.getString(R.string.remaining_months, diffMonths)
|
||||||
}
|
}
|
||||||
diffWeeks != 0L -> if (diffWeeks == 1L) {
|
|
||||||
|
diffWeeks != 0L ->
|
||||||
|
if (diffWeeks == 1L) {
|
||||||
res.getString(R.string.remaining_1week)
|
res.getString(R.string.remaining_1week)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.remaining_weeks, diffWeeks)
|
res.getString(R.string.remaining_weeks, diffWeeks)
|
||||||
}
|
}
|
||||||
diffDays != 0L -> if (diffDays == 1L) {
|
|
||||||
|
diffDays != 0L ->
|
||||||
|
if (diffDays == 1L) {
|
||||||
res.getString(R.string.remaining_1day)
|
res.getString(R.string.remaining_1day)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.remaining_days, diffDays)
|
res.getString(R.string.remaining_days, diffDays)
|
||||||
}
|
}
|
||||||
diffHours != 0L -> if (diffHours == 1L) {
|
|
||||||
|
diffHours != 0L ->
|
||||||
|
if (diffHours == 1L) {
|
||||||
res.getString(R.string.remaining_1hour)
|
res.getString(R.string.remaining_1hour)
|
||||||
} else {
|
} else {
|
||||||
res.getString(R.string.remaining_hours, diffHours)
|
res.getString(R.string.remaining_hours, diffHours)
|
||||||
}
|
}
|
||||||
|
|
||||||
diffMinutes == 1L -> res.getString(R.string.remaining_1Minute)
|
diffMinutes == 1L -> res.getString(R.string.remaining_1Minute)
|
||||||
else -> res.getString(R.string.remaining_minutes, diffMinutes)
|
else -> res.getString(R.string.remaining_minutes, diffMinutes)
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +174,8 @@ fun Duration.getMinuteOrSeconds(): DurationUnit {
|
||||||
|
|
||||||
fun Date.formatForLocale(): String {
|
fun Date.formatForLocale(): String {
|
||||||
val locale = Locale.getDefault()
|
val locale = Locale.getDefault()
|
||||||
val dateFormatter: DateFormat = if (locale == Locale.US || locale == Locale.ENGLISH) {
|
val dateFormatter: DateFormat =
|
||||||
|
if (locale == Locale.US || locale == Locale.ENGLISH) {
|
||||||
SimpleDateFormat("M/d/yy", locale)
|
SimpleDateFormat("M/d/yy", locale)
|
||||||
} else {
|
} else {
|
||||||
SimpleDateFormat.getDateInstance(DateFormat.LONG, locale)
|
SimpleDateFormat.getDateInstance(DateFormat.LONG, locale)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,10 @@ import com.google.firebase.ktx.Firebase
|
||||||
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
import com.habitrpg.android.habitica.ui.activities.BaseActivity
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
fun Resources.forceLocale(activity: BaseActivity, locale: Locale) {
|
fun Resources.forceLocale(
|
||||||
|
activity: BaseActivity,
|
||||||
|
locale: Locale,
|
||||||
|
) {
|
||||||
Locale.setDefault(locale)
|
Locale.setDefault(locale)
|
||||||
val configuration = Configuration()
|
val configuration = Configuration()
|
||||||
configuration.setLocale(locale)
|
configuration.setLocale(locale)
|
||||||
|
|
|
||||||
|
|
@ -3,24 +3,50 @@ package com.habitrpg.android.habitica.extensions
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
|
||||||
class OnChangeTextWatcher(private var function: (CharSequence?, Int, Int, Int) -> Unit) : TextWatcher {
|
class OnChangeTextWatcher(private var function: (CharSequence?, Int, Int, Int) -> Unit) :
|
||||||
override fun afterTextChanged(s: Editable?) { /* no-on */ }
|
TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) { // no-on
|
||||||
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { /* no-on */ }
|
override fun beforeTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
count: Int,
|
||||||
|
after: Int,
|
||||||
|
) { // no-on
|
||||||
|
}
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
before: Int,
|
||||||
|
count: Int,
|
||||||
|
) {
|
||||||
function(s, start, before, count)
|
function(s, start, before, count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BeforeChangeTextWatcher(private var function: (CharSequence?, Int, Int, Int) -> Unit) : TextWatcher {
|
class BeforeChangeTextWatcher(private var function: (CharSequence?, Int, Int, Int) -> Unit) :
|
||||||
override fun afterTextChanged(s: Editable?) { /* no-on */ }
|
TextWatcher {
|
||||||
|
override fun afterTextChanged(s: Editable?) { // no-on
|
||||||
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
override fun beforeTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
count: Int,
|
||||||
|
after: Int,
|
||||||
|
) {
|
||||||
function(s, start, count, after)
|
function(s, start, count, after)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { /* no-on */ }
|
override fun onTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
before: Int,
|
||||||
|
count: Int,
|
||||||
|
) { // no-on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AfterChangeTextWatcher(private var function: (Editable?) -> Unit) : TextWatcher {
|
class AfterChangeTextWatcher(private var function: (Editable?) -> Unit) : TextWatcher {
|
||||||
|
|
@ -28,7 +54,19 @@ class AfterChangeTextWatcher(private var function: (Editable?) -> Unit) : TextWa
|
||||||
function(s)
|
function(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { /* no-on */ }
|
override fun beforeTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { /* no-on */ }
|
start: Int,
|
||||||
|
count: Int,
|
||||||
|
after: Int,
|
||||||
|
) { // no-on
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(
|
||||||
|
s: CharSequence?,
|
||||||
|
start: Int,
|
||||||
|
before: Int,
|
||||||
|
count: Int,
|
||||||
|
) { // no-on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ import android.view.Window
|
||||||
import com.habitrpg.android.habitica.R
|
import com.habitrpg.android.habitica.R
|
||||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||||
|
|
||||||
fun Window.updateStatusBarColor(color: Int, isLight: Boolean) {
|
fun Window.updateStatusBarColor(
|
||||||
|
color: Int,
|
||||||
|
isLight: Boolean,
|
||||||
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
statusBarColor = color
|
statusBarColor = color
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
decorView.systemUiVisibility = if (isLight) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else View.SYSTEM_UI_FLAG_VISIBLE
|
decorView.systemUiVisibility =
|
||||||
|
if (isLight) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR else View.SYSTEM_UI_FLAG_VISIBLE
|
||||||
} else {
|
} else {
|
||||||
statusBarColor = context.getThemeColor(R.attr.colorPrimaryDark)
|
statusBarColor = context.getThemeColor(R.attr.colorPrimaryDark)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.habitrpg.android.habitica.extensions
|
package com.habitrpg.android.habitica.extensions
|
||||||
|
|
||||||
import com.habitrpg.android.habitica.models.tasks.Days
|
import com.habitrpg.android.habitica.models.tasks.Days
|
||||||
import com.habitrpg.shared.habitica.models.tasks.Frequency
|
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
|
|
@ -9,16 +8,16 @@ import java.time.ZonedDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.time.format.DateTimeFormatterBuilder
|
import java.time.format.DateTimeFormatterBuilder
|
||||||
import java.time.format.TextStyle
|
import java.time.format.TextStyle
|
||||||
import java.time.temporal.ChronoUnit
|
|
||||||
import java.time.temporal.TemporalAccessor
|
import java.time.temporal.TemporalAccessor
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
fun String.parseToZonedDateTime(): ZonedDateTime? {
|
fun String.parseToZonedDateTime(): ZonedDateTime? {
|
||||||
val parsed: TemporalAccessor = formatter().parseBest(
|
val parsed: TemporalAccessor =
|
||||||
|
formatter().parseBest(
|
||||||
this,
|
this,
|
||||||
ZonedDateTime::from,
|
ZonedDateTime::from,
|
||||||
LocalDateTime::from
|
LocalDateTime::from,
|
||||||
)
|
)
|
||||||
return if (parsed is ZonedDateTime) {
|
return if (parsed is ZonedDateTime) {
|
||||||
parsed
|
parsed
|
||||||
|
|
@ -46,7 +45,6 @@ fun formatter(): DateTimeFormatter =
|
||||||
.appendPattern("[XX]")
|
.appendPattern("[XX]")
|
||||||
.toFormatter()
|
.toFormatter()
|
||||||
|
|
||||||
|
|
||||||
fun ZonedDateTime.matchesRepeatDays(repeatDays: Days?): Boolean {
|
fun ZonedDateTime.matchesRepeatDays(repeatDays: Days?): Boolean {
|
||||||
repeatDays ?: return true // If no repeatDays specified, assume it matches
|
repeatDays ?: return true // If no repeatDays specified, assume it matches
|
||||||
|
|
||||||
|
|
@ -61,7 +59,3 @@ fun ZonedDateTime.matchesRepeatDays(repeatDays: Days?): Boolean {
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ import kotlin.time.toDuration
|
||||||
enum class AdType {
|
enum class AdType {
|
||||||
ARMOIRE,
|
ARMOIRE,
|
||||||
SPELL,
|
SPELL,
|
||||||
FAINT;
|
FAINT,
|
||||||
|
;
|
||||||
|
|
||||||
val adUnitID: String
|
val adUnitID: String
|
||||||
get() {
|
get() {
|
||||||
|
|
@ -67,7 +68,7 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
|
||||||
UNINITIALIZED,
|
UNINITIALIZED,
|
||||||
INITIALIZING,
|
INITIALIZING,
|
||||||
READY,
|
READY,
|
||||||
DISABLED
|
DISABLED,
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var sharedPreferences: SharedPreferences
|
private lateinit var sharedPreferences: SharedPreferences
|
||||||
|
|
@ -100,7 +101,10 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initialize(context: Context, onComplete: () -> Unit) {
|
fun initialize(
|
||||||
|
context: Context,
|
||||||
|
onComplete: () -> Unit,
|
||||||
|
) {
|
||||||
if (currentAdStatus != AdStatus.UNINITIALIZED) return
|
if (currentAdStatus != AdStatus.UNINITIALIZED) return
|
||||||
|
|
||||||
if (BuildConfig.DEBUG || BuildConfig.TESTING_LEVEL == "staff" || BuildConfig.TESTING_LEVEL == "alpha") {
|
if (BuildConfig.DEBUG || BuildConfig.TESTING_LEVEL == "staff" || BuildConfig.TESTING_LEVEL == "alpha") {
|
||||||
|
|
@ -119,19 +123,25 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fun whenAdsInitialized(context: Context, onComplete: () -> Unit) {
|
fun whenAdsInitialized(
|
||||||
|
context: Context,
|
||||||
|
onComplete: () -> Unit,
|
||||||
|
) {
|
||||||
when (currentAdStatus) {
|
when (currentAdStatus) {
|
||||||
AdStatus.READY -> {
|
AdStatus.READY -> {
|
||||||
onComplete()
|
onComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.DISABLED -> {
|
AdStatus.DISABLED -> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.UNINITIALIZED -> {
|
AdStatus.UNINITIALIZED -> {
|
||||||
initialize(context) {
|
initialize(context) {
|
||||||
onComplete()
|
onComplete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.INITIALIZING -> {
|
AdStatus.INITIALIZING -> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -189,15 +199,18 @@ class AdHandler(val activity: Activity, val type: AdType, val rewardAction: (Boo
|
||||||
AdStatus.READY -> {
|
AdStatus.READY -> {
|
||||||
showRewardedAd()
|
showRewardedAd()
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.DISABLED -> {
|
AdStatus.DISABLED -> {
|
||||||
rewardAction(false)
|
rewardAction(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.UNINITIALIZED -> {
|
AdStatus.UNINITIALIZED -> {
|
||||||
initialize(activity) {
|
initialize(activity) {
|
||||||
showRewardedAd()
|
showRewardedAd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AdStatus.INITIALIZING -> {
|
AdStatus.INITIALIZING -> {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,12 @@ import com.habitrpg.android.habitica.R
|
||||||
|
|
||||||
enum class AnalyticsTarget {
|
enum class AnalyticsTarget {
|
||||||
AMPLITUDE,
|
AMPLITUDE,
|
||||||
FIREBASE
|
FIREBASE,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class EventCategory(val key: String) {
|
enum class EventCategory(val key: String) {
|
||||||
BEHAVIOUR("behaviour"),
|
BEHAVIOUR("behaviour"),
|
||||||
NAVIGATION("navigation")
|
NAVIGATION("navigation"),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class HitType(val key: String) {
|
enum class HitType(val key: String) {
|
||||||
|
|
@ -26,7 +26,7 @@ enum class HitType(val key: String) {
|
||||||
PAGEVIEW("pageview"),
|
PAGEVIEW("pageview"),
|
||||||
CREATE_WIDGET("create"),
|
CREATE_WIDGET("create"),
|
||||||
REMOVE_WIDGET("remove"),
|
REMOVE_WIDGET("remove"),
|
||||||
UPDATE_WIDGET("update")
|
UPDATE_WIDGET("update"),
|
||||||
}
|
}
|
||||||
|
|
||||||
object Analytics {
|
object Analytics {
|
||||||
|
|
@ -39,16 +39,17 @@ object Analytics {
|
||||||
category: EventCategory?,
|
category: EventCategory?,
|
||||||
hitType: HitType?,
|
hitType: HitType?,
|
||||||
additionalData: Map<String, Any>? = null,
|
additionalData: Map<String, Any>? = null,
|
||||||
target: AnalyticsTarget? = null
|
target: AnalyticsTarget? = null,
|
||||||
) {
|
) {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val data = mutableMapOf<String, Any?>(
|
val data =
|
||||||
|
mutableMapOf<String, Any?>(
|
||||||
"eventAction" to eventAction,
|
"eventAction" to eventAction,
|
||||||
"eventCategory" to category?.key,
|
"eventCategory" to category?.key,
|
||||||
"hitType" to hitType?.key,
|
"hitType" to hitType?.key,
|
||||||
"status" to "displayed"
|
"status" to "displayed",
|
||||||
)
|
)
|
||||||
if (additionalData != null) {
|
if (additionalData != null) {
|
||||||
data.putAll(additionalData)
|
data.putAll(additionalData)
|
||||||
|
|
@ -74,17 +75,19 @@ object Analytics {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initialize(context: Context) {
|
fun initialize(context: Context) {
|
||||||
amplitude = Amplitude(
|
amplitude =
|
||||||
|
Amplitude(
|
||||||
Configuration(
|
Configuration(
|
||||||
context.getString(R.string.amplitude_app_id),
|
context.getString(R.string.amplitude_app_id),
|
||||||
context
|
context,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
firebase = FirebaseAnalytics.getInstance(context)
|
firebase = FirebaseAnalytics.getInstance(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun identify(sharedPrefs: SharedPreferences) {
|
fun identify(sharedPrefs: SharedPreferences) {
|
||||||
val identify = Identify()
|
val identify =
|
||||||
|
Identify()
|
||||||
.setOnce("androidStore", BuildConfig.STORE)
|
.setOnce("androidStore", BuildConfig.STORE)
|
||||||
sharedPrefs.getString("launch_screen", "")?.let {
|
sharedPrefs.getString("launch_screen", "")?.let {
|
||||||
identify.set("launch_screen", it)
|
identify.set("launch_screen", it)
|
||||||
|
|
@ -104,7 +107,10 @@ object Analytics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUserProperty(identifier: String, value: Any?) {
|
fun setUserProperty(
|
||||||
|
identifier: String,
|
||||||
|
value: Any?,
|
||||||
|
) {
|
||||||
if (this::amplitude.isInitialized) {
|
if (this::amplitude.isInitialized) {
|
||||||
amplitude.identify(mapOf(identifier to value))
|
amplitude.identify(mapOf(identifier to value))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ import com.habitrpg.common.habitica.helpers.launchCatching
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class AppConfigManager(contentRepository: ContentRepository?) : com.habitrpg.common.habitica.helpers.AppConfigManager() {
|
class AppConfigManager(contentRepository: ContentRepository?) :
|
||||||
|
com.habitrpg.common.habitica.helpers.AppConfigManager() {
|
||||||
private var worldState: WorldState? = null
|
private var worldState: WorldState? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
@ -122,7 +122,12 @@ class AppConfigManager(contentRepository: ContentRepository?) : com.habitrpg.com
|
||||||
if (worldState?.isValid == true) {
|
if (worldState?.isValid == true) {
|
||||||
for (event in worldState?.events ?: listOf(worldState?.currentEvent)) {
|
for (event in worldState?.events ?: listOf(worldState?.currentEvent)) {
|
||||||
if (event == null) return null
|
if (event == null) return null
|
||||||
val thisPromo = getHabiticaPromotionFromKey(event.promo ?: event.eventKey ?: "", event.start, event.end)
|
val thisPromo =
|
||||||
|
getHabiticaPromotionFromKey(
|
||||||
|
event.promo ?: event.eventKey ?: "",
|
||||||
|
event.start,
|
||||||
|
event.end,
|
||||||
|
)
|
||||||
if (thisPromo != null) {
|
if (thisPromo != null) {
|
||||||
promo = thisPromo
|
promo = thisPromo
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +183,8 @@ class AppConfigManager(contentRepository: ContentRepository?) : com.habitrpg.com
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBirthdayEvent(): WorldStateEvent? {
|
fun getBirthdayEvent(): WorldStateEvent? {
|
||||||
val events = ((worldState?.events as? List<WorldStateEvent>) ?: listOf(worldState?.currentEvent))
|
val events =
|
||||||
|
((worldState?.events as? List<WorldStateEvent>) ?: listOf(worldState?.currentEvent))
|
||||||
return events.firstOrNull { it?.eventKey == "birthday10" && it.end?.after(Date()) == true }
|
return events.firstOrNull { it?.eventKey == "birthday10" && it.end?.after(Date()) == true }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,13 @@ package com.habitrpg.android.habitica.helpers
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
class AprilFoolsHandler {
|
class AprilFoolsHandler {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var eventEnd: Date? = null
|
private var eventEnd: Date? = null
|
||||||
|
|
||||||
fun handle(name: String?, endDate: Date?) {
|
fun handle(
|
||||||
|
name: String?,
|
||||||
|
endDate: Date?,
|
||||||
|
) {
|
||||||
if (endDate != null) {
|
if (endDate != null) {
|
||||||
this.eventEnd = endDate
|
this.eventEnd = endDate
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,14 @@ import android.content.res.Resources
|
||||||
import com.habitrpg.android.habitica.models.tasks.Task
|
import com.habitrpg.android.habitica.models.tasks.Task
|
||||||
|
|
||||||
interface GroupPlanInfoProvider {
|
interface GroupPlanInfoProvider {
|
||||||
fun assignedTextForTask(resources: Resources, assignedUsers: List<String>): String
|
fun assignedTextForTask(
|
||||||
|
resources: Resources,
|
||||||
|
assignedUsers: List<String>,
|
||||||
|
): String
|
||||||
|
|
||||||
fun canScoreTask(task: Task): Boolean
|
fun canScoreTask(task: Task): Boolean
|
||||||
|
|
||||||
suspend fun canEditTask(task: Task): Boolean
|
suspend fun canEditTask(task: Task): Boolean
|
||||||
|
|
||||||
suspend fun canAddTasks(): Boolean
|
suspend fun canAddTasks(): Boolean
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,15 +15,18 @@ import kotlin.coroutines.EmptyCoroutineContext
|
||||||
@Composable
|
@Composable
|
||||||
fun <T> rememberFlow(
|
fun <T> rememberFlow(
|
||||||
flow: Flow<T>,
|
flow: Flow<T>,
|
||||||
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
|
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
|
||||||
): Flow<T> {
|
): Flow<T> {
|
||||||
return remember(key1 = flow, key2 = lifecycleOwner) { flow.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED) }
|
return remember(
|
||||||
|
key1 = flow,
|
||||||
|
key2 = lifecycleOwner,
|
||||||
|
) { flow.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun <T : R, R> Flow<T>.collectAsStateLifecycleAware(
|
fun <T : R, R> Flow<T>.collectAsStateLifecycleAware(
|
||||||
initial: R,
|
initial: R,
|
||||||
context: CoroutineContext = EmptyCoroutineContext
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
): State<R> {
|
): State<R> {
|
||||||
val lifecycleAwareFlow = rememberFlow(flow = this)
|
val lifecycleAwareFlow = rememberFlow(flow = this)
|
||||||
return lifecycleAwareFlow.collectAsState(initial = initial, context = context)
|
return lifecycleAwareFlow.collectAsState(initial = initial, context = context)
|
||||||
|
|
|
||||||
|
|
@ -10,21 +10,41 @@ import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class NotificationOpenHandler {
|
class NotificationOpenHandler {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun handleOpenedByNotification(
|
||||||
fun handleOpenedByNotification(identifier: String, intent: Intent) {
|
identifier: String,
|
||||||
|
intent: Intent,
|
||||||
|
) {
|
||||||
MainScope().launch(context = Dispatchers.Main) {
|
MainScope().launch(context = Dispatchers.Main) {
|
||||||
when (identifier) {
|
when (identifier) {
|
||||||
PushNotificationManager.PARTY_INVITE_PUSH_NOTIFICATION_KEY -> openNoPartyScreen()
|
PushNotificationManager.PARTY_INVITE_PUSH_NOTIFICATION_KEY -> openNoPartyScreen()
|
||||||
PushNotificationManager.QUEST_BEGUN_PUSH_NOTIFICATION_KEY -> openPartyScreen()
|
PushNotificationManager.QUEST_BEGUN_PUSH_NOTIFICATION_KEY -> openPartyScreen()
|
||||||
PushNotificationManager.QUEST_INVITE_PUSH_NOTIFICATION_KEY -> openPartyScreen()
|
PushNotificationManager.QUEST_INVITE_PUSH_NOTIFICATION_KEY -> openPartyScreen()
|
||||||
PushNotificationManager.GUILD_INVITE_PUSH_NOTIFICATION_KEY -> openGuildDetailScreen(intent.getStringExtra("groupID"))
|
PushNotificationManager.GUILD_INVITE_PUSH_NOTIFICATION_KEY ->
|
||||||
PushNotificationManager.RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY -> openPrivateMessageScreen(intent.getStringExtra("replyToUUID"), intent.getStringExtra("replyToUsername"))
|
openGuildDetailScreen(
|
||||||
|
intent.getStringExtra("groupID"),
|
||||||
|
)
|
||||||
|
|
||||||
|
PushNotificationManager.RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY ->
|
||||||
|
openPrivateMessageScreen(
|
||||||
|
intent.getStringExtra("replyToUUID"),
|
||||||
|
intent.getStringExtra("replyToUsername"),
|
||||||
|
)
|
||||||
|
|
||||||
PushNotificationManager.CHANGE_USERNAME_PUSH_NOTIFICATION_KEY -> openSettingsScreen()
|
PushNotificationManager.CHANGE_USERNAME_PUSH_NOTIFICATION_KEY -> openSettingsScreen()
|
||||||
PushNotificationManager.GIFT_ONE_GET_ONE_PUSH_NOTIFICATION_KEY -> openSubscriptionScreen()
|
PushNotificationManager.GIFT_ONE_GET_ONE_PUSH_NOTIFICATION_KEY -> openSubscriptionScreen()
|
||||||
PushNotificationManager.CHAT_MENTION_NOTIFICATION_KEY -> handleChatMessage(intent.getStringExtra("type"), intent.getStringExtra("groupID"))
|
PushNotificationManager.CHAT_MENTION_NOTIFICATION_KEY ->
|
||||||
PushNotificationManager.GROUP_ACTIVITY_NOTIFICATION_KEY -> handleChatMessage(intent.getStringExtra("type"), intent.getStringExtra("groupID"))
|
handleChatMessage(
|
||||||
|
intent.getStringExtra("type"),
|
||||||
|
intent.getStringExtra("groupID"),
|
||||||
|
)
|
||||||
|
|
||||||
|
PushNotificationManager.GROUP_ACTIVITY_NOTIFICATION_KEY ->
|
||||||
|
handleChatMessage(
|
||||||
|
intent.getStringExtra("type"),
|
||||||
|
intent.getStringExtra("groupID"),
|
||||||
|
)
|
||||||
|
|
||||||
PushNotificationManager.G1G1_PROMO_KEY -> openGiftOneGetOneInfoScreen()
|
PushNotificationManager.G1G1_PROMO_KEY -> openGiftOneGetOneInfoScreen()
|
||||||
else -> {
|
else -> {
|
||||||
intent.getStringExtra("openURL")?.let {
|
intent.getStringExtra("openURL")?.let {
|
||||||
|
|
@ -36,12 +56,21 @@ class NotificationOpenHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openSubscriptionScreen() {
|
private fun openSubscriptionScreen() {
|
||||||
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", true)))
|
MainNavigationController.navigate(
|
||||||
|
R.id.gemPurchaseActivity,
|
||||||
|
bundleOf(Pair("openSubscription", true)),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openPrivateMessageScreen(userID: String?, userName: String?) {
|
private fun openPrivateMessageScreen(
|
||||||
|
userID: String?,
|
||||||
|
userName: String?,
|
||||||
|
) {
|
||||||
if (userID != null && userName != null) {
|
if (userID != null && userName != null) {
|
||||||
MainNavigationController.navigate(R.id.inboxMessageListFragment, bundleOf("userID" to userID, "username" to userName))
|
MainNavigationController.navigate(
|
||||||
|
R.id.inboxMessageListFragment,
|
||||||
|
bundleOf("userID" to userID, "username" to userName),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
MainNavigationController.navigate(R.id.inboxFragment)
|
MainNavigationController.navigate(R.id.inboxFragment)
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +78,10 @@ class NotificationOpenHandler {
|
||||||
|
|
||||||
private fun openPartyScreen(isChatNotification: Boolean = false) {
|
private fun openPartyScreen(isChatNotification: Boolean = false) {
|
||||||
val tabToOpen = if (isChatNotification) 1 else 0
|
val tabToOpen = if (isChatNotification) 1 else 0
|
||||||
MainNavigationController.navigate(R.id.partyFragment, bundleOf("tabToOpen" to tabToOpen))
|
MainNavigationController.navigate(
|
||||||
|
R.id.partyFragment,
|
||||||
|
bundleOf("tabToOpen" to tabToOpen),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openNoPartyScreen() {
|
private fun openNoPartyScreen() {
|
||||||
|
|
@ -72,7 +104,10 @@ class NotificationOpenHandler {
|
||||||
MainNavigationController.navigate(R.id.prefsActivity)
|
MainNavigationController.navigate(R.id.prefsActivity)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleChatMessage(type: String?, groupID: String?) {
|
private fun handleChatMessage(
|
||||||
|
type: String?,
|
||||||
|
groupID: String?,
|
||||||
|
) {
|
||||||
when (type) {
|
when (type) {
|
||||||
"party" -> openPartyScreen()
|
"party" -> openPartyScreen()
|
||||||
"guild" -> openGuildDetailScreen(groupID)
|
"guild" -> openGuildDetailScreen(groupID)
|
||||||
|
|
|
||||||
|
|
@ -20,20 +20,26 @@ interface NotificationsManager {
|
||||||
var apiClient: WeakReference<ApiClient>?
|
var apiClient: WeakReference<ApiClient>?
|
||||||
|
|
||||||
fun setNotifications(current: List<Notification>)
|
fun setNotifications(current: List<Notification>)
|
||||||
|
|
||||||
fun getNotifications(): Flow<List<Notification>>
|
fun getNotifications(): Flow<List<Notification>>
|
||||||
|
|
||||||
fun getNotification(id: String): Notification?
|
fun getNotification(id: String): Notification?
|
||||||
fun dismissTaskNotification(context: Context, task: Task)
|
|
||||||
|
fun dismissTaskNotification(
|
||||||
|
context: Context,
|
||||||
|
task: Task,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainNotificationsManager : NotificationsManager {
|
class MainNotificationsManager : NotificationsManager {
|
||||||
|
|
||||||
private val seenNotifications: MutableMap<String, Boolean>
|
private val seenNotifications: MutableMap<String, Boolean>
|
||||||
override var apiClient: WeakReference<ApiClient>? = null
|
override var apiClient: WeakReference<ApiClient>? = null
|
||||||
|
|
||||||
private var lastNotificationHandling: Date? = null
|
private var lastNotificationHandling: Date? = null
|
||||||
private val notificationsFlow = MutableStateFlow<List<Notification>?>(null)
|
private val notificationsFlow = MutableStateFlow<List<Notification>?>(null)
|
||||||
private val displayedNotificationEvents = Channel<Notification>()
|
private val displayedNotificationEvents = Channel<Notification>()
|
||||||
override val displayNotificationEvents: Flow<Notification> = displayedNotificationEvents.receiveAsFlow().filterNotNull()
|
override val displayNotificationEvents: Flow<Notification> =
|
||||||
|
displayedNotificationEvents.receiveAsFlow().filterNotNull()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.seenNotifications = HashMap()
|
this.seenNotifications = HashMap()
|
||||||
|
|
@ -52,7 +58,10 @@ class MainNotificationsManager : NotificationsManager {
|
||||||
return notificationsFlow.value?.find { it.id == id }
|
return notificationsFlow.value?.find { it.id == id }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dismissTaskNotification(context: Context, task: Task) {
|
override fun dismissTaskNotification(
|
||||||
|
context: Context,
|
||||||
|
task: Task,
|
||||||
|
) {
|
||||||
NotificationManagerCompat.from(context).cancel(task.id.hashCode())
|
NotificationManagerCompat.from(context).cancel(task.id.hashCode())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,7 +74,8 @@ class MainNotificationsManager : NotificationsManager {
|
||||||
notifications
|
notifications
|
||||||
.filter { !this.seenNotifications.containsKey(it.id) }
|
.filter { !this.seenNotifications.containsKey(it.id) }
|
||||||
.map {
|
.map {
|
||||||
val notificationDisplayed = when (it.type) {
|
val notificationDisplayed =
|
||||||
|
when (it.type) {
|
||||||
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> true
|
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> true
|
||||||
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> true
|
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> true
|
||||||
Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> true
|
Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> true
|
||||||
|
|
|
||||||
|
|
@ -54,23 +54,29 @@ import kotlin.time.toDuration
|
||||||
class PurchaseHandler(
|
class PurchaseHandler(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val apiClient: ApiClient,
|
private val apiClient: ApiClient,
|
||||||
private val userViewModel: MainUserViewModel
|
private val userViewModel: MainUserViewModel,
|
||||||
) : PurchasesUpdatedListener, PurchasesResponseListener {
|
) : PurchasesUpdatedListener, PurchasesResponseListener {
|
||||||
private val billingClient =
|
private val billingClient =
|
||||||
BillingClient.newBuilder(context).setListener(this).enablePendingPurchases().build()
|
BillingClient.newBuilder(context).setListener(this).enablePendingPurchases().build()
|
||||||
|
|
||||||
override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList<Purchase>?) {
|
override fun onPurchasesUpdated(
|
||||||
|
result: BillingResult,
|
||||||
|
purchases: MutableList<Purchase>?,
|
||||||
|
) {
|
||||||
purchases?.let { processPurchases(result, it) }
|
purchases?.let { processPurchases(result, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onQueryPurchasesResponse(
|
override fun onQueryPurchasesResponse(
|
||||||
result: BillingResult,
|
result: BillingResult,
|
||||||
purchases: MutableList<Purchase>
|
purchases: MutableList<Purchase>,
|
||||||
) {
|
) {
|
||||||
processPurchases(result, purchases)
|
processPurchases(result, purchases)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processPurchases(result: BillingResult, purchases: List<Purchase>) {
|
private fun processPurchases(
|
||||||
|
result: BillingResult,
|
||||||
|
purchases: List<Purchase>,
|
||||||
|
) {
|
||||||
when (result.responseCode) {
|
when (result.responseCode) {
|
||||||
BillingClient.BillingResponseCode.OK -> {
|
BillingClient.BillingResponseCode.OK -> {
|
||||||
val mostRecentSub = findMostRecentSubscription(purchases)
|
val mostRecentSub = findMostRecentSubscription(purchases)
|
||||||
|
|
@ -79,8 +85,9 @@ class PurchaseHandler(
|
||||||
.filterNotNull().take(1).collect {
|
.filterNotNull().take(1).collect {
|
||||||
val plan = it.purchased!!.plan
|
val plan = it.purchased!!.plan
|
||||||
for (purchase in purchases) {
|
for (purchase in purchases) {
|
||||||
if (plan?.isActive == true && PurchaseTypes.allSubscriptionTypes.contains(
|
if (plan?.isActive == true &&
|
||||||
purchase.products.firstOrNull()
|
PurchaseTypes.allSubscriptionTypes.contains(
|
||||||
|
purchase.products.firstOrNull(),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (((plan.dateTerminated != null) == purchase.isAutoRenewing) ||
|
if (((plan.dateTerminated != null) == purchase.isAutoRenewing) ||
|
||||||
|
|
@ -125,7 +132,12 @@ class PurchaseHandler(
|
||||||
private var billingClientState: BillingClientState = BillingClientState.UNINITIALIZED
|
private var billingClientState: BillingClientState = BillingClientState.UNINITIALIZED
|
||||||
|
|
||||||
private enum class BillingClientState {
|
private enum class BillingClientState {
|
||||||
UNINITIALIZED, READY, UNAVAILABLE, DISCONNECTED, CONNECTING;
|
UNINITIALIZED,
|
||||||
|
READY,
|
||||||
|
UNAVAILABLE,
|
||||||
|
DISCONNECTED,
|
||||||
|
CONNECTING,
|
||||||
|
;
|
||||||
|
|
||||||
val canMaybePurchase: Boolean
|
val canMaybePurchase: Boolean
|
||||||
get() {
|
get() {
|
||||||
|
|
@ -134,6 +146,7 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
private var listeningRetryCount = 0
|
private var listeningRetryCount = 0
|
||||||
|
|
||||||
fun startListening() {
|
fun startListening() {
|
||||||
if (billingClient.connectionState == BillingClient.ConnectionState.CONNECTING ||
|
if (billingClient.connectionState == BillingClient.ConnectionState.CONNECTING ||
|
||||||
billingClient.connectionState == BillingClient.ConnectionState.CONNECTED ||
|
billingClient.connectionState == BillingClient.ConnectionState.CONNECTED ||
|
||||||
|
|
@ -147,7 +160,8 @@ class PurchaseHandler(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
billingClientState = BillingClientState.CONNECTING
|
billingClientState = BillingClientState.CONNECTING
|
||||||
billingClient.startConnection(object : BillingClientStateListener {
|
billingClient.startConnection(
|
||||||
|
object : BillingClientStateListener {
|
||||||
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
||||||
when (billingResult.responseCode) {
|
when (billingResult.responseCode) {
|
||||||
BillingClient.BillingResponseCode.OK -> {
|
BillingClient.BillingResponseCode.OK -> {
|
||||||
|
|
@ -156,12 +170,15 @@ class PurchaseHandler(
|
||||||
queryPurchases()
|
queryPurchases()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
|
BillingClient.BillingResponseCode.SERVICE_DISCONNECTED -> {
|
||||||
retryListening()
|
retryListening()
|
||||||
}
|
}
|
||||||
|
|
||||||
BillingClient.BillingResponseCode.SERVICE_TIMEOUT -> {
|
BillingClient.BillingResponseCode.SERVICE_TIMEOUT -> {
|
||||||
retryListening()
|
retryListening()
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
billingClientState = BillingClientState.UNAVAILABLE
|
billingClientState = BillingClientState.UNAVAILABLE
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +189,8 @@ class PurchaseHandler(
|
||||||
billingClientState = BillingClientState.DISCONNECTED
|
billingClientState = BillingClientState.DISCONNECTED
|
||||||
retryListening()
|
retryListening()
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun retryListening() {
|
private fun retryListening() {
|
||||||
|
|
@ -195,20 +213,22 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
billingClientState.canMaybePurchase && billingClient.isReady
|
billingClientState.canMaybePurchase && billingClient.isReady
|
||||||
}
|
}
|
||||||
val subResponse = billingClient.queryPurchasesAsync(
|
val subResponse =
|
||||||
|
billingClient.queryPurchasesAsync(
|
||||||
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS)
|
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS)
|
||||||
.build()
|
.build(),
|
||||||
)
|
)
|
||||||
processPurchases(subResponse.billingResult, subResponse.purchasesList)
|
processPurchases(subResponse.billingResult, subResponse.purchasesList)
|
||||||
val iapResponse = billingClient.queryPurchasesAsync(
|
val iapResponse =
|
||||||
|
billingClient.queryPurchasesAsync(
|
||||||
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP)
|
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP)
|
||||||
.build()
|
.build(),
|
||||||
)
|
)
|
||||||
processPurchases(iapResponse.billingResult, iapResponse.purchasesList)
|
processPurchases(iapResponse.billingResult, iapResponse.purchasesList)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGryphatriceSKU() =
|
suspend fun getGryphatriceSKU() =
|
||||||
getSKU(BillingClient.ProductType.INAPP, PurchaseTypes.JubilantGrphatrice)
|
getSKU(BillingClient.ProductType.INAPP, PurchaseTypes.JUBILANT_GRYPHATRICE)
|
||||||
|
|
||||||
suspend fun getAllGemSKUs() =
|
suspend fun getAllGemSKUs() =
|
||||||
getSKUs(BillingClient.ProductType.INAPP, PurchaseTypes.allGemTypes)
|
getSKUs(BillingClient.ProductType.INAPP, PurchaseTypes.allGemTypes)
|
||||||
|
|
@ -222,27 +242,38 @@ class PurchaseHandler(
|
||||||
suspend fun getInAppPurchaseSKU(identifier: String) =
|
suspend fun getInAppPurchaseSKU(identifier: String) =
|
||||||
getSKU(BillingClient.ProductType.INAPP, identifier)
|
getSKU(BillingClient.ProductType.INAPP, identifier)
|
||||||
|
|
||||||
private suspend fun getSKUs(type: String, identifiers: List<String>) =
|
private suspend fun getSKUs(
|
||||||
|
type: String,
|
||||||
|
identifiers: List<String>,
|
||||||
|
) =
|
||||||
loadInventory(type, identifiers) ?: emptyList()
|
loadInventory(type, identifiers) ?: emptyList()
|
||||||
|
|
||||||
private suspend fun getSKU(type: String, identifier: String): ProductDetails? {
|
private suspend fun getSKU(
|
||||||
|
type: String,
|
||||||
|
identifier: String,
|
||||||
|
): ProductDetails? {
|
||||||
val inventory = loadInventory(type, listOf(identifier))
|
val inventory = loadInventory(type, listOf(identifier))
|
||||||
return inventory?.firstOrNull()
|
return inventory?.firstOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadInventory(type: String, skus: List<String>): List<ProductDetails>? {
|
private suspend fun loadInventory(
|
||||||
|
type: String,
|
||||||
|
skus: List<String>,
|
||||||
|
): List<ProductDetails>? {
|
||||||
retryUntil {
|
retryUntil {
|
||||||
if (billingClientState == BillingClientState.DISCONNECTED) {
|
if (billingClientState == BillingClientState.DISCONNECTED) {
|
||||||
startListening()
|
startListening()
|
||||||
}
|
}
|
||||||
billingClientState.canMaybePurchase && billingClient.isReady
|
billingClientState.canMaybePurchase && billingClient.isReady
|
||||||
}
|
}
|
||||||
val params = QueryProductDetailsParams.newBuilder().setProductList(
|
val params =
|
||||||
|
QueryProductDetailsParams.newBuilder().setProductList(
|
||||||
skus.map {
|
skus.map {
|
||||||
Product.newBuilder().setProductId(it).setProductType(type).build()
|
Product.newBuilder().setProductId(it).setProductType(type).build()
|
||||||
}
|
},
|
||||||
).build()
|
).build()
|
||||||
val skuDetailsResult = withContext(Dispatchers.IO) {
|
val skuDetailsResult =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
billingClient.queryProductDetails(params)
|
billingClient.queryProductDetails(params)
|
||||||
}
|
}
|
||||||
return skuDetailsResult.productDetailsList
|
return skuDetailsResult.productDetailsList
|
||||||
|
|
@ -253,7 +284,7 @@ class PurchaseHandler(
|
||||||
skuDetails: ProductDetails,
|
skuDetails: ProductDetails,
|
||||||
recipient: String? = null,
|
recipient: String? = null,
|
||||||
recipientUsername: String? = null,
|
recipientUsername: String? = null,
|
||||||
isSaleGemPurchase: Boolean = false
|
isSaleGemPurchase: Boolean = false,
|
||||||
) {
|
) {
|
||||||
this.isSaleGemPurchase = isSaleGemPurchase
|
this.isSaleGemPurchase = isSaleGemPurchase
|
||||||
recipient?.let {
|
recipient?.let {
|
||||||
|
|
@ -264,14 +295,17 @@ class PurchaseHandler(
|
||||||
listOf(skuDetails).map {
|
listOf(skuDetails).map {
|
||||||
BillingFlowParams.ProductDetailsParams.newBuilder()
|
BillingFlowParams.ProductDetailsParams.newBuilder()
|
||||||
.setProductDetails(skuDetails).setOfferToken(
|
.setProductDetails(skuDetails).setOfferToken(
|
||||||
skuDetails.subscriptionOfferDetails?.first()?.offerToken ?: ""
|
skuDetails.subscriptionOfferDetails?.first()?.offerToken ?: "",
|
||||||
).build()
|
).build()
|
||||||
}
|
},
|
||||||
).build()
|
).build()
|
||||||
billingClient.launchBillingFlow(activity, flowParams)
|
billingClient.launchBillingFlow(activity, flowParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun consume(purchase: Purchase, retries: Int = 4) {
|
private suspend fun consume(
|
||||||
|
purchase: Purchase,
|
||||||
|
retries: Int = 4,
|
||||||
|
) {
|
||||||
retryUntil { billingClientState.canMaybePurchase && billingClient.isReady }
|
retryUntil { billingClientState.canMaybePurchase && billingClient.isReady }
|
||||||
val params = ConsumeParams.newBuilder().setPurchaseToken(purchase.purchaseToken).build()
|
val params = ConsumeParams.newBuilder().setPurchaseToken(purchase.purchaseToken).build()
|
||||||
val result = billingClient.consumePurchase(params)
|
val result = billingClient.consumePurchase(params)
|
||||||
|
|
@ -287,14 +321,19 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
private var processedPurchases = mutableSetOf<String>()
|
private var processedPurchases = mutableSetOf<String>()
|
||||||
|
|
||||||
private fun handle(purchase: Purchase) {
|
private fun handle(purchase: Purchase) {
|
||||||
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED || processedPurchases.contains(purchase.orderId)) {
|
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED ||
|
||||||
|
processedPurchases.contains(
|
||||||
|
purchase.orderId,
|
||||||
|
)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
purchase.orderId?.let { processedPurchases.add(it) }
|
purchase.orderId?.let { processedPurchases.add(it) }
|
||||||
val sku = purchase.products.firstOrNull()
|
val sku = purchase.products.firstOrNull()
|
||||||
when {
|
when {
|
||||||
sku == PurchaseTypes.JubilantGrphatrice -> {
|
sku == PurchaseTypes.JUBILANT_GRYPHATRICE -> {
|
||||||
val validationRequest = buildValidationRequest(purchase)
|
val validationRequest = buildValidationRequest(purchase)
|
||||||
MainScope().launchCatching {
|
MainScope().launchCatching {
|
||||||
try {
|
try {
|
||||||
|
|
@ -363,7 +402,10 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun acknowledgePurchase(purchase: Purchase, retries: Int = 4) {
|
private suspend fun acknowledgePurchase(
|
||||||
|
purchase: Purchase,
|
||||||
|
retries: Int = 4,
|
||||||
|
) {
|
||||||
val params =
|
val params =
|
||||||
AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.purchaseToken).build()
|
AcknowledgePurchaseParams.newBuilder().setPurchaseToken(purchase.purchaseToken).build()
|
||||||
val response = billingClient.acknowledgePurchase(params)
|
val response = billingClient.acknowledgePurchase(params)
|
||||||
|
|
@ -397,7 +439,10 @@ class PurchaseHandler(
|
||||||
return validationRequest
|
return validationRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleError(throwable: Throwable, purchase: Purchase) {
|
private fun handleError(
|
||||||
|
throwable: Throwable,
|
||||||
|
purchase: Purchase,
|
||||||
|
) {
|
||||||
when (throwable) {
|
when (throwable) {
|
||||||
is HttpException -> {
|
is HttpException -> {
|
||||||
if (throwable.code() == 401) {
|
if (throwable.code() == 401) {
|
||||||
|
|
@ -412,6 +457,7 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// Handles other potential errors such as IOException or an exception
|
// Handles other potential errors such as IOException or an exception
|
||||||
// thrown by billingClient.consumePurchase method that is not handled
|
// thrown by billingClient.consumePurchase method that is not handled
|
||||||
|
|
@ -425,7 +471,8 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun checkForSubscription(): Purchase? {
|
suspend fun checkForSubscription(): Purchase? {
|
||||||
val result = withContext(Dispatchers.IO) {
|
val result =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
val params =
|
val params =
|
||||||
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS)
|
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS)
|
||||||
.build()
|
.build()
|
||||||
|
|
@ -454,6 +501,7 @@ class PurchaseHandler(
|
||||||
}
|
}
|
||||||
|
|
||||||
private var alreadyTriedCancellation = false
|
private var alreadyTriedCancellation = false
|
||||||
|
|
||||||
suspend fun cancelSubscription(): User? {
|
suspend fun cancelSubscription(): User? {
|
||||||
if (alreadyTriedCancellation) return null
|
if (alreadyTriedCancellation) return null
|
||||||
alreadyTriedCancellation = true
|
alreadyTriedCancellation = true
|
||||||
|
|
@ -463,10 +511,10 @@ class PurchaseHandler(
|
||||||
|
|
||||||
private fun durationString(sku: String): String {
|
private fun durationString(sku: String): String {
|
||||||
return when (sku) {
|
return when (sku) {
|
||||||
PurchaseTypes.Subscription1MonthNoRenew, PurchaseTypes.Subscription1Month -> "1"
|
PurchaseTypes.SUBSCRIPTION_1_MONTH_NORENEW, PurchaseTypes.SUBSCRIPTION_1_MONTH -> "1"
|
||||||
PurchaseTypes.Subscription3MonthNoRenew, PurchaseTypes.Subscription3Month -> "3"
|
PurchaseTypes.SUBSCRIPTION_3_MONTH_NORENEW, PurchaseTypes.SUBSCRIPTION_3_MONTH -> "3"
|
||||||
PurchaseTypes.Subscription6MonthNoRenew, PurchaseTypes.Subscription6Month -> "6"
|
PurchaseTypes.SUBSCRIPTION_6_MONTH_NORENEW, PurchaseTypes.SUBSCRIPTION_6_MONTH -> "6"
|
||||||
PurchaseTypes.Subscription12MonthNoRenew, PurchaseTypes.Subscription12Month -> "12"
|
PurchaseTypes.SUBSCRIPTION_12_MONTH_NORENEW, PurchaseTypes.SUBSCRIPTION_12_MONTH -> "12"
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -477,18 +525,18 @@ class PurchaseHandler(
|
||||||
if (isSaleGemPurchase) {
|
if (isSaleGemPurchase) {
|
||||||
isSaleGemPurchase = false
|
isSaleGemPurchase = false
|
||||||
return when (sku) {
|
return when (sku) {
|
||||||
PurchaseTypes.Purchase4Gems -> "5"
|
PurchaseTypes.PURCHASE_4_GEMS -> "5"
|
||||||
PurchaseTypes.Purchase21Gems -> "30"
|
PurchaseTypes.PURCHASE_21_GEMS -> "30"
|
||||||
PurchaseTypes.Purchase42Gems -> "60"
|
PurchaseTypes.PURCHASE_42_GEMS -> "60"
|
||||||
PurchaseTypes.Purchase84Gems -> "125"
|
PurchaseTypes.PURCHASE_84_GEMS -> "125"
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return when (sku) {
|
return when (sku) {
|
||||||
PurchaseTypes.Purchase4Gems -> "4"
|
PurchaseTypes.PURCHASE_4_GEMS -> "4"
|
||||||
PurchaseTypes.Purchase21Gems -> "21"
|
PurchaseTypes.PURCHASE_21_GEMS -> "21"
|
||||||
PurchaseTypes.Purchase42Gems -> "42"
|
PurchaseTypes.PURCHASE_42_GEMS -> "42"
|
||||||
PurchaseTypes.Purchase84Gems -> "84"
|
PurchaseTypes.PURCHASE_84_GEMS -> "84"
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -496,33 +544,38 @@ class PurchaseHandler(
|
||||||
|
|
||||||
private val displayedConfirmations = mutableListOf<String>()
|
private val displayedConfirmations = mutableListOf<String>()
|
||||||
|
|
||||||
private fun displayConfirmationDialog(purchase: Purchase, giftedTo: String? = null) {
|
private fun displayConfirmationDialog(
|
||||||
|
purchase: Purchase,
|
||||||
|
giftedTo: String? = null,
|
||||||
|
) {
|
||||||
if (displayedConfirmations.contains(purchase.orderId)) {
|
if (displayedConfirmations.contains(purchase.orderId)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
purchase.orderId?.let { displayedConfirmations.add(it) }
|
purchase.orderId?.let { displayedConfirmations.add(it) }
|
||||||
CoroutineScope(Dispatchers.Main).launchCatching {
|
CoroutineScope(Dispatchers.Main).launchCatching {
|
||||||
val application = (context as? HabiticaBaseApplication)
|
val application =
|
||||||
|
(context as? HabiticaBaseApplication)
|
||||||
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launchCatching
|
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launchCatching
|
||||||
val sku = purchase.products.firstOrNull() ?: return@launchCatching
|
val sku = purchase.products.firstOrNull() ?: return@launchCatching
|
||||||
var title = context.getString(R.string.successful_purchase_generic)
|
var title = context.getString(R.string.successful_purchase_generic)
|
||||||
val message = when {
|
val message =
|
||||||
|
when {
|
||||||
PurchaseTypes.allSubscriptionNoRenewTypes.contains(sku) -> {
|
PurchaseTypes.allSubscriptionNoRenewTypes.contains(sku) -> {
|
||||||
title = context.getString(R.string.gift_confirmation_title)
|
title = context.getString(R.string.gift_confirmation_title)
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.gift_confirmation_text_sub,
|
R.string.gift_confirmation_text_sub,
|
||||||
giftedTo,
|
giftedTo,
|
||||||
durationString(sku)
|
durationString(sku),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
PurchaseTypes.allSubscriptionTypes.contains(sku) -> {
|
PurchaseTypes.allSubscriptionTypes.contains(sku) -> {
|
||||||
if (sku == PurchaseTypes.Subscription1Month) {
|
if (sku == PurchaseTypes.SUBSCRIPTION_1_MONTH) {
|
||||||
context.getString(R.string.subscription_confirmation)
|
context.getString(R.string.subscription_confirmation)
|
||||||
} else {
|
} else {
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.subscription_confirmation_multiple,
|
R.string.subscription_confirmation_multiple,
|
||||||
durationString(sku)
|
durationString(sku),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -532,7 +585,7 @@ class PurchaseHandler(
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.gift_confirmation_text_gems_new,
|
R.string.gift_confirmation_text_gems_new,
|
||||||
giftedTo,
|
giftedTo,
|
||||||
gemAmountString(sku)
|
gemAmountString(sku),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -559,13 +612,15 @@ class PurchaseHandler(
|
||||||
|
|
||||||
private fun displayGryphatriceConfirmationDialog(
|
private fun displayGryphatriceConfirmationDialog(
|
||||||
purchase: Purchase,
|
purchase: Purchase,
|
||||||
giftedTo: String? = null
|
giftedTo: String? = null,
|
||||||
) {
|
) {
|
||||||
MainScope().launch(ExceptionHandler.coroutine()) {
|
MainScope().launch(ExceptionHandler.coroutine()) {
|
||||||
val application = (context as? HabiticaBaseApplication)
|
val application =
|
||||||
|
(context as? HabiticaBaseApplication)
|
||||||
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launch
|
?: (context.applicationContext as? HabiticaBaseApplication) ?: return@launch
|
||||||
val title = context.getString(R.string.successful_purchase_generic)
|
val title = context.getString(R.string.successful_purchase_generic)
|
||||||
val message = if (giftedTo != null) {
|
val message =
|
||||||
|
if (giftedTo != null) {
|
||||||
context.getString(R.string.jubilant_gryphatrice_confirmation_gift)
|
context.getString(R.string.jubilant_gryphatrice_confirmation_gift)
|
||||||
} else {
|
} else {
|
||||||
context.getString(R.string.jubilant_gryphatrice_confirmation)
|
context.getString(R.string.jubilant_gryphatrice_confirmation)
|
||||||
|
|
@ -590,7 +645,11 @@ class PurchaseHandler(
|
||||||
private var pendingGifts: MutableMap<String, Triple<Date, String, String>> = HashMap()
|
private var pendingGifts: MutableMap<String, Triple<Date, String, String>> = HashMap()
|
||||||
private var preferences: SharedPreferences? = null
|
private var preferences: SharedPreferences? = null
|
||||||
|
|
||||||
fun addGift(sku: String, userID: String, username: String) {
|
fun addGift(
|
||||||
|
sku: String,
|
||||||
|
userID: String,
|
||||||
|
username: String,
|
||||||
|
) {
|
||||||
pendingGifts[sku] = Triple(Date(), userID, username)
|
pendingGifts[sku] = Triple(Date(), userID, username)
|
||||||
savePendingGifts()
|
savePendingGifts()
|
||||||
}
|
}
|
||||||
|
|
@ -616,7 +675,7 @@ suspend fun retryUntil(
|
||||||
initialDelay: Long = 100, // 0.1 second
|
initialDelay: Long = 100, // 0.1 second
|
||||||
maxDelay: Long = 1000, // 1 second
|
maxDelay: Long = 1000, // 1 second
|
||||||
factor: Double = 2.0,
|
factor: Double = 2.0,
|
||||||
block: suspend () -> Boolean
|
block: suspend () -> Boolean,
|
||||||
) {
|
) {
|
||||||
var currentDelay = initialDelay
|
var currentDelay = initialDelay
|
||||||
repeat(times - 1) {
|
repeat(times - 1) {
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,36 @@
|
||||||
package com.habitrpg.android.habitica.helpers
|
package com.habitrpg.android.habitica.helpers
|
||||||
|
|
||||||
object PurchaseTypes {
|
object PurchaseTypes {
|
||||||
const val JubilantGrphatrice = "com.habitrpg.android.habitica.iap.pets.gryphatrice_jubilant"
|
const val JUBILANT_GRYPHATRICE = "com.habitrpg.android.habitica.iap.pets.gryphatrice_jubilant"
|
||||||
const val Purchase4Gems = "com.habitrpg.android.habitica.iap.4gems"
|
const val PURCHASE_4_GEMS = "com.habitrpg.android.habitica.iap.4gems"
|
||||||
const val Purchase21Gems = "com.habitrpg.android.habitica.iap.21gems"
|
const val PURCHASE_21_GEMS = "com.habitrpg.android.habitica.iap.21gems"
|
||||||
const val Purchase42Gems = "com.habitrpg.android.habitica.iap.42gems"
|
const val PURCHASE_42_GEMS = "com.habitrpg.android.habitica.iap.42gems"
|
||||||
const val Purchase84Gems = "com.habitrpg.android.habitica.iap.84gems"
|
const val PURCHASE_84_GEMS = "com.habitrpg.android.habitica.iap.84gems"
|
||||||
val allGemTypes = listOf(Purchase4Gems, Purchase21Gems, Purchase42Gems, Purchase84Gems)
|
val allGemTypes = listOf(PURCHASE_4_GEMS, PURCHASE_21_GEMS, PURCHASE_42_GEMS, PURCHASE_84_GEMS)
|
||||||
const val Subscription1Month = "com.habitrpg.android.habitica.subscription.1month"
|
const val SUBSCRIPTION_1_MONTH = "com.habitrpg.android.habitica.subscription.1month"
|
||||||
const val Subscription3Month = "com.habitrpg.android.habitica.subscription.3month"
|
const val SUBSCRIPTION_3_MONTH = "com.habitrpg.android.habitica.subscription.3month"
|
||||||
const val Subscription6Month = "com.habitrpg.android.habitica.subscription.6month"
|
const val SUBSCRIPTION_6_MONTH = "com.habitrpg.android.habitica.subscription.6month"
|
||||||
const val Subscription12Month = "com.habitrpg.android.habitica.subscription.12month"
|
const val SUBSCRIPTION_12_MONTH = "com.habitrpg.android.habitica.subscription.12month"
|
||||||
val allSubscriptionTypes = mutableListOf(
|
val allSubscriptionTypes =
|
||||||
Subscription1Month,
|
mutableListOf(
|
||||||
Subscription3Month,
|
SUBSCRIPTION_1_MONTH,
|
||||||
Subscription6Month,
|
SUBSCRIPTION_3_MONTH,
|
||||||
Subscription12Month
|
SUBSCRIPTION_6_MONTH,
|
||||||
|
SUBSCRIPTION_12_MONTH,
|
||||||
)
|
)
|
||||||
const val Subscription1MonthNoRenew = "com.habitrpg.android.habitica.norenew_subscription.1month"
|
const val SUBSCRIPTION_1_MONTH_NORENEW =
|
||||||
const val Subscription3MonthNoRenew = "com.habitrpg.android.habitica.norenew_subscription.3month"
|
"com.habitrpg.android.habitica.norenew_subscription.1month"
|
||||||
const val Subscription6MonthNoRenew = "com.habitrpg.android.habitica.norenew_subscription.6month"
|
const val SUBSCRIPTION_3_MONTH_NORENEW =
|
||||||
const val Subscription12MonthNoRenew = "com.habitrpg.android.habitica.norenew_subscription.12month"
|
"com.habitrpg.android.habitica.norenew_subscription.3month"
|
||||||
var allSubscriptionNoRenewTypes = listOf(
|
const val SUBSCRIPTION_6_MONTH_NORENEW =
|
||||||
Subscription1MonthNoRenew,
|
"com.habitrpg.android.habitica.norenew_subscription.6month"
|
||||||
Subscription3MonthNoRenew,
|
const val SUBSCRIPTION_12_MONTH_NORENEW =
|
||||||
Subscription6MonthNoRenew,
|
"com.habitrpg.android.habitica.norenew_subscription.12month"
|
||||||
Subscription12MonthNoRenew
|
var allSubscriptionNoRenewTypes =
|
||||||
|
listOf(
|
||||||
|
SUBSCRIPTION_1_MONTH_NORENEW,
|
||||||
|
SUBSCRIPTION_3_MONTH_NORENEW,
|
||||||
|
SUBSCRIPTION_6_MONTH_NORENEW,
|
||||||
|
SUBSCRIPTION_12_MONTH_NORENEW,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import androidx.core.content.edit
|
||||||
import com.google.android.play.core.review.ReviewManagerFactory
|
import com.google.android.play.core.review.ReviewManagerFactory
|
||||||
|
|
||||||
class ReviewManager(context: Context, private val configManager: AppConfigManager) {
|
class ReviewManager(context: Context, private val configManager: AppConfigManager) {
|
||||||
|
|
||||||
private val reviewManager = ReviewManagerFactory.create(context)
|
private val reviewManager = ReviewManagerFactory.create(context)
|
||||||
private val sharedPref = context.getSharedPreferences("ReviewPrefs", Context.MODE_PRIVATE)
|
private val sharedPref = context.getSharedPreferences("ReviewPrefs", Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
|
@ -59,7 +58,10 @@ class ReviewManager(context: Context, private val configManager: AppConfigManage
|
||||||
return !(lastReviewCheckin != -1 && currentCheckins - lastReviewCheckin < 5)
|
return !(lastReviewCheckin != -1 && currentCheckins - lastReviewCheckin < 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestReview(activity: AppCompatActivity, currentCheckins: Int) {
|
fun requestReview(
|
||||||
|
activity: AppCompatActivity,
|
||||||
|
currentCheckins: Int,
|
||||||
|
) {
|
||||||
if (!canRequestReview(currentCheckins)) return
|
if (!canRequestReview(currentCheckins)) return
|
||||||
|
|
||||||
val request = reviewManager.requestReviewFlow()
|
val request = reviewManager.requestReviewFlow()
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ class SoundFile(val theme: String, private val fileName: String) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
player?.setDataSource(file?.path)
|
player?.setDataSource(file?.path)
|
||||||
val attributes = AudioAttributes.Builder()
|
val attributes =
|
||||||
|
AudioAttributes.Builder()
|
||||||
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
|
.setLegacyStreamType(AudioManager.STREAM_MUSIC)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@ class SoundFileLoader(private val context: Context) {
|
||||||
|
|
||||||
private val externalCacheDir: String?
|
private val externalCacheDir: String?
|
||||||
get() {
|
get() {
|
||||||
val cacheDir = HabiticaBaseApplication.getInstance(context)?.getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS)
|
val cacheDir =
|
||||||
|
HabiticaBaseApplication.getInstance(context)
|
||||||
|
?.getExternalFilesDir(Environment.DIRECTORY_NOTIFICATIONS)
|
||||||
return cacheDir?.path
|
return cacheDir?.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,35 +6,37 @@ import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class SoundManager @Inject constructor(var soundFileLoader: SoundFileLoader) {
|
class SoundManager
|
||||||
var soundTheme: String = SoundThemeOff
|
@Inject
|
||||||
|
constructor(var soundFileLoader: SoundFileLoader) {
|
||||||
|
var soundTheme: String = SOUND_THEME_OFF
|
||||||
|
|
||||||
private val loadedSoundFiles: MutableMap<String, SoundFile> = HashMap()
|
private val loadedSoundFiles: MutableMap<String, SoundFile> = HashMap()
|
||||||
|
|
||||||
fun preloadAllFiles() {
|
fun preloadAllFiles() {
|
||||||
loadedSoundFiles.clear()
|
loadedSoundFiles.clear()
|
||||||
if (soundTheme == SoundThemeOff) {
|
if (soundTheme == SOUND_THEME_OFF) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val soundFiles = ArrayList<SoundFile>()
|
val soundFiles = ArrayList<SoundFile>()
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundAchievementUnlocked))
|
soundFiles.add(SoundFile(soundTheme, SOUND_ACHIEVEMENT_UNLOCKED))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundChat))
|
soundFiles.add(SoundFile(soundTheme, SOUND_CHAT))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundDaily))
|
soundFiles.add(SoundFile(soundTheme, SOUND_DAILY))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundDeath))
|
soundFiles.add(SoundFile(soundTheme, SOUND_DEATH))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundItemDrop))
|
soundFiles.add(SoundFile(soundTheme, SOUND_ITEM_DROP))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundLevelUp))
|
soundFiles.add(SoundFile(soundTheme, SOUND_LEVEL_UP))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundMinusHabit))
|
soundFiles.add(SoundFile(soundTheme, SOUND_MINUS_HABIT))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundPlusHabit))
|
soundFiles.add(SoundFile(soundTheme, SOUND_PLUS_HABIT))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundReward))
|
soundFiles.add(SoundFile(soundTheme, SOUND_REWARD))
|
||||||
soundFiles.add(SoundFile(soundTheme, SoundTodo))
|
soundFiles.add(SoundFile(soundTheme, SOUND_TODO))
|
||||||
MainScope().launchCatching {
|
MainScope().launchCatching {
|
||||||
soundFileLoader.download(soundFiles)
|
soundFileLoader.download(soundFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadAndPlayAudio(type: String) {
|
fun loadAndPlayAudio(type: String) {
|
||||||
if (soundTheme == SoundThemeOff) {
|
if (soundTheme == SOUND_THEME_OFF) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,16 +56,16 @@ class SoundManager @Inject constructor(var soundFileLoader: SoundFileLoader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SoundAchievementUnlocked = "Achievement_Unlocked"
|
const val SOUND_ACHIEVEMENT_UNLOCKED = "Achievement_Unlocked"
|
||||||
const val SoundChat = "Chat"
|
const val SOUND_CHAT = "Chat"
|
||||||
const val SoundDaily = "Daily"
|
const val SOUND_DAILY = "Daily"
|
||||||
const val SoundDeath = "Death"
|
const val SOUND_DEATH = "Death"
|
||||||
const val SoundItemDrop = "Item_Drop"
|
const val SOUND_ITEM_DROP = "Item_Drop"
|
||||||
const val SoundLevelUp = "Level_Up"
|
const val SOUND_LEVEL_UP = "Level_Up"
|
||||||
const val SoundMinusHabit = "Minus_Habit"
|
const val SOUND_MINUS_HABIT = "Minus_Habit"
|
||||||
const val SoundPlusHabit = "Plus_Habit"
|
const val SOUND_PLUS_HABIT = "Plus_Habit"
|
||||||
const val SoundReward = "Reward"
|
const val SOUND_REWARD = "Reward"
|
||||||
const val SoundTodo = "Todo"
|
const val SOUND_TODO = "Todo"
|
||||||
const val SoundThemeOff = "off"
|
const val SOUND_THEME_OFF = "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,11 @@ import java.util.Date
|
||||||
class TaskAlarmManager(
|
class TaskAlarmManager(
|
||||||
private var context: Context,
|
private var context: Context,
|
||||||
private var taskRepository: TaskRepository,
|
private var taskRepository: TaskRepository,
|
||||||
private var authenticationHandler: AuthenticationHandler
|
private var authenticationHandler: AuthenticationHandler,
|
||||||
) {
|
) {
|
||||||
private val am: AlarmManager? = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
private val am: AlarmManager? = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||||
private val upcomingReminderOccurrencesToSchedule = 3
|
private val upcomingReminderOccurrencesToSchedule = 3
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedules multiple alarms for each reminder associated with a given task.
|
* Schedules multiple alarms for each reminder associated with a given task.
|
||||||
*
|
*
|
||||||
|
|
@ -60,7 +59,10 @@ class TaskAlarmManager(
|
||||||
*/
|
*/
|
||||||
private fun setAlarmsForTask(task: Task) {
|
private fun setAlarmsForTask(task: Task) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val reminderOccurencesToSchedule = if (task.type == TaskType.TODO) { 1 } else {
|
val reminderOccurencesToSchedule =
|
||||||
|
if (task.type == TaskType.TODO) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
// For dailies, we schedule multiple reminders in advance
|
// For dailies, we schedule multiple reminders in advance
|
||||||
upcomingReminderOccurrencesToSchedule
|
upcomingReminderOccurrencesToSchedule
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +84,6 @@ class TaskAlarmManager(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun removeAlarmsForTask(task: Task) {
|
fun removeAlarmsForTask(task: Task) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
task.reminders?.let { reminders ->
|
task.reminders?.let { reminders ->
|
||||||
|
|
@ -99,7 +100,8 @@ class TaskAlarmManager(
|
||||||
// We may be able to use repeating alarms instead of this in the future
|
// We may be able to use repeating alarms instead of this in the future
|
||||||
fun addAlarmForTaskId(taskId: String) {
|
fun addAlarmForTaskId(taskId: String) {
|
||||||
MainScope().launch(ExceptionHandler.coroutine()) {
|
MainScope().launch(ExceptionHandler.coroutine()) {
|
||||||
val task = taskRepository.getTaskCopy(taskId)
|
val task =
|
||||||
|
taskRepository.getTaskCopy(taskId)
|
||||||
.filter { task -> task.isValid && task.isManaged && TaskType.DAILY == task.type }
|
.filter { task -> task.isValid && task.isManaged && TaskType.DAILY == task.type }
|
||||||
.first()
|
.first()
|
||||||
setAlarmsForTask(task)
|
setAlarmsForTask(task)
|
||||||
|
|
@ -137,7 +139,11 @@ class TaskAlarmManager(
|
||||||
* @param remindersItem The reminder item containing details like ID and the time for the reminder.
|
* @param remindersItem The reminder item containing details like ID and the time for the reminder.
|
||||||
* If this is null, the method returns immediately without scheduling an alarm.
|
* If this is null, the method returns immediately without scheduling an alarm.
|
||||||
*/
|
*/
|
||||||
private fun setAlarmForRemindersItem(reminderItemTask: Task, remindersItem: RemindersItem?, occurrenceIndex: Int) {
|
private fun setAlarmForRemindersItem(
|
||||||
|
reminderItemTask: Task,
|
||||||
|
remindersItem: RemindersItem?,
|
||||||
|
occurrenceIndex: Int,
|
||||||
|
) {
|
||||||
if (remindersItem == null) return
|
if (remindersItem == null) return
|
||||||
|
|
||||||
val now = ZonedDateTime.now().withZoneSameLocal(ZoneId.systemDefault())?.toInstant()
|
val now = ZonedDateTime.now().withZoneSameLocal(ZoneId.systemDefault())?.toInstant()
|
||||||
|
|
@ -147,7 +153,6 @@ class TaskAlarmManager(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val intent = Intent(context, TaskReceiver::class.java)
|
val intent = Intent(context, TaskReceiver::class.java)
|
||||||
intent.action = remindersItem.id
|
intent.action = remindersItem.id
|
||||||
intent.putExtra(TASK_NAME_INTENT_KEY, reminderItemTask.text)
|
intent.putExtra(TASK_NAME_INTENT_KEY, reminderItemTask.text)
|
||||||
|
|
@ -157,39 +162,55 @@ class TaskAlarmManager(
|
||||||
val intentId = (remindersItem.id?.hashCode() ?: 0) + occurrenceIndex
|
val intentId = (remindersItem.id?.hashCode() ?: 0) + occurrenceIndex
|
||||||
|
|
||||||
// Cancel alarm if already exists
|
// Cancel alarm if already exists
|
||||||
val previousSender = PendingIntent.getBroadcast(
|
val previousSender =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
intentId,
|
intentId,
|
||||||
intent,
|
intent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_NO_CREATE)
|
withImmutableFlag(PendingIntent.FLAG_NO_CREATE),
|
||||||
)
|
)
|
||||||
if (previousSender != null) {
|
if (previousSender != null) {
|
||||||
previousSender.cancel()
|
previousSender.cancel()
|
||||||
am?.cancel(previousSender)
|
am?.cancel(previousSender)
|
||||||
}
|
}
|
||||||
|
|
||||||
val sender = PendingIntent.getBroadcast(
|
val sender =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
intentId,
|
intentId,
|
||||||
intent,
|
intent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_CANCEL_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_CANCEL_CURRENT),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
setAlarm(context, reminderZonedTime.toEpochMilli(), sender)
|
setAlarm(context, reminderZonedTime.toEpochMilli(), sender)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeAlarmForRemindersItem(remindersItem: RemindersItem, occurrenceIndex: Int? = null) {
|
private fun removeAlarmForRemindersItem(
|
||||||
|
remindersItem: RemindersItem,
|
||||||
|
occurrenceIndex: Int? = null,
|
||||||
|
) {
|
||||||
val intent = Intent(context, TaskReceiver::class.java)
|
val intent = Intent(context, TaskReceiver::class.java)
|
||||||
intent.action = remindersItem.id
|
intent.action = remindersItem.id
|
||||||
val intentId = if (occurrenceIndex != null) (remindersItem.id?.hashCode() ?: (0 and 0xfffffff)) + occurrenceIndex else (remindersItem.id?.hashCode() ?: (0 and 0xfffffff))
|
val intentId =
|
||||||
val sender = PendingIntent.getBroadcast(
|
if (occurrenceIndex != null) {
|
||||||
|
(
|
||||||
|
remindersItem.id?.hashCode()
|
||||||
|
?: (0 and 0xfffffff)
|
||||||
|
) + occurrenceIndex
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
remindersItem.id?.hashCode()
|
||||||
|
?: (0 and 0xfffffff)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val sender =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
intentId,
|
intentId,
|
||||||
intent,
|
intent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
val am = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
val am = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||||
sender.cancel()
|
sender.cancel()
|
||||||
|
|
@ -225,22 +246,24 @@ class TaskAlarmManager(
|
||||||
notificationIntent.putExtra(NotificationPublisher.CHECK_DAILIES, false)
|
notificationIntent.putExtra(NotificationPublisher.CHECK_DAILIES, false)
|
||||||
|
|
||||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||||
val previousSender = PendingIntent.getBroadcast(
|
val previousSender =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
0,
|
0,
|
||||||
notificationIntent,
|
notificationIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_NO_CREATE)
|
withImmutableFlag(PendingIntent.FLAG_NO_CREATE),
|
||||||
)
|
)
|
||||||
if (previousSender != null) {
|
if (previousSender != null) {
|
||||||
previousSender.cancel()
|
previousSender.cancel()
|
||||||
alarmManager?.cancel(previousSender)
|
alarmManager?.cancel(previousSender)
|
||||||
}
|
}
|
||||||
|
|
||||||
val pendingIntent = PendingIntent.getBroadcast(
|
val pendingIntent =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
0,
|
0,
|
||||||
notificationIntent,
|
notificationIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
|
|
||||||
setAlarm(context, triggerTime, pendingIntent)
|
setAlarm(context, triggerTime, pendingIntent)
|
||||||
|
|
@ -255,7 +278,11 @@ class TaskAlarmManager(
|
||||||
alarmManager?.cancel(displayIntent)
|
alarmManager?.cancel(displayIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setAlarm(context: Context, time: Long, pendingIntent: PendingIntent?) {
|
private fun setAlarm(
|
||||||
|
context: Context,
|
||||||
|
time: Long,
|
||||||
|
pendingIntent: PendingIntent?,
|
||||||
|
) {
|
||||||
HLogger.log(LogLevel.INFO, "TaskAlarmManager", "Scheduling for $time")
|
HLogger.log(LogLevel.INFO, "TaskAlarmManager", "Scheduling for $time")
|
||||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||||
|
|
||||||
|
|
@ -267,16 +294,24 @@ class TaskAlarmManager(
|
||||||
// For SDK >= Android 12, allows batching of reminders
|
// For SDK >= Android 12, allows batching of reminders
|
||||||
try {
|
try {
|
||||||
alarmManager?.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent)
|
alarmManager?.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pendingIntent)
|
||||||
Log.d("TaskAlarmManager", "setAlarm: Scheduling for $time using setAndAllowWhileIdle")
|
Log.d(
|
||||||
|
"TaskAlarmManager",
|
||||||
|
"setAlarm: Scheduling for $time using setAndAllowWhileIdle",
|
||||||
|
)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
when (ex) {
|
when (ex) {
|
||||||
is IllegalStateException, is SecurityException -> {
|
is IllegalStateException, is SecurityException -> {
|
||||||
alarmManager?.setWindow(AlarmManager.RTC_WAKEUP, time, 600000, pendingIntent)
|
alarmManager?.setWindow(
|
||||||
|
AlarmManager.RTC_WAKEUP,
|
||||||
|
time,
|
||||||
|
600000,
|
||||||
|
pendingIntent,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
throw ex
|
throw ex
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -15,34 +15,38 @@ import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class TaskDescriptionBuilder(private val context: Context) {
|
class TaskDescriptionBuilder(private val context: Context) {
|
||||||
|
|
||||||
fun describe(task: Task): String {
|
fun describe(task: Task): String {
|
||||||
return when (task.type) {
|
return when (task.type) {
|
||||||
TaskType.HABIT -> context.getString(
|
TaskType.HABIT ->
|
||||||
|
context.getString(
|
||||||
R.string.habit_summary_description,
|
R.string.habit_summary_description,
|
||||||
describeHabitDirections(task.up ?: false, task.down ?: false),
|
describeHabitDirections(task.up ?: false, task.down ?: false),
|
||||||
describeDifficulty(task.priority)
|
describeDifficulty(task.priority),
|
||||||
)
|
)
|
||||||
|
|
||||||
TaskType.TODO -> {
|
TaskType.TODO -> {
|
||||||
if (task.dueDate != null) {
|
if (task.dueDate != null) {
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.todo_summary_description_duedate,
|
R.string.todo_summary_description_duedate,
|
||||||
describeDifficulty(task.priority),
|
describeDifficulty(task.priority),
|
||||||
describeDate(task.dueDate!!)
|
describeDate(task.dueDate!!),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
context.getString(
|
context.getString(
|
||||||
R.string.todo_summary_description,
|
R.string.todo_summary_description,
|
||||||
describeDifficulty(task.priority)
|
describeDifficulty(task.priority),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TaskType.DAILY -> context.getString(
|
|
||||||
|
TaskType.DAILY ->
|
||||||
|
context.getString(
|
||||||
R.string.daily_summary_description,
|
R.string.daily_summary_description,
|
||||||
describeDifficulty(task.priority),
|
describeDifficulty(task.priority),
|
||||||
describeRepeatInterval(task.frequency, task.everyX ?: 1),
|
describeRepeatInterval(task.frequency, task.everyX ?: 1),
|
||||||
describeRepeatDays(task)
|
describeRepeatDays(task),
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +63,8 @@ class TaskDescriptionBuilder(private val context: Context) {
|
||||||
}
|
}
|
||||||
return when (task.frequency) {
|
return when (task.frequency) {
|
||||||
Frequency.WEEKLY -> {
|
Frequency.WEEKLY -> {
|
||||||
" " + if (task.repeat?.isEveryDay == true) {
|
" " +
|
||||||
|
if (task.repeat?.isEveryDay == true) {
|
||||||
context.getString(R.string.on_every_day_of_week)
|
context.getString(R.string.on_every_day_of_week)
|
||||||
} else {
|
} else {
|
||||||
if (task.repeat?.isOnlyWeekdays == true) {
|
if (task.repeat?.isOnlyWeekdays == true) {
|
||||||
|
|
@ -72,14 +77,18 @@ class TaskDescriptionBuilder(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Frequency.MONTHLY -> {
|
Frequency.MONTHLY -> {
|
||||||
" " + if (task.getDaysOfMonth()?.isNotEmpty() == true) {
|
" " +
|
||||||
val dayList = task.getDaysOfMonth()?.map {
|
if (task.getDaysOfMonth()?.isNotEmpty() == true) {
|
||||||
|
val dayList =
|
||||||
|
task.getDaysOfMonth()?.map {
|
||||||
withOrdinal(it)
|
withOrdinal(it)
|
||||||
}
|
}
|
||||||
context.getString(R.string.on_the_x, joinToCount(dayList))
|
context.getString(R.string.on_the_x, joinToCount(dayList))
|
||||||
} else if (task.getWeeksOfMonth()?.isNotEmpty() == true) {
|
} else if (task.getWeeksOfMonth()?.isNotEmpty() == true) {
|
||||||
val occurrence = when (task.getWeeksOfMonth()?.first()) {
|
val occurrence =
|
||||||
|
when (task.getWeeksOfMonth()?.first()) {
|
||||||
0 -> context.getString(R.string.first)
|
0 -> context.getString(R.string.first)
|
||||||
1 -> context.getString(R.string.second)
|
1 -> context.getString(R.string.second)
|
||||||
2 -> context.getString(R.string.third)
|
2 -> context.getString(R.string.third)
|
||||||
|
|
@ -89,18 +98,26 @@ class TaskDescriptionBuilder(private val context: Context) {
|
||||||
}
|
}
|
||||||
val dayStrings = task.repeat?.dayStrings(context) ?: listOf()
|
val dayStrings = task.repeat?.dayStrings(context) ?: listOf()
|
||||||
|
|
||||||
context.getString(R.string.on_the_x_of_month, occurrence, joinToCount(dayStrings))
|
context.getString(
|
||||||
|
R.string.on_the_x_of_month,
|
||||||
|
occurrence,
|
||||||
|
joinToCount(dayStrings),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Frequency.YEARLY -> " " + context.getString(
|
|
||||||
|
Frequency.YEARLY ->
|
||||||
|
" " +
|
||||||
|
context.getString(
|
||||||
R.string.on_x,
|
R.string.on_x,
|
||||||
task.startDate?.let {
|
task.startDate?.let {
|
||||||
val flags = DateUtils.FORMAT_SHOW_DATE + DateUtils.FORMAT_NO_YEAR
|
val flags = DateUtils.FORMAT_SHOW_DATE + DateUtils.FORMAT_NO_YEAR
|
||||||
DateUtils.formatDateTime(context, it.time, flags)
|
DateUtils.formatDateTime(context, it.time, flags)
|
||||||
} ?: ""
|
} ?: "",
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -121,24 +138,50 @@ class TaskDescriptionBuilder(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun describeRepeatInterval(interval: Frequency?, everyX: Int): String {
|
private fun describeRepeatInterval(
|
||||||
|
interval: Frequency?,
|
||||||
|
everyX: Int,
|
||||||
|
): String {
|
||||||
if (everyX == 0) {
|
if (everyX == 0) {
|
||||||
return context.getString(R.string.never)
|
return context.getString(R.string.never)
|
||||||
}
|
}
|
||||||
return when (interval) {
|
return when (interval) {
|
||||||
Frequency.DAILY -> context.resources.getQuantityString(R.plurals.repeat_daily, everyX, everyX)
|
Frequency.DAILY ->
|
||||||
Frequency.WEEKLY -> context.resources.getQuantityString(R.plurals.repeat_weekly, everyX, everyX)
|
context.resources.getQuantityString(
|
||||||
Frequency.MONTHLY -> context.resources.getQuantityString(
|
R.plurals.repeat_daily,
|
||||||
|
everyX,
|
||||||
|
everyX,
|
||||||
|
)
|
||||||
|
|
||||||
|
Frequency.WEEKLY ->
|
||||||
|
context.resources.getQuantityString(
|
||||||
|
R.plurals.repeat_weekly,
|
||||||
|
everyX,
|
||||||
|
everyX,
|
||||||
|
)
|
||||||
|
|
||||||
|
Frequency.MONTHLY ->
|
||||||
|
context.resources.getQuantityString(
|
||||||
R.plurals.repeat_monthly,
|
R.plurals.repeat_monthly,
|
||||||
everyX,
|
everyX,
|
||||||
everyX
|
everyX,
|
||||||
)
|
)
|
||||||
Frequency.YEARLY -> context.resources.getQuantityString(R.plurals.repeat_yearly, everyX, everyX)
|
|
||||||
|
Frequency.YEARLY ->
|
||||||
|
context.resources.getQuantityString(
|
||||||
|
R.plurals.repeat_yearly,
|
||||||
|
everyX,
|
||||||
|
everyX,
|
||||||
|
)
|
||||||
|
|
||||||
null -> ""
|
null -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun describeHabitDirections(up: Boolean, down: Boolean): String {
|
private fun describeHabitDirections(
|
||||||
|
up: Boolean,
|
||||||
|
down: Boolean,
|
||||||
|
): String {
|
||||||
return if (up && down) {
|
return if (up && down) {
|
||||||
context.getString(R.string.positive_and_negative)
|
context.getString(R.string.positive_and_negative)
|
||||||
} else if (up) {
|
} else if (up) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import com.habitrpg.android.habitica.models.user.Stats
|
||||||
import com.habitrpg.shared.habitica.models.Avatar
|
import com.habitrpg.shared.habitica.models.Avatar
|
||||||
|
|
||||||
class UserStatComputer {
|
class UserStatComputer {
|
||||||
|
|
||||||
interface StatsRow
|
interface StatsRow
|
||||||
|
|
||||||
inner class AttributeRow : StatsRow {
|
inner class AttributeRow : StatsRow {
|
||||||
|
|
@ -25,7 +24,10 @@ class UserStatComputer {
|
||||||
var stats: String? = null
|
var stats: String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun computeClassBonus(equipmentList: List<Equipment>?, user: Avatar): List<StatsRow> {
|
fun computeClassBonus(
|
||||||
|
equipmentList: List<Equipment>?,
|
||||||
|
user: Avatar,
|
||||||
|
): List<StatsRow> {
|
||||||
val skillRows = ArrayList<StatsRow>()
|
val skillRows = ArrayList<StatsRow>()
|
||||||
|
|
||||||
var strAttributes = 0f
|
var strAttributes = 0f
|
||||||
|
|
@ -41,7 +43,7 @@ class UserStatComputer {
|
||||||
// Summarize stats and fill equipment table
|
// Summarize stats and fill equipment table
|
||||||
for (i in equipmentList ?: emptyList()) {
|
for (i in equipmentList ?: emptyList()) {
|
||||||
val strength = i.str
|
val strength = i.str
|
||||||
val intelligence = i._int
|
val intelligence = i.intelligence
|
||||||
val constitution = i.con
|
val constitution = i.con
|
||||||
val perception = i.per
|
val perception = i.per
|
||||||
|
|
||||||
|
|
@ -88,8 +90,10 @@ class UserStatComputer {
|
||||||
}
|
}
|
||||||
|
|
||||||
var classBonus = 0.5f
|
var classBonus = 0.5f
|
||||||
val userClassMatchesGearClass = !classDoesNotExist && itemClass == user.stats?.habitClass
|
val userClassMatchesGearClass =
|
||||||
val userClassMatchesGearSpecialClass = !specialClassDoesNotExist && itemSpecialClass == user.stats?.habitClass
|
!classDoesNotExist && itemClass == user.stats?.habitClass
|
||||||
|
val userClassMatchesGearSpecialClass =
|
||||||
|
!specialClassDoesNotExist && itemSpecialClass == user.stats?.habitClass
|
||||||
|
|
||||||
if (!userClassMatchesGearClass && !userClassMatchesGearSpecialClass) classBonus = 0f
|
if (!userClassMatchesGearClass && !userClassMatchesGearSpecialClass) classBonus = 0f
|
||||||
|
|
||||||
|
|
@ -102,14 +106,17 @@ class UserStatComputer {
|
||||||
strClassBonus += strength * classBonus
|
strClassBonus += strength * classBonus
|
||||||
perClassBonus += perception * classBonus
|
perClassBonus += perception * classBonus
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats.HEALER -> {
|
Stats.HEALER -> {
|
||||||
conClassBonus += constitution * classBonus
|
conClassBonus += constitution * classBonus
|
||||||
intClassBonus += intelligence * classBonus
|
intClassBonus += intelligence * classBonus
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats.WARRIOR -> {
|
Stats.WARRIOR -> {
|
||||||
strClassBonus += strength * classBonus
|
strClassBonus += strength * classBonus
|
||||||
conClassBonus += constitution * classBonus
|
conClassBonus += constitution * classBonus
|
||||||
}
|
}
|
||||||
|
|
||||||
Stats.MAGE -> {
|
Stats.MAGE -> {
|
||||||
intClassBonus += intelligence * classBonus
|
intClassBonus += intelligence * classBonus
|
||||||
perClassBonus += perception * classBonus
|
perClassBonus += perception * classBonus
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ package com.habitrpg.android.habitica.helpers.notifications
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
class ChangeUsernameLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier)
|
class ChangeUsernameLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier)
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,11 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
|
||||||
class ChatMentionNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier) {
|
class ChatMentionNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier) {
|
||||||
override fun configureNotificationBuilder(data: MutableMap<String, String>): NotificationCompat.Builder {
|
override fun configureNotificationBuilder(data: MutableMap<String, String>): NotificationCompat.Builder {
|
||||||
val style = NotificationCompat.BigTextStyle()
|
val style =
|
||||||
|
NotificationCompat.BigTextStyle()
|
||||||
.setBigContentTitle(title)
|
.setBigContentTitle(title)
|
||||||
.bigText(message)
|
.bigText(message)
|
||||||
return super.configureNotificationBuilder(data)
|
return super.configureNotificationBuilder(data)
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ package com.habitrpg.android.habitica.helpers.notifications
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
class GenericLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier)
|
class GenericLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier)
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,5 @@ package com.habitrpg.android.habitica.helpers.notifications
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
|
||||||
class GiftOneGetOneLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier)
|
class GiftOneGetOneLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier)
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ import java.text.SimpleDateFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class GroupActivityNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier) {
|
class GroupActivityNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier) {
|
||||||
override fun getNotificationID(data: MutableMap<String, String>): Int {
|
override fun getNotificationID(data: MutableMap<String, String>): Int {
|
||||||
return data["groupID"].hashCode()
|
return data["groupID"].hashCode()
|
||||||
}
|
}
|
||||||
|
|
@ -27,17 +27,22 @@ class GroupActivityNotification(context: Context, identifier: String?) : Habitic
|
||||||
override fun configureNotificationBuilder(data: MutableMap<String, String>): NotificationCompat.Builder {
|
override fun configureNotificationBuilder(data: MutableMap<String, String>): NotificationCompat.Builder {
|
||||||
val user = Person.Builder().setName("You").build()
|
val user = Person.Builder().setName("You").build()
|
||||||
val message = makeMessageFromData(data)
|
val message = makeMessageFromData(data)
|
||||||
var style = NotificationCompat.MessagingStyle(user)
|
var style =
|
||||||
|
NotificationCompat.MessagingStyle(user)
|
||||||
.setGroupConversation(true)
|
.setGroupConversation(true)
|
||||||
.setConversationTitle(data["groupName"])
|
.setConversationTitle(data["groupName"])
|
||||||
|
|
||||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
|
val notificationManager =
|
||||||
val existingNotifications = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
context.getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
|
||||||
|
val existingNotifications =
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
notificationManager?.activeNotifications?.filter { it.id == getNotificationID(data) }
|
notificationManager?.activeNotifications?.filter { it.id == getNotificationID(data) }
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
val oldMessages = existingNotifications?.firstOrNull()?.notification?.extras?.getBundle("messages")?.get("messages") as? ArrayList<Map<String, String>> ?: arrayListOf()
|
val oldMessages =
|
||||||
|
existingNotifications?.firstOrNull()?.notification?.extras?.getBundle("messages")
|
||||||
|
?.get("messages") as? ArrayList<Map<String, String>> ?: arrayListOf()
|
||||||
for (oldMessage in oldMessages) {
|
for (oldMessage in oldMessages) {
|
||||||
style = style.addMessage(makeMessageFromData(oldMessage))
|
style = style.addMessage(makeMessageFromData(oldMessage))
|
||||||
}
|
}
|
||||||
|
|
@ -57,17 +62,21 @@ class GroupActivityNotification(context: Context, identifier: String?) : Habitic
|
||||||
return NotificationCompat.MessagingStyle.Message(
|
return NotificationCompat.MessagingStyle.Message(
|
||||||
messageText,
|
messageText,
|
||||||
timestamp.time,
|
timestamp.time,
|
||||||
sender
|
sender,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNotificationActions(notificationId: Int, data: Map<String, String>) {
|
override fun setNotificationActions(
|
||||||
|
notificationId: Int,
|
||||||
|
data: Map<String, String>,
|
||||||
|
) {
|
||||||
super.setNotificationActions(notificationId, data)
|
super.setNotificationActions(notificationId, data)
|
||||||
val groupID = data["groupID"] ?: return
|
val groupID = data["groupID"] ?: return
|
||||||
|
|
||||||
val actionName = context.getString(R.string.group_message_reply)
|
val actionName = context.getString(R.string.group_message_reply)
|
||||||
val replyLabel: String = context.getString(R.string.reply)
|
val replyLabel: String = context.getString(R.string.reply)
|
||||||
val remoteInput: RemoteInput = RemoteInput.Builder(actionName).run {
|
val remoteInput: RemoteInput =
|
||||||
|
RemoteInput.Builder(actionName).run {
|
||||||
setLabel(replyLabel)
|
setLabel(replyLabel)
|
||||||
build()
|
build()
|
||||||
}
|
}
|
||||||
|
|
@ -80,14 +89,14 @@ class GroupActivityNotification(context: Context, identifier: String?) : Habitic
|
||||||
context,
|
context,
|
||||||
groupID.hashCode(),
|
groupID.hashCode(),
|
||||||
intent,
|
intent,
|
||||||
withMutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withMutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
|
|
||||||
val action: NotificationCompat.Action =
|
val action: NotificationCompat.Action =
|
||||||
NotificationCompat.Action.Builder(
|
NotificationCompat.Action.Builder(
|
||||||
R.drawable.ic_send_grey_600_24dp,
|
R.drawable.ic_send_grey_600_24dp,
|
||||||
context.getString(R.string.reply),
|
context.getString(R.string.reply),
|
||||||
replyPendingIntent
|
replyPendingIntent,
|
||||||
)
|
)
|
||||||
.addRemoteInput(remoteInput)
|
.addRemoteInput(remoteInput)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,17 @@ import com.habitrpg.android.habitica.receivers.LocalNotificationActionReceiver
|
||||||
/**
|
/**
|
||||||
* Created by keithholliday on 7/1/16.
|
* Created by keithholliday on 7/1/16.
|
||||||
*/
|
*/
|
||||||
class GuildInviteLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier) {
|
class GuildInviteLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier) {
|
||||||
override fun configureMainIntent(intent: Intent) {
|
override fun configureMainIntent(intent: Intent) {
|
||||||
super.configureMainIntent(intent)
|
super.configureMainIntent(intent)
|
||||||
intent.putExtra("groupID", data?.get("groupID"))
|
intent.putExtra("groupID", data?.get("groupID"))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNotificationActions(notificationId: Int, data: Map<String, String>) {
|
override fun setNotificationActions(
|
||||||
|
notificationId: Int,
|
||||||
|
data: Map<String, String>,
|
||||||
|
) {
|
||||||
super.setNotificationActions(notificationId, data)
|
super.setNotificationActions(notificationId, data)
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
|
|
||||||
|
|
@ -26,11 +29,12 @@ class GuildInviteLocalNotification(context: Context, identifier: String?) : Habi
|
||||||
val groupID = data["groupID"]
|
val groupID = data["groupID"]
|
||||||
acceptInviteIntent.putExtra("groupID", groupID)
|
acceptInviteIntent.putExtra("groupID", groupID)
|
||||||
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntentAccept = PendingIntent.getBroadcast(
|
val pendingIntentAccept =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
groupID.hashCode(),
|
groupID.hashCode(),
|
||||||
acceptInviteIntent,
|
acceptInviteIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, "Accept", pendingIntentAccept)
|
notificationBuilder.addAction(0, "Accept", pendingIntentAccept)
|
||||||
|
|
||||||
|
|
@ -38,11 +42,12 @@ class GuildInviteLocalNotification(context: Context, identifier: String?) : Habi
|
||||||
rejectInviteIntent.action = res.getString(R.string.reject_guild_invite)
|
rejectInviteIntent.action = res.getString(R.string.reject_guild_invite)
|
||||||
rejectInviteIntent.putExtra("groupID", groupID)
|
rejectInviteIntent.putExtra("groupID", groupID)
|
||||||
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntentReject = PendingIntent.getBroadcast(
|
val pendingIntentReject =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
groupID.hashCode() + 1,
|
groupID.hashCode() + 1,
|
||||||
rejectInviteIntent,
|
rejectInviteIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, "Reject", pendingIntentReject)
|
notificationBuilder.addAction(0, "Reject", pendingIntentReject)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class HabiticaFirebaseMessagingService : FirebaseMessagingService() {
|
class HabiticaFirebaseMessagingService : FirebaseMessagingService() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
internal lateinit var pushNotificationManager: PushNotificationManager
|
internal lateinit var pushNotificationManager: PushNotificationManager
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,14 @@ import java.util.Date
|
||||||
*/
|
*/
|
||||||
abstract class HabiticaLocalNotification(
|
abstract class HabiticaLocalNotification(
|
||||||
protected var context: Context,
|
protected var context: Context,
|
||||||
protected var identifier: String?
|
protected var identifier: String?,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
protected var data: Map<String, String>? = null
|
protected var data: Map<String, String>? = null
|
||||||
protected var title: String? = null
|
protected var title: String? = null
|
||||||
protected var message: String? = null
|
protected var message: String? = null
|
||||||
|
|
||||||
protected var notificationBuilder = NotificationCompat.Builder(context, "default")
|
protected var notificationBuilder =
|
||||||
|
NotificationCompat.Builder(context, "default")
|
||||||
.setSmallIcon(R.drawable.ic_gryphon_white)
|
.setSmallIcon(R.drawable.ic_gryphon_white)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
|
|
||||||
|
|
@ -37,7 +37,11 @@ abstract class HabiticaLocalNotification(
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
open fun notifyLocally(title: String?, message: String?, data: MutableMap<String, String>) {
|
open fun notifyLocally(
|
||||||
|
title: String?,
|
||||||
|
message: String?,
|
||||||
|
data: MutableMap<String, String>,
|
||||||
|
) {
|
||||||
this.title = title
|
this.title = title
|
||||||
this.message = message
|
this.message = message
|
||||||
|
|
||||||
|
|
@ -65,15 +69,19 @@ abstract class HabiticaLocalNotification(
|
||||||
this.data = data
|
this.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun setNotificationActions(notificationId: Int, data: Map<String, String>) {
|
protected open fun setNotificationActions(
|
||||||
|
notificationId: Int,
|
||||||
|
data: Map<String, String>,
|
||||||
|
) {
|
||||||
val intent = Intent(context, MainActivity::class.java)
|
val intent = Intent(context, MainActivity::class.java)
|
||||||
configureMainIntent(intent)
|
configureMainIntent(intent)
|
||||||
intent.putExtra("NOTIFICATION_ID", notificationId)
|
intent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntent = PendingIntent.getActivity(
|
val pendingIntent =
|
||||||
|
PendingIntent.getActivity(
|
||||||
context,
|
context,
|
||||||
3000,
|
3000,
|
||||||
intent,
|
intent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
notificationBuilder.setContentIntent(pendingIntent)
|
notificationBuilder.setContentIntent(pendingIntent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,44 +4,95 @@ import android.content.Context
|
||||||
|
|
||||||
class HabiticaLocalNotificationFactory {
|
class HabiticaLocalNotificationFactory {
|
||||||
// use getShape method to get object of type shape
|
// use getShape method to get object of type shape
|
||||||
fun build(notificationType: String?, context: Context?): HabiticaLocalNotification {
|
fun build(
|
||||||
|
notificationType: String?,
|
||||||
|
context: Context?,
|
||||||
|
): HabiticaLocalNotification {
|
||||||
return when {
|
return when {
|
||||||
PushNotificationManager.PARTY_INVITE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
PushNotificationManager.PARTY_INVITE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
PartyInviteLocalNotification(context!!, notificationType)
|
PartyInviteLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
ReceivedPrivateMessageLocalNotification(context!!, notificationType)
|
ReceivedPrivateMessageLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.RECEIVED_GEMS_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.RECEIVED_GEMS_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
ReceivedGemsGiftLocalNotification(context!!, notificationType)
|
ReceivedGemsGiftLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.RECEIVED_SUBSCRIPTION_GIFT_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.RECEIVED_SUBSCRIPTION_GIFT_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
ReceivedSubscriptionGiftLocalNotification(context!!, notificationType)
|
ReceivedSubscriptionGiftLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.GUILD_INVITE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.GUILD_INVITE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
GuildInviteLocalNotification(context!!, notificationType)
|
GuildInviteLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.QUEST_INVITE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.QUEST_INVITE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
QuestInviteLocalNotification(context!!, notificationType)
|
QuestInviteLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.QUEST_BEGUN_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.QUEST_BEGUN_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
QuestBegunLocalNotification(context!!, notificationType)
|
QuestBegunLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.WON_CHALLENGE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.WON_CHALLENGE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
WonChallengeLocalNotification(context!!, notificationType)
|
WonChallengeLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.CHANGE_USERNAME_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.CHANGE_USERNAME_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
ChangeUsernameLocalNotification(context!!, notificationType)
|
ChangeUsernameLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.GIFT_ONE_GET_ONE_PUSH_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.GIFT_ONE_GET_ONE_PUSH_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
GiftOneGetOneLocalNotification(context!!, notificationType)
|
GiftOneGetOneLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.CHAT_MENTION_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.CHAT_MENTION_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
ChatMentionNotification(context!!, notificationType)
|
ChatMentionNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
PushNotificationManager.GROUP_ACTIVITY_NOTIFICATION_KEY.equals(notificationType, true) -> {
|
|
||||||
|
PushNotificationManager.GROUP_ACTIVITY_NOTIFICATION_KEY.equals(
|
||||||
|
notificationType,
|
||||||
|
true,
|
||||||
|
) -> {
|
||||||
GroupActivityNotification(context!!, notificationType)
|
GroupActivityNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
GenericLocalNotification(context!!, notificationType)
|
GenericLocalNotification(context!!, notificationType)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,12 @@ import com.habitrpg.android.habitica.receivers.LocalNotificationActionReceiver
|
||||||
/**
|
/**
|
||||||
* Created by keithholliday on 6/28/16.
|
* Created by keithholliday on 6/28/16.
|
||||||
*/
|
*/
|
||||||
class PartyInviteLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier) {
|
class PartyInviteLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier) {
|
||||||
override fun setNotificationActions(notificationId: Int, data: Map<String, String>) {
|
override fun setNotificationActions(
|
||||||
|
notificationId: Int,
|
||||||
|
data: Map<String, String>,
|
||||||
|
) {
|
||||||
super.setNotificationActions(notificationId, data)
|
super.setNotificationActions(notificationId, data)
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
|
|
||||||
|
|
@ -21,11 +24,12 @@ class PartyInviteLocalNotification(context: Context, identifier: String?) : Habi
|
||||||
val groupID = data["groupID"]
|
val groupID = data["groupID"]
|
||||||
acceptInviteIntent.putExtra("groupID", groupID)
|
acceptInviteIntent.putExtra("groupID", groupID)
|
||||||
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntentAccept = PendingIntent.getBroadcast(
|
val pendingIntentAccept =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
groupID.hashCode(),
|
groupID.hashCode(),
|
||||||
acceptInviteIntent,
|
acceptInviteIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, context.getString(R.string.accept), pendingIntentAccept)
|
notificationBuilder.addAction(0, context.getString(R.string.accept), pendingIntentAccept)
|
||||||
|
|
||||||
|
|
@ -33,11 +37,12 @@ class PartyInviteLocalNotification(context: Context, identifier: String?) : Habi
|
||||||
rejectInviteIntent.action = res.getString(R.string.reject_party_invite)
|
rejectInviteIntent.action = res.getString(R.string.reject_party_invite)
|
||||||
rejectInviteIntent.putExtra("groupID", groupID)
|
rejectInviteIntent.putExtra("groupID", groupID)
|
||||||
rejectInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
rejectInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntentReject = PendingIntent.getBroadcast(
|
val pendingIntentReject =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
groupID.hashCode() + 1,
|
groupID.hashCode() + 1,
|
||||||
rejectInviteIntent,
|
rejectInviteIntent,
|
||||||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT),
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, context.getString(R.string.reject), pendingIntentReject)
|
notificationBuilder.addAction(0, context.getString(R.string.reject), pendingIntentReject)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,8 @@ import java.io.IOException
|
||||||
class PushNotificationManager(
|
class PushNotificationManager(
|
||||||
var apiClient: ApiClient,
|
var apiClient: ApiClient,
|
||||||
private val sharedPreferences: SharedPreferences,
|
private val sharedPreferences: SharedPreferences,
|
||||||
private val context: Context
|
private val context: Context,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var refreshedToken: String = ""
|
var refreshedToken: String = ""
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value.isEmpty()) {
|
if (value.isEmpty()) {
|
||||||
|
|
@ -100,7 +99,8 @@ class PushNotificationManager(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun userIsSubscribedToNotificationType(type: String?): Boolean {
|
private fun userIsSubscribedToNotificationType(type: String?): Boolean {
|
||||||
val key = when {
|
val key =
|
||||||
|
when {
|
||||||
type == PARTY_INVITE_PUSH_NOTIFICATION_KEY -> "preference_push_invited_to_party"
|
type == PARTY_INVITE_PUSH_NOTIFICATION_KEY -> "preference_push_invited_to_party"
|
||||||
type?.contains(RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY) == true -> "preference_push_received_a_private_message"
|
type?.contains(RECEIVED_PRIVATE_MESSAGE_PUSH_NOTIFICATION_KEY) == true -> "preference_push_received_a_private_message"
|
||||||
type?.contains(RECEIVED_GEMS_PUSH_NOTIFICATION_KEY) == true -> "preference_push_gifted_gems"
|
type?.contains(RECEIVED_GEMS_PUSH_NOTIFICATION_KEY) == true -> "preference_push_gifted_gems"
|
||||||
|
|
@ -133,7 +133,11 @@ class PushNotificationManager(
|
||||||
const val G1G1_PROMO_KEY = "g1g1Promo"
|
const val G1G1_PROMO_KEY = "g1g1Promo"
|
||||||
private const val DEVICE_TOKEN_PREFERENCE_KEY = "device-token-preference"
|
private const val DEVICE_TOKEN_PREFERENCE_KEY = "device-token-preference"
|
||||||
|
|
||||||
fun displayNotification(remoteMessage: RemoteMessage, context: Context, pushNotificationManager: PushNotificationManager? = null) {
|
fun displayNotification(
|
||||||
|
remoteMessage: RemoteMessage,
|
||||||
|
context: Context,
|
||||||
|
pushNotificationManager: PushNotificationManager? = null,
|
||||||
|
) {
|
||||||
val remoteMessageIdentifier = remoteMessage.data["identifier"]
|
val remoteMessageIdentifier = remoteMessage.data["identifier"]
|
||||||
|
|
||||||
if (pushNotificationManager?.userIsSubscribedToNotificationType(remoteMessageIdentifier) != false) {
|
if (pushNotificationManager?.userIsSubscribedToNotificationType(remoteMessageIdentifier) != false) {
|
||||||
|
|
@ -144,14 +148,15 @@ class PushNotificationManager(
|
||||||
"receive notification",
|
"receive notification",
|
||||||
EventCategory.BEHAVIOUR,
|
EventCategory.BEHAVIOUR,
|
||||||
HitType.EVENT,
|
HitType.EVENT,
|
||||||
additionalData
|
additionalData,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val notificationFactory = HabiticaLocalNotificationFactory()
|
val notificationFactory = HabiticaLocalNotificationFactory()
|
||||||
val localNotification = notificationFactory.build(
|
val localNotification =
|
||||||
|
notificationFactory.build(
|
||||||
remoteMessageIdentifier,
|
remoteMessageIdentifier,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
localNotification.setExtras(remoteMessage.data)
|
localNotification.setExtras(remoteMessage.data)
|
||||||
val notification = remoteMessage.notification
|
val notification = remoteMessage.notification
|
||||||
|
|
@ -159,13 +164,13 @@ class PushNotificationManager(
|
||||||
localNotification.notifyLocally(
|
localNotification.notifyLocally(
|
||||||
notification.title ?: remoteMessage.data["title"],
|
notification.title ?: remoteMessage.data["title"],
|
||||||
notification.body ?: remoteMessage.data["body"],
|
notification.body ?: remoteMessage.data["body"],
|
||||||
remoteMessage.data
|
remoteMessage.data,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
localNotification.notifyLocally(
|
localNotification.notifyLocally(
|
||||||
remoteMessage.data["title"],
|
remoteMessage.data["title"],
|
||||||
remoteMessage.data["body"],
|
remoteMessage.data["body"],
|
||||||
remoteMessage.data
|
remoteMessage.data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,5 @@ import android.content.Context
|
||||||
/**
|
/**
|
||||||
* Created by keithholliday on 7/1/16.
|
* Created by keithholliday on 7/1/16.
|
||||||
*/
|
*/
|
||||||
class QuestBegunLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier)
|
class QuestBegunLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier)
|
||||||
|
|
|
||||||
|
|
@ -10,40 +10,46 @@ import com.habitrpg.android.habitica.receivers.LocalNotificationActionReceiver
|
||||||
/**
|
/**
|
||||||
* Created by keithholliday on 7/1/16.
|
* Created by keithholliday on 7/1/16.
|
||||||
*/
|
*/
|
||||||
class QuestInviteLocalNotification(context: Context, identifier: String?) : HabiticaLocalNotification(context, identifier) {
|
class QuestInviteLocalNotification(context: Context, identifier: String?) :
|
||||||
|
HabiticaLocalNotification(context, identifier) {
|
||||||
override fun getNotificationID(data: MutableMap<String, String>): Int {
|
override fun getNotificationID(data: MutableMap<String, String>): Int {
|
||||||
return 1000
|
return 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setNotificationActions(notificationId: Int, data: Map<String, String>) {
|
override fun setNotificationActions(
|
||||||
|
notificationId: Int,
|
||||||
|
data: Map<String, String>,
|
||||||
|
) {
|
||||||
super.setNotificationActions(notificationId, data)
|
super.setNotificationActions(notificationId, data)
|
||||||
val res = context.resources
|
val res = context.resources
|
||||||
|
|
||||||
val acceptInviteIntent = Intent(context, LocalNotificationActionReceiver::class.java)
|
val acceptInviteIntent = Intent(context, LocalNotificationActionReceiver::class.java)
|
||||||
acceptInviteIntent.action = res.getString(R.string.accept_quest_invite)
|
acceptInviteIntent.action = res.getString(R.string.accept_quest_invite)
|
||||||
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
acceptInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
val flags =
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE
|
PendingIntent.FLAG_UPDATE_CURRENT + PendingIntent.FLAG_IMMUTABLE
|
||||||
} else {
|
} else {
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
}
|
}
|
||||||
val pendingIntentAccept = PendingIntent.getBroadcast(
|
val pendingIntentAccept =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
3001,
|
3001,
|
||||||
acceptInviteIntent,
|
acceptInviteIntent,
|
||||||
flags
|
flags,
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, "Accept", pendingIntentAccept)
|
notificationBuilder.addAction(0, "Accept", pendingIntentAccept)
|
||||||
|
|
||||||
val rejectInviteIntent = Intent(context, LocalNotificationActionReceiver::class.java)
|
val rejectInviteIntent = Intent(context, LocalNotificationActionReceiver::class.java)
|
||||||
rejectInviteIntent.action = res.getString(R.string.reject_quest_invite)
|
rejectInviteIntent.action = res.getString(R.string.reject_quest_invite)
|
||||||
rejectInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
rejectInviteIntent.putExtra("NOTIFICATION_ID", notificationId)
|
||||||
val pendingIntentReject = PendingIntent.getBroadcast(
|
val pendingIntentReject =
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
2001,
|
2001,
|
||||||
rejectInviteIntent,
|
rejectInviteIntent,
|
||||||
flags
|
flags,
|
||||||
)
|
)
|
||||||
notificationBuilder.addAction(0, "Reject", pendingIntentReject)
|
notificationBuilder.addAction(0, "Reject", pendingIntentReject)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue