Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dual UI system #1045

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion atox/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
android:resource="@xml/file_paths" />
</provider>

<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTask">
<activity
android:name=".ActivityLauncher"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
Expand All @@ -57,5 +59,8 @@
<data android:mimeType="text/plain" />
</intent-filter>
</activity>

<activity android:name=".MainActivity" android:launchMode="singleTask" />
<activity android:name=".NewMainActivity" android:launchMode="singleTask" />
</application>
</manifest>
32 changes: 32 additions & 0 deletions atox/src/main/kotlin/ActivityLauncher.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ltd.evilcorp.atox

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import ltd.evilcorp.atox.settings.Settings
import javax.inject.Inject

class ActivityLauncher : Activity() {

@Inject
lateinit var settings: Settings

override fun onCreate(savedInstanceState: Bundle?) {
(application as App).component.inject(this)
super.onCreate(savedInstanceState)

val newIntent = intent.clone() as Intent

if (settings.wipUI) {
newIntent.setClass(applicationContext, NewMainActivity::class.java)
} else {
newIntent.setClass(applicationContext, MainActivity::class.java)
}
startActivity(newIntent)
}

override fun onStop() {
super.onStop()
finish()
}
}
2 changes: 1 addition & 1 deletion atox/src/main/kotlin/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fun Context.hasPermission(permission: String) =
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED

val Fragment.vmFactory: ViewModelFactory
get() = (requireActivity() as MainActivity).vmFactory
get() = (requireActivity() as? MainActivity)?.vmFactory ?: (requireActivity() as NewMainActivity).vmFactory

class NoSuchArgumentException(arg: String) : Exception("No such argument: $arg")

Expand Down
131 changes: 131 additions & 0 deletions atox/src/main/kotlin/NewMainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: 2019-2022 aTox contributors
//
// SPDX-License-Identifier: GPL-3.0-only

package ltd.evilcorp.atox

import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.bundleOf
import androidx.core.view.WindowCompat
import androidx.navigation.fragment.findNavController
import coil.Coil
import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import ltd.evilcorp.atox.di.ViewModelFactory
import ltd.evilcorp.atox.settings.Settings
import ltd.evilcorp.atox.ui.contactlist.ARG_SHARE
import javax.inject.Inject

private const val TAG = "NewMainActivity"
private const val SCHEME = "tox:"
private const val TOX_ID_LENGTH = 76

class NewMainActivity : AppCompatActivity() {
@Inject
lateinit var vmFactory: ViewModelFactory

@Inject
lateinit var autoAway: AutoAway

@Inject
lateinit var settings: Settings

override fun onCreate(savedInstanceState: Bundle?) {
(application as App).component.inject(this)

super.onCreate(savedInstanceState)

if (settings.disableScreenshots) {
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
}

AppCompatDelegate.setDefaultNightMode(settings.theme)

// The view inset/padding adjustments only run for Lollipop and newer.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
WindowCompat.setDecorFitsSystemWindows(window, false)
}

Coil.setImageLoader {
ImageLoader.Builder(this)
.componentRegistry {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
add(ImageDecoderDecoder(this@NewMainActivity))
} else {
add(GifDecoder())
}
}
.build()
}

setTheme(R.style.Theme_aTox_DayNight)
setContentView(R.layout.new_activity_main)

// Only handle intent the first time it triggers the app.
if (savedInstanceState != null) return
handleIntent(intent)
}

override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
handleIntent(intent)
}

override fun onPause() {
super.onPause()
autoAway.onBackground()
}

override fun onResume() {
super.onResume()
autoAway.onForeground()
}

private fun handleIntent(intent: Intent?) {
when (intent?.action) {
Intent.ACTION_VIEW -> handleToxLinkIntent(intent)
Intent.ACTION_SEND -> handleShareIntent(intent)
}
}

