@ -16,6 +16,7 @@
package com.keylesspalace.tusky
import android.Manifest
import android.app.NotificationManager
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
@ -41,6 +42,7 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.IntentCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.view.GravityCompat
import androidx.core.view.MenuProvider
@ -182,30 +184,39 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
?: return // will be redirected to LoginActivity by BaseActivity
var showNotificationTab = false
if ( intent != null ) {
// check for savedInstanceState in order to not handle intent events more than once
if ( intent != null && savedInstanceState == null ) {
val notificationId = intent . getIntExtra ( NOTIFICATION _ID , - 1 )
if ( notificationId != - 1 ) {
// opened from a notification action, cancel the notification
val notificationManager = getSystemService ( NOTIFICATION _SERVICE ) as NotificationManager
notificationManager . cancel ( intent . getStringExtra ( NOTIFICATION _TAG ) , notificationId )
}
/ * * there are two possibilities the accountId can be passed to MainActivity :
* - from our code as long ' account _id '
* - from our code as Long Intent Extra TUSKY _ACCOUNT _ID
* - from share shortcuts as String ' android . intent . extra . shortcut . ID '
* /
var accountId = intent . getLongExtra ( NotificationHelper . ACCOUNT _ID , - 1 )
if ( accountId == - 1L ) {
var tuskyA ccountId = intent . getLongExtra ( TUSKY _ ACCOUNT_ID , - 1 )
if ( tuskyA ccountId == - 1L ) {
val accountIdString = intent . getStringExtra ( ShortcutManagerCompat . EXTRA _SHORTCUT _ID )
if ( accountIdString != null ) {
accountId = accountIdString . toLong ( )
tuskyA ccountId = accountIdString . toLong ( )
}
}
val accountRequested = a ccountId != - 1L
if ( accountRequested && a ccountId != activeAccount . id ) {
accountManager . setActiveAccount ( a ccountId)
val accountRequested = tuskyA ccountId != - 1L
if ( accountRequested && tuskyA ccountId != activeAccount . id ) {
accountManager . setActiveAccount ( tuskyA ccountId)
}
val openDrafts = intent . getBooleanExtra ( OPEN _DRAFTS , false )
if ( canHandleMimeType ( intent . type ) ) {
if ( canHandleMimeType ( intent . type ) || intent . hasExtra ( COMPOSE _OPTIONS ) ) {
// Sharing to Tusky from an external app
if ( accountRequested ) {
// The correct account is already active
forwardShare ( intent )
forwardToComposeActivity ( intent )
} else {
// No account was provided, show the chooser
showAccountChooserDialog (
@ -216,10 +227,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
val requestedId = account . id
if ( requestedId == activeAccount . id ) {
// The correct account is already active
forwardShare ( intent )
forwardToComposeActivity ( intent )
} else {
// A different account was requested, restart the activity
intent . putExtra ( NotificationHelper . ACCOUNT _ID , requestedId )
intent . putExtra ( TUSKY _ ACCOUNT_ID , requestedId )
changeAccount ( requestedId , intent )
}
}
@ -229,10 +240,10 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
} else if ( openDrafts ) {
val intent = DraftsActivity . newIntent ( this )
startActivity ( intent )
} else if ( accountRequested && savedInstanceState == null ) {
} else if ( accountRequested && intent . hasExtra ( NOTIFICATION _TYPE ) ) {
// user clicked a notification, show follow requests for type FOLLOW_REQUEST,
// otherwise show notification tab
if ( intent . getStringExtra ( NotificationHelper . TYPE ) == Notification . Type . FOLLOW _REQUEST . name ) {
if ( intent . getSerializableExtra ( NOTIFICATION _ TYPE ) == Notification . Type . FOLLOW _REQUEST ) {
val intent = AccountListActivity . newIntent ( this , AccountListActivity . Type . FOLLOW _REQUESTS )
startActivityWithSlideInAnimation ( intent )
} else {
@ -422,12 +433,19 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
}
}
private fun forwardShare ( intent : Intent ) {
val composeIntent = Intent ( this , ComposeActivity :: class . java )
composeIntent . action = intent . action
composeIntent . type = intent . type
composeIntent . putExtras ( intent )
composeIntent . flags = Intent . FLAG _ACTIVITY _NEW _TASK or Intent . FLAG _ACTIVITY _CLEAR _TASK
private fun forwardToComposeActivity ( intent : Intent ) {
val composeOptions = IntentCompat . getParcelableExtra ( intent , COMPOSE _OPTIONS , ComposeActivity . ComposeOptions :: class . java )
val composeIntent = if ( composeOptions != null ) {
ComposeActivity . startIntent ( this , composeOptions )
} else {
Intent ( this , ComposeActivity :: class . java ) . apply {
action = intent . action
type = intent . type
putExtras ( intent )
flags = Intent . FLAG _ACTIVITY _NEW _TASK or Intent . FLAG _ACTIVITY _CLEAR _TASK
}
}
startActivity ( composeIntent )
finish ( )
}
@ -1043,8 +1061,75 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
private const val TAG = " MainActivity " // logging tag
private const val DRAWER _ITEM _ADD _ACCOUNT : Long = - 13
private const val DRAWER _ITEM _ANNOUNCEMENTS : Long = 14
const val REDIRECT _URL = " redirectUrl "
const val OPEN _DRAFTS = " draft "
private const val REDIRECT _URL = " redirectUrl "
private const val OPEN _DRAFTS = " draft "
private const val TUSKY _ACCOUNT _ID = " tuskyAccountId "
private const val COMPOSE _OPTIONS = " composeOptions "
private const val NOTIFICATION _TYPE = " notificationType "
private const val NOTIFICATION _TAG = " notificationTag "
private const val NOTIFICATION _ID = " notificationId "
/ * *
* Switches the active account to the provided accountId and then stays on MainActivity
* /
@JvmStatic
fun accountSwitchIntent ( context : Context , tuskyAccountId : Long ) : Intent {
return Intent ( context , MainActivity :: class . java ) . apply {
putExtra ( TUSKY _ACCOUNT _ID , tuskyAccountId )
}
}
/ * *
* Switches the active account to the accountId and takes the user to the correct place according to the notification they clicked
* /
@JvmStatic
fun openNotificationIntent ( context : Context , tuskyAccountId : Long , type : Notification . Type ) : Intent {
return accountSwitchIntent ( context , tuskyAccountId ) . apply {
putExtra ( NOTIFICATION _TYPE , type )
}
}
/ * *
* Switches the active account to the accountId and then opens ComposeActivity with the provided options
* @param tuskyAccountId the id of the Tusky account to open the screen with . Set to - 1 for current account .
* @param notificationId optional id of the notification that should be cancelled when this intent is opened
* @param notificationTag optional tag of the notification that should be cancelled when this intent is opened
* /
@JvmStatic
fun composeIntent (
context : Context ,
options : ComposeActivity . ComposeOptions ,
tuskyAccountId : Long = - 1 ,
notificationTag : String ? = null ,
notificationId : Int = - 1
) : Intent {
return accountSwitchIntent ( context , tuskyAccountId ) . apply {
action = Intent . ACTION _SEND // so it can be opened via shortcuts
putExtra ( COMPOSE _OPTIONS , options )
putExtra ( NOTIFICATION _TAG , notificationTag )
putExtra ( NOTIFICATION _ID , notificationId )
}
}
/ * *
* switches the active account to the accountId and then tries to resolve and show the provided url
* /
@JvmStatic
fun redirectIntent ( context : Context , tuskyAccountId : Long , url : String ) : Intent {
return accountSwitchIntent ( context , tuskyAccountId ) . apply {
putExtra ( REDIRECT _URL , url )
flags = Intent . FLAG _ACTIVITY _NEW _TASK or Intent . FLAG _ACTIVITY _CLEAR _TASK
}
}
/ * *
* switches the active account to the provided accountId and then opens drafts
* /
fun draftIntent ( context : Context , tuskyAccountId : Long ) : Intent {
return accountSwitchIntent ( context , tuskyAccountId ) . apply {
putExtra ( OPEN _DRAFTS , true )
}
}
}
}