@ -13,7 +13,6 @@ import android.content.Intent
import android.content.res.Configuration
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Color
import android.graphics.Rect
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
import android.os.Bundle
import android.os.Handler
import android.os.Handler
import android.os.Looper
import android.os.Looper
@ -22,13 +21,15 @@ import android.text.TextWatcher
import android.view.MenuItem
import android.view.MenuItem
import android.view.MotionEvent
import android.view.MotionEvent
import android.view.View
import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.view.WindowManager
import android.view.WindowManager
import android.view.animation.DecelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import android.widget.EditText
import android.widget.Toast
import android.widget.Toast
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsAnimationCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView
import androidx.room.Room
import androidx.room.Room
@ -61,6 +62,7 @@ import com.fox2code.mmm.utils.io.net.Http.Companion.hasWebView
import com.fox2code.mmm.utils.room.ReposListDatabase
import com.fox2code.mmm.utils.room.ReposListDatabase
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.elevation.SurfaceColors
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.material.progressindicator.LinearProgressIndicator
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputEditText
@ -70,6 +72,7 @@ import java.sql.Timestamp
class MainActivity : FoxActivity ( ) , OnRefreshListener , OverScrollHelper {
class MainActivity : FoxActivity ( ) , OnRefreshListener , OverScrollHelper {
private lateinit var bottomNavigationView : BottomNavigationView
val moduleViewListBuilder : ModuleViewListBuilder = ModuleViewListBuilder ( this )
val moduleViewListBuilder : ModuleViewListBuilder = ModuleViewListBuilder ( this )
val moduleViewListBuilderOnline : ModuleViewListBuilder = ModuleViewListBuilder ( this )
val moduleViewListBuilderOnline : ModuleViewListBuilder = ModuleViewListBuilder ( this )
var progressIndicator : LinearProgressIndicator ? = null
var progressIndicator : LinearProgressIndicator ? = null
@ -96,6 +99,12 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
override fun onResume ( ) {
override fun onResume ( ) {
onMainActivityResume ( this )
onMainActivityResume ( this )
// check that installed or online is selected depending on which recyclerview is visible
if ( moduleList !! . visibility == View . VISIBLE ) {
bottomNavigationView . selectedItemId = R . id . installed _menu _item
} else {
bottomNavigationView . selectedItemId = R . id . online _menu _item
}
super . onResume ( )
super . onResume ( )
}
}
@ -159,22 +168,8 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
}
}
setContentView ( R . layout . activity _main )
setContentView ( R . layout . activity _main )
this . setTitle ( R . string . app _name _v2 )
this . setTitle ( R . string . app _name _v2 )
// set window flags to ignore status bar
// set navigation bar color based on surfacecolors
if ( Build . VERSION . SDK _INT >= Build . VERSION_CODES . R ) {
window . navigationBarColor = SurfaceColors . SURFACE _2 . getColor ( this )
// ignore status bar space
this . window . setDecorFitsSystemWindows ( false )
} else {
this . window . setFlags (
WindowManager . LayoutParams . FLAG _LAYOUT _NO _LIMITS ,
WindowManager . LayoutParams . FLAG _LAYOUT _NO _LIMITS
)
}
if ( Build . VERSION . SDK _INT >= Build . VERSION_CODES . P ) {
val layoutParams = this . window . attributes
layoutParams . layoutInDisplayCutoutMode = // Support cutout in Android 9
WindowManager . LayoutParams . LAYOUT _IN _DISPLAY _CUTOUT _MODE _SHORT _EDGES
this . window . attributes = layoutParams
}
progressIndicator = findViewById ( R . id . progress _bar )
progressIndicator = findViewById ( R . id . progress _bar )
swipeRefreshLayout = findViewById ( R . id . swipe _refresh )
swipeRefreshLayout = findViewById ( R . id . swipe _refresh )
val swipeRefreshLayout = swipeRefreshLayout !!
val swipeRefreshLayout = swipeRefreshLayout !!
@ -185,6 +180,45 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
moduleListOnline = findViewById ( R . id . module _list _online )
moduleListOnline = findViewById ( R . id . module _list _online )
searchTextInputEditText = findViewById ( R . id . search _input )
searchTextInputEditText = findViewById ( R . id . search _input )
val textInputEditText = searchTextInputEditText !!
val textInputEditText = searchTextInputEditText !!
val view = findViewById < View > ( R . id . root _container )
var startBottom = 0f
var endBottom = 0f
ViewCompat . setWindowInsetsAnimationCallback (
view ,
object : WindowInsetsAnimationCompat . Callback ( DISPATCH _MODE _STOP ) {
// Override methods…
override fun onProgress (
insets : WindowInsetsCompat ,
runningAnimations : MutableList < WindowInsetsAnimationCompat >
) : WindowInsetsCompat {
// Find an IME animation.
val imeAnimation = runningAnimations . find {
it . typeMask and WindowInsetsCompat . Type . ime ( ) != 0
} ?: return insets
Timber . d ( " IME animation progress: %f " , imeAnimation . interpolatedFraction )
// smoothly offset the view based on the interpolated fraction of the IME animation.
view . translationY =
( startBottom - endBottom ) * ( 1 - imeAnimation . interpolatedFraction )
return insets
}
override fun onStart (
animation : WindowInsetsAnimationCompat ,
bounds : WindowInsetsAnimationCompat . BoundsCompat
) : WindowInsetsAnimationCompat . BoundsCompat {
// Record the position of the view after the IME transition.
endBottom = view . bottom . toFloat ( )
Timber . d ( " IME animation start: %f " , endBottom )
return bounds
}
override fun onPrepare ( animation : WindowInsetsAnimationCompat ) {
startBottom = view . bottom . toFloat ( )
Timber . d ( " IME animation prepare: %f " , startBottom )
}
}
)
// set search view listeners for text edit. filter the appropriate list based on visibility. do the filtering as the user types not just on submit as a background task
// set search view listeners for text edit. filter the appropriate list based on visibility. do the filtering as the user types not just on submit as a background task
textInputEditText . addTextChangedListener ( object : TextWatcher {
textInputEditText . addTextChangedListener ( object : TextWatcher {
override fun beforeTextChanged (
override fun beforeTextChanged (
@ -314,11 +348,17 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
// get background color and elevation of reboot fab
// get background color and elevation of reboot fab
moduleList . addOnScrollListener ( object : RecyclerView . OnScrollListener ( ) {
moduleList . addOnScrollListener ( object : RecyclerView . OnScrollListener ( ) {
override fun onScrollStateChanged ( recyclerView : RecyclerView , newState : Int ) {
override fun onScrollStateChanged ( recyclerView : RecyclerView , newState : Int ) {
if ( newState != RecyclerView . SCROLL _STATE _IDLE ) textInputEditText . clearFocus ( )
if ( newState != RecyclerView . SCROLL _STATE _IDLE ) {
// hide search view and reboot fab when scrolling - we have to account for padding, corners, and shadows
textInputEditText . clearFocus ( )
}
// hide reboot fab on scroll by fading it out
if ( newState == RecyclerView . SCROLL _STATE _DRAGGING ) {
if ( newState == RecyclerView . SCROLL _STATE _DRAGGING ) {
rebootFab . animate ( ) . translationY ( rebootFab . height . toFloat ( ) + 2 * 8 + 2 * 2 )
rebootFab . animate ( ) . alpha ( 0f ) . setDuration ( 300 )
. setInterpolator ( DecelerateInterpolator ( 2f ) ) . start ( )
. setListener ( object : AnimatorListenerAdapter ( ) {
override fun onAnimationEnd ( animation : Animator ) {
rebootFab . visibility = View . GONE
}
} )
}
}
}
}
@ -326,8 +366,8 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
super . onScrolled ( recyclerView , dx , dy )
super . onScrolled ( recyclerView , dx , dy )
// if the user scrolled up, show the search bar
// if the user scrolled up, show the search bar
if ( dy < 0 ) {
if ( dy < 0 ) {
rebootFab . animate( ) . translationY ( 0f ) . setInterpolator ( DecelerateInterpolator ( 2f ) )
rebootFab . visibility = View . VISIBLE
. start ( )
rebootFab . animate ( ) . alpha ( 1f ) . setDuration ( 300 ) . setListener ( null )
}
}
}
}
} )
} )
@ -337,16 +377,23 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
if ( newState != RecyclerView . SCROLL _STATE _IDLE ) textInputEditText . clearFocus ( )
if ( newState != RecyclerView . SCROLL _STATE _IDLE ) textInputEditText . clearFocus ( )
// hide search view when scrolling
// hide search view when scrolling
if ( newState == RecyclerView . SCROLL _STATE _DRAGGING ) {
if ( newState == RecyclerView . SCROLL _STATE _DRAGGING ) {
rebootFab . animate ( ) . translationY ( rebootFab . height . toFloat ( ) + 2 * 8 + 2 * 2 )
textInputEditText . clearFocus ( )
. setInterpolator ( DecelerateInterpolator ( 2f ) ) . start ( )
// animate reboot fab out
rebootFab . animate ( ) . alpha ( 0f ) . setDuration ( 300 )
. setListener ( object : AnimatorListenerAdapter ( ) {
override fun onAnimationEnd ( animation : Animator ) {
rebootFab . visibility = View . GONE
}
} )
}
}
}
}
override fun onScrolled ( recyclerView : RecyclerView , dx : Int , dy : Int ) {
override fun onScrolled ( recyclerView : RecyclerView , dx : Int , dy : Int ) {
super . onScrolled ( recyclerView , dx , dy )
super . onScrolled ( recyclerView , dx , dy )
// if the user scrolled up, show the search bar
// if the user scrolled up, show the reboot fab
if ( dy < 0 ) {
if ( dy < 0 ) {
rebootFab . animate ( ) . translationY ( 0f )
rebootFab . visibility = View . VISIBLE
rebootFab . animate ( ) . alpha ( 1f ) . setDuration ( 300 ) . setListener ( null )
}
}
}
}
} )
} )
@ -357,13 +404,19 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
this . updateScreenInsets ( this . resources . configuration )
this . updateScreenInsets ( this . resources . configuration )
// on the bottom nav, there's a settings item. open the settings activity when it's clicked.
// on the bottom nav, there's a settings item. open the settings activity when it's clicked.
val bottomNavigationView = findViewById < BottomNavigationView > ( R . id . bottom _navigation )
bottomNavigationView = findViewById ( R . id . bottom _navigation )
bottomNavigationView . setOnItemSelectedListener { item : MenuItem ->
bottomNavigationView . setOnItemSelectedListener { item : MenuItem ->
when ( item . itemId ) {
when ( item . itemId ) {
R . id . settings _menu _item -> {
R . id . settings _menu _item -> {
TrackHelper . track ( ) . event ( " view_list " , " settings " )
TrackHelper . track ( ) . event ( " view_list " , " settings " )
. with ( MainApplication . INSTANCE !! . tracker )
. with ( MainApplication . INSTANCE !! . tracker )
startActivity ( Intent ( this @MainActivity , SettingsActivity :: class . java ) )
// start settings activity so that when user presses back, they go back to main activity and on api34 they see a preview of the main activity. tell settings activity current active tab so that it can be selected when user goes back to main activity
val intent = Intent ( this @MainActivity , SettingsActivity :: class . java )
when ( bottomNavigationView . selectedItemId ) {
R . id . online _menu _item -> intent . putExtra ( " activeTab " , " online " )
R . id . installed _menu _item -> intent . putExtra ( " activeTab " , " installed " )
}
startActivity ( intent )
}
}
R . id . online _menu _item -> {
R . id . online _menu _item -> {
@ -420,24 +473,6 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
} else {
} else {
bottomNavigationView . selectedItemId = R . id . installed _menu _item
bottomNavigationView . selectedItemId = R . id . installed _menu _item
}
}
// update the padding of blur_frame to match the new bottom nav height
val blurFrame = findViewById < View > ( R . id . blur _frame )
blurFrame . post {
blurFrame . setPadding (
blurFrame . paddingLeft ,
blurFrame . paddingTop ,
blurFrame . paddingRight ,
bottomNavigationView . height
)
}
// for some reason, root_container has a margin at the top. remove it.
val rootContainer = findViewById < View > ( R . id . root _container )
rootContainer . post {
val params = rootContainer . layoutParams as MarginLayoutParams
params . topMargin = 0
rootContainer . layoutParams = params
rootContainer . y = 0f
}
// reset update module and update module count in main application
// reset update module and update module count in main application
MainApplication . INSTANCE !! . resetUpdateModule ( )
MainApplication . INSTANCE !! . resetUpdateModule ( )
tryGetMagiskPathAsync ( object : InstallerInitializer . Callback {
tryGetMagiskPathAsync ( object : InstallerInitializer . Callback {
@ -646,8 +681,6 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
//this.actionBarBlur.invalidate();
//this.actionBarBlur.invalidate();
overScrollInsetTop = statusBarHeight
overScrollInsetTop = statusBarHeight
overScrollInsetBottom = bottomInset
overScrollInsetBottom = bottomInset
// set root_container to have zero padding
findViewById < View > ( R . id . root _container ) . setPadding ( 0 , statusBarHeight , 0 , 0 )
}
}
private fun updateBlurState ( ) {
private fun updateBlurState ( ) {
@ -913,6 +946,15 @@ class MainActivity : FoxActivity(), OnRefreshListener, OverScrollHelper {
return super . dispatchTouchEvent ( event )
return super . dispatchTouchEvent ( event )
}
}
override fun setOnBackPressedCallback ( onBackPressedCallback : OnBackPressedCallback ? ) {
// if is on online list, go back to installed list
if ( moduleListOnline !! . visibility == View . VISIBLE ) {
bottomNavigationView . selectedItemId = R . id . installed _menu _item
} else {
super . setOnBackPressedCallback ( onBackPressedCallback )
}
}
companion object {
companion object {
fun getFoxActivity ( activity : FoxActivity ) : FoxActivity {
fun getFoxActivity ( activity : FoxActivity ) : FoxActivity {
return activity
return activity