Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
e660fabc
Commit
e660fabc
authored
Nov 06, 2021
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove BaseDownloader
parent
2115bcd8
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
191 additions
and
217 deletions
+191
-217
BaseDownloader.kt
...java/com/topjohnwu/magisk/core/download/BaseDownloader.kt
+0
-192
DownloadService.kt
...ava/com/topjohnwu/magisk/core/download/DownloadService.kt
+185
-21
ManagerHandler.kt
...java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
+2
-2
Subject.kt
...c/main/java/com/topjohnwu/magisk/core/download/Subject.kt
+2
-0
HomeFragment.kt
...rc/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
+2
-2
No files found.
app/src/main/java/com/topjohnwu/magisk/core/download/BaseDownloader.kt
deleted
100644 → 0
View file @
2115bcd8
package
com.topjohnwu.magisk.core.download
import
android.app.Notification
import
android.content.Intent
import
android.os.IBinder
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.MutableLiveData
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.ForegroundTracker
import
com.topjohnwu.magisk.core.base.BaseService
import
com.topjohnwu.magisk.core.utils.ProgressInputStream
import
com.topjohnwu.magisk.di.ServiceLocator
import
com.topjohnwu.magisk.view.Notifications
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.cancel
import
kotlinx.coroutines.launch
import
okhttp3.ResponseBody
import
timber.log.Timber
import
java.io.IOException
import
java.io.InputStream
import
java.util.*
import
kotlin.collections.HashMap
import
kotlin.random.Random.Default.nextInt
abstract
class
BaseDownloader
:
BaseService
()
{
private
val
hasNotifications
get
()
=
notifications
.
isNotEmpty
()
private
val
notifications
=
Collections
.
synchronizedMap
(
HashMap
<
Int
,
Notification
.
Builder
>())
private
val
coroutineScope
=
CoroutineScope
(
Dispatchers
.
IO
)
val
service
get
()
=
ServiceLocator
.
networkService
// -- Service overrides
override
fun
onBind
(
intent
:
Intent
?):
IBinder
?
=
null
override
fun
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
):
Int
{
intent
.
getParcelableExtra
<
Subject
>(
ACTION_KEY
)
?.
let
{
subject
->
update
(
subject
.
notifyID
())
coroutineScope
.
launch
{
try
{
subject
.
startDownload
()
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
notifyFail
(
subject
)
}
}
}
return
START_REDELIVER_INTENT
}
override
fun
onTaskRemoved
(
rootIntent
:
Intent
?)
{
super
.
onTaskRemoved
(
rootIntent
)
notifications
.
forEach
{
cancel
(
it
.
key
)
}
notifications
.
clear
()
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
coroutineScope
.
cancel
()
}
// -- Download logic
private
suspend
fun
Subject
.
startDownload
()
{
val
stream
=
service
.
fetchFile
(
url
).
toProgressStream
(
this
)
when
(
this
)
{
is
Subject
.
Module
->
// Download and process on-the-fly
stream
.
toModule
(
file
,
service
.
fetchInstaller
().
byteStream
())
is
Subject
.
Manager
->
handleAPK
(
this
,
stream
)
}
val
newId
=
notifyFinish
(
this
)
if
(
ForegroundTracker
.
hasForeground
)
onFinish
(
this
,
newId
)
if
(!
hasNotifications
)
stopSelf
()
}
private
fun
ResponseBody
.
toProgressStream
(
subject
:
Subject
):
InputStream
{
val
max
=
contentLength
()
val
total
=
max
.
toFloat
()
/
1048576
val
id
=
subject
.
notifyID
()
update
(
id
)
{
it
.
setContentTitle
(
subject
.
title
)
}
return
ProgressInputStream
(
byteStream
())
{
val
progress
=
it
.
toFloat
()
/
1048576
update
(
id
)
{
notification
->
if
(
max
>
0
)
{
broadcast
(
progress
/
total
,
subject
)
notification
.
setProgress
(
max
.
toInt
(),
it
.
toInt
(),
false
)
.
setContentText
(
"%.2f / %.2f MB"
.
format
(
progress
,
total
))
}
else
{
broadcast
(-
1f
,
subject
)
notification
.
setContentText
(
"%.2f MB / ??"
.
format
(
progress
))
}
}
}
}
// --- Notification managements
fun
Subject
.
notifyID
()
=
hashCode
()
private
fun
notifyFail
(
subject
:
Subject
)
=
lastNotify
(
subject
.
notifyID
())
{
broadcast
(-
2f
,
subject
)
it
.
setContentText
(
getString
(
R
.
string
.
download_file_error
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_notify_error
)
.
setOngoing
(
false
)
}
private
fun
notifyFinish
(
subject
:
Subject
)
=
lastNotify
(
subject
.
notifyID
())
{
broadcast
(
1f
,
subject
)
it
.
setIntent
(
subject
)
.
setContentTitle
(
subject
.
title
)
.
setContentText
(
getString
(
R
.
string
.
download_complete
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_sys_download_done
)
.
setProgress
(
0
,
0
,
false
)
.
setOngoing
(
false
)
.
setAutoCancel
(
true
)
}
private
fun
create
()
=
Notifications
.
progress
(
this
,
""
)
fun
update
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Unit
=
{})
{
val
wasEmpty
=
!
hasNotifications
val
notification
=
notifications
.
getOrPut
(
id
,
::
create
).
also
(
editor
)
if
(
wasEmpty
)
updateForeground
()
else
notify
(
id
,
notification
.
build
())
}
private
fun
lastNotify
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Notification
.
Builder
?
=
{
null
}
)
:
Int
{
val
notification
=
remove
(
id
)
?.
run
(
editor
)
?:
return
-
1
val
newId
:
Int
=
nextInt
()
notify
(
newId
,
notification
.
build
())
return
newId
}
protected
fun
remove
(
id
:
Int
)
=
notifications
.
remove
(
id
)
?.
also
{
updateForeground
();
cancel
(
id
)
}
?:
{
cancel
(
id
);
null
}()
private
fun
notify
(
id
:
Int
,
notification
:
Notification
)
{
Notifications
.
mgr
.
notify
(
id
,
notification
)
}
private
fun
cancel
(
id
:
Int
)
{
Notifications
.
mgr
.
cancel
(
id
)
}
private
fun
updateForeground
()
{
if
(
hasNotifications
)
{
val
(
id
,
notification
)
=
notifications
.
entries
.
first
()
startForeground
(
id
,
notification
.
build
())
}
else
{
stopForeground
(
false
)
}
}
// --- Implement custom logic
protected
abstract
suspend
fun
onFinish
(
subject
:
Subject
,
id
:
Int
)
protected
abstract
fun
Notification
.
Builder
.
setIntent
(
subject
:
Subject
):
Notification
.
Builder
// ---
companion
object
{
const
val
ACTION_KEY
=
"download_action"
private
val
progressBroadcast
=
MutableLiveData
<
Pair
<
Float
,
Subject
>?>()
fun
observeProgress
(
owner
:
LifecycleOwner
,
callback
:
(
Float
,
Subject
)
->
Unit
)
{
progressBroadcast
.
value
=
null
progressBroadcast
.
observe
(
owner
)
{
val
(
progress
,
subject
)
=
it
?:
return
@observe
callback
(
progress
,
subject
)
}
}
private
fun
broadcast
(
progress
:
Float
,
subject
:
Subject
)
{
progressBroadcast
.
postValue
(
progress
to
subject
)
}
}
}
app/src/main/java/com/topjohnwu/magisk/core/download/DownloadService.kt
View file @
e660fabc
package
com.topjohnwu.magisk.core.download
package
com.topjohnwu.magisk.core.download
import
android.annotation.SuppressLint
import
android.app.Notification
import
android.app.Notification
import
android.app.PendingIntent
import
android.app.PendingIntent
import
android.content.Context
import
android.content.Context
import
android.content.Intent
import
android.content.Intent
import
android.os.Build
import
android.os.Build
import
android.os.IBinder
import
androidx.core.net.toFile
import
androidx.core.net.toFile
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.MutableLiveData
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.BaseUIActivity
import
com.topjohnwu.magisk.arch.BaseUIActivity
import
com.topjohnwu.magisk.core.ForegroundTracker
import
com.topjohnwu.magisk.core.ForegroundTracker
import
com.topjohnwu.magisk.core.base.BaseService
import
com.topjohnwu.magisk.core.download.Action.Flash
import
com.topjohnwu.magisk.core.download.Action.Flash
import
com.topjohnwu.magisk.core.download.Subject.Manager
import
com.topjohnwu.magisk.core.download.Subject.Manager
import
com.topjohnwu.magisk.core.download.Subject.Module
import
com.topjohnwu.magisk.core.download.Subject.Module
import
com.topjohnwu.magisk.core.intent
import
com.topjohnwu.magisk.core.intent
import
com.topjohnwu.magisk.core.utils.ProgressInputStream
import
com.topjohnwu.magisk.di.ServiceLocator
import
com.topjohnwu.magisk.ui.flash.FlashFragment
import
com.topjohnwu.magisk.ui.flash.FlashFragment
import
com.topjohnwu.magisk.utils.APKInstall
import
com.topjohnwu.magisk.utils.APKInstall
import
com.topjohnwu.magisk.view.Notifications
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
com.topjohnwu.superuser.internal.UiThreadHandler
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.cancel
import
kotlinx.coroutines.launch
import
okhttp3.ResponseBody
import
timber.log.Timber
import
java.io.IOException
import
java.io.InputStream
import
java.util.*
import
kotlin.collections.HashMap
import
kotlin.random.Random.Default.nextInt
import
kotlin.random.Random.Default.nextInt
open
class
DownloadService
:
BaseDownloader
()
{
class
DownloadService
:
BaseService
()
{
private
val
context
get
()
=
this
private
val
context
get
()
=
this
private
val
hasNotifications
get
()
=
notifications
.
isNotEmpty
()
private
val
notifications
=
Collections
.
synchronizedMap
(
HashMap
<
Int
,
Notification
.
Builder
>())
private
val
coroutineScope
=
CoroutineScope
(
Dispatchers
.
IO
)
override
suspend
fun
onFinish
(
subject
:
Subject
,
id
:
Int
)
=
when
(
subject
)
{
val
service
get
()
=
ServiceLocator
.
networkService
is
Module
->
subject
.
onFinish
(
id
)
private
val
mgr
get
()
=
Notifications
.
mgr
is
Manager
->
subject
.
onFinish
(
id
)
// -- Service overrides
override
fun
onBind
(
intent
:
Intent
?):
IBinder
?
=
null
override
fun
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
):
Int
{
intent
.
getParcelableExtra
<
Subject
>(
SUBJECT_KEY
)
?.
let
{
subject
->
update
(
subject
.
notifyID
())
coroutineScope
.
launch
{
try
{
subject
.
startDownload
()
}
catch
(
e
:
IOException
)
{
Timber
.
e
(
e
)
notifyFail
(
subject
)
}
}
}
return
START_REDELIVER_INTENT
}
}
private
fun
Module
.
onFinish
(
id
:
Int
)
=
when
(
action
)
{
override
fun
onTaskRemoved
(
rootIntent
:
Intent
?)
{
Flash
->
{
super
.
onTaskRemoved
(
rootIntent
)
UiThreadHandler
.
run
{
notifications
.
forEach
{
mgr
.
cancel
(
it
.
key
)
}
(
ForegroundTracker
.
foreground
as
?
BaseUIActivity
<*,
*>)
notifications
.
clear
()
?.
navigation
?.
navigate
(
FlashFragment
.
install
(
file
,
id
))
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
coroutineScope
.
cancel
()
}
// -- Download logic
private
suspend
fun
Subject
.
startDownload
()
{
val
stream
=
service
.
fetchFile
(
url
).
toProgressStream
(
this
)
when
(
this
)
{
is
Module
->
// Download and process on-the-fly
stream
.
toModule
(
file
,
service
.
fetchInstaller
().
byteStream
())
is
Manager
->
handleAPK
(
this
,
stream
)
}
val
newId
=
notifyFinish
(
this
)
if
(
ForegroundTracker
.
hasForeground
)
onFinish
(
this
,
newId
)
if
(!
hasNotifications
)
stopSelf
()
}
private
fun
ResponseBody
.
toProgressStream
(
subject
:
Subject
):
InputStream
{
val
max
=
contentLength
()
val
total
=
max
.
toFloat
()
/
1048576
val
id
=
subject
.
notifyID
()
update
(
id
)
{
it
.
setContentTitle
(
subject
.
title
)
}
return
ProgressInputStream
(
byteStream
())
{
val
progress
=
it
.
toFloat
()
/
1048576
update
(
id
)
{
notification
->
if
(
max
>
0
)
{
broadcast
(
progress
/
total
,
subject
)
notification
.
setProgress
(
max
.
toInt
(),
it
.
toInt
(),
false
)
.
setContentText
(
"%.2f / %.2f MB"
.
format
(
progress
,
total
))
}
else
{
broadcast
(-
1f
,
subject
)
notification
.
setContentText
(
"%.2f MB / ??"
.
format
(
progress
))
}
}
}
}
}
else
->
Unit
}
}
private
fun
Manager
.
onFinish
(
id
:
Int
)
{
// --- Notifications
remove
(
id
)
APKInstall
.
install
(
context
,
file
.
toFile
())
private
fun
notifyFail
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyID
())
{
broadcast
(-
2f
,
subject
)
it
.
setContentText
(
getString
(
R
.
string
.
download_file_error
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_notify_error
)
.
setOngoing
(
false
)
}
private
fun
notifyFinish
(
subject
:
Subject
)
=
finalNotify
(
subject
.
notifyID
())
{
broadcast
(
1f
,
subject
)
it
.
setIntent
(
subject
)
.
setContentTitle
(
subject
.
title
)
.
setContentText
(
getString
(
R
.
string
.
download_complete
))
.
setSmallIcon
(
android
.
R
.
drawable
.
stat_sys_download_done
)
.
setProgress
(
0
,
0
,
false
)
.
setOngoing
(
false
)
.
setAutoCancel
(
true
)
}
private
fun
finalNotify
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Notification
.
Builder
)
:
Int
{
val
notification
=
remove
(
id
)
?.
run
(
editor
)
?:
return
-
1
val
newId
=
nextInt
()
mgr
.
notify
(
newId
,
notification
.
build
())
return
newId
}
}
// --- Customize finish notification
fun
create
()
=
Notifications
.
progress
(
this
,
""
)
override
fun
Notification
.
Builder
.
setIntent
(
subject
:
Subject
)
fun
update
(
id
:
Int
,
editor
:
(
Notification
.
Builder
)
->
Unit
=
{})
{
=
when
(
subject
)
{
val
wasEmpty
=
!
hasNotifications
val
notification
=
notifications
.
getOrPut
(
id
,
::
create
).
also
(
editor
)
if
(
wasEmpty
)
updateForeground
()
else
mgr
.
notify
(
id
,
notification
.
build
())
}
private
fun
remove
(
id
:
Int
):
Notification
.
Builder
?
{
val
n
=
notifications
.
remove
(
id
)
?.
also
{
updateForeground
()
}
mgr
.
cancel
(
id
)
return
n
}
private
fun
updateForeground
()
{
if
(
hasNotifications
)
{
val
(
id
,
notification
)
=
notifications
.
entries
.
first
()
startForeground
(
id
,
notification
.
build
())
}
else
{
stopForeground
(
false
)
}
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Subject
)
=
when
(
subject
)
{
is
Module
->
setIntent
(
subject
)
is
Module
->
setIntent
(
subject
)
is
Manager
->
setIntent
(
subject
)
is
Manager
->
setIntent
(
subject
)
}
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Module
)
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Module
)
=
when
(
subject
.
action
)
{
=
when
(
subject
.
action
)
{
Flash
->
setContentIntent
(
FlashFragment
.
installIntent
(
context
,
subject
.
file
))
Flash
->
setContentIntent
(
FlashFragment
.
installIntent
(
context
,
subject
.
file
))
else
->
setContentIntent
(
Intent
())
else
->
setContentIntent
(
Intent
())
}
}
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Manager
)
private
fun
Notification
.
Builder
.
setIntent
(
subject
:
Manager
)
=
=
setContentIntent
(
APKInstall
.
installIntent
(
context
,
subject
.
file
.
toFile
()))
setContentIntent
(
APKInstall
.
installIntent
(
context
,
subject
.
file
.
toFile
()))
@SuppressLint
(
"InlinedApi"
)
private
fun
Notification
.
Builder
.
setContentIntent
(
intent
:
Intent
)
=
private
fun
Notification
.
Builder
.
setContentIntent
(
intent
:
Intent
)
=
setContentIntent
(
PendingIntent
.
getActivity
(
context
,
nextInt
(),
intent
,
setContentIntent
(
PendingIntent
.
getActivity
(
context
,
nextInt
(),
intent
,
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_ONE_SHOT
))
PendingIntent
.
FLAG_IMMUTABLE
or
PendingIntent
.
FLAG_ONE_SHOT
))
// ---
// -- Post download processing
private
fun
onFinish
(
subject
:
Subject
,
id
:
Int
)
=
when
(
subject
)
{
is
Module
->
subject
.
onFinish
(
id
)
is
Manager
->
subject
.
onFinish
(
id
)
}
private
fun
Module
.
onFinish
(
id
:
Int
)
=
when
(
action
)
{
Flash
->
{
UiThreadHandler
.
run
{
(
ForegroundTracker
.
foreground
as
?
BaseUIActivity
<*,
*>)
?.
navigation
?.
navigate
(
FlashFragment
.
install
(
file
,
id
))
}
}
else
->
Unit
}
private
fun
Manager
.
onFinish
(
id
:
Int
)
{
remove
(
id
)
APKInstall
.
install
(
context
,
file
.
toFile
())
}
companion
object
{
companion
object
{
private
const
val
SUBJECT_KEY
=
"download_subject"
private
val
progressBroadcast
=
MutableLiveData
<
Pair
<
Float
,
Subject
>?>()
fun
observeProgress
(
owner
:
LifecycleOwner
,
callback
:
(
Float
,
Subject
)
->
Unit
)
{
progressBroadcast
.
value
=
null
progressBroadcast
.
observe
(
owner
)
{
val
(
progress
,
subject
)
=
it
?:
return
@observe
callback
(
progress
,
subject
)
}
}
private
fun
broadcast
(
progress
:
Float
,
subject
:
Subject
)
{
progressBroadcast
.
postValue
(
progress
to
subject
)
}
private
fun
intent
(
context
:
Context
,
subject
:
Subject
)
=
private
fun
intent
(
context
:
Context
,
subject
:
Subject
)
=
context
.
intent
<
DownloadService
>().
putExtra
(
ACTION
_KEY
,
subject
)
context
.
intent
<
DownloadService
>().
putExtra
(
SUBJECT
_KEY
,
subject
)
@SuppressLint
(
"InlinedApi"
)
fun
pendingIntent
(
context
:
Context
,
subject
:
Subject
):
PendingIntent
{
fun
pendingIntent
(
context
:
Context
,
subject
:
Subject
):
PendingIntent
{
return
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
{
return
if
(
Build
.
VERSION
.
SDK_INT
>=
26
)
{
PendingIntent
.
getForegroundService
(
context
,
nextInt
(),
intent
(
context
,
subject
),
PendingIntent
.
getForegroundService
(
context
,
nextInt
(),
intent
(
context
,
subject
),
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt
View file @
e660fabc
...
@@ -22,7 +22,7 @@ private fun Context.patch(apk: File) {
...
@@ -22,7 +22,7 @@ private fun Context.patch(apk: File) {
patched
.
renameTo
(
apk
)
patched
.
renameTo
(
apk
)
}
}
private
fun
BaseDownloader
.
notifyHide
(
id
:
Int
)
{
private
fun
DownloadService
.
notifyHide
(
id
:
Int
)
{
update
(
id
)
{
update
(
id
)
{
it
.
setProgress
(
0
,
0
,
true
)
it
.
setProgress
(
0
,
0
,
true
)
.
setContentTitle
(
getString
(
R
.
string
.
hide_app_title
))
.
setContentTitle
(
getString
(
R
.
string
.
hide_app_title
))
...
@@ -48,7 +48,7 @@ private class DupOutputStream(
...
@@ -48,7 +48,7 @@ private class DupOutputStream(
}
}
}
}
suspend
fun
BaseDownloader
.
handleAPK
(
subject
:
Subject
.
Manager
,
stream
:
InputStream
)
{
suspend
fun
DownloadService
.
handleAPK
(
subject
:
Subject
.
Manager
,
stream
:
InputStream
)
{
fun
write
(
output
:
OutputStream
)
{
fun
write
(
output
:
OutputStream
)
{
val
ext
=
subject
.
externalFile
.
outputStream
()
val
ext
=
subject
.
externalFile
.
outputStream
()
val
o
=
DupOutputStream
(
ext
,
output
)
val
o
=
DupOutputStream
(
ext
,
output
)
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/Subject.kt
View file @
e660fabc
...
@@ -52,6 +52,8 @@ sealed class Subject : Parcelable {
...
@@ -52,6 +52,8 @@ sealed class Subject : Parcelable {
val
externalFile
get
()
=
MediaStoreUtils
.
getFile
(
"$title.apk"
).
uri
val
externalFile
get
()
=
MediaStoreUtils
.
getFile
(
"$title.apk"
).
uri
}
}
fun
notifyID
()
=
hashCode
()
}
}
sealed
class
Action
:
Parcelable
{
sealed
class
Action
:
Parcelable
{
...
...
app/src/main/java/com/topjohnwu/magisk/ui/home/HomeFragment.kt
View file @
e660fabc
...
@@ -6,7 +6,7 @@ import android.widget.ImageView
...
@@ -6,7 +6,7 @@ import android.widget.ImageView
import
android.widget.TextView
import
android.widget.TextView
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.arch.BaseUIFragment
import
com.topjohnwu.magisk.arch.BaseUIFragment
import
com.topjohnwu.magisk.core.download.
BaseDownloader
import
com.topjohnwu.magisk.core.download.
DownloadService
import
com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
import
com.topjohnwu.magisk.databinding.FragmentHomeMd2Binding
import
com.topjohnwu.magisk.di.viewModel
import
com.topjohnwu.magisk.di.viewModel
import
com.topjohnwu.magisk.events.RebootEvent
import
com.topjohnwu.magisk.events.RebootEvent
...
@@ -21,7 +21,7 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
...
@@ -21,7 +21,7 @@ class HomeFragment : BaseUIFragment<HomeViewModel, FragmentHomeMd2Binding>() {
super
.
onStart
()
super
.
onStart
()
activity
.
title
=
resources
.
getString
(
R
.
string
.
section_home
)
activity
.
title
=
resources
.
getString
(
R
.
string
.
section_home
)
setHasOptionsMenu
(
true
)
setHasOptionsMenu
(
true
)
BaseDownloader
.
observeProgress
(
this
,
viewModel
::
onProgressUpdate
)
DownloadService
.
observeProgress
(
this
,
viewModel
::
onProgressUpdate
)
}
}
private
fun
checkTitle
(
text
:
TextView
,
icon
:
ImageView
)
{
private
fun
checkTitle
(
text
:
TextView
,
icon
:
ImageView
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment