Skip to content

Commit

Permalink
Merge branch 'main' into feature/rv_divider
Browse files Browse the repository at this point in the history
  • Loading branch information
MostafaMohamed2002 committed Oct 13, 2024
2 parents 8d2f700 + 4511f77 commit 597876d
Show file tree
Hide file tree
Showing 30 changed files with 516 additions and 3,139 deletions.
18 changes: 13 additions & 5 deletions .github/workflows/pr_maintainer_checklist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,19 @@ jobs:
If you're not already a member of our [public Matrix community](https://matrix.to/#/#scribe_community:matrix.org), please consider joining! We'd suggest using [Element](https://element.io/) as your Matrix client, and definitely join the General and Android rooms once you're in. Also consider joining our [bi-weekly Saturday dev syncs](https://etherpad.wikimedia.org/p/scribe-dev-sync). It'd be great to have you!
### Maintainer checklist
- [ ] The commit messages for the remote branch should be checked to make sure the contributor's email is set up correctly so that they receive credit for their contribution
- The contributor's name and icon in remote commits should be the same as what appears in the PR
- If there's a mismatch, the contributor needs to make sure that the [email they use for GitHub](https://github.com/settings/emails) matches what they have for `git config user.email` in their local Scribe-Android repo
- [ ] The linting and formatting workflows within the [PR checks](https://github.com/scribe-org/Scribe-Android/pull/${{ github.event.pull_request.number }}/checks) do not indicate new errors in the files changed
- [ ] The [CHANGELOG](https://github.com/scribe-org/Scribe-Android/blob/main/CHANGELOG.md) has been updated with a description of the changes for the upcoming release and the corresponding issue (if necessary)
- name: First PR Contributor Email Check
id: first_interaction
uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: |
## First PR Commit Check
- [ ] The commit messages for the remote branch should be checked to make sure the contributor's email is set up correctly so that they receive credit for their contribution
- The contributor's name and icon in remote commits should be the same as what appears in the PR
- If there's a mismatch, the contributor needs to make sure that the [email they use for GitHub](https://github.com/settings/emails) matches what they have for `git config user.email` in their local Scribe-Android repo
9 changes: 9 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ plugins {
id("org.jmailen.kotlinter")
id("io.gitlab.arturbosch.detekt")
id("com.google.devtools.ksp") version "2.0.0-1.0.22" apply true
id("de.mannodermaus.android-junit5") version "1.11.2.0"
}

val kotlinVersion by extra("2.0.0")
val junit5Version by extra("5.11.2")
val mockkVersion by extra("1.13.13")

android {
compileSdk = 34
Expand Down Expand Up @@ -114,6 +118,11 @@ dependencies {
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.cardview:cardview:1.0.0")
implementation("androidx.viewpager2:viewpager2:1.1.0")
implementation("com.google.android.play:core:1.10.0")

testImplementation("org.junit.jupiter:junit-jupiter-api:$junit5Version")
testImplementation("io.mockk:mockk:$mockkVersion")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junit5Version")

api("joda-time:joda-time:2.10.13")
api("com.github.tibbi:RecyclerView-FastScroller:e7d3e150c4")
Expand Down
172 changes: 28 additions & 144 deletions app/src/main/java/be/scri/activities/BaseSimpleActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,14 @@ import android.os.Build
import android.os.Bundle
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.Settings
import android.telecom.TelecomManager
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.WindowManager
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import be.scri.R
import be.scri.dialogs.ConfirmationDialog
import be.scri.dialogs.WritePermissionDialog
import be.scri.dialogs.WritePermissionDialog.Mode
import be.scri.extensions.addBit
import be.scri.extensions.baseConfig
import be.scri.extensions.buildDocumentUriSdk30
Expand All @@ -41,21 +35,13 @@ import be.scri.extensions.getColoredDrawableWithColor
import be.scri.extensions.getContrastColor
import be.scri.extensions.getFirstParentLevel
import be.scri.extensions.getFirstParentPath
import be.scri.extensions.getPermissionString
import be.scri.extensions.getProperStatusBarColor
import be.scri.extensions.getProperTextColor
import be.scri.extensions.getThemeId
import be.scri.extensions.hasPermission
import be.scri.extensions.hideKeyboard
import be.scri.extensions.humanizePath
import be.scri.extensions.isAppInstalledOnSDCard
import be.scri.extensions.isPathOnOTG
import be.scri.extensions.isPathOnSD
import be.scri.extensions.isShowingAndroidSAFDialog
import be.scri.extensions.isShowingOTGDialog
import be.scri.extensions.isShowingSAFCreateDocumentDialogSdk30
import be.scri.extensions.isShowingSAFDialog
import be.scri.extensions.isShowingSAFDialogSdk30
import be.scri.extensions.removeBit
import be.scri.extensions.showErrorToast
import be.scri.extensions.storeAndroidTreeUri
Expand Down Expand Up @@ -287,10 +273,11 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
resultData: Intent?,
) {
super.onActivityResult(requestCode, resultCode, resultData)
val partition =
try {
val partition: String =
if (checkedDocumentPath.length >= 18) {
checkedDocumentPath.substring(9, 18)
} catch (e: Exception) {
} else {
showErrorToast("An unexpected error occurred while extracting the substring.")
""
}

Expand Down Expand Up @@ -358,8 +345,12 @@ abstract class BaseSimpleActivity : AppCompatActivity() {

try {
startActivityForResult(this, requestCode)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: ActivityNotFoundException) {
showErrorToast("No application found to handle this request.")
} catch (e: SecurityException) {
showErrorToast("Security exception: ${e.message}")
} catch (e: IllegalArgumentException) {
showErrorToast("Invalid argument provided: ${e.message}")
}
}
}
Expand Down Expand Up @@ -392,8 +383,12 @@ abstract class BaseSimpleActivity : AppCompatActivity() {

try {
startActivityForResult(intent, requestCode)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: ActivityNotFoundException) {
showErrorToast("No application found to handle this request.")
} catch (e: SecurityException) {
showErrorToast("Security exception: ${e.message}")
} catch (e: IllegalArgumentException) {
showErrorToast("Invalid argument provided: ${e.message}")
}
}
} else {
Expand Down Expand Up @@ -435,8 +430,10 @@ abstract class BaseSimpleActivity : AppCompatActivity() {

try {
startActivityForResult(intent, requestCode)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: ActivityNotFoundException) {
showErrorToast("No application found to handle this request.")
} catch (e: SecurityException) {
showErrorToast("Security exception: ${e.message}")
}
}
} else {
Expand Down Expand Up @@ -511,82 +508,6 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
}

@RequiresApi(Build.VERSION_CODES.O)
fun launchCustomizeNotificationsIntent() {
Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
startActivity(this)
}
}

// synchronous return value determines only if we are showing the SAF dialog, callback result tells if the SD or OTG permission has been granted
fun handleSAFDialog(
path: String,
callback: (success: Boolean) -> Unit,
): Boolean {
hideKeyboard()
return if (!packageName.startsWith("be.scri")) {
callback(true)
false
} else if (isShowingSAFDialog(path) || isShowingOTGDialog(path)) {
funAfterSAFPermission = callback
true
} else {
callback(true)
false
}
}

fun handleSAFDialogSdk30(
path: String,
callback: (success: Boolean) -> Unit,
): Boolean {
hideKeyboard()
return if (!packageName.startsWith("be.scri")) {
callback(true)
false
} else if (isShowingSAFDialogSdk30(path)) {
funAfterSdk30Action = callback
true
} else {
callback(true)
false
}
}

fun handleSAFCreateDocumentDialogSdk30(
path: String,
callback: (success: Boolean) -> Unit,
): Boolean {
hideKeyboard()
return if (!packageName.startsWith("be.scri")) {
callback(true)
false
} else if (isShowingSAFCreateDocumentDialogSdk30(path)) {
funAfterSdk30Action = callback
true
} else {
callback(true)
false
}
}

fun handleAndroidSAFDialog(
path: String,
callback: (success: Boolean) -> Unit,
): Boolean {
hideKeyboard()
return if (!packageName.startsWith("be.scri")) {
callback(true)
false
} else if (isShowingAndroidSAFDialog(path)) {
funAfterSAFPermission = callback
true
} else {
callback(true)
false
}
}

fun handleOTGPermission(callback: (success: Boolean) -> Unit) {
hideKeyboard()
if (baseConfig.otgTreeUri.isNotEmpty()) {
Expand All @@ -595,24 +516,6 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
}

funAfterSAFPermission = callback
WritePermissionDialog(this, Mode.Otg) {
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
try {
startActivityForResult(this, OPEN_DOCUMENT_TREE_OTG)
return@apply
} catch (e: Exception) {
type = "*/*"
}

try {
startActivityForResult(this, OPEN_DOCUMENT_TREE_OTG)
} catch (e: ActivityNotFoundException) {
toast(R.string.system_service_disabled, Toast.LENGTH_LONG)
} catch (e: Exception) {
toast(R.string.unknown_error_occurred)
}
}
}
}

@SuppressLint("NewApi")
Expand All @@ -626,8 +529,10 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
try {
val deleteRequest = MediaStore.createDeleteRequest(contentResolver, uris).intentSender
startIntentSenderForResult(deleteRequest, Companion.DELETE_FILE_SDK_30_HANDLER, null, 0, 0, 0)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: SecurityException) {
showErrorToast("Security exception: ${e.message}")
} catch (e: IllegalArgumentException) {
showErrorToast("Illegal argument: ${e.message}")
}
} else {
callback(false)
Expand All @@ -645,8 +550,10 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
try {
val writeRequest = MediaStore.createWriteRequest(contentResolver, uris).intentSender
startIntentSenderForResult(writeRequest, Companion.UPDATE_FILE_SDK_30_HANDLER, null, 0, 0, 0)
} catch (e: Exception) {
showErrorToast(e)
} catch (e: SecurityException) {
showErrorToast("Security exception: ${e.message}")
} catch (e: IllegalArgumentException) {
showErrorToast("Illegal argument: ${e.message}")
}
} else {
callback(false)
Expand All @@ -669,20 +576,6 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
}
}