private fun handleToxLinkIntent(intent: Intent) {
val data = intent.dataString ?: ""
Log.i(TAG, "Got uri with data: $data")
if (!data.startsWith(SCHEME) || data.length != SCHEME.length + TOX_ID_LENGTH) {
Log.e(TAG, "Got malformed uri: $data")
return
}

supportFragmentManager.findFragmentById(R.id.nav_host_fragment)?.findNavController()?.navigate(
R.id.addContactFragment,
bundleOf("toxId" to data.drop(SCHEME.length)),
)
}

private fun handleShareIntent(intent: Intent) {
if (intent.type != "text/plain") {
Log.e(TAG, "Got unsupported share type ${intent.type}")
return
}

val data = intent.getStringExtra(Intent.EXTRA_TEXT)
if (data.isNullOrEmpty()) {
Log.e(TAG, "Got share intent with no data")
return
}

Log.i(TAG, "Got text share: $data")
val navController =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment)?.findNavController() ?: return
navController.navigate(R.id.contactListFragment, bundleOf(ARG_SHARE to data))
}
}
9 changes: 8 additions & 1 deletion atox/src/main/kotlin/ToxService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.launch
import ltd.evilcorp.atox.settings.Settings
import ltd.evilcorp.atox.tox.ToxStarter
import ltd.evilcorp.core.repository.UserRepository
import ltd.evilcorp.core.vo.ConnectionStatus
Expand Down Expand Up @@ -58,6 +59,9 @@ class ToxService : LifecycleService() {
@Inject
lateinit var proximityScreenOff: ProximityScreenOff

@Inject
lateinit var settings: Settings

private fun createNotificationChannel() {
val channel = NotificationChannelCompat.Builder(channelId, NotificationManagerCompat.IMPORTANCE_LOW)
.setName("Tox Service")
Expand All @@ -74,7 +78,10 @@ class ToxService : LifecycleService() {

private fun notificationFor(status: ConnectionStatus?): Notification {
val pendingIntent: PendingIntent =
Intent(this, MainActivity::class.java).let { notificationIntent ->
Intent(
this,
if (settings.wipUI) NewMainActivity::class.java else MainActivity::class.java,
).let { notificationIntent ->
PendingIntentCompat.getActivity(this, 0, notificationIntent, 0)
}

Expand Down
4 changes: 4 additions & 0 deletions atox/src/main/kotlin/di/AppComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import android.content.Context
import dagger.BindsInstance
import dagger.Component
import ltd.evilcorp.atox.ActionReceiver
import ltd.evilcorp.atox.ActivityLauncher
import ltd.evilcorp.atox.BootReceiver
import ltd.evilcorp.atox.MainActivity
import ltd.evilcorp.atox.NewMainActivity
import ltd.evilcorp.atox.ToxService
import javax.inject.Singleton

Expand All @@ -29,7 +31,9 @@ interface AppComponent {
fun create(@BindsInstance appContext: Context): AppComponent
}

fun inject(activity: ActivityLauncher)
fun inject(activity: MainActivity)
fun inject(activity: NewMainActivity)
fun inject(service: ToxService)
fun inject(receiver: BootReceiver)
fun inject(receiver: ActionReceiver)
Expand Down
6 changes: 6 additions & 0 deletions atox/src/main/kotlin/di/ViewModelModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import ltd.evilcorp.atox.ui.friendrequest.FriendRequestViewModel
import ltd.evilcorp.atox.ui.settings.SettingsViewModel
import ltd.evilcorp.atox.ui.userprofile.UserProfileViewModel
import kotlin.reflect.KClass
import ltd.evilcorp.atox.newui.settings.SettingsViewModel as NewSettingsViewModel

@MustBeDocumented
@Target(
Expand Down Expand Up @@ -73,6 +74,11 @@ abstract class ViewModelModule {
@ViewModelKey(SettingsViewModel::class)
abstract fun bindSettingsViewModel(vm: SettingsViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(NewSettingsViewModel::class)
abstract fun bindNewSettingsViewModel(vm: NewSettingsViewModel): ViewModel

@Binds
@IntoMap
@ViewModelKey(UserProfileViewModel::class)
Expand Down
Loading