Skip to content

Commit

Permalink
Merge pull request #180 from LivingWithHippos/dev
Browse files Browse the repository at this point in the history
Merge dev for new release
  • Loading branch information
LivingWithHippos authored Dec 10, 2021
2 parents f36dac2 + 5dab83b commit 8416487
Show file tree
Hide file tree
Showing 88 changed files with 1,374 additions and 680 deletions.
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,11 @@ You can take a look at the project [here](https://github.com/LivingWithHippos/un

### Screenshots :iphone:

| Home | New Download | Download Details |
| ------------- | ------------- | ------------- |
| <img width="150" src="/extra_assets/screenshots/home.png?raw=true" alt="User Screen"> <img width="150" src="/extra_assets/screenshots/home_dark.png?raw=true" alt="Dark User Screen"> | <img width="150" src="/extra_assets/screenshots/new_download.png?raw=true" alt="New Download Screen"> | <img width="150" src="/extra_assets/screenshots/download_details_streaming.png?raw=true" alt="Download Details Screen"> |
| User | Downloads List | Download Details | New Download | Search |
| ------------- | ------------- | ------------- |------------- |------------- |
| <img width="150" src="/extra_assets/screenshots/user.png?raw=true" alt="User Screen"> | <img width="150" src="/extra_assets/screenshots/downloads_list.png?raw=true" alt="List of downloads"> | <img width="150" src="/extra_assets/screenshots/download_details.png?raw=true" alt="Download details screen"> | <img width="150" src="/extra_assets/screenshots/new_download.png?raw=true" alt="New download screen"> | <img width="150" src="/extra_assets/screenshots/search.png?raw=true" alt="Search screen"> |


| Torrent Download | Download List |
|--------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------|
| <img width="150" src="/extra_assets/screenshots/torrent_details.png?raw=true" alt="Torrent Download Screen"> | <img width="150" src="/extra_assets/screenshots/download_list.png?raw=true" alt="Download List Screen"> |

### Installation :calling:

You have multiple options to install Unchained for Android:
Expand All @@ -52,9 +48,9 @@ You have multiple options to install Unchained for Android:
### Developing and Contributing :writing_hand:


Contributions are welcome. You can use the [discussion tab](https://github.com/LivingWithHippos/unchained-android/discussions) to ask for help setting up the project.
Contributions are welcome. You can use the [discussion tab](https://github.com/LivingWithHippos/unchained-android/discussions) to ask for help setting up the project. At the moment at least Android Studio 2021.1.1 is needed to build the project.

The dev branch is the one where the developement happens, it gets merged into master when a release is ready.
The dev branch is the one where the development happens, it gets merged into master when a release is ready.

A debug version is available, it reports automatically any crash information, it can be useful to help me debug errors.

Expand Down Expand Up @@ -115,6 +111,7 @@ LWeoBVVmaYAiZ3oGaLAV9sV2dvY62XxdCF

Logo and symbols inspired by [minimal logo design set](https://www.rawpixel.com/image/843352/minimal-logo-designs-set) offered by [rawpixel.com](https://www.rawpixel.com)
Icons by [Fluent UI](https://www.svgrepo.com/collection/fluent-ui-icons-outlined/) offered by [SVG Repo](https://www.svgrepo.com/)
Backgrounds courtesy of [haikei](https://haikei.app/) and [SVG Backgrounds](https://www.svgbackgrounds.com/)

### Thanks, Mr. Unchained :muscle:

Expand Down
23 changes: 23 additions & 0 deletions app/.run/Check dependencies updates.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Check dependencies updates" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="--scan" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="dependencyUpdates" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>
11 changes: 5 additions & 6 deletions app/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ if (apiPropertiesFile.exists()) {

android {

compileSdkVersion 31
buildToolsVersion "30.0.3"
compileSdk 31

defaultConfig {
applicationId "com.github.livingwithhippos.unchained"
minSdkVersion 22
targetSdkVersion 31
versionCode 26
versionName "4.20.1-beta"
minSdk 22
targetSdk 31
versionCode 27
versionName "4.27.2-beta"
// limit resources for a list of locales
// resConfigs "en", "it"

Expand Down
8 changes: 8 additions & 0 deletions app/app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@
-keep class * extends com.google.protobuf.GeneratedMessageLite {
<fields>;
}

-dontwarn org.bouncycastle.jsse.BCSSLParameters
-dontwarn org.bouncycastle.jsse.BCSSLSocket
-dontwarn org.bouncycastle.jsse.provider.BouncyCastleJsseProvider
-dontwarn org.conscrypt.*
-dontwarn org.openjsse.javax.net.ssl.SSLParameters
-dontwarn org.openjsse.javax.net.ssl.SSLSocket
-dontwarn org.openjsse.net.ssl.OpenJSSE
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ class MainActivity : AppCompatActivity() {
)

viewModel.fsmAuthenticationState.observe(
this,
{
this
) {
if (it != null) {
when (it.getContentIfNotHandled()) {
null -> {
// do nothing
Expand Down Expand Up @@ -170,8 +171,11 @@ class MainActivity : AppCompatActivity() {
}
}
}
} else {
Countly.sharedInstance().events()
.recordEvent("fsmAuthenticationState observable was null")
}
)
}

// disable the bottom menu items before loading the credentials
disableBottomNavItems(
Expand All @@ -191,20 +195,42 @@ class MainActivity : AppCompatActivity() {
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
)

viewModel.linkLiveData.observe(
this,
EventObserver { link ->
when {
link.endsWith(TYPE_UNCHAINED, ignoreCase = true) -> {
downloadPlugin(link)
viewModel.linkLiveData.observe(this) {
if (it == null) {
Countly.sharedInstance().events().recordEvent("linkLiveData observable was null")
} else {
it.getContentIfNotHandled()?.let { link ->
when {
link.endsWith(TYPE_UNCHAINED, ignoreCase = true) -> {
downloadPlugin(link)
}
else -> {
// check the authentication
processExternalRequestOnAuthentication(Uri.parse(link))
}
}
}
}
}

viewModel.jumpTabLiveData.observe(this, EventObserver {
when (it) {
"user" -> {
// do nothing
}
"downloads" -> {
lifecycleScope.launch {
doubleClickBottomItem(R.id.navigation_lists)
}
else -> {
// check the authentication
processExternalRequestOnAuthentication(Uri.parse(link))
}
"search" -> {
lifecycleScope.launch {
doubleClickBottomItem(R.id.navigation_search)
}
}
}
)
})


// monitor if the torrent notification service needs to be started. It monitor the preference change itself
// for the shutting down part
Expand All @@ -222,13 +248,19 @@ class MainActivity : AppCompatActivity() {
val currentToast: Toast = Toast.makeText(this, "", Toast.LENGTH_SHORT)

viewModel.messageLiveData.observe(
this,
EventObserver {
currentToast.cancel()
currentToast.setText(getString(it))
currentToast.show()
this
) {
if (it == null) {
Countly.sharedInstance().events()
.recordEvent("messageLiveData observable was null")
} else {
it.getContentIfNotHandled()?.let { message ->
currentToast.cancel()
currentToast.setText(getString(message))
currentToast.show()
}
}
)
}

// start the notification system if enabled
if (preferences.getBoolean(KEY_TORRENT_NOTIFICATIONS, false)) {
Expand All @@ -237,16 +269,20 @@ class MainActivity : AppCompatActivity() {
}

viewModel.connectivityLiveData.observe(
this,
{
if (it) {
Timber.d("connection enabled")
} else {
this
) {
when (it) {
true -> Timber.d("connection enabled")
false -> {
Timber.e("connection disabled")
applicationContext.showToast(R.string.no_network_connection)
}
null -> {
Countly.sharedInstance().events()
.recordEvent("connectivityLiveData observable was null")
}
}
)
}
viewModel.setupConnectivityCheck(applicationContext)
}

Expand Down
1 change: 1 addition & 0 deletions app/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<activity
android:name=".settings.view.SettingsActivity"
android:parentActivityName=".base.MainActivity" />

<activity
android:exported="true"
android:name=".base.MainActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,45 +52,47 @@ class AuthenticationFragment : UnchainedFragment(), ButtonListener {
authBinding.loginMessageDirect = getLoginMessage(LOGIN_TYPE_DIRECT)
authBinding.loginMessageIndirect = getLoginMessage(LOGIN_TYPE_INDIRECT)

activityViewModel.fsmAuthenticationState.observe(viewLifecycleOwner, {

when (it.peekContent()) {
FSMAuthenticationState.AuthenticatedOpenToken -> {
val action =
AuthenticationFragmentDirections.actionAuthenticationToUser()
findNavController().navigate(action)
}
FSMAuthenticationState.AuthenticatedPrivateToken -> {
val action =
AuthenticationFragmentDirections.actionAuthenticationToUser()
findNavController().navigate(action)
}
FSMAuthenticationState.StartNewLogin -> {
// reset the current data
authBinding.auth = null
authBinding.secrets = null
authBinding.token = null
// get the authentication link to start the process
viewModel.fetchAuthenticationInfo()
}
FSMAuthenticationState.WaitingUserConfirmation -> {
// start the next auth step
viewModel.fetchSecrets()
}
FSMAuthenticationState.WaitingToken -> {
viewModel.fetchToken()
}
FSMAuthenticationState.CheckCredentials, FSMAuthenticationState.RefreshingOpenToken -> {
// managed by activity
}
is FSMAuthenticationState.WaitingUserAction -> {
// todo: depending on the action required show an error or restart the process
}
FSMAuthenticationState.Start -> {
// this shouldn't happen
activityViewModel.fsmAuthenticationState.observe(viewLifecycleOwner) {

if (it != null) {
when (it.peekContent()) {
FSMAuthenticationState.AuthenticatedOpenToken -> {
val action =
AuthenticationFragmentDirections.actionAuthenticationToUser()
findNavController().navigate(action)
}
FSMAuthenticationState.AuthenticatedPrivateToken -> {
val action =
AuthenticationFragmentDirections.actionAuthenticationToUser()
findNavController().navigate(action)
}
FSMAuthenticationState.StartNewLogin -> {
// reset the current data
authBinding.auth = null
authBinding.secrets = null
authBinding.token = null
// get the authentication link to start the process
viewModel.fetchAuthenticationInfo()
}
FSMAuthenticationState.WaitingUserConfirmation -> {
// start the next auth step
viewModel.fetchSecrets()
}
FSMAuthenticationState.WaitingToken -> {
viewModel.fetchToken()
}
FSMAuthenticationState.CheckCredentials, FSMAuthenticationState.RefreshingOpenToken -> {
// managed by activity
}
is FSMAuthenticationState.WaitingUserAction -> {
// todo: depending on the action required show an error or restart the process
}
FSMAuthenticationState.Start -> {
// this shouldn't happen
}
}
}
})
}

// 1. start checking for the auth link
viewModel.authLiveData.observe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.github.livingwithhippos.unchained.base

import android.app.Dialog
import android.os.Bundle
import android.widget.Button
import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.setFragmentResult
Expand All @@ -13,26 +12,17 @@ class DeleteDialogFragment : DialogFragment() {

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {

// Use the Builder class for convenient dialog construction
val builder = MaterialAlertDialogBuilder(it)

// Get the layout inflater
val inflater = it.layoutInflater

val view = inflater.inflate(R.layout.dialog_delete_confirmation, null)

view.findViewById<Button>(R.id.bConfirmDelete).setOnClickListener {
setFragmentResult("deleteActionKey", bundleOf("deleteConfirmation" to true))
dismiss()
}

builder.setView(view)
.setTitle(R.string.confirm_removal)
.setNeutralButton(getString(R.string.close)) { dialog, _ ->
val title = arguments?.getString("title") ?: getString(R.string.delete)
builder.setMessage(R.string.confirm_item_removal_description)
.setTitle(title)
.setPositiveButton(R.string.delete) { _, _ ->
setFragmentResult("deleteActionKey", bundleOf("deleteConfirmation" to true))
}
.setNegativeButton(R.string.close) { dialog, _ ->
dialog.cancel()
}
// Create the AlertDialog object and return it
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
Expand Down
Loading

0 comments on commit 8416487

Please sign in to comment.