fun handlePermission(
permissionId: Int,
callback: (granted: Boolean) -> Unit,
) {
actionOnPermission = null
if (hasPermission(permissionId)) {
callback(true)
} else {
isAskingPermissions = true
actionOnPermission = callback
ActivityCompat.requestPermissions(this, arrayOf(getPermissionString(permissionId)), Companion.GENERIC_PERM_HANDLER)
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
Expand All @@ -695,13 +588,6 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
}
}

fun checkAppOnSDCard() {
if (!baseConfig.wasAppOnSDShown && isAppInstalledOnSDCard()) {
baseConfig.wasAppOnSDShown = true
ConfirmationDialog(this, "", R.string.app_on_sd_card, R.string.ok, 0) {}
}
}

@SuppressLint("InlinedApi")
protected fun launchSetDefaultDialerIntent() {
if (isQPlus()) {
Expand All @@ -716,8 +602,6 @@ abstract class BaseSimpleActivity : AppCompatActivity() {
startActivityForResult(this, REQUEST_CODE_SET_DEFAULT_DIALER)
} catch (e: ActivityNotFoundException) {
toast(R.string.no_app_found)
} catch (e: Exception) {
showErrorToast(e)
}
}
}
Expand Down
19 changes: 0 additions & 19 deletions app/src/main/java/be/scri/activities/BaseSplashActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,16 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import be.scri.R
import be.scri.extensions.baseConfig
import be.scri.extensions.checkAppIconColor
import be.scri.extensions.checkAppSideloading
import be.scri.extensions.getSharedTheme
import be.scri.extensions.isThankYouInstalled
import be.scri.extensions.isUsingSystemDarkTheme
import be.scri.extensions.showSideloadingDialog
import be.scri.helpers.SIDELOADING_TRUE
import be.scri.helpers.SIDELOADING_UNCHECKED

abstract class BaseSplashActivity : AppCompatActivity() {
abstract fun initActivity()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (baseConfig.appSideloadingStatus == SIDELOADING_UNCHECKED) {
if (checkAppSideloading()) {
return
}
} else if (baseConfig.appSideloadingStatus == SIDELOADING_TRUE) {
showSideloadingDialog()
return
}

baseConfig.apply {
if (isUsingAutoTheme) {
val isUsingSystemDarkTheme = isUsingSystemDarkTheme()
Expand All @@ -53,11 +39,6 @@ abstract class BaseSplashActivity : AppCompatActivity() {
navigationBarColor = it.navigationBarColor
accentColor = it.accentColor
}

if (baseConfig.appIconColor != it.appIconColor) {
baseConfig.appIconColor = it.appIconColor
checkAppIconColor()
}
}
initActivity()
}
Expand Down
Loading

0 comments on commit 597876d

Please sign in to comment.