Skip to content

Commit

Permalink
Merge pull request #796 from StepicOrg/release/1.166
Browse files Browse the repository at this point in the history
Release/1.166
  • Loading branch information
rostikjoystick authored Mar 25, 2021
2 parents 6691347 + f92884c commit fdd0eca
Show file tree
Hide file tree
Showing 66 changed files with 928 additions and 152 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ object RemoteConfig {
const val IS_PEER_REVIEW_ENABLED = "is_peer_review_enabled"
const val IS_DISABLED_STEPS_SUPPORTED = "is_disabled_steps_supported"
const val SEARCH_QUERY_PARAMS_ANDROID = "search_query_params_android"
const val IS_NEW_HOME_SCREEN_ENABLED = "is_new_home_screen_enabled"
}
3 changes: 3 additions & 0 deletions app/src/main/java/org/stepic/droid/di/AppCoreComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ import org.stepik.android.view.injection.solutions.SolutionsComponent
import org.stepik.android.view.injection.step.StepComponent
import org.stepik.android.view.injection.step.StepDiscussionBusModule
import org.stepik.android.view.injection.step_quiz.StepQuizBusModule
import org.stepik.android.view.injection.stories.StoriesComponent
import org.stepik.android.view.injection.story.StoryComponent
import org.stepik.android.view.injection.story.StoryDataModule
import org.stepik.android.view.injection.story_deeplink.StoryDeepLinkComponent
Expand Down Expand Up @@ -259,6 +260,8 @@ interface AppCoreComponent {

fun storyDeepLinkComponentBuilder(): StoryDeepLinkComponent.Builder

fun storiesComponentBuilder(): StoriesComponent.Builder

fun inject(someActivity: FragmentActivityBase)

fun inject(adapter: StepikRadioGroupAdapter)
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/stepic/droid/storage/dao/StepDaoImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ constructor(
instructionType = cursor.getString(DbStructureStep.Column.INSTRUCTION_TYPE)?.let(ReviewStrategyType::valueOf),

isEnabled = cursor.getIntOrNull(cursor.getColumnIndex(DbStructureStep.Column.IS_ENABLED))?.let { it > 0 },
needsPlan = cursor.getString(DbStructureStep.Column.NEEDS_PLAN),

position = cursor.getLong(DbStructureStep.Column.POSITION),
hasSubmissionRestriction = cursor.getBoolean(DbStructureStep.Column.HAS_SUBMISSION_RESTRICTION),
Expand Down Expand Up @@ -84,6 +85,7 @@ constructor(
values.put(DbStructureStep.Column.INSTRUCTION_TYPE, step.instructionType?.name)

values.put(DbStructureStep.Column.IS_ENABLED, step.isEnabled)
values.put(DbStructureStep.Column.NEEDS_PLAN, step.needsPlan)

values.put(DbStructureStep.Column.VIEWED_BY, step.viewedBy)
values.put(DbStructureStep.Column.PASSED_BY, step.passedBy)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.stepic.droid.storage.migration

import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import org.stepik.android.cache.step.structure.DbStructureStep

object MigrationFrom65To66 : Migration(65, 66) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE ${DbStructureStep.TABLE_NAME} ADD COLUMN ${DbStructureStep.Column.NEEDS_PLAN} TEXT")
db.execSQL("CREATE TABLE IF NOT EXISTS `CourseRecommendation` (`id` INTEGER NOT NULL, `courses` TEXT NOT NULL, PRIMARY KEY (`id`))")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ object Migrations {
MigrationFrom61To62,
MigrationFrom62To63,
MigrationFrom63To64,
MigrationFrom64To65
MigrationFrom64To65,
MigrationFrom65To66
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import android.view.MenuItem
import androidx.annotation.IdRes
import androidx.fragment.app.Fragment
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import kotlinx.android.synthetic.main.activity_main_feed.*
import org.stepic.droid.R
import org.stepic.droid.analytic.Analytic
import org.stepic.droid.base.App
import org.stepic.droid.base.Client
import org.stepic.droid.configuration.RemoteConfig
import org.stepic.droid.core.StepikDevicePoster
import org.stepic.droid.core.earlystreak.contract.EarlyStreakListener
import org.stepic.droid.core.presenters.ProfileMainFeedPresenter
Expand Down Expand Up @@ -98,6 +100,9 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
@Inject
internal lateinit var threadPoolExecutor: ThreadPoolExecutor

@Inject
internal lateinit var remoteConfig: FirebaseRemoteConfig

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
notificationClickedCheck(intent)
Expand Down Expand Up @@ -191,6 +196,15 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
}

when (getFragmentIndexFromIntent(launchIntent)) {
HOME_INDEX -> {
navigationView.selectedItemId = R.id.home
val storyId = launchIntent?.getStoryId()
if (storyId != null) {
StoryDeepLinkDialogFragment
.newInstance(storyId, launchIntent.dataString ?: "")
.showIfNotExists(supportFragmentManager, StoryDeepLinkDialogFragment.TAG)
}
}
CATALOG_INDEX -> {
navigationView.selectedItemId = R.id.catalog
launchIntent?.data?.pathSegments?.let {
Expand All @@ -206,7 +220,10 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
if (storyId != null) {
StoryDeepLinkDialogFragment
.newInstance(storyId, launchIntent.dataString ?: "")
.showIfNotExists(supportFragmentManager, StoryDeepLinkDialogFragment.TAG)
.showIfNotExists(
supportFragmentManager,
StoryDeepLinkDialogFragment.TAG
)
}
}
}
Expand All @@ -227,7 +244,13 @@ class MainFeedActivity : BackToExitActivityWithSmartLockBase(),
when {
it.contains(NOTIFICATIONS_DEEPLINK) -> return NOTIFICATIONS_INDEX
it.contains(CATALOG_DEEPLINK) -> return CATALOG_INDEX
it.contains(STORY_DEEPLINK) -> return CATALOG_INDEX
it.contains(STORY_DEEPLINK) -> {
return if (remoteConfig.getBoolean(RemoteConfig.IS_NEW_HOME_SCREEN_ENABLED)) {
HOME_INDEX
} else {
CATALOG_INDEX
}
}
else -> {}
}
}
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/java/org/stepic/droid/ui/fragments/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,31 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import kotlinx.android.synthetic.main.fragment_home.*
import kotlinx.android.synthetic.main.home_streak_view.*
import kotlinx.android.synthetic.main.view_centered_toolbar.*
import org.stepic.droid.R
import org.stepic.droid.analytic.AmplitudeAnalytic
import org.stepic.droid.base.App
import org.stepic.droid.base.FragmentBase
import org.stepic.droid.configuration.RemoteConfig
import org.stepic.droid.core.presenters.HomeStreakPresenter
import org.stepic.droid.core.presenters.contracts.HomeStreakView
import org.stepic.droid.util.commitNow
import org.stepik.android.view.course_list.ui.fragment.CourseListPopularFragment
import org.stepik.android.view.course_list.ui.fragment.CourseListUserHorizontalFragment
import org.stepik.android.view.course_list.ui.fragment.CourseListVisitedHorizontalFragment
import org.stepik.android.view.fast_continue.ui.fragment.FastContinueFragment
import org.stepik.android.view.stories.ui.fragment.StoriesFragment
import ru.nobird.android.stories.transition.SharedTransitionsManager
import ru.nobird.android.stories.ui.delegate.SharedTransitionContainerDelegate
import javax.inject.Inject

class HomeFragment : FragmentBase(), HomeStreakView {
companion object {
const val TAG = "HomeFragment"
const val HOME_DEEPLINK_STORY_KEY = "home_deeplink_story_key"

fun newInstance(): HomeFragment = HomeFragment()
private const val fastContinueTag = "fastContinueTag"
Expand All @@ -32,6 +38,9 @@ class HomeFragment : FragmentBase(), HomeStreakView {
@Inject
lateinit var homeStreakPresenter: HomeStreakPresenter

@Inject
lateinit var remoteConfig: FirebaseRemoteConfig

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
analytic.reportAmplitudeEvent(AmplitudeAnalytic.Home.HOME_SCREEN_OPENED)
Expand All @@ -54,6 +63,9 @@ class HomeFragment : FragmentBase(), HomeStreakView {

if (savedInstanceState == null) {
childFragmentManager.commitNow {
if (remoteConfig.getBoolean(RemoteConfig.IS_NEW_HOME_SCREEN_ENABLED)) {
add(R.id.homeMainContainer, StoriesFragment.newInstance())
}
add(R.id.homeMainContainer, FastContinueFragment.newInstance(), fastContinueTag)
add(R.id.homeMainContainer, CourseListUserHorizontalFragment.newInstance())
add(R.id.homeMainContainer, CourseListVisitedHorizontalFragment.newInstance())
Expand All @@ -65,6 +77,26 @@ class HomeFragment : FragmentBase(), HomeStreakView {
homeStreakPresenter.onNeedShowStreak()
}

override fun onStart() {
super.onStart()
if (remoteConfig.getBoolean(RemoteConfig.IS_NEW_HOME_SCREEN_ENABLED)) {
SharedTransitionsManager.registerTransitionDelegate(HOME_DEEPLINK_STORY_KEY, object :
SharedTransitionContainerDelegate {
override fun getSharedView(position: Int): View? =
storyDeepLinkMockView

override fun onPositionChanged(position: Int) {}
})
}
}

override fun onStop() {
if (remoteConfig.getBoolean(RemoteConfig.IS_NEW_HOME_SCREEN_ENABLED)) {
SharedTransitionsManager.unregisterTransitionDelegate(HOME_DEEPLINK_STORY_KEY)
}
super.onStop()
}

override fun onDestroyView() {
homeStreakPresenter.detachView(this)
super.onDestroyView()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import org.stepik.android.domain.catalog.model.CatalogBlock
import org.stepik.android.domain.review_instruction.model.ReviewInstruction
import org.stepik.android.domain.review_session.model.ReviewSession
import org.stepik.android.cache.code_preference.model.CodePreference
import org.stepik.android.cache.course_recommendations.dao.CourseRecommendationsDao
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation
import org.stepik.android.domain.visited_courses.model.VisitedCourse

@Database(
Expand All @@ -27,7 +29,8 @@ import org.stepik.android.domain.visited_courses.model.VisitedCourse
VisitedCourse::class,
CatalogBlock::class,
StoryReactionEntity::class,
CodePreference::class
CodePreference::class,
CourseRecommendation::class
],
version = AppDatabase.VERSION,
exportSchema = false
Expand All @@ -41,7 +44,7 @@ import org.stepik.android.domain.visited_courses.model.VisitedCourse
)
abstract class AppDatabase : RoomDatabase() {
companion object {
const val VERSION = 65
const val VERSION = 66
const val NAME = "stepic_database.db"
}

Expand All @@ -51,4 +54,5 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun catalogBlockDao(): CatalogBlockDao
abstract fun storyReactionDao(): StoryReactionDao
abstract fun codePreferenceDao(): CodePreferenceDao
abstract fun courseRecommendationsDao(): CourseRecommendationsDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.stepik.android.cache.course_recommendations

import io.reactivex.Completable
import io.reactivex.Maybe
import org.stepik.android.cache.course_recommendations.dao.CourseRecommendationsDao
import org.stepik.android.data.course_recommendations.source.CourseRecommendationsCacheDataSource
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation
import javax.inject.Inject

class CourseRecommendationsCacheDataSourceImpl
@Inject
constructor(
private val courseRecommendationsDao: CourseRecommendationsDao
) : CourseRecommendationsCacheDataSource {
override fun getCourseRecommendations(): Maybe<List<CourseRecommendation>> =
courseRecommendationsDao.getCourseRecommendations()

override fun saveCourseRecommendations(courseRecommendations: List<CourseRecommendation>): Completable =
courseRecommendationsDao
.clearCourseRecommendations()
.andThen(courseRecommendationsDao.insertCourseRecommendations(courseRecommendations))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.stepik.android.cache.course_recommendations.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import io.reactivex.Completable
import io.reactivex.Maybe
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation

@Dao
interface CourseRecommendationsDao {
@Query("SELECT * FROM CourseRecommendation")
fun getCourseRecommendations(): Maybe<List<CourseRecommendation>>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertCourseRecommendations(courseRecommendations: List<CourseRecommendation>): Completable

@Query("DELETE FROM CourseRecommendation")
fun clearCourseRecommendations(): Completable
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ object DbStructureStep {
const val INSTRUCTION_TYPE = "instruction_type"

const val IS_ENABLED = "is_enabled"
const val NEEDS_PLAN = "needs_plan"

const val VIEWED_BY = "viewed_by"
const val PASSED_BY = "passed_by"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.stepik.android.data.course_recommendations.repository

import io.reactivex.Maybe
import org.stepik.android.data.course_recommendations.source.CourseRecommendationsCacheDataSource
import org.stepik.android.data.course_recommendations.source.CourseRecommendationsRemoteDataSource
import org.stepik.android.domain.base.DataSourceType
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation
import org.stepik.android.domain.course_recommendations.repository.CourseRecommendationsRepository
import ru.nobird.android.domain.rx.doCompletableOnSuccess
import javax.inject.Inject

class CourseRecommendationsRepositoryImpl
@Inject
constructor(
private val courseRecommendationsRemoteDataSource: CourseRecommendationsRemoteDataSource,
private val courseRecommendationsCacheDataSource: CourseRecommendationsCacheDataSource
) : CourseRecommendationsRepository {
override fun getCourseRecommendations(language: String, primarySourceType: DataSourceType): Maybe<List<CourseRecommendation>> {
val remoteSource = courseRecommendationsRemoteDataSource
.getCourseRecommendations(language)
.doCompletableOnSuccess { courseRecommendationsCacheDataSource.saveCourseRecommendations(it) }

val cacheDataSource = courseRecommendationsCacheDataSource
.getCourseRecommendations()

return when (primarySourceType) {
DataSourceType.REMOTE ->
remoteSource
.onErrorResumeNext(cacheDataSource)

DataSourceType.CACHE ->
cacheDataSource
.switchIfEmpty(remoteSource)

else ->
throw IllegalArgumentException("Unsupported source type = $primarySourceType")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.stepik.android.data.course_recommendations.source

import io.reactivex.Completable
import io.reactivex.Maybe
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation

interface CourseRecommendationsCacheDataSource {
fun getCourseRecommendations(): Maybe<List<CourseRecommendation>>
fun saveCourseRecommendations(courseRecommendations: List<CourseRecommendation>): Completable
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.stepik.android.data.course_recommendations.source

import io.reactivex.Maybe
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation

interface CourseRecommendationsRemoteDataSource {
fun getCourseRecommendations(language: String): Maybe<List<CourseRecommendation>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.stepik.android.domain.course_recommendations.interactor

import io.reactivex.Maybe
import org.stepic.droid.preferences.SharedPreferenceHelper
import org.stepik.android.domain.base.DataSourceType
import org.stepik.android.domain.course_recommendations.model.CourseRecommendation
import org.stepik.android.domain.course_recommendations.repository.CourseRecommendationsRepository
import javax.inject.Inject

class CourseRecommendationsInteractor
@Inject
constructor(
private val sharedPreferenceHelper: SharedPreferenceHelper,
private val courseRecommendationsRepository: CourseRecommendationsRepository
) {
fun fetchCourseRecommendations(): Maybe<List<CourseRecommendation>> =
courseRecommendationsRepository
.getCourseRecommendations(language = sharedPreferenceHelper.languageForFeatured, primarySourceType = DataSourceType.REMOTE)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.stepik.android.domain.course_recommendations.model

import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.annotations.SerializedName

@Entity
data class CourseRecommendation(
@PrimaryKey
@SerializedName("id")
val id: Long,
@SerializedName("courses")
val courses: List<Long>
)
Loading

0 comments on commit fdd0eca

Please sign in to comment.