Задача: Спроектировать Дзен как продукт
- умная лента
- поиск*
- 50 мил DAU
- текстовые статьи, фото, видео
- каналы ,можно подписаться
- уведомления push
- генерация контента
| import android.content.SharedPreferences | |
| import com.google.crypto.tink.Aead | |
| import com.google.crypto.tink.KeysetHandle | |
| import com.google.crypto.tink.RegistryConfiguration | |
| import com.google.crypto.tink.TinkProtoKeysetFormat | |
| import com.google.crypto.tink.aead.AeadConfig | |
| import com.google.crypto.tink.aead.PredefinedAeadParameters | |
| import com.google.crypto.tink.integration.android.AndroidKeystore | |
| import com.google.crypto.tink.subtle.Base64 | |
| import com.google.crypto.tink.subtle.Hex |
| data class Event( | |
| val id: Int, | |
| val image: Image?, | |
| val title: String, | |
| val description: String?, | |
| val areQuestionsAllowed: Boolean, | |
| val startDate: Instant, | |
| val endDate: Instant, | |
| val organizer: User, | |
| val address: EventLocation?, |
| import java.nio.file.* | |
| import java.util.zip.ZipEntry | |
| import java.util.zip.ZipOutputStream | |
| import kotlin.io.path.* | |
| @OptIn(ExperimentalPathApi::class) | |
| fun ZipOutputStream.addFolder(entryName: String, folder: Path) { | |
| for (path in folder.walk()) { | |
| val relativized = folder.relativize(path) | |
| val prefix = if (entryName.isNotEmpty()) { |
| class SyncChallengesProgressUseCase @Inject constructor( | |
| private val challengesRepository: ChallengesRepository, | |
| private val getStepsFromFitnessApp: GetStepsFromFitnessAppUseCase, | |
| getPhoneManufactureData: GetPhoneManufactureDataUseCase | |
| ) { | |
| private val deviceId = getPhoneManufactureData().deviceId | |
| suspend operator fun invoke(startDate: Instant): SyncChallengesProgressResult { | |
| val now = Clock.System.now() | |
| if (startDate.daysUntil(now, TimeZone.currentSystemDefault()) == 0) { |
| @Singleton | |
| class OAuthTokenLocalDataSource @Inject constructor( | |
| app: Application | |
| ) { | |
| private val sharedPrefs: SharedPreferences = EncryptedSharedPreferences.create( | |
| "oauth_token_local_data_source", | |
| MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC), | |
| app, | |
| EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, | |
| EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM |
| import android.util.Log | |
| import com.bugsnag.android.Bugsnag | |
| import timber.log.Timber | |
| import java.util.* | |
| class BugsnagTree : Timber.DebugTree() { | |
| // Adding one to the initial size accounts for the add before remove. | |
| private val buffer = ArrayDeque<String>(BUFFER_SIZE + 1) | |
| override fun isLoggable(tag: String?, priority: Int): Boolean = priority >= Log.INFO |
Задача: Спроектировать Дзен как продукт
| private fun initAppUpdateFlow() { | |
| logcat { "check app update" } | |
| val appUpdateManager = AppUpdateManagerFactory.create(this) | |
| lifecycleScope.launch { | |
| try { | |
| appUpdateManager.requestUpdateFlow().collect(::onAppUpdateResult) | |
| } catch (e: InstallException) { | |
| logcat(LogPriority.ERROR) { "Failed to request app update flow\n${e.asLog()}" } | |
| } | |
| } |
| inline class CurrencyCode private constructor(private val isoCode: String) { | |
| override fun toString(): String = isoCode | |
| companion object { | |
| fun from(isoCode: String): CurrencyCode { | |
| require(isoCode.matches("^[A-Za-z]{3}$".toRegex())) { | |
| "Invalid ISO 4217 currency code format: $isoCode" | |
| } | |
| return CurrencyCode(isoCode.toUpperCase(Locale.ROOT).intern()) |
| class CompositeOnFocusChangeListener constructor( | |
| vararg listeners: OnFocusChangeListener | |
| ) : OnFocusChangeListener, MutableSet<OnFocusChangeListener> by listeners.toMutableSet() { | |
| override fun onFocusChange(view: View, hasFocus: Boolean) { | |
| forEach { it.onFocusChange(view, hasFocus) } | |
| } | |
| } | |
| fun View.addOnFocusChangeListener(listener: OnFocusChangeListener) { |