Skip to content

Commit

Permalink
Merge pull request #195 from StepicOrg/release/1.49
Browse files Browse the repository at this point in the history
Release/1.49
  • Loading branch information
eadm authored Dec 15, 2017
2 parents 4c2de99 + 06f3a9c commit dbbb29c
Show file tree
Hide file tree
Showing 110 changed files with 1,847 additions and 433 deletions.
6 changes: 5 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ dependencies {
implementation libraries.appMetrica

implementation libraries.calligraphy
implementation libraries.lottie

implementation libraries.firebaseMessaging
implementation libraries.firebaseAppindexing
Expand All @@ -157,7 +158,10 @@ dependencies {
implementation libraries.recyclerAnimators
implementation libraries.materialProgress
implementation libraries.circleImageView
implementation libraries.bottomNavigationView
implementation libraries.ahbottomnavigation
implementation libraries.circleIndicator

implementation libraries.shortcutBadger

debugImplementation libraries.leakCanary
releaseImplementation libraries.leakCanaryNoOp
Expand Down
7 changes: 1 addition & 6 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,4 @@
#BottomNavigationHelper uses reflection for changing this field (watch support updates for removing the reflection)
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}

-keep public class android.support.design.widget.BottomNavigationView { *; }
-keep public class android.support.design.internal.BottomNavigationMenuView { *; }
-keep public class android.support.design.internal.BottomNavigationPresenter { *; }
-keep public class android.support.design.internal.BottomNavigationItemView { *; }
}
303 changes: 153 additions & 150 deletions app/src/main/AndroidManifest.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/src/main/assets/allAnimations/firstAnimation.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/src/main/assets/allAnimations/fourthAnimation.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/src/main/assets/allAnimations/secondAnimation.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions app/src/main/assets/allAnimations/thirdAnimation.json

Large diffs are not rendered by default.

16 changes: 13 additions & 3 deletions app/src/main/java/org/stepic/droid/analytic/Analytic.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@

