From 079a10cb21b40366130b9551992c76d894770e76 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 20 Jan 2022 13:30:07 +0300 Subject: [PATCH 01/18] Add manual benefit support --- .../interactor/CourseBenefitsInteractor.kt | 2 +- .../course_revenue/model/CourseBenefit.kt | 6 +- .../delegate/CourseBenefitsAdapterDelegate.kt | 58 ++++++++++++------- .../TransactionBottomSheetDialogFragment.kt | 18 +++++- app/src/main/res/values-be/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 7 files changed, 61 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/org/stepik/android/domain/course_revenue/interactor/CourseBenefitsInteractor.kt b/app/src/main/java/org/stepik/android/domain/course_revenue/interactor/CourseBenefitsInteractor.kt index ff27b5fa93..ecdbdc45ad 100644 --- a/app/src/main/java/org/stepik/android/domain/course_revenue/interactor/CourseBenefitsInteractor.kt +++ b/app/src/main/java/org/stepik/android/domain/course_revenue/interactor/CourseBenefitsInteractor.kt @@ -58,7 +58,7 @@ constructor( private fun resolveCourseBenefitListItems(courseBenefits: PagedList): Single> = userRepository - .getUsers(courseBenefits.map(CourseBenefit::buyer)) + .getUsers(courseBenefits.mapNotNull(CourseBenefit::buyer)) .map { users -> val userMap = users.associateBy(User::id) courseBenefits.transform { diff --git a/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt b/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt index 521c239996..12f8403c81 100644 --- a/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt +++ b/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt @@ -12,7 +12,7 @@ data class CourseBenefit( @SerializedName("user") val user: Long, @SerializedName("buyer") - val buyer: Long, + val buyer: Long?, @SerializedName("course") val course: Long, @SerializedName("time") @@ -22,9 +22,11 @@ data class CourseBenefit( @SerializedName("amount") val amount: String, @SerializedName("payment_amount") - val paymentAmount: String, + val paymentAmount: String?, @SerializedName("currency_code") val currencyCode: String, + @SerializedName("description") + val description: String?, @SerializedName("is_z_link_used") val isZLinkUsed: Boolean?, @SerializedName("is_invoice_payment") diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt index 1a0021301e..fda03323a9 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt @@ -47,7 +47,18 @@ class CourseBenefitsAdapterDelegate( decimalFormat.minimumFractionDigits = 2 purchaseRefundIcon.setImageDrawable(getIconDrawable(data.courseBenefit)) - purchaseRefundName.text = data.user?.fullName ?: data.courseBenefit.buyer.toString() + purchaseRefundName.text = + if (data.courseBenefit.buyer == null && !data.courseBenefit.isInvoicePayment) { + buildString { + append(context.getString(R.string.transaction_manual_channel)) + if (data.courseBenefit.description != null) { + append(": ${data.courseBenefit.description}") + } + } + } else { + data.user?.fullName ?: data.courseBenefit.buyer.toString() + } + purchaseRefundDate.text = DateTimeHelper.getPrintableDate( data.courseBenefit.time, DateTimeHelper.DISPLAY_DATETIME_PATTERN, @@ -55,7 +66,7 @@ class CourseBenefitsAdapterDelegate( ) val transactionSum = if (data.courseBenefit.status == CourseBenefit.Status.DEBITED) { - revenuePriceMapper.mapToDisplayPrice(data.courseBenefit.currencyCode, decimalFormat.format(data.courseBenefit.paymentAmount.toDoubleOrNull() ?: 0.0)) + revenuePriceMapper.mapToDisplayPrice(data.courseBenefit.currencyCode, decimalFormat.format(data.courseBenefit.paymentAmount?.toDoubleOrNull() ?: 0.0)) } else { context.getString(R.string.course_benefits_refund) } @@ -79,26 +90,33 @@ class CourseBenefitsAdapterDelegate( } private fun getIconDrawable(data: CourseBenefit): Drawable? = - if (data.status == CourseBenefit.Status.DEBITED) { - when { - data.isZLinkUsed == true -> - AppCompatResources.getDrawable(context, R.drawable.ic_purchase_z_link) - - data.isInvoicePayment -> { - AppCompatResources - .getDrawable(context, R.drawable.ic_purchase_stepik) - ?.mutate() - ?.let { DrawableCompat.wrap(it) } - ?.also { - DrawableCompat.setTint(it, ContextCompat.getColor(context, R.color.color_on_background)) - DrawableCompat.setTintMode(it, PorterDuff.Mode.SRC_IN) - } + if (data.buyer == null && !data.isInvoicePayment) { + getTintedDrawable(R.color.color_on_surface_alpha_38) + } else { + if (data.status == CourseBenefit.Status.DEBITED) { + when { + data.isZLinkUsed == true -> + AppCompatResources.getDrawable(context, R.drawable.ic_purchase_z_link) + + data.isInvoicePayment -> + getTintedDrawable(R.color.color_on_background) + + else -> + AppCompatResources.getDrawable(context, R.drawable.ic_purchase_stepik) } - else -> - AppCompatResources.getDrawable(context, R.drawable.ic_purchase_stepik) + } else { + AppCompatResources.getDrawable(context, R.drawable.ic_refund) } - } else { - AppCompatResources.getDrawable(context, R.drawable.ic_refund) } + + private fun getTintedDrawable(tint: Int): Drawable? = + AppCompatResources + .getDrawable(context, R.drawable.ic_purchase_stepik) + ?.mutate() + ?.let { DrawableCompat.wrap(it) } + ?.also { + DrawableCompat.setTint(it, ContextCompat.getColor(context, tint)) + DrawableCompat.setTintMode(it, PorterDuff.Mode.SRC_IN) + } } } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt index a52bdcc6f7..c81a0992f4 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt @@ -95,20 +95,32 @@ class TransactionBottomSheetDialogFragment : BottomSheetDialogFragment() { transactionBuyerValue.isVisible = user != null buyerOverlayView.setOnClickListener { user?.let { screenManager.openProfile(requireContext(), it.id) } } - transactionPaymentValue.text = revenuePriceMapper.mapToDisplayPrice(courseBenefit.currencyCode, decimalFormat.format(courseBenefit.paymentAmount.toDoubleOrNull() ?: 0.0)) + transactionPaymentValue.text = + revenuePriceMapper.mapToDisplayPrice(courseBenefit.currencyCode, decimalFormat.format(courseBenefit.paymentAmount?.toDoubleOrNull() ?: 0.0)) transactionPromoCodeValue.text = courseBenefit.promoCode.orEmpty() transactionPromoCodeTitle.isVisible = courseBenefit.promoCode != null transactionPromoCodeValue.isVisible = courseBenefit.promoCode != null - transactionChannelTitle.isVisible = courseBenefit.status == CourseBenefit.Status.DEBITED - transactionChannelValue.isVisible = courseBenefit.status == CourseBenefit.Status.DEBITED + val isChannelInfoVisible = courseBenefit.status == CourseBenefit.Status.DEBITED || + (courseBenefit.buyer == null && !courseBenefit.isInvoicePayment) + + transactionChannelTitle.isVisible = isChannelInfoVisible + transactionChannelValue.isVisible = isChannelInfoVisible transactionChannelValue.text = when { courseBenefit.isZLinkUsed == true -> getString(R.string.transaction_z_link_channel) courseBenefit.isInvoicePayment -> getString(R.string.transaction_invoice_channel) + courseBenefit.buyer == null && !courseBenefit.isInvoicePayment -> { + buildString { + append(getString(R.string.transaction_manual_channel)) + if (courseBenefit.description != null) { + append(": ${courseBenefit.description}") + } + } + } else -> getString(R.string.transaction_stepik_channel) } diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 8b6f558e7f..20b3d1f4e2 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -1004,6 +1004,7 @@ Пераход праз Stepik Пераход па z-спасылцы Аплаты па ліку + Уручную Ваш працэнт %s%% з продажаў за вылікам камісіі Stepik Ваш даход diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 798fdae50a..16380ffdf0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1141,6 +1141,7 @@ Переход через Stepik Переход по z-ссылке Оплата по счету + Вручную Ваш процент %s%% с продаж за вычетом комиссии Stepik Ваш доход diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fae66c0821..3d01c5945a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1202,6 +1202,7 @@ Came via Stepik Came via Z-link Payment on account + Manually Your share %s%% of sales revenue minus Stepik\'s fee Your earnings From 3005535f8d0ebac294c3192a23e11f5701f86bb0 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 20 Jan 2022 14:04:18 +0300 Subject: [PATCH 02/18] Add announcements field to Course --- .../org/stepic/droid/storage/dao/CourseDaoImpl.kt | 2 ++ .../droid/storage/migration/MigrationFrom78To79.kt | 11 +++++++++++ .../org/stepic/droid/storage/migration/Migrations.kt | 3 ++- .../droid/storage/structure/DbStructureCourse.kt | 1 + .../stepik/android/cache/base/database/AppDatabase.kt | 2 +- .../android/migration_wrapper/MigrationWrappers.kt | 3 ++- .../src/main/java/org/stepik/android/model/Course.kt | 2 ++ 7 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt diff --git a/app/src/main/java/org/stepic/droid/storage/dao/CourseDaoImpl.kt b/app/src/main/java/org/stepic/droid/storage/dao/CourseDaoImpl.kt index b5e61bc298..74a3504cfa 100644 --- a/app/src/main/java/org/stepic/droid/storage/dao/CourseDaoImpl.kt +++ b/app/src/main/java/org/stepic/droid/storage/dao/CourseDaoImpl.kt @@ -37,6 +37,7 @@ constructor( intro = cursor.getString(DbStructureCourse.Columns.INTRO), introVideo = Video(id = cursor.getLong(DbStructureCourse.Columns.INTRO_VIDEO_ID)), language = cursor.getString(DbStructureCourse.Columns.LANGUAGE), + announcements = DbParseHelper.parseStringToLongList(cursor.getString(DbStructureCourse.Columns.ANNOUNCEMENTS)), authors = DbParseHelper.parseStringToLongList(cursor.getString(DbStructureCourse.Columns.AUTHORS)), instructors = DbParseHelper.parseStringToLongList(cursor.getString(DbStructureCourse.Columns.INSTRUCTORS)), sections = DbParseHelper.parseStringToLongList(cursor.getString(DbStructureCourse.Columns.SECTIONS)), @@ -106,6 +107,7 @@ constructor( values.put(DbStructureCourse.Columns.INTRO, course.intro) values.put(DbStructureCourse.Columns.INTRO_VIDEO_ID, course.introVideo?.id ?: -1) // todo add complete course entity and remove this hack values.put(DbStructureCourse.Columns.LANGUAGE, course.language) + values.put(DbStructureCourse.Columns.ANNOUNCEMENTS, DbParseHelper.parseLongListToString(course.announcements)) values.put(DbStructureCourse.Columns.AUTHORS, DbParseHelper.parseLongListToString(course.authors)) values.put(DbStructureCourse.Columns.INSTRUCTORS, DbParseHelper.parseLongListToString(course.instructors)) values.put(DbStructureCourse.Columns.SECTIONS, DbParseHelper.parseLongListToString(course.sections)) diff --git a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt new file mode 100644 index 0000000000..cb8c74f559 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt @@ -0,0 +1,11 @@ +package org.stepic.droid.storage.migration + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase +import org.stepic.droid.storage.structure.DbStructureCourse + +object MigrationFrom78To79 : Migration(78, 79) { + override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE ${DbStructureCourse.TABLE_NAME} ADD COLUMN ${DbStructureCourse.Columns.ANNOUNCEMENTS} TEXT") + } +} \ No newline at end of file diff --git a/app/src/main/java/org/stepic/droid/storage/migration/Migrations.kt b/app/src/main/java/org/stepic/droid/storage/migration/Migrations.kt index 640c717472..04b61b75ee 100644 --- a/app/src/main/java/org/stepic/droid/storage/migration/Migrations.kt +++ b/app/src/main/java/org/stepic/droid/storage/migration/Migrations.kt @@ -209,6 +209,7 @@ object Migrations { MigrationFrom74To75, MigrationFrom75To76, MigrationFrom76To77, - MigrationFrom77To78 + MigrationFrom77To78, + MigrationFrom78To79 ) } \ No newline at end of file diff --git a/app/src/main/java/org/stepic/droid/storage/structure/DbStructureCourse.kt b/app/src/main/java/org/stepic/droid/storage/structure/DbStructureCourse.kt index 6f623d49f1..a63f4ed488 100644 --- a/app/src/main/java/org/stepic/droid/storage/structure/DbStructureCourse.kt +++ b/app/src/main/java/org/stepic/droid/storage/structure/DbStructureCourse.kt @@ -19,6 +19,7 @@ object DbStructureCourse { const val INTRO_VIDEO_ID = "intro_video_id" const val LANGUAGE = "language" + const val ANNOUNCEMENTS = "announcements" const val AUTHORS = "authors" const val INSTRUCTORS = "instructors" const val SECTIONS = "sections" diff --git a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt index 94cef6d750..f015c9ed15 100644 --- a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt +++ b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt @@ -65,7 +65,7 @@ import org.stepik.android.domain.wishlist.model.WishlistEntry ) abstract class AppDatabase : RoomDatabase() { companion object { - const val VERSION = 78 + const val VERSION = 79 const val NAME = "stepic_database.db" } diff --git a/app/src/sharedTest/java/org/stepik/android/migration_wrapper/MigrationWrappers.kt b/app/src/sharedTest/java/org/stepik/android/migration_wrapper/MigrationWrappers.kt index 9c9c3be9c3..05e9c68f2c 100644 --- a/app/src/sharedTest/java/org/stepik/android/migration_wrapper/MigrationWrappers.kt +++ b/app/src/sharedTest/java/org/stepik/android/migration_wrapper/MigrationWrappers.kt @@ -28,6 +28,7 @@ object MigrationWrappers { object : MigrationWrapper(MigrationFrom74To75) {}, object : MigrationWrapper(MigrationFrom75To76) {}, object : MigrationWrapper(MigrationFrom76To77) {}, - object : MigrationWrapper(MigrationFrom77To78) {} + object : MigrationWrapper(MigrationFrom77To78) {}, + object : MigrationWrapper(MigrationFrom78To79) {} ) } \ No newline at end of file diff --git a/model/src/main/java/org/stepik/android/model/Course.kt b/model/src/main/java/org/stepik/android/model/Course.kt index 4cb2e01991..a6d8af9fda 100644 --- a/model/src/main/java/org/stepik/android/model/Course.kt +++ b/model/src/main/java/org/stepik/android/model/Course.kt @@ -32,6 +32,8 @@ data class Course( @SerializedName("language") val language: String? = null, + @SerializedName("announcements") + val announcements: List? = null, @SerializedName("authors") val authors: List? = null, @SerializedName("instructors") From 208be583cd6f3cb3a4cfdce684e29582adfcc0bd Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 20 Jan 2022 15:09:30 +0300 Subject: [PATCH 03/18] Add Announcement entity --- .../storage/migration/MigrationFrom78To79.kt | 1 + .../cache/base/database/AppDatabase.kt | 4 +- .../cache/base/mapper/DateConverter.kt | 8 +++ .../domain/announcement/model/Announcement.kt | 65 +++++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt diff --git a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt index cb8c74f559..22bb4f7238 100644 --- a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt +++ b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt @@ -7,5 +7,6 @@ import org.stepic.droid.storage.structure.DbStructureCourse object MigrationFrom78To79 : Migration(78, 79) { override fun migrate(db: SupportSQLiteDatabase) { db.execSQL("ALTER TABLE ${DbStructureCourse.TABLE_NAME} ADD COLUMN ${DbStructureCourse.Columns.ANNOUNCEMENTS} TEXT") + db.execSQL("CREATE TABLE IF NOT EXISTS `Announcement` (`id` INTEGER NOT NULL, `course` INTEGER NOT NULL, `user` INTEGER, `subject` TEXT NOT NULL, `text` TEXT NOT NULL, `createDate` INTEGER, `nextDate` INTEGER, `sentDate` INTEGER, `status` TEXT NOT NULL, `isRestrictedByScore` INTEGER NOT NULL, `scorePercentMin` INTEGER NOT NULL, `scorePercentMax` INTEGER NOT NULL, `emailTemplate` TEXT, `isScheduled` INTEGER NOT NULL, `startDate` INTEGER, `mailPeriodDays` INTEGER NOT NULL, `mailQuantity` INTEGER NOT NULL, `isInfinite` INTEGER NOT NULL, `onEnroll` INTEGER NOT NULL, `publishCount` INTEGER, `queueCount` INTEGER, `sentCount` INTEGER, `openCount` INTEGER, `clickCount` INTEGER, `estimatedStartDate` INTEGER, `estimatedFinishDate` INTEGER, `noticeDates` TEXT NOT NULL, PRIMARY KEY(`id`))") } } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt index f015c9ed15..efdd472eba 100644 --- a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt +++ b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt @@ -26,6 +26,7 @@ import org.stepik.android.cache.mobile_tiers.dao.MobileTiersDao import org.stepik.android.cache.proctor_session.dao.ProctorSessionDao import org.stepik.android.cache.rubric.dao.RubricDao import org.stepik.android.cache.wishlist.dao.WishlistDao +import org.stepik.android.domain.announcement.model.Announcement import org.stepik.android.domain.course_purchase.model.BillingPurchasePayload import org.stepik.android.domain.course_recommendations.model.CourseRecommendation import org.stepik.android.domain.exam_session.model.ExamSession @@ -51,7 +52,8 @@ import org.stepik.android.domain.wishlist.model.WishlistEntry MobileTier::class, LightSku::class, WishlistEntry::class, - BillingPurchasePayload::class + BillingPurchasePayload::class, + Announcement::class ], version = AppDatabase.VERSION, exportSchema = false diff --git a/app/src/main/java/org/stepik/android/cache/base/mapper/DateConverter.kt b/app/src/main/java/org/stepik/android/cache/base/mapper/DateConverter.kt index 5b205729f7..8ebc3b6620 100644 --- a/app/src/main/java/org/stepik/android/cache/base/mapper/DateConverter.kt +++ b/app/src/main/java/org/stepik/android/cache/base/mapper/DateConverter.kt @@ -11,4 +11,12 @@ class DateConverter { @TypeConverter fun longToDate(long: Long): Date? = long.takeIf { it > -1 }?.let(::Date) + + @TypeConverter + fun dateListToLongList(dates: List?): List? = + dates?.map { it.time } + + @TypeConverter + fun longListToDateList(longs: List?): List? = + longs?.map { Date(it) } } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt b/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt new file mode 100644 index 0000000000..c00c4c41e6 --- /dev/null +++ b/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt @@ -0,0 +1,65 @@ +package org.stepik.android.domain.announcement.model + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.google.gson.annotations.SerializedName +import java.util.Date + +@Entity +data class Announcement( + @SerializedName("id") + @PrimaryKey + val id: Long, + @SerializedName("course") + val course: Long, + @SerializedName("user") + val user: Long?, + @SerializedName("subject") + val subject: String, + @SerializedName("text") + val text: String, + @SerializedName("create_date") + val createDate: Date?, + @SerializedName("next_date") + val nextDate: Date?, + @SerializedName("sent_date") + val sentDate: Date?, + @SerializedName("status") + val status: String, + @SerializedName("is_restricted_by_score") + val isRestrictedByScore: Boolean, + @SerializedName("score_percent_min") + val scorePercentMin: Int, + @SerializedName("score_percent_max") + val scorePercentMax: Int, + @SerializedName("email_template") + val emailTemplate: String?, + @SerializedName("is_scheduled") + val isScheduled: Boolean, + @SerializedName("start_date") + val startDate: Date?, + @SerializedName("mail_period_days") + val mailPeriodDays: Int, + @SerializedName("mail_quantity") + val mailQuantity: Int, + @SerializedName("is_infinite") + val isInfinite: Boolean, + @SerializedName("on_enroll") + val onEnroll: Boolean, + @SerializedName("publish_count") + val publishCount: Int?, + @SerializedName("queue_count") + val queueCount: Int?, + @SerializedName("sent_count") + val sentCount: Int?, + @SerializedName("open_count") + val openCount: Int?, + @SerializedName("click_count") + val clickCount: Int?, + @SerializedName("estimated_start_date") + val estimatedStartDate: Date?, + @SerializedName("estimated_finish_date") + val estimatedFinishDate: Date?, + @SerializedName("notice_dates") + val noticeDates: List = emptyList() +) From 73c7f1a435eae7383a992c2245773b38ff8cb140 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 20 Jan 2022 15:51:59 +0300 Subject: [PATCH 04/18] Add Announcement cache, remote, data and domain layers --- .../AnnouncementCacheDataSourceImpl.kt | 20 ++++++++ .../cache/announcement/dao/AnnouncementDao.kt | 18 +++++++ .../cache/base/database/AppDatabase.kt | 2 + .../repository/AnnouncementRepositoryImpl.kt | 27 +++++++++++ .../source/AnnouncementCacheDataSource.kt | 10 ++++ .../source/AnnouncementRemoteDataSource.kt | 8 ++++ .../domain/announcement/model/Announcement.kt | 5 +- .../repository/AnnouncementRepository.kt | 9 ++++ .../AnnouncementRemoteDataSourceImpl.kt | 19 ++++++++ .../model/AnnouncementResponse.kt | 13 +++++ .../service/AnnouncementService.kt | 11 +++++ .../announcement/AnnouncementDataModule.kt | 48 +++++++++++++++++++ 12 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/stepik/android/cache/announcement/AnnouncementCacheDataSourceImpl.kt create mode 100644 app/src/main/java/org/stepik/android/cache/announcement/dao/AnnouncementDao.kt create mode 100644 app/src/main/java/org/stepik/android/data/announcement/repository/AnnouncementRepositoryImpl.kt create mode 100644 app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementCacheDataSource.kt create mode 100644 app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementRemoteDataSource.kt create mode 100644 app/src/main/java/org/stepik/android/domain/announcement/repository/AnnouncementRepository.kt create mode 100644 app/src/main/java/org/stepik/android/remote/announcement/AnnouncementRemoteDataSourceImpl.kt create mode 100644 app/src/main/java/org/stepik/android/remote/announcement/model/AnnouncementResponse.kt create mode 100644 app/src/main/java/org/stepik/android/remote/announcement/service/AnnouncementService.kt create mode 100644 app/src/main/java/org/stepik/android/view/injection/announcement/AnnouncementDataModule.kt diff --git a/app/src/main/java/org/stepik/android/cache/announcement/AnnouncementCacheDataSourceImpl.kt b/app/src/main/java/org/stepik/android/cache/announcement/AnnouncementCacheDataSourceImpl.kt new file mode 100644 index 0000000000..289a8daf41 --- /dev/null +++ b/app/src/main/java/org/stepik/android/cache/announcement/AnnouncementCacheDataSourceImpl.kt @@ -0,0 +1,20 @@ +package org.stepik.android.cache.announcement + +import io.reactivex.Completable +import io.reactivex.Single +import org.stepik.android.cache.announcement.dao.AnnouncementDao +import org.stepik.android.data.announcement.source.AnnouncementCacheDataSource +import org.stepik.android.domain.announcement.model.Announcement +import javax.inject.Inject + +class AnnouncementCacheDataSourceImpl +@Inject +constructor( + private val announcementDao: AnnouncementDao +) : AnnouncementCacheDataSource { + override fun getAnnouncements(announcementIds: List): Single> = + announcementDao.getAnnouncement(announcementIds) + + override fun saveAnnouncements(announcements: List): Completable = + announcementDao.saveAnnouncements(announcements) +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/cache/announcement/dao/AnnouncementDao.kt b/app/src/main/java/org/stepik/android/cache/announcement/dao/AnnouncementDao.kt new file mode 100644 index 0000000000..0111ffa6b0 --- /dev/null +++ b/app/src/main/java/org/stepik/android/cache/announcement/dao/AnnouncementDao.kt @@ -0,0 +1,18 @@ +package org.stepik.android.cache.announcement.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import io.reactivex.Completable +import io.reactivex.Single +import org.stepik.android.domain.announcement.model.Announcement + +@Dao +interface AnnouncementDao { + @Query("SELECT * FROM Announcement WHERE id IN (:announcementIds)") + fun getAnnouncement(announcementIds: List): Single> + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun saveAnnouncements(announcements: List): Completable +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt index efdd472eba..e18ff64cce 100644 --- a/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt +++ b/app/src/main/java/org/stepik/android/cache/base/database/AppDatabase.kt @@ -3,6 +3,7 @@ package org.stepik.android.cache.base.database import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters +import org.stepik.android.cache.announcement.dao.AnnouncementDao import org.stepik.android.cache.base.mapper.CollectionConverter import org.stepik.android.cache.base.mapper.DateConverter import org.stepik.android.cache.catalog.dao.CatalogBlockDao @@ -85,4 +86,5 @@ abstract class AppDatabase : RoomDatabase() { abstract fun lightSkuDao(): LightSkuDao abstract fun wishlistDao(): WishlistDao abstract fun billingPurchasePayloadDao(): BillingPurchasePayloadDao + abstract fun announcementDao(): AnnouncementDao } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/data/announcement/repository/AnnouncementRepositoryImpl.kt b/app/src/main/java/org/stepik/android/data/announcement/repository/AnnouncementRepositoryImpl.kt new file mode 100644 index 0000000000..ce88c7dc96 --- /dev/null +++ b/app/src/main/java/org/stepik/android/data/announcement/repository/AnnouncementRepositoryImpl.kt @@ -0,0 +1,27 @@ +package org.stepik.android.data.announcement.repository + +import io.reactivex.Single +import org.stepik.android.data.announcement.source.AnnouncementCacheDataSource +import org.stepik.android.data.announcement.source.AnnouncementRemoteDataSource +import org.stepik.android.data.base.repository.delegate.ListRepositoryDelegate +import org.stepik.android.domain.announcement.model.Announcement +import org.stepik.android.domain.announcement.repository.AnnouncementRepository +import org.stepik.android.domain.base.DataSourceType +import javax.inject.Inject + +class AnnouncementRepositoryImpl +@Inject +constructor( + private val announcementRemoteDataSource: AnnouncementRemoteDataSource, + private val announcementCacheDataSource: AnnouncementCacheDataSource +) : AnnouncementRepository { + private val delegate = + ListRepositoryDelegate( + announcementRemoteDataSource::getAnnouncements, + announcementCacheDataSource::getAnnouncements, + announcementCacheDataSource::saveAnnouncements + ) + + override fun getAnnouncements(announcementIds: List, sourceType: DataSourceType): Single> = + delegate.get(announcementIds, sourceType, allowFallback = true) +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementCacheDataSource.kt b/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementCacheDataSource.kt new file mode 100644 index 0000000000..ea1cf3e6bf --- /dev/null +++ b/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementCacheDataSource.kt @@ -0,0 +1,10 @@ +package org.stepik.android.data.announcement.source + +import io.reactivex.Completable +import io.reactivex.Single +import org.stepik.android.domain.announcement.model.Announcement + +interface AnnouncementCacheDataSource { + fun getAnnouncements(announcementIds: List): Single> + fun saveAnnouncements(announcements: List): Completable +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementRemoteDataSource.kt b/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementRemoteDataSource.kt new file mode 100644 index 0000000000..a905bf75ce --- /dev/null +++ b/app/src/main/java/org/stepik/android/data/announcement/source/AnnouncementRemoteDataSource.kt @@ -0,0 +1,8 @@ +package org.stepik.android.data.announcement.source + +import io.reactivex.Single +import org.stepik.android.domain.announcement.model.Announcement + +interface AnnouncementRemoteDataSource { + fun getAnnouncements(announcementIds: List): Single> +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt b/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt index c00c4c41e6..88fd8ab52b 100644 --- a/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt +++ b/app/src/main/java/org/stepik/android/domain/announcement/model/Announcement.kt @@ -3,13 +3,14 @@ package org.stepik.android.domain.announcement.model import androidx.room.Entity import androidx.room.PrimaryKey import com.google.gson.annotations.SerializedName +import ru.nobird.android.core.model.Identifiable import java.util.Date @Entity data class Announcement( @SerializedName("id") @PrimaryKey - val id: Long, + override val id: Long, @SerializedName("course") val course: Long, @SerializedName("user") @@ -62,4 +63,4 @@ data class Announcement( val estimatedFinishDate: Date?, @SerializedName("notice_dates") val noticeDates: List = emptyList() -) +) : Identifiable diff --git a/app/src/main/java/org/stepik/android/domain/announcement/repository/AnnouncementRepository.kt b/app/src/main/java/org/stepik/android/domain/announcement/repository/AnnouncementRepository.kt new file mode 100644 index 0000000000..e8ebcf5423 --- /dev/null +++ b/app/src/main/java/org/stepik/android/domain/announcement/repository/AnnouncementRepository.kt @@ -0,0 +1,9 @@ +package org.stepik.android.domain.announcement.repository + +import io.reactivex.Single +import org.stepik.android.domain.announcement.model.Announcement +import org.stepik.android.domain.base.DataSourceType + +interface AnnouncementRepository { + fun getAnnouncements(announcementIds: List, sourceType: DataSourceType = DataSourceType.CACHE): Single> +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/remote/announcement/AnnouncementRemoteDataSourceImpl.kt b/app/src/main/java/org/stepik/android/remote/announcement/AnnouncementRemoteDataSourceImpl.kt new file mode 100644 index 0000000000..de44345b39 --- /dev/null +++ b/app/src/main/java/org/stepik/android/remote/announcement/AnnouncementRemoteDataSourceImpl.kt @@ -0,0 +1,19 @@ +package org.stepik.android.remote.announcement + +import io.reactivex.Single +import org.stepik.android.data.announcement.source.AnnouncementRemoteDataSource +import org.stepik.android.domain.announcement.model.Announcement +import org.stepik.android.remote.announcement.model.AnnouncementResponse +import org.stepik.android.remote.announcement.service.AnnouncementService +import javax.inject.Inject + +class AnnouncementRemoteDataSourceImpl +@Inject +constructor( + private val announcementService: AnnouncementService +) : AnnouncementRemoteDataSource { + override fun getAnnouncements(announcementIds: List): Single> = + announcementService + .getAnnouncements(announcementIds) + .map(AnnouncementResponse::announcements) +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/remote/announcement/model/AnnouncementResponse.kt b/app/src/main/java/org/stepik/android/remote/announcement/model/AnnouncementResponse.kt new file mode 100644 index 0000000000..edb71b8bd6 --- /dev/null +++ b/app/src/main/java/org/stepik/android/remote/announcement/model/AnnouncementResponse.kt @@ -0,0 +1,13 @@ +package org.stepik.android.remote.announcement.model + +import com.google.gson.annotations.SerializedName +import org.stepik.android.domain.announcement.model.Announcement +import org.stepik.android.model.Meta +import org.stepik.android.remote.base.model.MetaResponse + +class AnnouncementResponse( + @SerializedName("meta") + override val meta: Meta, + @SerializedName("announcements") + val announcements: List +) : MetaResponse \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/remote/announcement/service/AnnouncementService.kt b/app/src/main/java/org/stepik/android/remote/announcement/service/AnnouncementService.kt new file mode 100644 index 0000000000..5007adafb6 --- /dev/null +++ b/app/src/main/java/org/stepik/android/remote/announcement/service/AnnouncementService.kt @@ -0,0 +1,11 @@ +package org.stepik.android.remote.announcement.service + +import io.reactivex.Single +import org.stepik.android.remote.announcement.model.AnnouncementResponse +import retrofit2.http.GET +import retrofit2.http.Query + +interface AnnouncementService { + @GET("api/announcements") + fun getAnnouncements(@Query("ids[]") announcementIds: List): Single +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/injection/announcement/AnnouncementDataModule.kt b/app/src/main/java/org/stepik/android/view/injection/announcement/AnnouncementDataModule.kt new file mode 100644 index 0000000000..3bb81e584d --- /dev/null +++ b/app/src/main/java/org/stepik/android/view/injection/announcement/AnnouncementDataModule.kt @@ -0,0 +1,48 @@ +package org.stepik.android.view.injection.announcement + +import dagger.Binds +import dagger.Module +import dagger.Provides +import org.stepik.android.cache.announcement.AnnouncementCacheDataSourceImpl +import org.stepik.android.cache.announcement.dao.AnnouncementDao +import org.stepik.android.cache.base.database.AppDatabase +import org.stepik.android.data.announcement.repository.AnnouncementRepositoryImpl +import org.stepik.android.data.announcement.source.AnnouncementCacheDataSource +import org.stepik.android.data.announcement.source.AnnouncementRemoteDataSource +import org.stepik.android.domain.announcement.repository.AnnouncementRepository +import org.stepik.android.remote.announcement.AnnouncementRemoteDataSourceImpl +import org.stepik.android.remote.announcement.service.AnnouncementService +import org.stepik.android.view.injection.base.Authorized +import retrofit2.Retrofit +import retrofit2.create + +@Module +abstract class AnnouncementDataModule { + @Binds + internal abstract fun bindAnnouncementRepository( + announcementRepositoryImpl: AnnouncementRepositoryImpl + ): AnnouncementRepository + + @Binds + internal abstract fun bindAnnouncementRemoteDataSource( + announcementRemoteDataSourceImpl: AnnouncementRemoteDataSourceImpl + ): AnnouncementRemoteDataSource + + @Binds + internal abstract fun bindAnnouncementCacheDataSource( + announcementCacheDataSourceImpl: AnnouncementCacheDataSourceImpl + ): AnnouncementCacheDataSource + + @Module + companion object { + @Provides + @JvmStatic + internal fun provideAnnouncementDao(appDatabase: AppDatabase): AnnouncementDao = + appDatabase.announcementDao() + + @Provides + @JvmStatic + internal fun provideAnnouncementService(@Authorized retrofit: Retrofit): AnnouncementService = + retrofit.create() + } +} \ No newline at end of file From 14553d0c1ae24ef4aac03000610c91c00f33e2cb Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 20 Jan 2022 17:01:41 +0300 Subject: [PATCH 05/18] Add isManual property to course benefit --- .../android/domain/course_revenue/model/CourseBenefit.kt | 4 ++++ .../ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt | 4 ++-- .../ui/dialog/TransactionBottomSheetDialogFragment.kt | 5 ++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt b/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt index 12f8403c81..6bac630d29 100644 --- a/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt +++ b/app/src/main/java/org/stepik/android/domain/course_revenue/model/CourseBenefit.kt @@ -2,6 +2,7 @@ package org.stepik.android.domain.course_revenue.model import android.os.Parcelable import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.android.parcel.Parcelize import java.util.Date @@ -42,4 +43,7 @@ data class CourseBenefit( @SerializedName("refunded") REFUNDED("refunded") } + @IgnoredOnParcel + val isManual: Boolean = + buyer == null && !isInvoicePayment } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt index fda03323a9..a91639ef9c 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt @@ -48,7 +48,7 @@ class CourseBenefitsAdapterDelegate( purchaseRefundIcon.setImageDrawable(getIconDrawable(data.courseBenefit)) purchaseRefundName.text = - if (data.courseBenefit.buyer == null && !data.courseBenefit.isInvoicePayment) { + if (data.courseBenefit.isManual) { buildString { append(context.getString(R.string.transaction_manual_channel)) if (data.courseBenefit.description != null) { @@ -90,7 +90,7 @@ class CourseBenefitsAdapterDelegate( } private fun getIconDrawable(data: CourseBenefit): Drawable? = - if (data.buyer == null && !data.isInvoicePayment) { + if (data.isManual) { getTintedDrawable(R.color.color_on_surface_alpha_38) } else { if (data.status == CourseBenefit.Status.DEBITED) { diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt index c81a0992f4..d40babf29f 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt @@ -102,8 +102,7 @@ class TransactionBottomSheetDialogFragment : BottomSheetDialogFragment() { transactionPromoCodeTitle.isVisible = courseBenefit.promoCode != null transactionPromoCodeValue.isVisible = courseBenefit.promoCode != null - val isChannelInfoVisible = courseBenefit.status == CourseBenefit.Status.DEBITED || - (courseBenefit.buyer == null && !courseBenefit.isInvoicePayment) + val isChannelInfoVisible = courseBenefit.status == CourseBenefit.Status.DEBITED || courseBenefit.isManual transactionChannelTitle.isVisible = isChannelInfoVisible transactionChannelValue.isVisible = isChannelInfoVisible @@ -113,7 +112,7 @@ class TransactionBottomSheetDialogFragment : BottomSheetDialogFragment() { getString(R.string.transaction_z_link_channel) courseBenefit.isInvoicePayment -> getString(R.string.transaction_invoice_channel) - courseBenefit.buyer == null && !courseBenefit.isInvoicePayment -> { + courseBenefit.isManual -> { buildString { append(getString(R.string.transaction_manual_channel)) if (courseBenefit.description != null) { From 39c1200ab469f85443309ce950243076826da2fc Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Fri, 21 Jan 2022 16:21:57 +0300 Subject: [PATCH 06/18] Add new design for certificate item --- .../CertificateProfileAdapterDelegate.kt | 51 ----------- .../CertificateProfileAdapterDelegate.kt | 89 +++++++++++++++++++ .../fragment/ProfileCertificatesFragment.kt | 8 +- .../drawable/bg_certificate_profile_item.xml | 30 +++++++ .../layout/fragment_profile_certificates.xml | 5 +- .../res/layout/item_certificate_profile.xml | 88 ++++++++++++++---- app/src/main/res/values/strings.xml | 5 ++ 7 files changed, 205 insertions(+), 71 deletions(-) delete mode 100644 app/src/main/java/org/stepik/android/view/certificate/ui/adapter/CertificateProfileAdapterDelegate.kt create mode 100644 app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt create mode 100644 app/src/main/res/drawable/bg_certificate_profile_item.xml diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/CertificateProfileAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/CertificateProfileAdapterDelegate.kt deleted file mode 100644 index d67c79d017..0000000000 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/CertificateProfileAdapterDelegate.kt +++ /dev/null @@ -1,51 +0,0 @@ -package org.stepik.android.view.certificate.ui.adapter - -import android.content.res.ColorStateList -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.widget.AppCompatTextView -import androidx.core.content.ContextCompat -import androidx.core.widget.TextViewCompat -import org.stepic.droid.R -import org.stepic.droid.model.CertificateViewItem -import org.stepik.android.model.Certificate -import ru.nobird.android.ui.adapterdelegates.AdapterDelegate -import ru.nobird.android.ui.adapterdelegates.DelegateViewHolder - -class CertificateProfileAdapterDelegate( - private val onItemClick: (String) -> Unit -) : AdapterDelegate>() { - override fun isForViewType(position: Int, data: CertificateViewItem): Boolean = - true - - override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = - ViewHolder(createView(parent, R.layout.item_certificate_profile)) - - private inner class ViewHolder( - root: View - ) : DelegateViewHolder(root) { - - private val certificateTextView = root as AppCompatTextView - - init { - root.setOnClickListener { onItemClick(itemData?.certificate?.url.orEmpty()) } - } - - override fun onBind(data: CertificateViewItem) { - certificateTextView.text = data.title.orEmpty() - - val tintColorRes = - when (data.certificate.type) { - Certificate.Type.REGULAR -> - R.color.certificate_regular - Certificate.Type.DISTINCTION -> - R.color.certificate_distinction - else -> - R.color.white - } - - TextViewCompat.setCompoundDrawableTintList(certificateTextView, - ColorStateList.valueOf(ContextCompat.getColor(context, tintColorRes))) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt new file mode 100644 index 0000000000..d8e87f0de9 --- /dev/null +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt @@ -0,0 +1,89 @@ +package org.stepik.android.view.certificate.ui.adapter.delegate + +import android.graphics.drawable.LayerDrawable +import android.graphics.drawable.RippleDrawable +import android.view.View +import android.view.ViewGroup +import androidx.core.content.ContextCompat +import androidx.core.view.isVisible +import by.kirich1409.viewbindingdelegate.viewBinding +import org.stepic.droid.databinding.ItemCertificateProfileBinding +import org.stepic.droid.model.CertificateViewItem +import ru.nobird.android.ui.adapterdelegates.AdapterDelegate +import ru.nobird.android.ui.adapterdelegates.DelegateViewHolder +import com.bumptech.glide.Glide +import org.stepic.droid.R +import org.stepik.android.model.Certificate +import org.stepik.android.view.step_quiz_choice.ui.delegate.LayerListDrawableDelegate + +class CertificateProfileAdapterDelegate( + private val onItemClick: (String) -> Unit +) : AdapterDelegate>() { + override fun isForViewType(position: Int, data: CertificateViewItem): Boolean = + true + + override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = + ViewHolder(createView(parent, R.layout.item_certificate_profile)) + + private inner class ViewHolder(root: View) : DelegateViewHolder(root) { + private val viewBinding: ItemCertificateProfileBinding by viewBinding { ItemCertificateProfileBinding.bind(root) } + private val layerListDrawableDelegate = LayerListDrawableDelegate( + listOf( + R.id.certificate_regular, + R.id.certificate_distinction + ), + (viewBinding.root.background as RippleDrawable).findDrawableByLayerId(R.id.certificate_layer_list) as LayerDrawable + ) + + init { + viewBinding.root.setOnClickListener { onItemClick(itemData?.certificate?.url.orEmpty()) } + } + + override fun onBind(data: CertificateViewItem) { + viewBinding.certificateCourseTitle.text = data.title.orEmpty() + + val certificateColor = + when (data.certificate.type) { + Certificate.Type.REGULAR -> + ContextCompat.getColor(context, R.color.certificate_regular) + Certificate.Type.DISTINCTION -> + ContextCompat.getColor(context, R.color.certificate_distinction) + else -> + ContextCompat.getColor(context, R.color.white) + } + + val hasGrade = data.certificate.grade != null + + viewBinding.certificateProgress.isVisible = hasGrade + viewBinding.certificateProgressPercentage.isVisible = hasGrade + viewBinding.certificateCourseTitle.maxLines = + if (hasGrade) { + 2 + } else { + 3 + } + + layerListDrawableDelegate.showLayer(getRootBackgroundLayer(data.certificate)) + viewBinding.certificateProgress.setIndicatorColor(certificateColor) + viewBinding.certificateProgress.max = 100 + viewBinding.certificateProgress.progress = data.certificate.grade?.toIntOrNull() ?: 0 + viewBinding.certificateProgressPercentage.setTextColor(certificateColor) + viewBinding.certificateProgressPercentage.text = context.getString(R.string.certificates_percentage, data.certificate.grade) + + Glide.with(context) + .load(data.coverFullPath) + .placeholder(ContextCompat.getDrawable(context, R.drawable.general_placeholder)) + .into(viewBinding.certificateCourseIcon) + } + + private fun getRootBackgroundLayer(certificate: Certificate): Int = + when (certificate.type) { + Certificate.Type.REGULAR -> + R.id.certificate_regular + Certificate.Type.DISTINCTION -> + R.id.certificate_distinction + else -> + throw IllegalArgumentException("Invalid certificate type") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt index c3d69453ad..c6fe190bfc 100644 --- a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt +++ b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt @@ -14,7 +14,7 @@ import org.stepic.droid.core.ScreenManager import org.stepic.droid.model.CertificateViewItem import org.stepik.android.presentation.profile_certificates.ProfileCertificatesPresenter import org.stepik.android.presentation.profile_certificates.ProfileCertificatesView -import org.stepik.android.view.certificate.ui.adapter.CertificateProfileAdapterDelegate +import org.stepik.android.view.certificate.ui.adapter.delegate.CertificateProfileAdapterDelegate import org.stepik.android.view.ui.delegate.ViewStateDelegate import ru.nobird.android.ui.adapters.DefaultDelegateAdapter import ru.nobird.android.view.base.ui.extension.argument @@ -74,7 +74,7 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica tryAgain.setOnClickListener { setDataToPresenter(forceUpdate = true) } profileCertificatesTitle.setOnClickListener { screenManager.showCertificates(requireContext(), profileId, isCurrentUser) } - profileCertificatesRecycler.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + profileCertificatesRecycler.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) profileCertificatesRecycler.isNestedScrollingEnabled = false profileCertificatesRecycler.adapter = certificatesAdapter @@ -108,12 +108,12 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica isCurrentUser = state.profileData.isCurrentUser } is ProfileCertificatesView.State.CertificatesCache -> { - certificatesAdapter.items = state.certificates.take(CERTIFICATES_TO_DISPLAY) + certificatesAdapter.items = state.certificates profileId = state.profileData.user.id isCurrentUser = state.profileData.isCurrentUser } is ProfileCertificatesView.State.CertificatesRemote -> { - certificatesAdapter.items = state.certificates.take(CERTIFICATES_TO_DISPLAY) + certificatesAdapter.items = state.certificates profileId = state.profileData.user.id isCurrentUser = state.profileData.isCurrentUser } diff --git a/app/src/main/res/drawable/bg_certificate_profile_item.xml b/app/src/main/res/drawable/bg_certificate_profile_item.xml new file mode 100644 index 0000000000..9de406e7fe --- /dev/null +++ b/app/src/main/res/drawable/bg_certificate_profile_item.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_profile_certificates.xml b/app/src/main/res/layout/fragment_profile_certificates.xml index 84c8498dbe..bd29ec787e 100644 --- a/app/src/main/res/layout/fragment_profile_certificates.xml +++ b/app/src/main/res/layout/fragment_profile_certificates.xml @@ -45,8 +45,11 @@ diff --git a/app/src/main/res/layout/item_certificate_profile.xml b/app/src/main/res/layout/item_certificate_profile.xml index 3f233acca6..5dc513c64b 100644 --- a/app/src/main/res/layout/item_certificate_profile.xml +++ b/app/src/main/res/layout/item_certificate_profile.xml @@ -1,19 +1,77 @@ - \ No newline at end of file + android:layout_marginLeft="8dp" + android:layout_marginRight="8dp" + android:background="@drawable/bg_certificate_profile_item" + android:minHeight="104dp" + android:padding="8dp"> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fae66c0821..56266d634d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1296,4 +1296,9 @@ Help center https://support.stepik.org/hc/en-us Version: %s + + + %s%% + Certificate + Certificate with distinction From c2f59dd50a86ed30a2abdc9fcb6b9ab4506713cd Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Fri, 21 Jan 2022 16:32:05 +0300 Subject: [PATCH 07/18] Add isWithScore field to Certificate model --- .../droid/storage/migration/MigrationFrom78To79.kt | 2 ++ .../android/cache/certificates/dao/CertificateDaoImpl.kt | 9 ++++----- .../certificates/structure/DbStructureCertificate.kt | 1 + .../main/java/org/stepik/android/model/Certificate.kt | 4 +++- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt index 22bb4f7238..6f3ae03bb4 100644 --- a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt +++ b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt @@ -3,9 +3,11 @@ package org.stepic.droid.storage.migration import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase import org.stepic.droid.storage.structure.DbStructureCourse +import org.stepik.android.cache.certificates.structure.DbStructureCertificate object MigrationFrom78To79 : Migration(78, 79) { override fun migrate(db: SupportSQLiteDatabase) { + db.execSQL("ALTER TABLE ${DbStructureCertificate.TABLE_NAME} ADD COLUMN ${DbStructureCertificate.Columns.IS_WITH_SCORE} INTEGER") db.execSQL("ALTER TABLE ${DbStructureCourse.TABLE_NAME} ADD COLUMN ${DbStructureCourse.Columns.ANNOUNCEMENTS} TEXT") db.execSQL("CREATE TABLE IF NOT EXISTS `Announcement` (`id` INTEGER NOT NULL, `course` INTEGER NOT NULL, `user` INTEGER, `subject` TEXT NOT NULL, `text` TEXT NOT NULL, `createDate` INTEGER, `nextDate` INTEGER, `sentDate` INTEGER, `status` TEXT NOT NULL, `isRestrictedByScore` INTEGER NOT NULL, `scorePercentMin` INTEGER NOT NULL, `scorePercentMax` INTEGER NOT NULL, `emailTemplate` TEXT, `isScheduled` INTEGER NOT NULL, `startDate` INTEGER, `mailPeriodDays` INTEGER NOT NULL, `mailQuantity` INTEGER NOT NULL, `isInfinite` INTEGER NOT NULL, `onEnroll` INTEGER NOT NULL, `publishCount` INTEGER, `queueCount` INTEGER, `sentCount` INTEGER, `openCount` INTEGER, `clickCount` INTEGER, `estimatedStartDate` INTEGER, `estimatedFinishDate` INTEGER, `noticeDates` TEXT NOT NULL, PRIMARY KEY(`id`))") } diff --git a/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt b/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt index f3b0393187..8c1d64be7f 100644 --- a/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt +++ b/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt @@ -4,10 +4,7 @@ import android.content.ContentValues import android.database.Cursor import org.stepic.droid.storage.dao.DaoBase import org.stepic.droid.storage.operations.DatabaseOperations -import org.stepic.droid.util.getDate -import org.stepic.droid.util.getInt -import org.stepic.droid.util.getLong -import org.stepic.droid.util.getString +import org.stepic.droid.util.* import org.stepik.android.cache.certificates.structure.DbStructureCertificate import org.stepik.android.model.Certificate import javax.inject.Inject @@ -43,7 +40,8 @@ constructor( previewUrl = cursor.getString(DbStructureCertificate.Columns.PREVIEW_URL), savedFullName = cursor.getString(DbStructureCertificate.Columns.SAVED_FULLNAME), editsCount = cursor.getInt(DbStructureCertificate.Columns.EDITS_COUNT), - allowedEditsCount = cursor.getInt(DbStructureCertificate.Columns.ALLOWED_EDITS_COUNT) + allowedEditsCount = cursor.getInt(DbStructureCertificate.Columns.ALLOWED_EDITS_COUNT), + isWithScore = cursor.getBoolean(DbStructureCertificate.Columns.IS_WITH_SCORE) ) override fun getContentValues(persistentObject: Certificate): ContentValues = @@ -63,5 +61,6 @@ constructor( put(DbStructureCertificate.Columns.SAVED_FULLNAME, persistentObject.savedFullName) put(DbStructureCertificate.Columns.EDITS_COUNT, persistentObject.editsCount) put(DbStructureCertificate.Columns.ALLOWED_EDITS_COUNT, persistentObject.allowedEditsCount) + put(DbStructureCertificate.Columns.IS_WITH_SCORE, persistentObject.isWithScore) } } \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/cache/certificates/structure/DbStructureCertificate.kt b/app/src/main/java/org/stepik/android/cache/certificates/structure/DbStructureCertificate.kt index 9c1772edce..ede3a2a36b 100644 --- a/app/src/main/java/org/stepik/android/cache/certificates/structure/DbStructureCertificate.kt +++ b/app/src/main/java/org/stepik/android/cache/certificates/structure/DbStructureCertificate.kt @@ -22,6 +22,7 @@ object DbStructureCertificate { const val SAVED_FULLNAME = "saved_fullname" const val EDITS_COUNT = "edits_count" const val ALLOWED_EDITS_COUNT = "allowed_edits_count" + const val IS_WITH_SCORE = "is_with_score" } fun createTable(db: SupportSQLiteDatabase) { diff --git a/model/src/main/java/org/stepik/android/model/Certificate.kt b/model/src/main/java/org/stepik/android/model/Certificate.kt index f48106123a..b5151179ab 100644 --- a/model/src/main/java/org/stepik/android/model/Certificate.kt +++ b/model/src/main/java/org/stepik/android/model/Certificate.kt @@ -40,7 +40,9 @@ data class Certificate( @SerializedName("edits_count") val editsCount: Int, @SerializedName("allowed_edits_count") - val allowedEditsCount: Int + val allowedEditsCount: Int, + @SerializedName("is_with_score") + val isWithScore: Boolean ) : Parcelable { /* From ff742f570a2b8b3d75315d4e2bed84b278950ab8 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Fri, 21 Jan 2022 17:24:01 +0300 Subject: [PATCH 08/18] Fix certificate grade visibility --- .../android/cache/certificates/dao/CertificateDaoImpl.kt | 6 +++++- .../adapter/delegate/CertificateProfileAdapterDelegate.kt | 2 +- .../ui/adapter/delegate/CertificatesAdapterDelegate.kt | 1 + app/src/main/res/layout/item_certificate_profile.xml | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt b/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt index 8c1d64be7f..2de8492834 100644 --- a/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt +++ b/app/src/main/java/org/stepik/android/cache/certificates/dao/CertificateDaoImpl.kt @@ -4,7 +4,11 @@ import android.content.ContentValues import android.database.Cursor import org.stepic.droid.storage.dao.DaoBase import org.stepic.droid.storage.operations.DatabaseOperations -import org.stepic.droid.util.* +import org.stepic.droid.util.getDate +import org.stepic.droid.util.getInt +import org.stepic.droid.util.getLong +import org.stepic.droid.util.getString +import org.stepic.droid.util.getBoolean import org.stepik.android.cache.certificates.structure.DbStructureCertificate import org.stepik.android.model.Certificate import javax.inject.Inject diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt index d8e87f0de9..73036b6536 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt @@ -52,7 +52,7 @@ class CertificateProfileAdapterDelegate( ContextCompat.getColor(context, R.color.white) } - val hasGrade = data.certificate.grade != null + val hasGrade = data.certificate.isWithScore viewBinding.certificateProgress.isVisible = hasGrade viewBinding.certificateProgressPercentage.isVisible = hasGrade diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt index c861a93b6f..f6dff0a3e9 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt @@ -60,6 +60,7 @@ class CertificatesAdapterDelegate( certificateGradeView.text = context.resources.getString(R.string.certificate_result_with_substitution, data.certificate.grade ?: "") + certificateGradeView.isVisible = data.certificate.isWithScore certificateNameChangeButton.isVisible = data.certificate.editsCount < data.certificate.allowedEditsCount && isCurrentUser Glide.with(context) diff --git a/app/src/main/res/layout/item_certificate_profile.xml b/app/src/main/res/layout/item_certificate_profile.xml index 5dc513c64b..26e0eb660b 100644 --- a/app/src/main/res/layout/item_certificate_profile.xml +++ b/app/src/main/res/layout/item_certificate_profile.xml @@ -7,7 +7,7 @@ android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:background="@drawable/bg_certificate_profile_item" - android:minHeight="104dp" + android:minHeight="114dp" android:padding="8dp"> Date: Fri, 21 Jan 2022 17:33:57 +0300 Subject: [PATCH 09/18] Set certificate score visible by default --- .../org/stepic/droid/storage/migration/MigrationFrom78To79.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt index 6f3ae03bb4..2ea7d651c9 100644 --- a/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt +++ b/app/src/main/java/org/stepic/droid/storage/migration/MigrationFrom78To79.kt @@ -7,7 +7,7 @@ import org.stepik.android.cache.certificates.structure.DbStructureCertificate object MigrationFrom78To79 : Migration(78, 79) { override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE ${DbStructureCertificate.TABLE_NAME} ADD COLUMN ${DbStructureCertificate.Columns.IS_WITH_SCORE} INTEGER") + db.execSQL("ALTER TABLE ${DbStructureCertificate.TABLE_NAME} ADD COLUMN ${DbStructureCertificate.Columns.IS_WITH_SCORE} INTEGER DEFAULT 1") db.execSQL("ALTER TABLE ${DbStructureCourse.TABLE_NAME} ADD COLUMN ${DbStructureCourse.Columns.ANNOUNCEMENTS} TEXT") db.execSQL("CREATE TABLE IF NOT EXISTS `Announcement` (`id` INTEGER NOT NULL, `course` INTEGER NOT NULL, `user` INTEGER, `subject` TEXT NOT NULL, `text` TEXT NOT NULL, `createDate` INTEGER, `nextDate` INTEGER, `sentDate` INTEGER, `status` TEXT NOT NULL, `isRestrictedByScore` INTEGER NOT NULL, `scorePercentMin` INTEGER NOT NULL, `scorePercentMax` INTEGER NOT NULL, `emailTemplate` TEXT, `isScheduled` INTEGER NOT NULL, `startDate` INTEGER, `mailPeriodDays` INTEGER NOT NULL, `mailQuantity` INTEGER NOT NULL, `isInfinite` INTEGER NOT NULL, `onEnroll` INTEGER NOT NULL, `publishCount` INTEGER, `queueCount` INTEGER, `sentCount` INTEGER, `openCount` INTEGER, `clickCount` INTEGER, `estimatedStartDate` INTEGER, `estimatedFinishDate` INTEGER, `noticeDates` TEXT NOT NULL, PRIMARY KEY(`id`))") } From 9ac62b515fa305d9a7c6a443c9b474a0444a44e8 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Fri, 21 Jan 2022 19:37:08 +0300 Subject: [PATCH 10/18] Refactor CertificateViewItem, add Placeholder and Data variants --- .../org/stepic/droid/core/ScreenManager.java | 4 +-- .../stepic/droid/core/ScreenManagerImpl.java | 8 ++--- .../java/org/stepic/droid/core/ShareHelper.kt | 4 +-- .../org/stepic/droid/core/ShareHelperImpl.kt | 6 ++-- .../stepic/droid/model/CertificateListItem.kt | 17 +++++++++ .../stepic/droid/model/CertificateViewItem.kt | 35 ------------------- .../ui/dialogs/CertificateShareDialog.java | 14 ++++---- .../CertificateShareDialogFragment.java | 6 ++-- .../interactor/CertificatesInteractor.kt | 6 ++-- .../certificate/CertificatesPresenter.kt | 14 ++++---- .../certificate/CertificatesView.kt | 8 ++--- .../ProfileCertificatesView.kt | 6 ++-- .../ui/activity/CertificatesActivity.kt | 10 +++--- .../CertificateProfileAdapterDelegate.kt | 17 ++++----- .../delegate/CertificatesAdapterDelegate.kt | 25 ++++++------- .../fragment/ProfileCertificatesFragment.kt | 6 ++-- 16 files changed, 84 insertions(+), 102 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/model/CertificateListItem.kt delete mode 100644 app/src/main/java/org/stepic/droid/model/CertificateViewItem.kt diff --git a/app/src/main/java/org/stepic/droid/core/ScreenManager.java b/app/src/main/java/org/stepic/droid/core/ScreenManager.java index 53276d9e2b..aaf875d92c 100644 --- a/app/src/main/java/org/stepic/droid/core/ScreenManager.java +++ b/app/src/main/java/org/stepic/droid/core/ScreenManager.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.stepic.droid.model.CertificateViewItem; +import org.stepic.droid.model.CertificateListItem; import org.stepic.droid.social.SocialMedia; import org.stepik.android.domain.auth.model.SocialAuthType; import org.stepik.android.domain.course.analytic.CourseViewSource; @@ -91,7 +91,7 @@ public interface ScreenManager { void openInWeb(Activity context, String path); - void addCertificateToLinkedIn(CertificateViewItem certificateViewItem); + void addCertificateToLinkedIn(CertificateListItem.Data certificateListItem); void showCertificates(Context context); diff --git a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java index 586729b6c3..739d913505 100644 --- a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java +++ b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java @@ -33,7 +33,7 @@ import org.stepic.droid.configuration.EndpointResolver; import org.stepic.droid.configuration.Config; import org.stepic.droid.di.AppSingleton; -import org.stepic.droid.model.CertificateViewItem; +import org.stepic.droid.model.CertificateListItem; import org.stepic.droid.preferences.SharedPreferenceHelper; import org.stepic.droid.preferences.UserPreferences; import org.stepic.droid.social.SocialMedia; @@ -531,7 +531,7 @@ public void openInWeb(Activity context, String path) { } @Override - public void addCertificateToLinkedIn(CertificateViewItem certificateViewItem) { + public void addCertificateToLinkedIn(CertificateListItem.Data certificateListItem) { // TODO: 19/10/2017 linkedin exporting is not working due to changing API params is not filled StringBuilder sb = new StringBuilder(); @@ -539,9 +539,9 @@ public void addCertificateToLinkedIn(CertificateViewItem certificateViewItem) { sb.append("_ed=");//linkedin id parameter sb.append(AppConstants.LINKEDIN_ED_ID); sb.append("&pfCertificationName="); // linkedin cert name - sb.append(URLEncoder.encode(certificateViewItem.getTitle())); + sb.append(URLEncoder.encode(certificateListItem.getTitle())); sb.append("&pfCertificationUrl=");//linkedin certificate url - sb.append(certificateViewItem.getCertificate().getUrl()); + sb.append(certificateListItem.getCertificate().getUrl()); final Intent intent = new Intent(Intent.ACTION_VIEW); diff --git a/app/src/main/java/org/stepic/droid/core/ShareHelper.kt b/app/src/main/java/org/stepic/droid/core/ShareHelper.kt index b1e75c8521..00ac70f60e 100644 --- a/app/src/main/java/org/stepic/droid/core/ShareHelper.kt +++ b/app/src/main/java/org/stepic/droid/core/ShareHelper.kt @@ -1,7 +1,7 @@ package org.stepic.droid.core import android.content.Intent -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepik.android.model.* import org.stepik.android.model.Unit import org.stepik.android.model.user.User @@ -9,7 +9,7 @@ import org.stepik.android.model.user.User interface ShareHelper { fun getIntentForCourseSharing(course: Course): Intent - fun getIntentForShareCertificate(certificateViewItem: CertificateViewItem): Intent + fun getIntentForShareCertificate(certificateListItem: CertificateListItem.Data): Intent fun getIntentForStepSharing(step: Step, lesson: Lesson, unit: Unit?): Intent diff --git a/app/src/main/java/org/stepic/droid/core/ShareHelperImpl.kt b/app/src/main/java/org/stepic/droid/core/ShareHelperImpl.kt index 02252d1f60..d17dd5ec6e 100644 --- a/app/src/main/java/org/stepic/droid/core/ShareHelperImpl.kt +++ b/app/src/main/java/org/stepic/droid/core/ShareHelperImpl.kt @@ -6,7 +6,7 @@ import android.net.Uri import org.stepic.droid.R import org.stepic.droid.configuration.EndpointResolver import org.stepic.droid.di.AppSingleton -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepic.droid.util.StringUtil import org.stepic.droid.util.resolvers.text.TextResolver import org.stepik.android.model.* @@ -46,8 +46,8 @@ constructor( return getShareIntentBase(textForSharing) } - override fun getIntentForShareCertificate(certificateViewItem: CertificateViewItem): Intent = - getShareIntentBase(certificateViewItem.certificate.url ?: " ") + override fun getIntentForShareCertificate(certificateListItem: CertificateListItem.Data): Intent = + getShareIntentBase(certificateListItem.certificate.url ?: " ") override fun getIntentForStepSharing(step: Step, lesson: Lesson, unit: Unit?): Intent { val textForSharing = Uri.parse(StringUtil.getUriForStep(endpointResolver.getBaseUrl(), lesson, unit, step)).toString() diff --git a/app/src/main/java/org/stepic/droid/model/CertificateListItem.kt b/app/src/main/java/org/stepic/droid/model/CertificateListItem.kt new file mode 100644 index 0000000000..799e065bf6 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/model/CertificateListItem.kt @@ -0,0 +1,17 @@ +package org.stepic.droid.model + +import android.os.Parcelable +import kotlinx.android.parcel.Parcelize +import org.stepik.android.model.Certificate + +sealed class CertificateListItem : Parcelable { + @Parcelize + data class Data( + val certificate: Certificate, + val title: String?, + val coverFullPath: String? + ) : CertificateListItem() + + @Parcelize + object Placeholder : CertificateListItem() +} diff --git a/app/src/main/java/org/stepic/droid/model/CertificateViewItem.kt b/app/src/main/java/org/stepic/droid/model/CertificateViewItem.kt deleted file mode 100644 index cbc3a3455c..0000000000 --- a/app/src/main/java/org/stepic/droid/model/CertificateViewItem.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.stepic.droid.model - -import android.os.Parcel -import android.os.Parcelable -import org.stepik.android.model.Certificate - -data class CertificateViewItem( - val certificate: Certificate, - val title: String?, - val coverFullPath: String? -): Parcelable { - - override fun describeContents() = 0 - - override fun writeToParcel(dest: Parcel, flags: Int) { - dest.writeParcelable(certificate, flags) - dest.writeString(title) - dest.writeString(coverFullPath) - } - - companion object { - @JvmField val CREATOR: Parcelable.Creator = object : Parcelable.Creator { - override fun createFromParcel(source: Parcel): CertificateViewItem = - CertificateViewItem( - source.readParcelable(Certificate::class.java.classLoader)!!, - source.readString(), - source.readString() - ) - - override fun newArray(size: Int): Array { - return arrayOfNulls(size) - } - } - } -} diff --git a/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialog.java b/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialog.java index 1f67507aa9..4e2de96ba7 100644 --- a/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialog.java +++ b/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialog.java @@ -16,7 +16,7 @@ import org.stepic.droid.base.App; import org.stepic.droid.core.ScreenManager; import org.stepic.droid.core.ShareHelper; -import org.stepic.droid.model.CertificateViewItem; +import org.stepic.droid.model.CertificateListItem; import org.stepic.droid.util.ContextExtensionsKt; import org.stepic.droid.util.DisplayUtils; @@ -25,7 +25,7 @@ public class CertificateShareDialog extends BottomSheetDialog { @NotNull - private final CertificateViewItem certificateViewItem; + private final CertificateListItem.Data certificateListItem; @Inject ScreenManager screenManager; @@ -36,9 +36,9 @@ public class CertificateShareDialog extends BottomSheetDialog { @Inject Analytic analytic; - public CertificateShareDialog(@NonNull Context context, @NotNull CertificateViewItem certificateViewItem) { + public CertificateShareDialog(@NonNull Context context, @NotNull CertificateListItem.Data certificateListItem) { super(context); - this.certificateViewItem = certificateViewItem; + this.certificateListItem = certificateListItem; App.Companion.component().inject(this); } @@ -61,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onClick(View view) { dismiss(); - screenManager.addCertificateToLinkedIn(certificateViewItem); + screenManager.addCertificateToLinkedIn(certificateListItem); } }); @@ -73,7 +73,7 @@ public void onClick(View view) { ContextExtensionsKt.copyTextToClipboard( getContext(), App.Companion.getAppContext().getString(R.string.copy_link_title), - certificateViewItem.getCertificate().getUrl(), + certificateListItem.getCertificate().getUrl(), getContext().getResources().getString(R.string.link_copied_title) ); } @@ -84,7 +84,7 @@ public void onClick(View view) { public void onClick(View view) { dismiss(); analytic.reportEvent(Analytic.Certificate.SHARE_LINK_CERTIFICATE); - Intent intent = shareHelper.getIntentForShareCertificate(certificateViewItem); + Intent intent = shareHelper.getIntentForShareCertificate(certificateListItem); getContext().startActivity(intent); } }); diff --git a/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialogFragment.java b/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialogFragment.java index 85900f4354..c03a1b5e4b 100644 --- a/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialogFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/dialogs/CertificateShareDialogFragment.java @@ -7,14 +7,14 @@ import androidx.fragment.app.DialogFragment; import org.jetbrains.annotations.NotNull; -import org.stepic.droid.model.CertificateViewItem; +import org.stepic.droid.model.CertificateListItem; public class CertificateShareDialogFragment extends DialogFragment { public static final String TAG = "certificate_share_dialog"; private static final String CERTIFICATE_VIEW_ITEM_KEY = "certificateViewItemKey"; - public static DialogFragment newInstance(@NotNull CertificateViewItem viewItem) { + public static DialogFragment newInstance(@NotNull CertificateListItem.Data viewItem) { Bundle args = new Bundle(); args.putParcelable(CERTIFICATE_VIEW_ITEM_KEY, viewItem); DialogFragment fragment = new CertificateShareDialogFragment(); @@ -25,7 +25,7 @@ public static DialogFragment newInstance(@NotNull CertificateViewItem viewItem) @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { - CertificateViewItem viewItem = getArguments().getParcelable(CERTIFICATE_VIEW_ITEM_KEY); + CertificateListItem.Data viewItem = getArguments().getParcelable(CERTIFICATE_VIEW_ITEM_KEY); return new CertificateShareDialog(getContext(), viewItem); } diff --git a/app/src/main/java/org/stepik/android/domain/certificate/interactor/CertificatesInteractor.kt b/app/src/main/java/org/stepik/android/domain/certificate/interactor/CertificatesInteractor.kt index 7f6f8c8d70..6a2fb2f61a 100644 --- a/app/src/main/java/org/stepik/android/domain/certificate/interactor/CertificatesInteractor.kt +++ b/app/src/main/java/org/stepik/android/domain/certificate/interactor/CertificatesInteractor.kt @@ -1,7 +1,7 @@ package org.stepik.android.domain.certificate.interactor import io.reactivex.Single -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import ru.nobird.android.core.model.PagedList import org.stepik.android.domain.base.DataSourceType import org.stepik.android.domain.certificate.repository.CertificateRepository @@ -16,7 +16,7 @@ constructor( private val certificateRepository: CertificateRepository, private val courseRepository: CourseRepository ) { - fun getCertificates(userId: Long, page: Int = 1, sourceType: DataSourceType = DataSourceType.CACHE): Single> = + fun getCertificates(userId: Long, page: Int = 1, sourceType: DataSourceType = DataSourceType.CACHE): Single> = certificateRepository.getCertificates(userId, page, sourceType) .flatMap { certificates -> val courseIds = @@ -30,7 +30,7 @@ constructor( PagedList( certificates.map { certificate -> - CertificateViewItem( + CertificateListItem.Data( certificate, coursesMap[certificate.course]?.title, coursesMap[certificate.course]?.cover diff --git a/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesPresenter.kt b/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesPresenter.kt index 58085a620c..815ffcdcb4 100644 --- a/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesPresenter.kt +++ b/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesPresenter.kt @@ -8,7 +8,7 @@ import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.subscribeBy import org.stepic.droid.di.qualifiers.BackgroundScheduler import org.stepic.droid.di.qualifiers.MainScheduler -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import ru.nobird.android.core.model.PagedList import ru.nobird.android.core.model.concatWithPagedList import org.stepik.android.domain.base.DataSourceType @@ -83,12 +83,12 @@ constructor( oldState.certificates oldState is CertificatesView.State.CertificatesCache -> - emptyList() + emptyList() else -> return } - val nextPage = (currentItems as? PagedList) + val nextPage = (currentItems as? PagedList) ?.page ?.plus(1) ?: 1 @@ -158,11 +158,11 @@ constructor( .subscribeBy( onSuccess = { updatedCertificate -> val updatedItems = currentItems.transform { - map { certificateViewItem -> - if (certificateViewItem.certificate.id == updatedCertificate.id) { - certificateViewItem.copy(certificate = updatedCertificate) + map { certificateListItem -> + if (certificateListItem.certificate.id == updatedCertificate.id) { + certificateListItem.copy(certificate = updatedCertificate) } else { - certificateViewItem + certificateListItem } } } diff --git a/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesView.kt b/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesView.kt index 20cffb5f30..f6e812cc18 100644 --- a/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesView.kt +++ b/app/src/main/java/org/stepik/android/presentation/certificate/CertificatesView.kt @@ -1,6 +1,6 @@ package org.stepik.android.presentation.certificate -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepik.android.model.Certificate import ru.nobird.android.core.model.PagedList @@ -11,9 +11,9 @@ interface CertificatesView { object EmptyCertificates : State() object NetworkError : State() - class CertificatesCache(val certificates: PagedList) : State() - class CertificatesRemote(val certificates: PagedList) : State() - class CertificatesRemoteLoading(val certificates: PagedList) : State() + class CertificatesCache(val certificates: PagedList) : State() + class CertificatesRemote(val certificates: PagedList) : State() + class CertificatesRemoteLoading(val certificates: PagedList) : State() } fun setState(state: State) diff --git a/app/src/main/java/org/stepik/android/presentation/profile_certificates/ProfileCertificatesView.kt b/app/src/main/java/org/stepik/android/presentation/profile_certificates/ProfileCertificatesView.kt index 88a18702d6..4dc9b294a1 100644 --- a/app/src/main/java/org/stepik/android/presentation/profile_certificates/ProfileCertificatesView.kt +++ b/app/src/main/java/org/stepik/android/presentation/profile_certificates/ProfileCertificatesView.kt @@ -1,6 +1,6 @@ package org.stepik.android.presentation.profile_certificates -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepik.android.domain.profile.model.ProfileData interface ProfileCertificatesView { @@ -8,8 +8,8 @@ interface ProfileCertificatesView { object Idle : State() object SilentLoading : State() class Loading(val profileData: ProfileData) : State() - class CertificatesCache(val certificates: List, val profileData: ProfileData) : State() - class CertificatesRemote(val certificates: List, val profileData: ProfileData) : State() + class CertificatesCache(val certificates: List, val profileData: ProfileData) : State() + class CertificatesRemote(val certificates: List, val profileData: ProfileData) : State() object Error : State() object NoCertificates : State() } diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/activity/CertificatesActivity.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/activity/CertificatesActivity.kt index 9c95c4fb53..6dc00534b2 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/activity/CertificatesActivity.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/activity/CertificatesActivity.kt @@ -15,7 +15,7 @@ import kotlinx.android.synthetic.main.progress_bar_on_empty_screen.* import org.stepic.droid.R import org.stepic.droid.base.App import org.stepic.droid.base.FragmentActivityBase -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepic.droid.ui.dialogs.CertificateShareDialogFragment import org.stepic.droid.ui.dialogs.LoadingProgressDialogFragment import org.stepic.droid.ui.util.initCenteredToolbar @@ -57,7 +57,7 @@ class CertificatesActivity : private val certificatesPresenter: CertificatesPresenter by viewModels { viewModelFactory } - private var certificatesAdapter: DefaultDelegateAdapter = DefaultDelegateAdapter() + private var certificatesAdapter: DefaultDelegateAdapter = DefaultDelegateAdapter() private val progressDialogFragment: DialogFragment = LoadingProgressDialogFragment.newInstance() @@ -174,12 +174,12 @@ class CertificatesActivity : showChangeNameDialog(certificate, attemptedFullName) } - private fun onNeedShowShareDialog(certificateViewItem: CertificateViewItem?) { - if (certificateViewItem == null) { + private fun onNeedShowShareDialog(certificateListItem: CertificateListItem.Data?) { + if (certificateListItem == null) { return } CertificateShareDialogFragment - .newInstance(certificateViewItem) + .newInstance(certificateListItem) .showIfNotExists(supportFragmentManager, CertificateShareDialogFragment.TAG) } diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt index 73036b6536..3ccfaa94c4 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt @@ -8,24 +8,24 @@ import androidx.core.content.ContextCompat import androidx.core.view.isVisible import by.kirich1409.viewbindingdelegate.viewBinding import org.stepic.droid.databinding.ItemCertificateProfileBinding -import org.stepic.droid.model.CertificateViewItem import ru.nobird.android.ui.adapterdelegates.AdapterDelegate import ru.nobird.android.ui.adapterdelegates.DelegateViewHolder import com.bumptech.glide.Glide import org.stepic.droid.R +import org.stepic.droid.model.CertificateListItem import org.stepik.android.model.Certificate import org.stepik.android.view.step_quiz_choice.ui.delegate.LayerListDrawableDelegate class CertificateProfileAdapterDelegate( private val onItemClick: (String) -> Unit -) : AdapterDelegate>() { - override fun isForViewType(position: Int, data: CertificateViewItem): Boolean = - true +) : AdapterDelegate>() { + override fun isForViewType(position: Int, data: CertificateListItem): Boolean = + data is CertificateListItem.Data - override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = + override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = ViewHolder(createView(parent, R.layout.item_certificate_profile)) - private inner class ViewHolder(root: View) : DelegateViewHolder(root) { + private inner class ViewHolder(root: View) : DelegateViewHolder(root) { private val viewBinding: ItemCertificateProfileBinding by viewBinding { ItemCertificateProfileBinding.bind(root) } private val layerListDrawableDelegate = LayerListDrawableDelegate( listOf( @@ -36,10 +36,11 @@ class CertificateProfileAdapterDelegate( ) init { - viewBinding.root.setOnClickListener { onItemClick(itemData?.certificate?.url.orEmpty()) } + viewBinding.root.setOnClickListener { (itemData as? CertificateListItem.Data)?.let { onItemClick(it.certificate.url.orEmpty()) } } } - override fun onBind(data: CertificateViewItem) { + override fun onBind(data: CertificateListItem) { + data as CertificateListItem.Data viewBinding.certificateCourseTitle.text = data.title.orEmpty() val certificateColor = diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt index f6dff0a3e9..a85691fd82 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesAdapterDelegate.kt @@ -7,26 +7,26 @@ import androidx.core.view.isVisible import com.bumptech.glide.Glide import kotlinx.android.synthetic.main.certificate_item.view.* import org.stepic.droid.R -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepik.android.model.Certificate import ru.nobird.android.ui.adapterdelegates.AdapterDelegate import ru.nobird.android.ui.adapterdelegates.DelegateViewHolder class CertificatesAdapterDelegate( private val onItemClick: (String) -> Unit, - private val onShareButtonClick: (CertificateViewItem) -> Unit, - private val onChangeNameClick: (CertificateViewItem) -> Unit, + private val onShareButtonClick: (CertificateListItem.Data) -> Unit, + private val onChangeNameClick: (CertificateListItem.Data) -> Unit, private val isCurrentUser: Boolean -) : AdapterDelegate>() { - override fun isForViewType(position: Int, data: CertificateViewItem): Boolean = - true +) : AdapterDelegate>() { + override fun isForViewType(position: Int, data: CertificateListItem): Boolean = + data is CertificateListItem.Data - override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = + override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = ViewHolder(createView(parent, R.layout.certificate_item)) private inner class ViewHolder( root: View - ) : DelegateViewHolder(root) { + ) : DelegateViewHolder(root) { private val certificateTitleView = root.certificate_title private val certificateIcon = root.certificate_icon @@ -39,12 +39,13 @@ class CertificatesAdapterDelegate( ContextCompat.getDrawable(context, R.drawable.general_placeholder) init { - root.setOnClickListener { onItemClick(itemData?.certificate?.url ?: "") } - certificateShareButton.setOnClickListener { onShareButtonClick(itemData as CertificateViewItem) } - certificateNameChangeButton.setOnClickListener { itemData?.let(onChangeNameClick) } + root.setOnClickListener { (itemData as? CertificateListItem.Data)?.let { onItemClick(it.certificate.url ?: "") } } + certificateShareButton.setOnClickListener { onShareButtonClick(itemData as CertificateListItem.Data) } + certificateNameChangeButton.setOnClickListener { (itemData as? CertificateListItem.Data)?.let(onChangeNameClick) } } - override fun onBind(data: CertificateViewItem) { + override fun onBind(data: CertificateListItem) { + data as CertificateListItem.Data certificateTitleView.text = data.title ?: "" certificateDescription.text = diff --git a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt index c6fe190bfc..339ac63ebb 100644 --- a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt +++ b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt @@ -11,7 +11,7 @@ import kotlinx.android.synthetic.main.fragment_profile_certificates.* import org.stepic.droid.R import org.stepic.droid.base.App import org.stepic.droid.core.ScreenManager -import org.stepic.droid.model.CertificateViewItem +import org.stepic.droid.model.CertificateListItem import org.stepik.android.presentation.profile_certificates.ProfileCertificatesPresenter import org.stepik.android.presentation.profile_certificates.ProfileCertificatesView import org.stepik.android.view.certificate.ui.adapter.delegate.CertificateProfileAdapterDelegate @@ -22,8 +22,6 @@ import javax.inject.Inject class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certificates), ProfileCertificatesView { companion object { - private const val CERTIFICATES_TO_DISPLAY = 4 - fun newInstance(userId: Long): Fragment = ProfileCertificatesFragment() .apply { @@ -42,7 +40,7 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica private val certificatesPresenter: ProfileCertificatesPresenter by viewModels { viewModelFactory } private lateinit var viewStateDelegate: ViewStateDelegate - private lateinit var certificatesAdapter: DefaultDelegateAdapter + private lateinit var certificatesAdapter: DefaultDelegateAdapter private var profileId = 0L From 92bdc07656e412ca686b234a6ff98a553c05156b Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Fri, 21 Jan 2022 20:38:46 +0300 Subject: [PATCH 11/18] Add profile certificates skeleton --- ...icatesProfilePlaceholderAdapterDelegate.kt | 18 +++++++ .../fragment/ProfileCertificatesFragment.kt | 7 +++ .../item_certificate_profile_skeleton.xml | 49 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesProfilePlaceholderAdapterDelegate.kt create mode 100644 app/src/main/res/layout/item_certificate_profile_skeleton.xml diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesProfilePlaceholderAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesProfilePlaceholderAdapterDelegate.kt new file mode 100644 index 0000000000..80948305d0 --- /dev/null +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificatesProfilePlaceholderAdapterDelegate.kt @@ -0,0 +1,18 @@ +package org.stepik.android.view.certificate.ui.adapter.delegate + +import android.view.View +import android.view.ViewGroup +import org.stepic.droid.R +import org.stepic.droid.model.CertificateListItem +import ru.nobird.android.ui.adapterdelegates.AdapterDelegate +import ru.nobird.android.ui.adapterdelegates.DelegateViewHolder + +class CertificatesProfilePlaceholderAdapterDelegate : AdapterDelegate>() { + override fun isForViewType(position: Int, data: CertificateListItem): Boolean = + data is CertificateListItem.Placeholder + + override fun onCreateViewHolder(parent: ViewGroup): DelegateViewHolder = + ViewHolder(createView(parent, R.layout.item_certificate_profile_skeleton)) + + private class ViewHolder(root: View) : DelegateViewHolder(root) +} \ No newline at end of file diff --git a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt index 339ac63ebb..36e1a99982 100644 --- a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt +++ b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt @@ -15,6 +15,7 @@ import org.stepic.droid.model.CertificateListItem import org.stepik.android.presentation.profile_certificates.ProfileCertificatesPresenter import org.stepik.android.presentation.profile_certificates.ProfileCertificatesView import org.stepik.android.view.certificate.ui.adapter.delegate.CertificateProfileAdapterDelegate +import org.stepik.android.view.certificate.ui.adapter.delegate.CertificatesProfilePlaceholderAdapterDelegate import org.stepik.android.view.ui.delegate.ViewStateDelegate import ru.nobird.android.ui.adapters.DefaultDelegateAdapter import ru.nobird.android.view.base.ui.extension.argument @@ -50,6 +51,7 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica injectComponent() certificatesAdapter = DefaultDelegateAdapter() + certificatesAdapter += CertificatesProfilePlaceholderAdapterDelegate() certificatesAdapter += CertificateProfileAdapterDelegate(::onCertificateClicked) } @@ -102,6 +104,11 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica when (state) { is ProfileCertificatesView.State.Loading -> { + certificatesAdapter.items = listOf( + CertificateListItem.Placeholder, + CertificateListItem.Placeholder, + CertificateListItem.Placeholder + ) profileId = state.profileData.user.id isCurrentUser = state.profileData.isCurrentUser } diff --git a/app/src/main/res/layout/item_certificate_profile_skeleton.xml b/app/src/main/res/layout/item_certificate_profile_skeleton.xml new file mode 100644 index 0000000000..b974bf7a1c --- /dev/null +++ b/app/src/main/res/layout/item_certificate_profile_skeleton.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + \ No newline at end of file From 040f3e8fa04e5694d8637cf56f62af2259d18e24 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Mon, 24 Jan 2022 19:35:47 +0300 Subject: [PATCH 12/18] Add certificate heading --- .../CertificateProfileAdapterDelegate.kt | 9 ++++--- .../res/layout/item_certificate_profile.xml | 1 + .../item_certificate_profile_skeleton.xml | 27 ++++++++++++------- app/src/main/res/values-be/strings.xml | 4 +++ app/src/main/res/values-ru/strings.xml | 4 +++ 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt index 3ccfaa94c4..73b42638de 100644 --- a/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/certificate/ui/adapter/delegate/CertificateProfileAdapterDelegate.kt @@ -43,18 +43,19 @@ class CertificateProfileAdapterDelegate( data as CertificateListItem.Data viewBinding.certificateCourseTitle.text = data.title.orEmpty() - val certificateColor = + val (certificateColor, certificateHeading) = when (data.certificate.type) { Certificate.Type.REGULAR -> - ContextCompat.getColor(context, R.color.certificate_regular) + ContextCompat.getColor(context, R.color.certificate_regular) to context.getString(R.string.certificates_regular_title) Certificate.Type.DISTINCTION -> - ContextCompat.getColor(context, R.color.certificate_distinction) + ContextCompat.getColor(context, R.color.certificate_distinction) to context.getString(R.string.certificates_distinction_title) else -> - ContextCompat.getColor(context, R.color.white) + ContextCompat.getColor(context, R.color.white) to "" } val hasGrade = data.certificate.isWithScore + viewBinding.certificateHeading.text = certificateHeading viewBinding.certificateProgress.isVisible = hasGrade viewBinding.certificateProgressPercentage.isVisible = hasGrade viewBinding.certificateCourseTitle.maxLines = diff --git a/app/src/main/res/layout/item_certificate_profile.xml b/app/src/main/res/layout/item_certificate_profile.xml index 26e0eb660b..7339552b88 100644 --- a/app/src/main/res/layout/item_certificate_profile.xml +++ b/app/src/main/res/layout/item_certificate_profile.xml @@ -26,6 +26,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:maxLines="2" + android:textAllCaps="true" android:textAppearance="?textAppearanceCaption" app:layout_constraintBottom_toBottomOf="@id/certificateCourseIcon" app:layout_constraintHorizontal_bias="0" diff --git a/app/src/main/res/layout/item_certificate_profile_skeleton.xml b/app/src/main/res/layout/item_certificate_profile_skeleton.xml index b974bf7a1c..b84aa22de8 100644 --- a/app/src/main/res/layout/item_certificate_profile_skeleton.xml +++ b/app/src/main/res/layout/item_certificate_profile_skeleton.xml @@ -1,6 +1,5 @@ - + app:radius="@dimen/course_image_radius" /> + + + android:layout_marginTop="12dp" /> + android:layout_marginTop="8dp" /> + android:layout_alignParentRight="true" /> + android:layout_marginTop="2dp" /> \ No newline at end of file diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 20b3d1f4e2..d1a3e84330 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -1074,4 +1074,8 @@ Даведачны цэнтр https://support.stepik.org/hc/ru Версія: %s + + + Сертыфікат + Сертыфікат з адзнакай diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 16380ffdf0..d59c40f7e1 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1210,4 +1210,8 @@ Справочный центр https://support.stepik.org/hc/ru Версия: %s + + + Сертификат + Сертификат с отличием From 123d2f1a42b2dc15644bfc8cfed857fef2194e60 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Tue, 25 Jan 2022 10:33:02 +0300 Subject: [PATCH 13/18] Remove old skeleton --- .../ui/fragment/ProfileCertificatesFragment.kt | 2 +- app/src/main/res/layout/fragment_profile_certificates.xml | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt index 36e1a99982..daa99d77a6 100644 --- a/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt +++ b/app/src/main/java/org/stepik/android/view/profile_certificates/ui/fragment/ProfileCertificatesFragment.kt @@ -65,7 +65,7 @@ class ProfileCertificatesFragment : Fragment(R.layout.fragment_profile_certifica viewStateDelegate = ViewStateDelegate() viewStateDelegate.addState() viewStateDelegate.addState() - viewStateDelegate.addState(view, profileCertificatesLoading) + viewStateDelegate.addState(view, profileCertificatesRecycler) viewStateDelegate.addState(view, certificatesLoadingError) viewStateDelegate.addState(view, profileCertificatesRecycler) viewStateDelegate.addState(view, profileCertificatesRecycler) diff --git a/app/src/main/res/layout/fragment_profile_certificates.xml b/app/src/main/res/layout/fragment_profile_certificates.xml index bd29ec787e..dc5d9b8c0b 100644 --- a/app/src/main/res/layout/fragment_profile_certificates.xml +++ b/app/src/main/res/layout/fragment_profile_certificates.xml @@ -30,11 +30,6 @@ style="@style/ProfileItemHeader" /> - - Date: Tue, 25 Jan 2022 10:42:14 +0300 Subject: [PATCH 14/18] APPS-3587: update room version to support M1 --- build.gradle | 6 ++++++ dependencies.gradle | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index db43a7937a..86a113b6f5 100644 --- a/build.gradle +++ b/build.gradle @@ -52,6 +52,12 @@ allprojects { dirs 'libs/aars' } } + + configurations.all { + resolutionStrategy { + force libraries.jdbc + } + } } configurations.all { diff --git a/dependencies.gradle b/dependencies.gradle index e4aebb8caf..780f1f25e5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -31,7 +31,8 @@ ext.versions = [ constraintLayout : '1.1.3', material : '1.3.0', fragment : '1.2.5', - room : '2.2.5', + room : '2.3.0', + jdbc : '3.34.0', browser : '1.3.0', archComponents : '2.2.0', @@ -148,6 +149,7 @@ ext.libraries = [ fragmentKtx : "androidx.fragment:fragment-ktx:$versions.fragment", room : "androidx.room:room-runtime:$versions.room", roomCompiler : "androidx.room:room-compiler:$versions.room", + jdbc : "org.xerial:sqlite-jdbc:$versions.jdbc", browser : "androidx.browser:browser:$versions.browser", archCompiler : "androidx.lifecycle:lifecycle-common-java8:$versions.archComponents", From a9783e7badcf0dfe4af56e0d23b0683709a74770 Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Tue, 25 Jan 2022 10:59:18 +0300 Subject: [PATCH 15/18] Update vertical bias for certificate percentage --- app/src/main/res/layout/item_certificate_profile.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/layout/item_certificate_profile.xml b/app/src/main/res/layout/item_certificate_profile.xml index 7339552b88..2d262f7be7 100644 --- a/app/src/main/res/layout/item_certificate_profile.xml +++ b/app/src/main/res/layout/item_certificate_profile.xml @@ -70,6 +70,7 @@ android:layout_marginTop="4dp" android:layout_marginBottom="4dp" android:textAppearance="?textAppearanceSubtitle2" + app:layout_constraintVertical_bias="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/certificateCourseTitle" From 1f0a67848e17a0fe0747e41790e8b07e4f197a4d Mon Sep 17 00:00:00 2001 From: Stepik Bot Date: Wed, 26 Jan 2022 03:04:49 +0000 Subject: [PATCH 16/18] "inc version to 2237" --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 780f1f25e5..7ed0fc7f83 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,6 +1,6 @@ ext.versions = [ - code : 2236, - name : '1.206', + code : 2237, + name : '1.207', minSdk : 21, targetSdk : 30, From be0eaae32802984c54baa2f46c41d90f81c981ac Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 27 Jan 2022 09:30:41 +0300 Subject: [PATCH 17/18] Remove isManual property --- .../ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt | 4 ++-- .../ui/dialog/TransactionBottomSheetDialogFragment.kt | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt index a91639ef9c..fda03323a9 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/adapter/delegate/CourseBenefitsAdapterDelegate.kt @@ -48,7 +48,7 @@ class CourseBenefitsAdapterDelegate( purchaseRefundIcon.setImageDrawable(getIconDrawable(data.courseBenefit)) purchaseRefundName.text = - if (data.courseBenefit.isManual) { + if (data.courseBenefit.buyer == null && !data.courseBenefit.isInvoicePayment) { buildString { append(context.getString(R.string.transaction_manual_channel)) if (data.courseBenefit.description != null) { @@ -90,7 +90,7 @@ class CourseBenefitsAdapterDelegate( } private fun getIconDrawable(data: CourseBenefit): Drawable? = - if (data.isManual) { + if (data.buyer == null && !data.isInvoicePayment) { getTintedDrawable(R.color.color_on_surface_alpha_38) } else { if (data.status == CourseBenefit.Status.DEBITED) { diff --git a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt index d40babf29f..c81a0992f4 100644 --- a/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt +++ b/app/src/main/java/org/stepik/android/view/course_revenue/ui/dialog/TransactionBottomSheetDialogFragment.kt @@ -102,7 +102,8 @@ class TransactionBottomSheetDialogFragment : BottomSheetDialogFragment() { transactionPromoCodeTitle.isVisible = courseBenefit.promoCode != null transactionPromoCodeValue.isVisible = courseBenefit.promoCode != null - val isChannelInfoVisible = courseBenefit.status == CourseBenefit.Status.DEBITED || courseBenefit.isManual + val isChannelInfoVisible = courseBenefit.status == CourseBenefit.Status.DEBITED || + (courseBenefit.buyer == null && !courseBenefit.isInvoicePayment) transactionChannelTitle.isVisible = isChannelInfoVisible transactionChannelValue.isVisible = isChannelInfoVisible @@ -112,7 +113,7 @@ class TransactionBottomSheetDialogFragment : BottomSheetDialogFragment() { getString(R.string.transaction_z_link_channel) courseBenefit.isInvoicePayment -> getString(R.string.transaction_invoice_channel) - courseBenefit.isManual -> { + courseBenefit.buyer == null && !courseBenefit.isInvoicePayment -> { buildString { append(getString(R.string.transaction_manual_channel)) if (courseBenefit.description != null) { From bec0e9c2e370817ca119e67083b8f0d2135473fc Mon Sep 17 00:00:00 2001 From: Rostislav Smirnov Date: Thu, 27 Jan 2022 14:49:00 +0300 Subject: [PATCH 18/18] Fix event names --- .../domain/retention/analytic/RetentionNotificationDismissed.kt | 2 +- .../domain/retention/analytic/RetentionNotificationShown.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationDismissed.kt b/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationDismissed.kt index 614f491517..9b5f946aea 100644 --- a/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationDismissed.kt +++ b/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationDismissed.kt @@ -12,7 +12,7 @@ data class RetentionNotificationDismissed( } override val name: String = - "Retention notification clicked" + "Retention notification dismissed" override val params: Map = mapOf(PARAM_DAY to day) diff --git a/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationShown.kt b/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationShown.kt index 8d6f388ca5..bac1bfe4c7 100644 --- a/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationShown.kt +++ b/app/src/main/java/org/stepik/android/domain/retention/analytic/RetentionNotificationShown.kt @@ -10,7 +10,7 @@ class RetentionNotificationShown( } override val name: String = - "Retention notification clicked" + "Retention notification shown" override val params: Map = mapOf(PARAM_DAY to day)