Skip to content

Commit

Permalink
Merge pull request #989 from hyperskill/release/1.55
Browse files Browse the repository at this point in the history
Release 1.55
  • Loading branch information
ivan-magda authored Apr 16, 2024
2 parents 00187be + b4d7066 commit 8a07481
Show file tree
Hide file tree
Showing 203 changed files with 2,394 additions and 1,642 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/android_beta_deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

# Build and submit to the Firebase App Distribution
firebase-deployment:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android_deploy_to_firebase_manually.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

# Build and submit to the Firebase App Distribution
firebase-deployment:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/android_release_deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

# Build and submit to the Google Play
deployment:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

files-changed:
name: Detect changes
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ios_beta_deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

# Build, archive for ad-hoc and submit to Firebase App Distribution
deployment:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ios_release_deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
uses: actions/checkout@v4.1.1

- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v2.1.2
uses: gradle/actions/wrapper-validation@v3

# Build, archive for app-store and submit to App Store Connect
deployment:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import by.kirich1409.viewbindingdelegate.viewBinding
import co.touchlab.kermit.Logger
import org.hyperskill.app.android.HyperskillApp
import org.hyperskill.app.android.R
import org.hyperskill.app.android.auth.view.ui.navigation.AuthFlow
import org.hyperskill.app.android.auth.view.ui.navigation.AuthSocialScreen
import org.hyperskill.app.android.core.extensions.logger
import org.hyperskill.app.android.core.extensions.openUrl
import org.hyperskill.app.android.core.view.ui.dialog.CreateMagicLinkLoadingProgressDialogFragment
import org.hyperskill.app.android.core.view.ui.dialog.LoadingProgressDialogFragment
Expand All @@ -36,13 +38,16 @@ class AuthCredentialsFragment :
ReduxView<AuthCredentialsFeature.State, AuthCredentialsFeature.Action.ViewAction> {

companion object {
private const val LOG_TAG = "AuthCredentialsFragment"
fun newInstance(): AuthCredentialsFragment =
AuthCredentialsFragment()
}

private lateinit var authCredentialsErrorMapper: AuthCredentialsErrorMapper
private lateinit var viewModelFactory: ViewModelProvider.Factory

private val logger: Logger by logger(LOG_TAG)

private val viewStateDelegate: ViewStateDelegate<AuthCredentialsFeature.FormState> = ViewStateDelegate()
private val authCredentialsViewModel: AuthCredentialsViewModel by reduxViewModel(this) { viewModelFactory }
private val viewBinding by viewBinding(FragmentAuthEmailBinding::bind)
Expand Down Expand Up @@ -121,7 +126,7 @@ class AuthCredentialsFragment :
is AuthCredentialsFeature.Action.ViewAction.CompleteAuthFlow ->
(parentFragment as? AuthFlow)?.onAuthSuccess(action.profile)
is AuthCredentialsFeature.Action.ViewAction.OpenUrl ->
requireContext().openUrl(action.url)
requireContext().openUrl(action.url, logger)
is AuthCredentialsFeature.Action.ViewAction.ShowGetMagicLinkError ->
viewBinding.root.snackbar(SharedRes.string.common_error)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package org.hyperskill.app.android.challenge.delegate

import android.app.Activity
import android.content.Context
import android.net.Uri
import android.widget.Toast
import androidx.browser.customtabs.CustomTabsIntent
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.touchlab.kermit.Logger
import kotlinx.coroutines.flow.MutableStateFlow
import org.hyperskill.app.R
import org.hyperskill.app.android.challenge.ui.ChallengeCard
import org.hyperskill.app.android.core.extensions.launchUrlInCustomTabs
import org.hyperskill.app.android.core.extensions.openUrl
import org.hyperskill.app.android.core.extensions.setHyperskillColors
import org.hyperskill.app.android.core.view.ui.dialog.CreateMagicLinkLoadingProgressDialogFragment
import org.hyperskill.app.android.core.view.ui.dialog.dismissDialogFragmentIfExists
import org.hyperskill.app.android.core.view.ui.widget.compose.HyperskillTheme
Expand Down Expand Up @@ -59,24 +57,21 @@ class ChallengeCardDelegate {
}

fun handleAction(
context: Context,
activity: Activity,
action: ChallengeWidgetFeature.Action.ViewAction
fragment: Fragment,
action: ChallengeWidgetFeature.Action.ViewAction,
logger: Logger
) {
when (action) {
is ChallengeWidgetFeature.Action.ViewAction.OpenUrl -> {
if (action.shouldOpenInApp) {
val intent = CustomTabsIntent.Builder()
.setHyperskillColors(context)
.build()
intent.launchUrl(activity, Uri.parse(action.url))
fragment.launchUrlInCustomTabs(action.url, logger)
} else {
context.openUrl(action.url)
fragment.requireContext().openUrl(action.url, logger)
}
}
ChallengeWidgetFeature.Action.ViewAction.ShowNetworkError -> {
Toast
.makeText(context, R.string.common_error, Toast.LENGTH_SHORT)
.makeText(fragment.requireContext(), R.string.common_error, Toast.LENGTH_SHORT)
.show()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,44 @@ import android.content.ContextWrapper
import android.content.Intent
import android.net.Uri
import android.widget.Toast
import co.touchlab.kermit.Logger

fun Context.openUrl(uri: Uri) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = uri
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
fun Context.openUrl(
url: String,
logger: Logger
) {
openUrl(Uri.parse(url), logger)
}

fun Context.openUrl(
url: Uri,
logger: Logger
) {
openUrl(url) { e ->
logger.e(e) {
"Unable to open url in browser."
}
Toast.makeText(
this,
getString(org.hyperskill.app.R.string.external_link_error, uri),
getString(org.hyperskill.app.R.string.external_link_error),
Toast.LENGTH_SHORT
).show()
}
}

fun Context.openUrl(url: String) {
openUrl(Uri.parse(url))
fun Context.openUrl(
uri: Uri,
onError: (e: Throwable) -> Unit
) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = uri

// ActivityNotFoundException means there is no browser on the device
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
onError(e)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,75 @@
package org.hyperskill.app.android.core.extensions

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.net.Uri
import android.widget.Toast
import androidx.browser.customtabs.CustomTabColorSchemeParams
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import co.touchlab.kermit.Logger
import org.hyperskill.app.R

fun CustomTabsIntent.Builder.setHyperskillColors(context: Context): CustomTabsIntent.Builder =
setDefaultColorSchemeParams(
CustomTabColorSchemeParams.Builder()
.setToolbarColor(ContextCompat.getColor(context, R.color.color_primary_variant))
.build()
)
)

fun Fragment.launchUrlInCustomTabs(
url: String,
logger: Logger
) {
launchUrlInCustomTabs(url) { e ->
logger.e(e) {
"Unable to launch url in custom tabs nor in browser."
}
Toast.makeText(
requireContext(),
getString(R.string.external_link_error),
Toast.LENGTH_SHORT
).show()
}
}

fun Fragment.launchUrlInCustomTabs(
url: String,
onError: (e: Throwable) -> Unit
) {
CustomTabsIntent.Builder()
.setHyperskillColors(requireContext())
.build()
.launchUrlSafe(
requireActivity(),
Uri.parse(url),
onError
)
}

fun CustomTabsIntent.launchUrlSafe(
activity: Activity,
url: Uri,
onError: (e: Throwable) -> Unit
) {
// ActivityNotFoundException means there is no browser on the device
try {
launchUrl(activity, url)
} catch (e: ActivityNotFoundException) {
onError(e)
}
}

@Deprecated(
message = "Don't call launchUrl directly. Use launchUrlSafe instead.",
replaceWith = ReplaceWith(
expression = "launchUrlSafe",
imports = arrayOf("org.hyperskill.app.android.core.extensions.launchUrlSafe")
),
level = DeprecationLevel.ERROR
)
@Suppress("EXTENSION_SHADOWED_BY_MEMBER", "UnusedParameter")
fun CustomTabsIntent.launchUrl(context: Context, url: Uri): Nothing =
error("Don't call launchUrl directly. Use launchUrlSafe instead.")
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.hyperskill.app.android.core.extensions

import co.touchlab.kermit.Logger
import org.hyperskill.app.android.HyperskillApp

/**
* Provides logger with specified [tag],
* taking it from [HyperskillApp.graph]
*/
fun logger(tag: String): Lazy<Logger> =
LazyLoggerProvider(tag)

private class LazyLoggerProvider(private val tag: String) : Lazy<Logger> {

private var logger: Logger? = null
override val value: Logger
get() = logger ?: HyperskillApp.graph().loggerComponent.logger.withTag(tag)

override fun isInitialized(): Boolean =
logger != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,28 @@ import android.content.Context
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import co.touchlab.kermit.Logger
import org.hyperskill.app.android.core.extensions.logger
import org.hyperskill.app.android.core.extensions.openUrl

open class ExternalLinkWebViewClient(
private val context: Context
) : WebViewClient() {

companion object {
private const val LOG_TAG = "ExternalLinkWebViewClient"
}

private val logger: Logger by logger(LOG_TAG)

@Suppress("OVERRIDE_DEPRECATION")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
context.openUrl(url)
context.openUrl(url, logger)
return true
}

override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
context.openUrl(request.url)
context.openUrl(request.url, logger)
return true
}
}
Loading

0 comments on commit 8a07481

Please sign in to comment.