public interface Analytic {

interface Onboarding {
String CLOSED = "onboarding_closed";
String ACTION = "onboarding_action";
String COMPLETE = "onboarding_complete";
String SCREEN_OPENED = "onboarding_screen_opened";

String SCREEN_PARAM = "screen";
}

interface Code {
String TOOLBAR_SELECTED = "code_toolbar_selected";
String TOOLBAR_SELECTED_LANGUAGE = "language";
Expand Down Expand Up @@ -38,9 +47,6 @@ interface FastContinue {
String EMPTY_COURSES_SHOWN = "fast_continue_empty_courses";
String EMPTY_COURSES_CLICK = "fast_continue_empty_courses_click";

String NO_INTERNET_SHOWN = "fast_continue_no_internet";
String NO_INTERNET_CLICK = "fast_continue_no_internet_click";

String AUTH_SHOWN = "fast_continue_auth";
String AUTH_CLICK = "fast_continue_auth_click";

Expand Down Expand Up @@ -74,6 +80,10 @@ interface Login {

String TAP_ON_FIELDS = "tap_on_fields_login";
String TYPING_TEXT_FIELDS = "typing_text_fields_login";

String FACEBOOK_ERROR = "facebook_error";
String GOOGLE_FAILED_STATUS = "google_sign_in_failed";
String GOOGLE_AUTH_CODE_NULL = "google_auth_code_null";
}

interface System {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.stepic.droid.notifications.StepikNotificationManager;
import org.stepic.droid.preferences.SharedPreferenceHelper;
import org.stepic.droid.preferences.UserPreferences;
import org.stepic.droid.services.NotificationsViewPusher;
import org.stepic.droid.storage.operations.DatabaseFacade;
import org.stepic.droid.ui.util.CloseIconHolder;
import org.stepic.droid.util.AppConstants;
Expand Down Expand Up @@ -99,10 +100,18 @@ public abstract class FragmentActivityBase extends AppCompatActivity {
@Inject
protected FontsProvider fontsProvider;

@Inject
protected NotificationsViewPusher notificationsViewPusher;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
App.Companion.component().inject(this);

if (savedInstanceState == null && AppConstants.OPEN_NOTIFICATION.equals(getIntent().getAction())) {
notificationsViewPusher.pushToViewedNotificationsQueue(
getIntent().getLongExtra(AppConstants.KEY_NOTIFICATION_ID, 0));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package org.stepic.droid.configuration
object RemoteConfig {
const val MIN_DELAY_RATE_DIALOG_SEC = "min_delay_rate_dialog_sec"
const val SHOW_STREAK_DIALOG_AFTER_LOGIN = "show_streak_dialog_after_login"
const val SHOW_NOTIFICATIONS_BADGES = "show_notifications_badges"
}
23 changes: 23 additions & 0 deletions app/src/main/java/org/stepic/droid/core/FirstCoursePoster.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.stepic.droid.core

import org.stepic.droid.di.course_list.CourseGeneralScope
import org.stepic.droid.model.Course
import org.stepic.droid.util.RxOptional
import javax.inject.Inject

@CourseGeneralScope
class FirstCoursePoster
@Inject
constructor(
private val firstCourseSubjectHolder: FirstCourseSubjectHolder
) {
fun postFirstCourse(course: Course?) {
firstCourseSubjectHolder.firstCourseSubject.onNext(RxOptional(course))
}

fun postConnectionError() {
if (!firstCourseSubjectHolder.firstCourseSubject.hasValue()) {
firstCourseSubjectHolder.firstCourseSubject.onNext(RxOptional(null))
}
}
}
14 changes: 14 additions & 0 deletions app/src/main/java/org/stepic/droid/core/FirstCourseProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.stepic.droid.core

import io.reactivex.Observable
import org.stepic.droid.di.course_list.CourseGeneralScope
import org.stepic.droid.model.Course
import org.stepic.droid.util.RxOptional
import javax.inject.Inject

@CourseGeneralScope
class FirstCourseProvider
@Inject
constructor(private val firstCourseSubjectHolder: FirstCourseSubjectHolder) {
fun firstCourse(): Observable<RxOptional<Course>> = firstCourseSubjectHolder.firstCourseSubject
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.stepic.droid.core

import io.reactivex.subjects.BehaviorSubject
import org.stepic.droid.di.course_list.CourseGeneralScope
import org.stepic.droid.model.Course
import org.stepic.droid.util.RxOptional
import javax.inject.Inject


@CourseGeneralScope
class FirstCourseSubjectHolder
@Inject
constructor() {
val firstCourseSubject = BehaviorSubject.create<RxOptional<Course>>()
}
2 changes: 2 additions & 0 deletions app/src/main/java/org/stepic/droid/core/ScreenManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,6 @@ public interface ScreenManager {
void showCoursesList(Activity activity, @NotNull CoursesCarouselInfo info, @Nullable CollectionDescriptionColors collectionDescriptionColors);

void showListOfTag(Activity activity, @NotNull Tag tag);

void showOnboarding(@NotNull Activity activity);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.stepic.droid.preferences.UserPreferences;
import org.stepic.droid.services.ViewPusher;
import org.stepic.droid.ui.activities.AboutAppActivity;
import org.stepic.droid.ui.activities.AnimatedOnboardingActivity;
import org.stepic.droid.ui.activities.CertificatesActivity;
import org.stepic.droid.ui.activities.CommentsActivity;
import org.stepic.droid.ui.activities.CourseDetailActivity;
Expand Down Expand Up @@ -139,6 +140,12 @@ public void showListOfTag(Activity activity, @NotNull Tag tag) {
TagActivity.Companion.launch(activity, tag);
}

@Override
public void showOnboarding(@NotNull Activity activity) {
Intent intent = new Intent(activity, AnimatedOnboardingActivity.class);
activity.startActivity(intent);
}

@Override
public void showLaunchScreen(Context context, boolean fromMainFeed, int index) {
analytic.reportEvent(Analytic.Screens.SHOW_LAUNCH);
Expand Down
20 changes: 18 additions & 2 deletions app/src/main/java/org/stepic/droid/core/StepikDevicePosterImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ constructor(
sharedPreferencesHelper.authResponseFromStore!! //for logged user only work
val token = tokenNullable!!
val response = api.registerDevice(token).execute()
if (!response.isSuccessful && response.code() != 400) { //400 -- device already registered
throw Exception("response was failed. it is ok. code: " + response.code())
if (!response.isSuccessful) { //400 -- device already registered
if (response.code() == 400) {
renewDeviceRegistration(token)
} else {
throw Exception("response was failed. it is ok. code: " + response.code())
}
}
sharedPreferencesHelper.setIsGcmTokenOk(true)

Expand All @@ -36,4 +40,16 @@ constructor(
sharedPreferencesHelper.setIsGcmTokenOk(false)
}
}

private fun renewDeviceRegistration(token: String) {
val deviceId = api.getDevicesByRegistrationId(token).execute()?.body()?.devices?.firstOrNull()?.id
if (deviceId != null) {
val response = api.renewDeviceRegistration(deviceId, token).execute()
if (!response.isSuccessful) {
throw Exception("Can't renew device registration for device: $deviceId")
}
} else {
throw Exception("Can't get device id for token: $token")
}
}
}
14 changes: 9 additions & 5 deletions app/src/main/java/org/stepic/droid/core/StepikLogoutManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import android.app.DownloadManager
import android.os.Build
import android.webkit.CookieManager
import org.stepic.droid.concurrency.MainHandler
import org.stepic.droid.di.AppSingleton
import org.stepic.droid.notifications.badges.NotificationsBadgesLogoutPoster
import org.stepic.droid.preferences.SharedPreferenceHelper
import org.stepic.droid.preferences.UserPreferences
import org.stepic.droid.storage.operations.DatabaseFacade
Expand All @@ -12,13 +14,16 @@ import org.stepic.droid.util.RWLocks
import java.util.concurrent.ThreadPoolExecutor
import javax.inject.Inject

@AppSingleton
class StepikLogoutManager
@Inject constructor(private val threadPoolExecutor: ThreadPoolExecutor,
private val mainHandler: MainHandler,
private val userPreferences: UserPreferences,
private val systemDownloadManager: DownloadManager,
private val sharedPreferenceHelper: SharedPreferenceHelper,
private val databaseFacade: DatabaseFacade) {
private val databaseFacade: DatabaseFacade,
private val notificationsBadgesLogoutPoster: NotificationsBadgesLogoutPoster
) {

fun logout(afterClearData: () -> Unit) {
threadPoolExecutor.execute {
Expand All @@ -40,19 +45,18 @@ class StepikLogoutManager
RWLocks.ClearEnrollmentsLock.writeLock().unlock()
}
mainHandler.post {
notificationsBadgesLogoutPoster.clearCounter()
afterClearData.invoke()
}
}
}

private fun removeCookiesCompat() {
CookieManager.getInstance()
if (Build.VERSION.SDK_INT < 21) {
@Suppress("DEPRECATION")
CookieManager.getInstance().removeAllCookie()
} else {
mainHandler.post {
CookieManager.getInstance().removeAllCookies() {}
}
CookieManager.getInstance().removeAllCookies(null)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.stepic.droid.core.presenters

import io.reactivex.Scheduler
import io.reactivex.disposables.Disposable
import org.stepic.droid.core.FirstCourseProvider
import org.stepic.droid.core.presenters.contracts.FastContinueView
import org.stepic.droid.di.course_list.CourseGeneralScope
import org.stepic.droid.di.qualifiers.MainScheduler
import org.stepic.droid.preferences.SharedPreferenceHelper
import javax.inject.Inject

@CourseGeneralScope
class FastContinuePresenter
@Inject
constructor(
private val sharedPreferenceHelper: SharedPreferenceHelper,
private val firstCourseProvider: FirstCourseProvider,
@MainScheduler
private val mainScheduler: Scheduler
) : PresenterBase<FastContinueView>() {

private var disposable: Disposable? = null

fun onCreated() {
if (sharedPreferenceHelper.authResponseFromStore != null) {
view?.onLoading()
subscribeToFirstCourse()
} else {
view?.onAnonymous()
}
}

private fun subscribeToFirstCourse() {
disposable = firstCourseProvider
.firstCourse()
.observeOn(mainScheduler)
.subscribe {
val course = it.value
if (course == null) {
view?.onEmptyCourse()
} else {
view?.onShowCourse(course)
}
}
}

override fun detachView(view: FastContinueView) {
disposable?.dispose()
super.detachView(view)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.stepic.droid.core.presenters.contracts.NotificationListView
import org.stepic.droid.di.notifications.NotificationsScope
import org.stepic.droid.model.NotificationCategory
import org.stepic.droid.notifications.StepikNotificationManager
import org.stepic.droid.notifications.badges.NotificationsBadgesManager
import org.stepic.droid.notifications.model.Notification
import org.stepic.droid.notifications.model.NotificationType
import org.stepic.droid.util.not
Expand All @@ -31,21 +32,23 @@ class NotificationListPresenter
private val config: Config,
private val analytic: Analytic,
private val stepikNotificationManager: StepikNotificationManager,
private val internetEnabledListenerClient: Client<InternetEnabledListener>
private val internetEnabledListenerClient: Client<InternetEnabledListener>,
private val notificationsBadgesManager: NotificationsBadgesManager
) : PresenterBase<NotificationListView>(), InternetEnabledListener {
private var notificationCategory: NotificationCategory? = null
val isLoading = AtomicBoolean(false)
val wasShown = AtomicBoolean(false)
val hasNextPage = AtomicBoolean(true)
private val page = AtomicInteger(1)
val notificationList: MutableList<Notification> = ArrayList<Notification>()
val notificationList: MutableList<Notification> = ArrayList()
val notificationMapIdToPosition: MutableMap<Long, Int> = HashMap()

/**
* return false if were cancelled
*/
@MainThread
fun init(notificationCategory: NotificationCategory): Boolean {
notificationsBadgesManager.syncCounter()
this.notificationCategory = notificationCategory
if (!isLoading && !wasShown) {
//it is not lock, it is just check, but we still can enter twice if we use it in multithreading way, but it is only for main thread.
Expand Down Expand Up @@ -153,6 +156,7 @@ class NotificationListPresenter
if (isSuccess) {
mainHandler.post {
onNotificationShouldBeRead(id)
notificationsBadgesManager.syncCounter()
}
} else {
val pos = notificationMapIdToPosition[id]
Expand Down Expand Up @@ -201,6 +205,7 @@ class NotificationListPresenter
try {
val response = api.markAsReadAllType(notificationCategoryLocal).execute()
if (response.isSuccessful) {
notificationsBadgesManager.syncCounter()
notificationList.forEach {
it.is_unread = false
}
Expand Down
Loading

0 comments on commit dbbb29c

Please sign in to comment.