manager redesign

This commit is contained in:
Xinto 2020-10-31 23:45:39 +04:00
parent 68e9241ab8
commit ca637c5114
199 changed files with 4274 additions and 2631 deletions

View File

@ -20,13 +20,12 @@ android {
applicationId "com.vanced.manager"
minSdkVersion 21
targetSdkVersion 30
versionCode 131
versionName "1.3.1 (Arcturus)"
versionCode 200
versionName "2.0.0 (.nomagisk)"
vectorDrawables.useSupportLibrary = true
buildConfigField "String[]", "MANAGER_LANGUAGES", "{" + surroundWithQuotes(langs) + "}"
buildConfigField "String[]", "MANAGER_LANGUAGE_NAMES", "{" + surroundWithQuotes(getLanguageNames()) + "}"
}
lintOptions {
@ -83,20 +82,6 @@ def getLanguages() {
return langs.toArray()
}
def getLanguageNames() {
List<String> langnames = new ArrayList<String>()
for (int i = 0; i < langs.size(); i++) {
if (langs[i].length() > 2) {
Locale loc = new Locale(langs[i].substring(0, langs[i].length() - 3), langs[i].substring(langs[i].length() - 2))
langnames.add(loc.getDisplayLanguage(loc).capitalize() + " (" + loc.getDisplayCountry(loc).capitalize() + ")")
} else {
Locale loc = new Locale(langs[i])
langnames.add(loc.getDisplayLanguage(loc).capitalize())
}
}
return langnames.toArray()
}
def surroundWithQuotes(Object[] arr) {
String[] dummyArr = arr
for (int i = 0; i < arr.length; i++) {
@ -114,31 +99,33 @@ dependencies {
// AndroidX
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.browser:browser:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.3'
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.fragment:fragment-ktx:1.2.5'
implementation 'androidx.lifecycle:lifecycle-livedata-core-ktx:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
implementation 'com.google.android.material:material:1.3.0-alpha02'
implementation 'com.google.android.material:material:1.3.0-alpha03'
// Other
implementation 'com.beust:klaxon:5.3'
implementation 'com.crowdin.platform:mobile-sdk:1.1.6'
implementation 'com.github.florent37:viewtooltip:1.2.2'
implementation 'com.github.kittinunf.fuel:fuel:2.2.3'
implementation 'com.github.kittinunf.fuel:fuel-coroutines:2.2.3'
implementation 'com.github.kittinunf.fuel:fuel-json:2.2.3'
implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1'
implementation 'com.github.topjohnwu.libsu:core:3.0.1'
implementation 'com.github.topjohnwu.libsu:io:3.0.1'
implementation 'com.google.firebase:firebase-messaging:20.2.4'
implementation 'com.google.firebase:firebase-perf:19.0.8'
implementation 'com.github.topjohnwu.libsu:core:3.0.2'
implementation 'com.github.topjohnwu.libsu:io:3.0.2'
implementation 'com.google.android:flexbox:2.0.1'
implementation 'com.google.firebase:firebase-messaging:21.0.0'
implementation 'com.google.firebase:firebase-perf:19.0.9'
implementation 'com.google.firebase:firebase-analytics-ktx:18.0.0'
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
implementation 'com.mindorks.android:prdownloader:0.6.0'
implementation 'com.google.firebase:firebase-analytics-ktx:17.5.0'
implementation 'com.google.firebase:firebase-crashlytics:17.2.1'
implementation 'com.squareup.okhttp3:logging-interceptor:4.8.1'
}

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.vanced.manager">
@ -14,6 +13,7 @@
<package android:name="com.vanced.android.youtube" />
<package android:name="com.google.android.youtube" />
<package android:name="com.vanced.android.apps.youtube.music" />
<package android:name="com.google.android.apps.youtube.music" />
<package android:name="com.mgoogle.android.gms" />
</queries>
@ -40,22 +40,26 @@
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<activity
android:name=".ui.WelcomeActivity"
android:theme="@style/DarkTheme.Blue"/>
<activity
android:name=".ui.MainActivity"
android:label="@string/app_name"
android:theme="@style/DarkTheme.Blue"
android:configChanges="layoutDirection|locale"
android:exported="true"/>
android:exported="true"
android:label="@string/app_name"
android:theme="@style/DarkTheme.Blue" />
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
<provider
android:authorities="${applicationId}.provider"
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
@ -79,10 +83,9 @@
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_name" />
<service android:name=".core.installer.SplitInstallerService" />
<service android:name=".core.installer.AppUninstallerService" />
<service android:name=".core.installer.AppInstallerService" />
</application>
</manifest>
</manifest>

View File

@ -0,0 +1,84 @@
package com.vanced.manager.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.RecyclerView
import com.github.florent37.viewtooltip.ViewTooltip
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewAppBinding
import com.vanced.manager.model.DataModel
import com.vanced.manager.ui.dialogs.AppInfoDialog
import com.vanced.manager.ui.viewmodels.HomeViewModel
class AppListAdapter(
private val context: FragmentActivity,
private val viewModel: HomeViewModel,
private val tooltip: ViewTooltip
) : RecyclerView.Adapter<AppListAdapter.ListViewHolder>() {
val apps = mutableListOf<String>()
val dataModels = mutableListOf<DataModel?>()
private val rootDataModels = mutableListOf<DataModel?>()
private val prefs = getDefaultSharedPreferences(context)
private var itemCount = 0
private val isRoot = prefs.getString("vanced_variant", "nonroot") == "root"
inner class ListViewHolder(private val binding: ViewAppBinding) : RecyclerView.ViewHolder(binding.root) {
val appCard = binding.appCard
fun bind(position: Int) {
binding.viewModel = viewModel
binding.dataModel = if (isRoot) rootDataModels[position] else dataModels[position]
binding.app = apps[position]
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
val view = ViewAppBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ListViewHolder(view)
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
holder.bind(position)
holder.appCard.setOnClickListener {
tooltip.close()
AppInfoDialog(
apps[position],
dataModels[position]?.appIcon,
dataModels[position]?.changelog?.get()
).show(context.supportFragmentManager, "info")
}
}
override fun getItemCount(): Int = itemCount
init {
if (prefs.getBoolean("enable_vanced", true)) {
dataModels.add(viewModel.vanced.get())
rootDataModels.add(viewModel.vancedRoot.get())
apps.add(context.getString(R.string.vanced))
itemCount++
}
if (prefs.getBoolean("enable_music", false)) {
dataModels.add(viewModel.music.get())
rootDataModels.add(viewModel.musicRoot.get())
apps.add(context.getString(R.string.music))
itemCount++
}
if (!isRoot) {
dataModels.add(viewModel.microg.get())
apps.add(context.getString(R.string.microg))
itemCount++
}
}
}

View File

@ -1,38 +0,0 @@
package com.vanced.manager.adapter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.vanced.manager.R
import com.vanced.manager.ui.viewmodels.HomeViewModel
class ChangelogAdapter(private val variant: String, viewModel: HomeViewModel?): RecyclerView.Adapter<ChangelogAdapter.ChangelogViewHolder>() {
private val nonrootChangelogs = arrayOf(viewModel?.vanced?.get()?.changelog?.get(), viewModel?.music?.get()?.changelog?.get(), viewModel?.microg?.get()?.changelog?.get(), viewModel?.manager?.get()?.changelog?.get())
private val rootChangelogs = arrayOf(viewModel?.vanced?.get()?.changelog?.get(), viewModel?.manager?.get()?.changelog?.get())
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChangelogViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.view_changelog, parent, false)
return ChangelogViewHolder(view)
}
override fun getItemCount(): Int = if (variant == "root") 2 else 4
override fun onBindViewHolder(holder: ChangelogViewHolder, position: Int) {
holder.changelog.text =
if (variant == "root")
rootChangelogs[position]
else
nonrootChangelogs[position]
}
open class ChangelogViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val changelog: TextView = itemView.findViewById(R.id.changelog_text)
}
}

View File

@ -0,0 +1,60 @@
package com.vanced.manager.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.google.firebase.messaging.FirebaseMessaging
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewNotificationSettingBinding
import com.vanced.manager.model.NotifModel
class GetNotifAdapter(context: Context) : RecyclerView.Adapter<GetNotifAdapter.GetNotifViewHolder>() {
private val vanced = NotifModel(
"Vanced-Update",
context.getString(R.string.push_notifications, context.getString(R.string.vanced)),
context.getString(R.string.push_notifications_summary, context.getString(R.string.vanced)),
"vanced_notifs"
)
private val music = NotifModel(
"MicroG-Update",
context.getString(R.string.push_notifications, context.getString(R.string.music)),
context.getString(R.string.push_notifications_summary, context.getString(R.string.music)),
"music_notifs"
)
private val microg = NotifModel(
"Music-Update",
context.getString(R.string.push_notifications, context.getString(R.string.microg)),
context.getString(R.string.push_notifications_summary, context.getString(R.string.microg)),
"microg_notifs"
)
private val apps = arrayOf(vanced, music, microg)
inner class GetNotifViewHolder(val binding: ViewNotificationSettingBinding) : RecyclerView.ViewHolder(binding.root) {
val switch = binding.notifSwitch
fun bind(position: Int) {
binding.app = apps[position]
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GetNotifViewHolder {
val view = ViewNotificationSettingBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return GetNotifViewHolder(view)
}
override fun onBindViewHolder(holder: GetNotifViewHolder, position: Int) {
holder.bind(position)
holder.switch.setOnCheckedListener { _, isChecked ->
when (isChecked) {
true -> FirebaseMessaging.getInstance().subscribeToTopic(apps[position].topic)
false -> FirebaseMessaging.getInstance().unsubscribeFromTopic(apps[position].topic)
}
}
}
override fun getItemCount(): Int = 3
}

View File

@ -0,0 +1,77 @@
package com.vanced.manager.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewSocialLinkBinding
import com.vanced.manager.model.LinkModel
import com.vanced.manager.ui.viewmodels.HomeViewModel
class LinkAdapter(context: Context, private val viewModel: HomeViewModel) : RecyclerView.Adapter<LinkAdapter.LinkViewHolder>() {
private val instagram = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_instagram),
"https://instagram.com/vanced.youtube"
)
private val youtube = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_youtube),
"https://youtube.com/c/YouTubeVanced"
)
private val github = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_github),
"https://github.com/YTVanced/VancedManager"
)
private val website = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_website),
"https://vancedapp.com"
)
private val telegram = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_telegram),
"https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w"
)
private val twitter = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_twitter),
"https://twitter.com/YTVanced"
)
private val discord = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_discord),
"https://discord.gg/WCGNdRruzb"
)
private val reddit = LinkModel(
ContextCompat.getDrawable(context, R.drawable.ic_reddit),
"https://www.reddit.com/r/Vanced/"
)
val links = arrayOf(instagram, youtube, github, website, telegram, twitter, discord, reddit)
inner class LinkViewHolder(private val binding: ViewSocialLinkBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(position: Int) {
binding.viewModel = viewModel
binding.linkModel = links[position]
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LinkViewHolder {
val view = ViewSocialLinkBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return LinkViewHolder(view)
}
override fun onBindViewHolder(holder: LinkViewHolder, position: Int) {
holder.bind(position)
}
override fun getItemCount(): Int = links.size
}

View File

@ -0,0 +1,56 @@
package com.vanced.manager.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.RecyclerView
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewAppCheckboxBinding
import com.vanced.manager.model.SelectAppModel
class SelectAppsAdapter(context: Context) : RecyclerView.Adapter<SelectAppsAdapter.SelectAppsViewHolder>() {
private val prefs by lazy { getDefaultSharedPreferences(context) }
private val vanced = SelectAppModel(
context.getString(R.string.vanced),
"YouTube Vanced is the stock Android YouTube App, but better!",
"vanced",
prefs.getBoolean("enable_vanced", true)
)
private val music = SelectAppModel(
context.getString(R.string.music),
"Vanced, but for YouTube Music!\nrelatively less feature rich but fulfils your needs.",
"music",
prefs.getBoolean("enable_music", false)
)
val apps = arrayOf(vanced, music)
inner class SelectAppsViewHolder(binding: ViewAppCheckboxBinding) : RecyclerView.ViewHolder(binding.root) {
val appName = binding.appCheckboxText
val appDescription = binding.appCheckboxDescription
val appCard = binding.appCheckboxBg
val checkbox = binding.appCheckbox
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectAppsViewHolder {
val view = ViewAppCheckboxBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return SelectAppsViewHolder(view)
}
override fun onBindViewHolder(holder: SelectAppsViewHolder, position: Int) {
holder.appName.text = apps[position].appName
holder.appDescription.text = apps[position].appDescription
holder.checkbox.isChecked = apps[position].isChecked
holder.appCard.setOnClickListener {
holder.checkbox.isChecked = !holder.checkbox.isChecked
apps[position].isChecked = !apps[position].isChecked
}
}
override fun getItemCount(): Int = 2
}

View File

@ -0,0 +1,57 @@
package com.vanced.manager.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewSponsorBinding
import com.vanced.manager.model.SponsorModel
import com.vanced.manager.ui.viewmodels.HomeViewModel
class SponsorAdapter(context: Context, private val viewModel: HomeViewModel) : RecyclerView.Adapter<SponsorAdapter.LinkViewHolder>() {
private val brave = SponsorModel(
ContextCompat.getDrawable(context, R.drawable.ic_brave),
"Brave",
"https://vancedapp.com/brave"
)
private val adguard = SponsorModel(
ContextCompat.getDrawable(context, R.drawable.ic_adguard),
"AdGuard",
"https://vancedapp.com/adguard"
)
val sponsors = arrayOf(brave, adguard)
inner class LinkViewHolder(private val binding: ViewSponsorBinding) : RecyclerView.ViewHolder(binding.root) {
//val cardBg = binding.linkBg
//val descText = binding.linkAppDescription
fun bind(position: Int) {
binding.viewModel = viewModel
binding.sponsor = sponsors[position]
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LinkViewHolder {
val view = ViewSponsorBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return LinkViewHolder(view)
}
override fun onBindViewHolder(holder: LinkViewHolder, position: Int) {
//holder.cardBg.setCardBackgroundColor()
holder.bind(position)
// val lp = holder.cardBg
// if (lp is FlexboxLayoutManager.LayoutParams) {
// val flexboxLp = lp as FlexboxLayoutManager.LayoutParams
// flexboxLp.flexGrow = 1.0f
// flexboxLp.alignSelf = AlignItems.STRETCH
// }
}
override fun getItemCount(): Int = 2
}

View File

@ -0,0 +1,35 @@
package com.vanced.manager.adapter
import android.content.Context
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.TextView
import com.vanced.manager.model.VancedPrefModel
class VancedPrefArray(context: Context, textViewResourceId: Int, private val values: Array<VancedPrefModel>) : ArrayAdapter<VancedPrefModel?>(context, textViewResourceId, values) {
override fun getCount(): Int {
return values.size
}
override fun getItem(position: Int): VancedPrefModel? {
return values[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val label = super.getView(position, convertView, parent) as TextView
label.text = values[position].name
return label
}
override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View {
val label = super.getDropDownView(position, convertView, parent) as TextView
label.text = values[position].name
return label
}
}

View File

@ -1,88 +0,0 @@
package com.vanced.manager.adapter
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.tabs.TabLayoutMediator
import com.vanced.manager.R
import com.vanced.manager.databinding.ViewHomeBinding
import com.vanced.manager.ui.viewmodels.HomeViewModel
class VariantAdapter(private val viewModel: HomeViewModel, private val context: Context) : RecyclerView.Adapter<VariantAdapter.VariantAdapterHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VariantAdapterHolder {
val view = ViewHomeBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return VariantAdapterHolder(view, context)
}
override fun onBindViewHolder(holder: VariantAdapterHolder, position: Int) {
val variants = arrayOf("nonroot", "root")
holder.bind(variants[position], viewModel)
}
override fun getItemCount(): Int = 2
class VariantAdapterHolder(private val homeBinding: ViewHomeBinding, private val context: Context) : RecyclerView.ViewHolder(homeBinding.root) {
private var isExpanded: Boolean = false
fun bind(variant: String, viewModel: HomeViewModel) {
with (homeBinding) {
this.variant = variant
this.viewModel = viewModel
with(includeChangelogsLayout) {
changelogButton.setOnClickListener {
with (includeChangelogsLayout) {
viewpager.visibility = if (isExpanded) View.GONE else View.VISIBLE
tablayout.visibility = if (isExpanded) View.GONE else View.VISIBLE
changelogButton.animate().apply {
rotation(if (isExpanded) 0F else 180F)
interpolator = AccelerateDecelerateInterpolator()
}
isExpanded = !isExpanded
}
}
viewpager.adapter = ChangelogAdapter(variant, viewModel)
val nonrootTitles = arrayOf("Vanced", "Music", "microG", "Manager")
val rootTitles = arrayOf("Vanced", "Manager")
TabLayoutMediator(tablayout, viewpager) { tab, position ->
tab.text =
if (variant == "root") {
rootTitles[position]
} else {
nonrootTitles[position]
}
}.attach()
}
includeVancedLayout.vancedCard.setOnLongClickListener {
versionToast("Vanced", viewModel.vanced.get()?.installedVersionName?.get()!!)
true
}
includeMusicLayout.musicCard.setOnLongClickListener {
versionToast("Music", viewModel.music.get()?.installedVersionName?.get()!!)
true
}
includeMicrogLayout.microgCard.setOnLongClickListener {
versionToast("MicroG", viewModel.microg.get()?.installedVersionName?.get()!!)
true
}
}
}
private fun versionToast(name: String, app: String?) {
val clip = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clip.setPrimaryClip(ClipData.newPlainText(name, app))
Toast.makeText(context, context.getString(R.string.version_toast, name), Toast.LENGTH_LONG).show()
}
}
}

View File

@ -11,6 +11,9 @@ import com.crowdin.platform.data.remote.NetworkType
import com.downloader.PRDownloader
import com.vanced.manager.utils.InternetTools.baseUrl
import com.vanced.manager.utils.JsonHelper.getJson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
open class App: Application() {
@ -34,13 +37,25 @@ open class App: Application() {
}
open fun loadJsonAsync() {
val latest = runBlocking { getJson("${getDefaultSharedPreferences(this@App).getString("install_url", baseUrl)}/latest.json") }
open fun loadJsonAsync() = CoroutineScope(Dispatchers.IO).launch {
val latest = getJson("${getDefaultSharedPreferences(this@App).getString("install_url", baseUrl)}/latest.json")
vanced.set(latest?.obj("vanced"))
music.set(latest?.obj("music"))
microg.set(latest?.obj("microg"))
manager.set(latest?.obj("manager"))
vanced.apply {
set(latest?.obj("vanced"))
notifyChange()
}
music.apply {
set(latest?.obj("music"))
notifyChange()
}
microg.apply {
set(latest?.obj("microg"))
notifyChange()
}
manager.apply {
set(latest?.obj("manager"))
notifyChange()
}
}
override fun onConfigurationChanged(newConfig: Configuration) {

View File

@ -1,14 +1,12 @@
package com.vanced.manager.core.downloader
import android.content.Context
import android.widget.Toast
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.vanced.manager.R
import com.vanced.manager.core.App
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.microgProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.PackageHelper.install
import kotlinx.coroutines.CoroutineScope
@ -17,39 +15,37 @@ import kotlinx.coroutines.launch
object MicrogDownloader {
fun downloadMicrog(context: Context) {
fun downloadMicrog(
context: Context,
) {
CoroutineScope(Dispatchers.IO).launch {
val url = (context.applicationContext as App).microg.get()?.string("url")
microgProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("apk")?.path, "microg.apk")
downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("microg")?.path, "microg.apk")
.build()
.setOnStartOrResumeListener {
mutableInstall.value = true
microgProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, url?.let { getFileNameFromUrl(it) }))
microgProgress.get()?.showDownloadBar?.set(true)
.setOnStartOrResumeListener {
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, url?.let { getFileNameFromUrl(it) }))
}
.setOnCancelListener {
mutableInstall.value = false
microgProgress.get()?.showDownloadBar?.set(false)
}
.setOnProgressListener { progress ->
microgProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
install("microg", "${context.getExternalFilesDir("apk")}/microg.apk", context)
microgProgress.get()?.showDownloadBar?.set(false)
microgProgress.get()?.showInstallCircle?.set(true)
startMicrogInstall(context)
}
override fun onError(error: Error?) {
mutableInstall.value = false
microgProgress.get()?.showDownloadBar?.set(false)
Toast.makeText(context, context.getString(R.string.error_downloading, "microG"), Toast.LENGTH_SHORT).show()
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.error_downloading, "microG"))
}
})
}
}
fun startMicrogInstall(context: Context) {
downloadProgress.get()?.installing?.set(true)
downloadProgress.get()?.reset()
install("${context.getExternalFilesDir("microg")}/microg.apk", context)
}
}

View File

@ -1,14 +1,14 @@
package com.vanced.manager.core.downloader
import android.content.Context
import android.widget.Toast
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.vanced.manager.R
import com.vanced.manager.core.App
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.musicProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools.baseUrl
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.PackageHelper.install
import kotlinx.coroutines.CoroutineScope
@ -17,35 +17,29 @@ import kotlinx.coroutines.launch
object MusicDownloader {
private var variant: String? = null
fun downloadMusic(context: Context){
CoroutineScope(Dispatchers.IO).launch {
val url = "https://vanced.app/api/v1/music/v${(context.applicationContext as App).music.get()?.string("version")}.apk"
val prefs = getDefaultSharedPreferences(context)
variant = prefs.getString("vanced_variant", "nonroot")
val url = "${prefs.getString("install_url", baseUrl)}/music/v${(context.applicationContext as App).music.get()?.string("version")}.apk"
musicProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("apk")?.path, "music.apk")
downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("music/$variant")?.path, "music.apk")
.build()
.setOnStartOrResumeListener {
mutableInstall.value = true
musicProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url)))
musicProgress.get()?.showDownloadBar?.set(true)
.setOnStartOrResumeListener {
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url)))
}
.setOnProgressListener { progress ->
musicProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
}
.setOnCancelListener {
mutableInstall.value = false
musicProgress.get()?.showDownloadBar?.set(false)
downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
install("music", "${context.getExternalFilesDir("apk")}/music.apk", context)
musicProgress.get()?.showDownloadBar?.set(false)
musicProgress.get()?.showInstallCircle?.set(true)
startMusicInstall(context)
}
override fun onError(error: Error?) {
mutableInstall.value = false
musicProgress.get()?.showDownloadBar?.set(false)
Toast.makeText(context, context.getString(R.string.error_downloading, "Music"), Toast.LENGTH_SHORT).show()
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.error_downloading, "Music"))
}
})
@ -53,4 +47,10 @@ object MusicDownloader {
}
fun startMusicInstall(context: Context) {
downloadProgress.get()?.installing?.set(true)
downloadProgress.get()?.reset()
install("${context.getExternalFilesDir("music/$variant")}/music.apk", context)
}
}

View File

@ -3,7 +3,6 @@ package com.vanced.manager.core.downloader
import android.content.Context
import android.content.SharedPreferences
import android.os.Build
import android.widget.Toast
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.downloader.Error
import com.downloader.OnDownloadListener
@ -12,12 +11,12 @@ import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.logEvent
import com.vanced.manager.R
import com.vanced.manager.core.App
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.vancedProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.AppUtils.vancedRootPkg
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools
import com.vanced.manager.utils.InternetTools.baseUrl
import com.vanced.manager.utils.InternetTools.getFileNameFromUrl
import com.vanced.manager.utils.LanguageHelper.getDefaultVancedLanguages
import com.vanced.manager.utils.PackageHelper.getPkgVerCode
import com.vanced.manager.utils.PackageHelper.installVanced
import com.vanced.manager.utils.PackageHelper.installVancedRoot
@ -40,24 +39,28 @@ object VancedDownloader {
private var installUrl: String? = null
private var variant: String? = null
private var theme: String? = null
private var lang: Array<String>? = null
private var lang: MutableList<String>? = null
private lateinit var themePath: String
private var count: Int = 0
private var succesfulLangCount: Int = 0
private var hashUrl = ""
private var vancedVersionCode = 0
private var vancedVersion: String? = null
fun downloadVanced(context: Context){
private var downloadPath: String? = null
fun downloadVanced(context: Context) {
val app = context.applicationContext as App
File(context.getExternalFilesDir("apks")?.path as String).deleteRecursively()
defPrefs = getDefaultSharedPreferences(context)
installUrl = defPrefs.getString("install_url", baseUrl)
prefs = context.getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
variant = defPrefs.getString("vanced_variant", "nonroot")
lang = prefs.getString("lang", "en")?.split(", ")?.toTypedArray()
downloadPath = context.getExternalFilesDir("vanced/$variant")?.path
File(downloadPath.toString()).deleteRecursively()
lang = prefs.getString("lang", getDefaultVancedLanguages(app))?.split(", ")?.toMutableList()
theme = prefs.getString("theme", "dark")
vancedVersion = app.vanced.get()?.string("version")
themePath = "$installUrl/apks/v$vancedVersion/$variant/Theme"
@ -69,6 +72,7 @@ object VancedDownloader {
Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a"
else -> "armeabi_v7a"
}
count = 0
vancedVersionCode = app.vanced.get()?.int("versionCode") ?: 0
downloadSplits(context)
@ -89,19 +93,13 @@ object VancedDownloader {
else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?")
}
vancedProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("apks")?.path, getFileNameFromUrl(url))
downloadProgress.get()?.currentDownload = PRDownloader.download(url, downloadPath, getFileNameFromUrl(url))
.build()
.setOnStartOrResumeListener {
mutableInstall.value = true
vancedProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url)))
vancedProgress.get()?.showDownloadBar?.set(true)
.setOnStartOrResumeListener {
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.downloading_file, getFileNameFromUrl(url)))
}
.setOnProgressListener { progress ->
vancedProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
}
.setOnCancelListener {
mutableInstall.value = false
vancedProgress.get()?.showDownloadBar?.set(false)
downloadProgress.get()?.downloadProgress?.set((progress.currentBytes * 100 / progress.totalBytes).toInt())
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
@ -112,7 +110,7 @@ object VancedDownloader {
if (downloadStockCheck(context))
downloadSplits(context, "arch")
else
prepareInstall(variant!!, context)
startVancedInstall(context)
} else
downloadSplits(context, "theme")
} else
@ -122,10 +120,11 @@ object VancedDownloader {
"dpi" -> downloadSplits(context, "lang")
"lang" -> {
count++
succesfulLangCount++
if (count < lang?.count()!!)
downloadSplits(context, "lang")
else
prepareInstall(variant!!, context)
startVancedInstall(context)
}
}
@ -133,22 +132,24 @@ object VancedDownloader {
override fun onError(error: Error?) {
if (type == "lang") {
count++
if (count < lang?.count()!!)
downloadSplits(context, "lang")
else
prepareInstall(variant!!, context)
when {
count < lang?.count()!! -> downloadSplits(context, "lang")
succesfulLangCount == 0 -> {
lang?.add("en")
downloadSplits(context, "lang")
}
else -> startVancedInstall(context)
}
} else {
count = 0
mutableInstall.value = false
vancedProgress.get()?.showDownloadBar?.set(false)
Toast.makeText(context, context.getString(R.string.error_downloading, getFileNameFromUrl(url)), Toast.LENGTH_SHORT).show()
downloadProgress.get()?.downloadingFile?.set(context.getString(R.string.error_downloading, getFileNameFromUrl(url)))
}
}
})
}
}
private fun downloadStockCheck(context: Context) :Boolean {
fun downloadStockCheck(context: Context): Boolean {
return try {
getPkgVerCode(vancedRootPkg, context.packageManager) != vancedVersionCode
} catch (e: Exception) {
@ -161,18 +162,16 @@ object VancedDownloader {
}
private fun validateTheme(context: Context): Boolean {
val themeS = context.getExternalFilesDir("apks")?.path + "/${theme}.apk"
val themeF = File(themeS)
val themeF = File(downloadPath, "${theme}.apk")
runBlocking { getSha256(theme!!, context) }
return checkSHA256(sha256Val!!,themeF)
}
private fun prepareInstall(variant: String, context: Context) {
count = 0
vancedProgress.get()?.showDownloadBar?.set(false)
vancedProgress.get()?.showInstallCircle?.set(true)
fun startVancedInstall(context: Context, variant: String? = this.variant) {
downloadProgress.get()?.installing?.set(true)
downloadProgress.get()?.reset()
FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.SELECT_ITEM) {
param("vanced_variant", variant)
variant?.let { param("vanced_variant", it) }
theme?.let { param("vanced_theme", it) }
}
if (variant == "root")

View File

@ -5,16 +5,13 @@ import android.content.Intent
import android.content.pm.PackageInstaller
import android.os.IBinder
import android.util.Log
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.microgProgress
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.musicProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.AppUtils.sendCloseDialog
import com.vanced.manager.utils.AppUtils.sendFailure
import com.vanced.manager.utils.AppUtils.sendRefresh
class AppInstallerService: Service() {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val app = intent.getStringExtra("app")
when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
Log.d(TAG, "Requesting user confirmation for installation")
@ -28,13 +25,12 @@ class AppInstallerService: Service() {
}
PackageInstaller.STATUS_SUCCESS -> {
Log.d(TAG, "Installation succeed")
if (app == "microg") microgProgress.get()?.showInstallCircle?.set(false) else musicProgress.get()?.showInstallCircle?.set(false)
mutableInstall.postValue(false)
sendCloseDialog(this)
sendRefresh(this)
}
else -> {
sendCloseDialog(this)
sendFailure(intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999), this)
if (app == "microg") microgProgress.get()?.showInstallCircle?.set(false) else musicProgress.get()?.showInstallCircle?.set(false)
}
}
stopSelf()

View File

@ -1,49 +0,0 @@
package com.vanced.manager.core.installer
import android.app.Service
import android.content.Intent
import android.content.pm.PackageInstaller
import android.os.IBinder
import android.util.Log
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.vancedProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.AppUtils.sendFailure
import com.vanced.manager.utils.AppUtils.sendRefresh
class SplitInstallerService: Service() {
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) {
PackageInstaller.STATUS_PENDING_USER_ACTION -> {
Log.d(TAG, "Requesting user confirmation for installation")
val confirmationIntent = intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT)
confirmationIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
startActivity(confirmationIntent)
} catch (e: Exception) {
}
}
PackageInstaller.STATUS_SUCCESS -> {
Log.d(TAG, "Installation succeed")
vancedProgress.get()?.showInstallCircle?.set(false)
mutableInstall.postValue(false)
sendRefresh(this)
}
else -> {
sendFailure(intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999), this)
vancedProgress.get()?.showInstallCircle?.set(false)
}
}
stopSelf()
return START_NOT_STICKY
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
companion object{
const val TAG = "VMInstall"
}
}

View File

@ -0,0 +1,12 @@
package com.vanced.manager.model
import android.graphics.drawable.Drawable
data class AppListModel(
val icon: Drawable?,
val appName: String?,
val remoteVersion: String?,
val installedVersion: String?,
val changelog: String?,
val pkg: String?
)

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.graphics.drawable.Drawable
import android.os.Build
import androidx.core.content.ContextCompat
import androidx.databinding.Observable
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.databinding.ObservableInt
@ -16,8 +17,10 @@ import kotlinx.coroutines.launch
open class DataModel(
private val jsonObject: ObservableField<JsonObject?>,
private val appPkg: String,
private val context: Context
private val context: Context,
val appPkg: String,
val appName: String,
val appIcon: Drawable?
) {
private val versionCode = ObservableInt()
@ -27,7 +30,7 @@ open class DataModel(
val versionName = ObservableField<String>()
val installedVersionName = ObservableField<String>()
val buttonTxt = ObservableField<String>()
val buttonIcon = ObservableField<Drawable>()
//val buttonIcon = ObservableField<Drawable>()
val changelog = ObservableField<String>()
fun fetch() = CoroutineScope(Dispatchers.IO).launch {
@ -37,12 +40,18 @@ open class DataModel(
versionCode.set(jsonObject.get()?.int("versionCode") ?: 0)
installedVersionCode.set(getPkgVersionCode(isAppInstalled.get(), appPkg))
buttonTxt.set(compareInt(installedVersionCode.get(), versionCode.get()))
buttonIcon.set(compareIntDrawable(installedVersionCode.get(), versionCode.get()))
//buttonIcon.set(compareIntDrawable(installedVersionCode.get(), versionCode.get()))
changelog.set(jsonObject.get()?.string("changelog") ?: context.getString(R.string.unavailable))
}
init {
fetch()
jsonObject.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() {
override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
fetch()
}
})
}
private fun getPkgVersionName(toCheck: Boolean, pkg: String): String {
@ -82,5 +91,5 @@ open class DataModel(
else -> ContextCompat.getDrawable(context, R.drawable.ic_download)
}
}
}

View File

@ -0,0 +1,8 @@
package com.vanced.manager.model
import android.graphics.drawable.Drawable
data class LinkModel(
val linkIcon: Drawable?,
val linkUrl: String,
)

View File

@ -0,0 +1,8 @@
package com.vanced.manager.model
data class NotifModel(
val topic: String,
val switchTitle: String,
val switchSummary: String,
val key: String
)

View File

@ -8,16 +8,18 @@ open class ProgressModel {
val downloadProgress = ObservableInt()
val downloadingFile = ObservableField<String>()
val showInstallCircle = ObservableBoolean()
val showDownloadBar = ObservableBoolean()
val installing = ObservableBoolean()
var currentDownload: Int = 0
init {
fun reset() {
downloadProgress.set(0)
downloadingFile.set("")
showInstallCircle.set(false)
showDownloadBar.set(false)
}
init {
installing.set(false)
reset()
}
}

View File

@ -0,0 +1,8 @@
package com.vanced.manager.model
data class SelectAppModel(
val appName: String,
val appDescription: String,
val tag: String,
var isChecked: Boolean
)

View File

@ -0,0 +1,9 @@
package com.vanced.manager.model
import android.graphics.drawable.Drawable
data class SponsorModel(
val logo: Drawable?,
val name: String,
val url: String
)

View File

@ -0,0 +1,6 @@
package com.vanced.manager.model
data class VancedPrefModel(
val name: String,
val value: String
)

View File

@ -20,10 +20,9 @@ import com.google.firebase.messaging.FirebaseMessaging
import com.vanced.manager.R
import com.vanced.manager.databinding.ActivityMainBinding
import com.vanced.manager.ui.dialogs.DialogContainer
import com.vanced.manager.ui.dialogs.ManagerUpdateDialog
import com.vanced.manager.ui.fragments.HomeFragmentDirections
import com.vanced.manager.ui.fragments.SettingsFragmentDirections
import com.vanced.manager.ui.fragments.UpdateCheckFragment
import com.vanced.manager.utils.AppUtils.installing
import com.vanced.manager.utils.InternetTools
import com.vanced.manager.utils.LanguageContextWrapper
import com.vanced.manager.utils.PackageHelper
@ -53,15 +52,14 @@ class MainActivity : AppCompatActivity() {
with(binding) {
lifecycleOwner = this@MainActivity
setSupportActionBar(homeToolbar)
homeToolbar.setupWithNavController(this@MainActivity.navHost, AppBarConfiguration(this@MainActivity.navHost.graph))
setSupportActionBar(toolbar)
toolbar.setupWithNavController(this@MainActivity.navHost, AppBarConfiguration(this@MainActivity.navHost.graph))
}
navHost.addOnDestinationChangedListener { _, currFrag: NavDestination, _ ->
setDisplayHomeAsUpEnabled(currFrag.id != R.id.home_fragment)
}
initDialogs()
initDialogs(intent.getBooleanExtra("firstLaunch", false))
}
override fun onBackPressed() {
@ -70,7 +68,7 @@ class MainActivity : AppCompatActivity() {
}
private fun setDisplayHomeAsUpEnabled(isNeeded: Boolean) {
binding.homeToolbar.navigationIcon = if (isNeeded) ContextCompat.getDrawable(this, R.drawable.ic_keyboard_backspace_black_24dp) else null
binding.toolbar.navigationIcon = if (isNeeded) ContextCompat.getDrawable(this, R.drawable.ic_keyboard_backspace_black_24dp) else null
}
override fun onPause() {
@ -85,8 +83,6 @@ class MainActivity : AppCompatActivity() {
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (installing.value!!)
return false
when (item.itemId) {
android.R.id.home -> {
@ -101,6 +97,9 @@ class MainActivity : AppCompatActivity() {
navHost.navigate(HomeFragmentDirections.toSettingsFragment())
return true
}
R.id.toolbar_update_manager -> {
ManagerUpdateDialog(false).show(supportFragmentManager, "manager_update")
}
R.id.dev_settings -> {
navHost.navigate(SettingsFragmentDirections.toDevSettingsFragment())
return true
@ -126,13 +125,13 @@ class MainActivity : AppCompatActivity() {
finish()
}
private fun initDialogs() {
private fun initDialogs(firstLaunch: Boolean) {
val prefs = getDefaultSharedPreferences(this)
val variant = prefs.getString("vanced_variant", "nonroot")
prefs.getBoolean("show_root_dialog", true)
when {
prefs.getBoolean("firstStart", true) -> {
firstLaunch -> {
DialogContainer.showSecurityDialog(this)
with(FirebaseMessaging.getInstance()) {
subscribeToTopic("Vanced-Update")
@ -158,7 +157,7 @@ class MainActivity : AppCompatActivity() {
private fun checkUpdates() {
if (InternetTools.isUpdateAvailable(this)) {
UpdateCheckFragment().show(supportFragmentManager, "UpdateCheck")
ManagerUpdateDialog(false).show(supportFragmentManager, "UpdateCheck")
}
}

View File

@ -0,0 +1,24 @@
package com.vanced.manager.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.navigation.findNavController
import com.vanced.manager.R
import com.vanced.manager.databinding.ActivityWelcomeBinding
class WelcomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityWelcomeBinding
private val navHost by lazy { findNavController(R.id.welcome_navhost) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome)
}
override fun onBackPressed() {
if (!navHost.popBackStack())
finish()
}
}

View File

@ -0,0 +1,50 @@
package com.vanced.manager.ui.core
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import com.vanced.manager.R
import kotlinx.android.synthetic.main.view_preference.view.*
class EmptyPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyle, defStyleRes) {
init {
LayoutInflater.from(context).inflate(R.layout.view_preference, this, true)
initAttrs(context, attrs)
}
fun setTitle(newTitle: String) {
preference_title.text = newTitle
}
fun setSummary(newSummary: String) {
preference_summary.text = newSummary
preference_summary.visibility = View.VISIBLE
preference_title.setPadding(0, 0, 0, 0)
}
private fun initAttrs(context: Context, attrs: AttributeSet?) {
attrs?.let { mAttrs ->
val typedArray = context.obtainStyledAttributes(mAttrs, R.styleable.EmptyPreference, 0, 0)
val title = typedArray.getText(R.styleable.EmptyPreference_preference_title)
val summary = typedArray.getText(R.styleable.EmptyPreference_preference_summary)
if (summary != null) {
preference_summary.text = summary
} else {
preference_summary.visibility = View.GONE
preference_title.setPadding(0, 12, 0, 12)
}
preference_title.text = title
typedArray.recycle()
}
}
}

View File

@ -0,0 +1,38 @@
package com.vanced.manager.ui.core
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import androidx.recyclerview.widget.RecyclerView
class ItemDecoration(private val line: Drawable?) : RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
with(outRect) {
top = 4
bottom = 4
}
}
override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
val dividerLeft = parent.paddingLeft
val dividerRight = parent.width - parent.paddingRight
val childCount = parent.childCount
(0..childCount - 2).forEach {
val child = parent.getChildAt(it)
val params = child.layoutParams as RecyclerView.LayoutParams
val dividerTop: Int = child.bottom + params.bottomMargin
val dividerBottom: Int = dividerTop + line!!.intrinsicHeight
line.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom)
line.draw(c)
}
}
}

View File

@ -0,0 +1,33 @@
package com.vanced.manager.ui.core
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.LinearLayout
import com.vanced.manager.R
import kotlinx.android.synthetic.main.view_preference_category.view.*
class PreferenceCategory @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
) : LinearLayout(context, attrs, defStyle) {
init {
LayoutInflater.from(context).inflate(R.layout.view_preference_category, this, true)
initAttrs(context, attrs)
setPadding(0, 4, 0, 0)
orientation = VERTICAL
}
private fun initAttrs(context: Context, attrs: AttributeSet?) {
attrs.let { mAttrs ->
val typedArray = context.obtainStyledAttributes(mAttrs, R.styleable.PreferenceCategory, 0, 0)
val title = typedArray.getText(R.styleable.PreferenceCategory_category_title)
category_title.text = title
typedArray.recycle()
}
}
}

View File

@ -0,0 +1,112 @@
package com.vanced.manager.ui.core
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.widget.CompoundButton
import android.widget.FrameLayout
import androidx.databinding.BindingAdapter
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.vanced.manager.R
import kotlinx.android.synthetic.main.view_preference_switch.view.*
class PreferenceSwitch @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyle, defStyleRes) {
private val prefs by lazy { getDefaultSharedPreferences(context) }
private var prefKey: String = ""
private var defValue: Boolean = false
private var mListener: OnCheckedListener? = null
init {
LayoutInflater.from(context).inflate(R.layout.view_preference_switch, this, true)
initAttrs(context, attrs)
}
override fun onFinishInflate() {
super.onFinishInflate()
preference_switch.isChecked = prefs.getBoolean(prefKey, defValue)
setOnClickListener {
preference_switch.isChecked = !preference_switch.isChecked
Log.d("clickTest", "clicked")
}
preference_switch.setOnCheckedChangeListener { buttonView, isChecked ->
prefs.edit().putBoolean(prefKey, isChecked).apply()
mListener?.onChecked(buttonView, isChecked)
}
}
fun setOnCheckedListener(method: (buttonView: CompoundButton, isChecked: Boolean) -> Unit) {
mListener = object : OnCheckedListener{
override fun onChecked(buttonView: CompoundButton, isChecked: Boolean) {
method(buttonView, isChecked)
}
}
}
fun setOnCheckedListener(listener: OnCheckedListener?) {
mListener = listener
}
private fun initAttrs(context: Context, attrs: AttributeSet?) {
attrs?.let { mAttrs ->
val typedArray = context.obtainStyledAttributes(mAttrs, R.styleable.PreferenceSwitch, 0, 0)
val title = typedArray.getText(R.styleable.PreferenceSwitch_switch_title)
val summary = typedArray.getText(R.styleable.PreferenceSwitch_switch_summary)
val key = typedArray.getText(R.styleable.PreferenceSwitch_switch_key)
val value = typedArray.getBoolean(R.styleable.PreferenceSwitch_switch_def_value, false)
if (key != null)
prefKey = key.toString()
defValue = value
preference_switch_title.text = title
if (summary != null) {
preference_switch_summary.text = summary
}
typedArray.recycle()
}
}
interface OnCheckedListener {
fun onChecked(buttonView: CompoundButton, isChecked: Boolean)
}
companion object {
@JvmStatic
@BindingAdapter("app:switch_title")
fun setTitle(view: PreferenceSwitch, newTitle: String) {
view.preference_switch_title.text = newTitle
}
@JvmStatic
@BindingAdapter("app:switch_summary")
fun setSummary(view: PreferenceSwitch, newSummary: String) {
view.preference_switch_summary.text = newSummary
}
@JvmStatic
@BindingAdapter("app:switch_key")
fun setKey(view: PreferenceSwitch, newKey: String) {
view.prefKey = newKey
view.preference_switch.isChecked = view.prefs.getBoolean(view.prefKey, view.defValue)
}
@JvmStatic
@BindingAdapter("app:switch_def_val")
fun setDefaultValue(view: PreferenceSwitch, newVal: Boolean) {
view.defValue = newVal
view.preference_switch.isChecked = view.prefs.getBoolean(view.prefKey, view.defValue)
}
}
}

View File

@ -3,14 +3,22 @@ package com.vanced.manager.ui.core
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.vanced.manager.ui.MainActivity
import com.vanced.manager.ui.WelcomeActivity
class SplashScreenActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(Intent(this@SplashScreenActivity, MainActivity::class.java))
finish()
if (getDefaultSharedPreferences(this).getBoolean("firstLaunch", true)) {
startActivity(Intent(this@SplashScreenActivity, WelcomeActivity::class.java))
finish()
} else {
startActivity(Intent(this@SplashScreenActivity, MainActivity::class.java))
finish()
}
}
}

View File

@ -0,0 +1,88 @@
package com.vanced.manager.ui.dialogs
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.downloader.PRDownloader
import com.vanced.manager.R
import com.vanced.manager.core.downloader.MicrogDownloader.downloadMicrog
import com.vanced.manager.core.downloader.MusicDownloader.downloadMusic
import com.vanced.manager.core.downloader.VancedDownloader.downloadVanced
import com.vanced.manager.databinding.DialogAppDownloadBinding
import com.vanced.manager.utils.DownloadHelper.downloadProgress
class AppDownloadDialog(
private val app: String,
private val installing: Boolean = false
) : DialogFragment() {
private lateinit var binding: DialogAppDownloadBinding
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) }
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
CLOSE_DIALOG -> dismiss()
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (dialog != null && dialog?.window != null) {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_app_download, container, false)
binding.progress = downloadProgress.get()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
isCancelable = false
binding.appDownloadHeader.text = requireActivity().getString(R.string.installing_app, app)
binding.appDownloadCancel.setOnClickListener {
if (downloadProgress.get()?.installing?.get() == true)
return@setOnClickListener
PRDownloader.cancel(downloadProgress.get()!!.currentDownload)
dismiss()
}
if (!installing) {
when (app) {
requireActivity().getString(R.string.vanced) -> downloadVanced(requireActivity())
requireActivity().getString(R.string.music) -> downloadMusic(requireActivity())
requireActivity().getString(R.string.microg) -> downloadMicrog(requireActivity())
}
}
}
override fun onResume() {
super.onResume()
registerReceiver()
}
private fun registerReceiver() {
val intentFilter = IntentFilter()
intentFilter.addAction(CLOSE_DIALOG)
localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter)
}
companion object {
const val CLOSE_DIALOG = "close_dialog"
}
}

View File

@ -0,0 +1,38 @@
package com.vanced.manager.ui.dialogs
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogAppInfoBinding
class AppInfoDialog(
private val appName: String?,
private val appIcon: Drawable?,
private val changelog: String?
) : DialogFragment() {
private lateinit var binding: DialogAppInfoBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
if (dialog != null && dialog?.window != null) {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_app_info, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.aboutAppName.text = requireActivity().getString(R.string.about_app, appName)
binding.aboutAppImage.setImageDrawable(appIcon)
binding.aboutAppChangelog.text = changelog
}
}

View File

@ -8,10 +8,8 @@ import androidx.core.content.ContextCompat.startActivity
import androidx.preference.PreferenceManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.vanced.manager.R
import com.vanced.manager.core.downloader.VancedDownloader.downloadVanced
import com.vanced.manager.utils.InternetTools.openUrl
import com.vanced.manager.utils.MiuiHelper
import com.vanced.manager.utils.PackageHelper.installVanced
object DialogContainer {
@ -36,7 +34,7 @@ object DialogContainer {
show()
}
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
prefs.edit().putBoolean("firstStart", false).apply()
prefs.edit().putBoolean("firstLaunch", false).apply()
}
private fun showMiuiDialog(context: Context) {
@ -57,22 +55,6 @@ object DialogContainer {
}
}
//TODO
fun installOrDownload(context: Context) {
MaterialAlertDialogBuilder(context).apply {
setTitle("")
setMessage("")
setNegativeButton("") { dialog, _ ->
downloadVanced(context)
dialog.dismiss()
}
setPositiveButton(context.getString(R.string.button_reinstall)) { dialog, _ ->
installVanced(context)
dialog.dismiss()
}
}
}
fun statementFalse(context: Context) {
MaterialAlertDialogBuilder(context).apply {
setTitle("Wait what?")

View File

@ -0,0 +1,51 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.vanced.manager.R
import com.vanced.manager.core.downloader.MicrogDownloader.startMicrogInstall
import com.vanced.manager.core.downloader.MusicDownloader.startMusicInstall
import com.vanced.manager.core.downloader.VancedDownloader.startVancedInstall
import com.vanced.manager.databinding.DialogInstallationFilesDetectedBinding
import com.vanced.manager.utils.Extensions.show
class InstallationFilesDetectedDialog(private val app: String) : BottomSheetDialogFragment() {
private lateinit var binding: DialogInstallationFilesDetectedBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_installation_files_detected, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.installationDetectedTitle.text = requireActivity().getString(R.string.app_install_files_detected, app)
binding.installationDetectedSummary.text = requireActivity().getString(R.string.app_install_files_detected_summary, app)
binding.installationDetectedRedownload.setOnClickListener {
dismiss()
AppDownloadDialog(app).show(requireActivity())
}
binding.installationDetectedInstall.setOnClickListener {
when (app) {
requireActivity().getString(R.string.vanced) -> startVancedInstall(requireActivity(), getDefaultSharedPreferences(requireActivity()).getString("vanced_variant", "nonroot"))
requireActivity().getString(R.string.music) -> startMusicInstall(requireActivity())
requireActivity().getString(R.string.microg) -> startMicrogInstall(requireActivity())
}
AppDownloadDialog(app, true).show(requireActivity())
}
}
}

View File

@ -0,0 +1,45 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerAccentColorBinding
import com.vanced.manager.utils.Extensions.getCheckedButtonTag
class ManagerAccentColorDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogManagerAccentColorBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_manager_accent_color, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val accent = prefs.getString("manager_accent", "Blue")
view.findViewWithTag<MaterialRadioButton>(accent).isChecked = true
binding.accentSave.setOnClickListener {
val newPref = binding.accentRadiogroup.getCheckedButtonTag()
if (accent != newPref) {
prefs.edit().putString("manager_accent", newPref).apply()
dismiss()
requireActivity().recreate()
} else {
dismiss()
}
}
}
}

View File

@ -0,0 +1,64 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.BuildConfig.MANAGER_LANGUAGES
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerLanguageBinding
import com.vanced.manager.utils.Extensions.getCheckedButtonTag
import com.vanced.manager.utils.LanguageHelper.getLanguageFormat
import java.util.*
class ManagerLanguageDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogManagerLanguageBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_manager_language, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
addRadioButtons()
val language = prefs.getString("manager_lang", "System Default")
view.findViewWithTag<MaterialRadioButton>(language).isChecked = true
binding.languageSave.setOnClickListener {
val newPref = binding.languageRadiogroup.getCheckedButtonTag()
if (language != newPref) {
prefs.edit().putString("manager_lang", newPref).apply()
dismiss()
requireActivity().recreate()
} else {
dismiss()
}
}
}
private fun addRadioButtons() {
requireActivity().runOnUiThread {
(arrayOf("System Default") + MANAGER_LANGUAGES).forEach { lang ->
val button = MaterialRadioButton(requireActivity()).apply {
text = getLanguageFormat(requireActivity(), lang)
textSize = 18f
tag = lang
}
binding.languageRadiogroup.addView(button, MATCH_PARENT, WRAP_CONTENT)
}
}
}
}

View File

@ -0,0 +1,44 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerThemeBinding
import com.vanced.manager.utils.Extensions.getCheckedButtonTag
class ManagerThemeDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogManagerThemeBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_manager_theme, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val theme = prefs.getString("manager_theme", "System Default")
view.findViewWithTag<MaterialRadioButton>(theme).isChecked = true
binding.themeSave.setOnClickListener {
val newPref = binding.themeRadiogroup.getCheckedButtonTag()
if (theme != newPref) {
prefs.edit().putString("manager_theme", newPref).apply()
dismiss()
requireActivity().recreate()
} else {
dismiss()
}
}
}
}

View File

@ -0,0 +1,89 @@
package com.vanced.manager.ui.dialogs
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.downloader.PRDownloader
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerUpdateBinding
import com.vanced.manager.utils.DownloadHelper.downloadManager
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import com.vanced.manager.utils.InternetTools.isUpdateAvailable
class ManagerUpdateDialog(
private val forceUpdate: Boolean
) : DialogFragment() {
private lateinit var binding: DialogManagerUpdateBinding
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) }
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
CLOSE_DIALOG -> dismiss()
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (dialog != null && dialog?.window != null) {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
isCancelable = false
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_manager_update, container, false)
binding.progress = downloadProgress.get()
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (forceUpdate) {
binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient)
downloadManager(requireActivity())
} else
checkUpdates()
binding.managerUpdateCancel.setOnClickListener {
PRDownloader.cancel(downloadProgress.get()!!.currentDownload)
dismiss()
}
}
override fun onResume() {
super.onResume()
registerReceiver()
}
private fun checkUpdates() {
if (isUpdateAvailable(requireActivity())) {
binding.managerUpdatePatient.text = requireActivity().getString(R.string.please_be_patient)
downloadManager(requireActivity())
} else
binding.managerUpdatePatient.text = requireActivity().getString(R.string.update_not_found)
}
private fun registerReceiver() {
val intentFilter = IntentFilter()
intentFilter.addAction(CLOSE_DIALOG)
localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter)
}
companion object {
const val CLOSE_DIALOG = "close_dialog"
}
}

View File

@ -0,0 +1,44 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R
import com.vanced.manager.databinding.DialogManagerVariantBinding
import com.vanced.manager.utils.Extensions.getCheckedButtonTag
class ManagerVariantDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogManagerVariantBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_manager_variant, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val variant = prefs.getString("vanced_variant", "nonroot")
view.findViewWithTag<MaterialRadioButton>(variant).isChecked = true
binding.variantSave.setOnClickListener {
val newPref = binding.variantRadiogroup.getCheckedButtonTag()
if (variant != newPref) {
prefs.edit().putString("vanced_variant", newPref).apply()
dismiss()
requireActivity().recreate()
} else {
dismiss()
}
}
}
}

View File

@ -0,0 +1,50 @@
package com.vanced.manager.ui.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.vanced.manager.R
import com.vanced.manager.adapter.SelectAppsAdapter
import com.vanced.manager.databinding.DialogSelectAppsBinding
class SelectAppsDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogSelectAppsBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_select_apps, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val ad = SelectAppsAdapter(requireActivity())
binding.selectAppsRecycler.apply {
layoutManager = LinearLayoutManager(requireActivity())
adapter = ad
setHasFixedSize(true)
}
binding.selectAppsSave.setOnClickListener {
if (ad.apps.all { app -> !app.isChecked }) {
Toast.makeText(requireActivity(), R.string.select_at_least_one_app, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
ad.apps.forEach { app ->
prefs.edit().putBoolean("enable_${app.tag}", app.isChecked).apply()
}
dismiss()
}
}
}

View File

@ -1,4 +1,4 @@
package com.vanced.manager.ui.fragments
package com.vanced.manager.ui.dialogs
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
@ -14,7 +14,7 @@ import com.google.android.material.button.MaterialButton
import com.vanced.manager.R
import com.vanced.manager.utils.InternetTools.baseUrl
class URLChangeFragment : DialogFragment() {
class URLChangeDialog : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -23,7 +23,7 @@ class URLChangeFragment : DialogFragment() {
if (dialog != null && dialog?.window != null) {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
return inflater.inflate(R.layout.fragment_custom_url, container, false)
return inflater.inflate(R.layout.dialog_custom_url, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -39,7 +39,7 @@ class URLChangeFragment : DialogFragment() {
saveUrl(finalUrl)
}
view.findViewById<MaterialButton>(R.id.url_reset).setOnClickListener {saveUrl(baseUrl)}
view.findViewById<MaterialButton>(R.id.url_reset).setOnClickListener { saveUrl(baseUrl) }
}
private fun saveUrl(url: String) {

View File

@ -1,6 +1,7 @@
package com.vanced.manager.ui.fragments
package com.vanced.manager.ui.dialogs
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -8,28 +9,28 @@ import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.LinearLayout
import android.widget.Toast
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.google.android.material.button.MaterialButton
import com.google.android.material.checkbox.MaterialCheckBox
import com.vanced.manager.R
import com.vanced.manager.core.App
import com.vanced.manager.core.downloader.VancedDownloader.downloadVanced
import com.vanced.manager.utils.LanguageHelper.getDefaultVancedLanguages
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.*
class VancedLanguageSelectionFragment : Fragment() {
class VancedLanguageSelectionDialog : BottomSheetDialogFragment() {
private lateinit var langs: MutableList<String>
private val prefs by lazy { requireActivity().getSharedPreferences("installPrefs", Context.MODE_PRIVATE) }
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.title = getString(R.string.install)
return inflater.inflate(R.layout.fragment_vanced_language_selection, container, false)
}
@ -40,33 +41,35 @@ class VancedLanguageSelectionFragment : Fragment() {
langs = app.vanced.get()?.array<String>("langs")?.value ?: mutableListOf("null")
loadBoxes(view.findViewById(R.id.lang_button_ll))
view.findViewById<MaterialButton>(R.id.vanced_install_finish).setOnClickListener {
val chosenLangs = mutableListOf("en")
val chosenLangs = mutableListOf<String>()
if (!langs.contains("null"))
langs.forEach { lang ->
if (view.findViewWithTag<MaterialCheckBox>(lang).isChecked) {
chosenLangs.add(lang)
}
}
with(requireActivity()) {
getSharedPreferences("installPrefs", Context.MODE_PRIVATE)?.edit()?.apply {
putString("lang", chosenLangs.joinToString())?.apply()
putBoolean("valuesModified", true).apply()
}
downloadVanced(requireActivity())
if (chosenLangs.isEmpty()) {
Toast.makeText(requireActivity(), R.string.select_at_least_one_lang, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
view.findNavController().navigate(R.id.action_installTo_homeFragment)
prefs?.edit()?.putString("lang", chosenLangs.joinToString())?.apply()
dismiss()
}
}
@ExperimentalStdlibApi
private fun loadBoxes(ll: LinearLayout) {
CoroutineScope(Dispatchers.Main).launch {
if (this@VancedLanguageSelectionFragment::langs.isInitialized) {
val langPrefs = prefs.getString("lang", getDefaultVancedLanguages(requireActivity()))
if (this@VancedLanguageSelectionDialog::langs.isInitialized) {
if (!langs.contains("null")) {
langs.forEach { lang ->
val loc = Locale(lang)
val box: MaterialCheckBox = MaterialCheckBox(requireActivity()).apply {
tag = lang
isChecked = langPrefs!!.contains(lang)
text = loc.getDisplayLanguage(loc).capitalize(Locale.ROOT)
textSize = 18F
typeface = ResourcesCompat.getFont(requireActivity(), R.font.exo_bold)
@ -79,4 +82,9 @@ class VancedLanguageSelectionFragment : Fragment() {
}
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
VancedPreferencesDialog().show(requireActivity().supportFragmentManager, "")
}
}

View File

@ -0,0 +1,82 @@
package com.vanced.manager.ui.dialogs
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
import androidx.databinding.DataBindingUtil
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.vanced.manager.R
import com.vanced.manager.adapter.VancedPrefArray
import com.vanced.manager.databinding.DialogInstallationPreferencesBinding
import com.vanced.manager.model.VancedPrefModel
import com.vanced.manager.utils.LanguageHelper.getDefaultVancedLanguages
import java.util.*
class VancedPreferencesDialog : BottomSheetDialogFragment() {
private lateinit var binding: DialogInstallationPreferencesBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.dialog_installation_preferences, container, false)
return binding.root
}
@ExperimentalStdlibApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val prefs = requireActivity().getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
val langPrefs = prefs.getString("lang", getDefaultVancedLanguages(requireActivity()))?.split(", ")?.toTypedArray()
val showLang = mutableListOf<String>()
if (langPrefs != null) {
for (lang in langPrefs) {
val loc = Locale(lang)
showLang.add(loc.getDisplayLanguage(loc).capitalize(Locale.ROOT))
}
}
val darkTheme = VancedPrefModel(
requireActivity().getString(R.string.install_light_dark),
"dark"
)
val blackTheme = VancedPrefModel(
requireActivity().getString(R.string.install_light_black),
"black"
)
val adapter = arrayOf(darkTheme, blackTheme)
binding.themeSpinner.adapter = VancedPrefArray(requireActivity(), android.R.layout.simple_spinner_dropdown_item, adapter)
binding.themeSpinner.setSelection(if (prefs.getString("theme", "dark") == "dark") 0 else 1)
binding.openLanguageSelector.setOnClickListener {
dismiss()
VancedLanguageSelectionDialog().show(requireActivity().supportFragmentManager, "")
}
binding.chosenLang.text = requireActivity().getString(R.string.chosen_lang, showLang)
binding.themeSpinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
prefs.edit().putString("theme", adapter[position].value).apply()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
return
}
}
binding.chosenPrefsInstall.setOnClickListener {
dismiss()
AppDownloadDialog(requireActivity().getString(R.string.vanced)).show(requireActivity().supportFragmentManager, "InstallVanced")
}
}
}

View File

@ -1,59 +0,0 @@
package com.vanced.manager.ui.fragments
import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import com.vanced.manager.R
import com.vanced.manager.databinding.FragmentChosenPreferencesBinding
import java.util.*
class ChosenPreferenceDialogFragment : DialogFragment() {
private lateinit var binding: FragmentChosenPreferencesBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
dialog?.window?.apply { setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) }
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_chosen_preferences, container, false)
return binding.root
}
@ExperimentalStdlibApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val prefs = requireActivity().getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
val langPrefs = prefs.getString("lang", "en")?.split(", ")?.toTypedArray()
val newPrefs = mutableListOf<String>()
if (langPrefs != null) {
for (lang in langPrefs) {
val loc = Locale(lang)
newPrefs.add(loc.getDisplayLanguage(loc).capitalize(Locale.ROOT))
}
}
binding.chosenTheme.text = requireActivity().getString(R.string.chosen_theme, prefs.getString("theme", "dark")?.capitalize(Locale.ROOT))
binding.chosenLang.text = requireActivity().getString(R.string.chosen_lang, newPrefs.joinToString())
binding.chosenPrefsClose.setOnClickListener { dismiss() }
binding.chosenPrefsReset.setOnClickListener {
prefs.edit {
putString("theme", "dark")
putString("lang", "en")
putBoolean("valuesModified", false)
}
dismiss()
}
}
}

View File

@ -8,38 +8,40 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.vanced.manager.R
import com.vanced.manager.ui.MainActivity
import com.vanced.manager.utils.DownloadHelper.downloadManager
import com.vanced.manager.ui.WelcomeActivity
import com.vanced.manager.ui.dialogs.ManagerUpdateDialog
import com.vanced.manager.ui.dialogs.URLChangeDialog
class DevSettingsFragment: PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.dev_settings, rootKey)
val ftSwitch: Preference? = findPreference("firststart_switch")
val ftSwitch: Preference? = findPreference("firstlaunch_switch")
val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
ftSwitch?.setOnPreferenceClickListener {
AlertDialog.Builder(requireContext())
.setTitle("FirstStart activated")
.setTitle("FirstLaunch activated")
.setMessage("boolean will be activated on next app start")
.setPositiveButton("Restart") { _, _ ->
run {
startActivity(Intent(requireContext(), MainActivity::class.java))
startActivity(Intent(requireContext(), WelcomeActivity::class.java))
activity?.finish()
}
}
.create()
.show()
prefs.edit().putBoolean("firstStart", true).apply()
prefs.edit().putBoolean("firstLaunch", true).apply()
prefs.edit().putBoolean("show_changelog_tooltip", true).apply()
true
}
findPreference<Preference>("install_url")?.setOnPreferenceClickListener {
URLChangeFragment().show(childFragmentManager.beginTransaction(), "Install URL")
URLChangeDialog().show(childFragmentManager.beginTransaction(), "Install URL")
true
}
@ -56,7 +58,7 @@ class DevSettingsFragment: PreferenceFragmentCompat() {
val forceUpdate: Preference? = findPreference("force_update")
forceUpdate?.setOnPreferenceClickListener {
downloadManager(true, requireActivity())
ManagerUpdateDialog(true).show(requireActivity().supportFragmentManager, "update_manager")
true
}

View File

@ -0,0 +1,53 @@
package com.vanced.manager.ui.fragments
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.topjohnwu.superuser.Shell
import com.vanced.manager.R
import com.vanced.manager.databinding.FragmentGrantRootBinding
import com.vanced.manager.ui.MainActivity
class GrantRootFragment : Fragment(), View.OnClickListener {
private lateinit var binding: FragmentGrantRootBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_grant_root, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.grantRootFinishFab.setOnClickListener(this)
binding.grantRootFab.setOnClickListener(this)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.grant_root_fab -> {
if (Shell.rootAccess()) {
getDefaultSharedPreferences(requireActivity()).edit().putString("vanced_variant", "root").apply()
} else {
Toast.makeText(requireActivity(), R.string.root_not_granted, Toast.LENGTH_SHORT).show()
}
}
R.id.grant_root_finish_fab -> {
val intent = Intent(requireActivity(), MainActivity::class.java)
intent.putExtra("firstLaunch", true)
startActivity(intent)
requireActivity().finish()
}
}
}
}

View File

@ -6,24 +6,25 @@ import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.view.*
import android.view.animation.AnimationUtils
import android.widget.Toast
import androidx.core.content.res.ResourcesCompat
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.navigation.findNavController
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.topjohnwu.superuser.Shell
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.florent37.viewtooltip.ViewTooltip
import com.google.android.flexbox.FlexboxLayoutManager
import com.google.android.flexbox.JustifyContent
import com.vanced.manager.R
import com.vanced.manager.adapter.VariantAdapter
import com.vanced.manager.adapter.AppListAdapter
import com.vanced.manager.adapter.LinkAdapter
import com.vanced.manager.adapter.SponsorAdapter
import com.vanced.manager.databinding.FragmentHomeBinding
import com.vanced.manager.ui.dialogs.DialogContainer.installAlertBuilder
import com.vanced.manager.ui.viewmodels.HomeViewModel
import com.vanced.manager.ui.viewmodels.HomeViewModelFactory
import com.vanced.manager.utils.AppUtils.installing
open class HomeFragment : Fragment() {
@ -32,26 +33,28 @@ open class HomeFragment : Fragment() {
HomeViewModelFactory(requireActivity())
}
private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) }
private val prefs by lazy { PreferenceManager.getDefaultSharedPreferences(requireActivity()) }
private lateinit var tooltip: ViewTooltip
private val tabListener = object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
if (tab.position == 1 && !Shell.rootAccess()) {
Toast.makeText(requireActivity(), getString(R.string.root_not_granted), Toast.LENGTH_SHORT).show()
}
val variant = if (tab.position == 1) "root" else "nonroot"
getDefaultSharedPreferences(requireActivity()).edit().putString("vanced_variant", variant).apply()
}
override fun onTabUnselected(tab: TabLayout.Tab) {
return
}
override fun onTabReselected(tab: TabLayout.Tab) {
return
}
}
// private val tabListener = object : TabLayout.OnTabSelectedListener {
//
// override fun onTabSelected(tab: TabLayout.Tab) {
// if (tab.position == 1 && !Shell.rootAccess()) {
// Toast.makeText(requireActivity(), getString(R.string.root_not_granted), Toast.LENGTH_SHORT).show()
// }
// val variant = if (tab.position == 1) "root" else "nonroot"
// getDefaultSharedPreferences(requireActivity()).edit().putString("vanced_variant", variant).apply()
// }
//
// override fun onTabUnselected(tab: TabLayout.Tab) {
// return
// }
//
// override fun onTabReselected(tab: TabLayout.Tab) {
// return
// }
//
// }
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
@ -67,36 +70,79 @@ open class HomeFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
viewModel.navigateDestination.observe(viewLifecycleOwner, {
val content = it.getContentIfNotHandled()
if(content != null){
if (content != null){
view.findNavController().navigate(content)
}
})
with(binding) {
mainViewpager.adapter = VariantAdapter(viewModel, requireActivity())
TabLayoutMediator(mainTablayout, mainViewpager) { tab, position ->
val variants = arrayOf("nonroot", "root")
tab.text = variants[position]
}.attach()
mainTablayout.getTabAt(if (getDefaultSharedPreferences(requireActivity()).getString("vanced_variant", "nonroot") == "root") 1 else 0)?.select()
viewModel = this@HomeFragment.viewModel
tooltip = ViewTooltip
.on(recyclerAppList)
.position(ViewTooltip.Position.TOP)
.autoHide(false, 0)
.color(ResourcesCompat.getColor(requireActivity().resources, R.color.Twitter, null))
.withShadow(false)
.corner(25)
.onHide {
prefs.edit().putBoolean("show_changelog_tooltip", false).apply()
}
.text(requireActivity().getString(R.string.app_changelog_tooltip))
if (prefs.getBoolean("show_changelog_tooltip", true)) {
tooltip.show()
}
recyclerAppList.apply {
layoutManager = LinearLayoutManager(requireActivity())
adapter = AppListAdapter(requireActivity(), this@HomeFragment.viewModel, tooltip)
setHasFixedSize(true)
}
recyclerSponsors.apply {
val lm = FlexboxLayoutManager(requireActivity())
lm.justifyContent = JustifyContent.SPACE_EVENLY
layoutManager = lm
setHasFixedSize(true)
adapter = SponsorAdapter(requireActivity(), this@HomeFragment.viewModel)
}
recyclerLinks.apply {
val lm = FlexboxLayoutManager(requireActivity())
lm.justifyContent = JustifyContent.SPACE_EVENLY
layoutManager = lm
setHasFixedSize(true)
adapter = LinkAdapter(requireActivity(), this@HomeFragment.viewModel)
}
}
installing.observe(viewLifecycleOwner, { value ->
if (value) hideTab() else showTab()
})
// with(binding) {
// mainViewpager.adapter = VariantAdapter(viewModel, requireActivity())
// TabLayoutMediator(mainTablayout, mainViewpager) { tab, position ->
// val variants = arrayOf("nonroot", "root")
// tab.text = variants[position]
// }.attach()
// mainTablayout.getTabAt(if (getDefaultSharedPreferences(requireActivity()).getString("vanced_variant", "nonroot") == "root") 1 else 0)?.select()
// }
// installing.observe(viewLifecycleOwner, { value ->
// if (value) hideTab() else showTab()
// })
}
override fun onPause() {
super.onPause()
localBroadcastManager.unregisterReceiver(broadcastReceiver)
binding.mainTablayout.removeOnTabSelectedListener(tabListener)
tooltip.close()
//binding.mainTablayout.removeOnTabSelectedListener(tabListener)
}
override fun onResume() {
super.onResume()
registerReceivers()
binding.mainTablayout.addOnTabSelectedListener(tabListener)
// binding.mainTablayout.addOnTabSelectedListener(tabListener)
}
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
@ -108,27 +154,27 @@ open class HomeFragment : Fragment() {
}
}
private fun hideTab() {
val tabHide = AnimationUtils.loadAnimation(requireActivity(), R.anim.tablayout_exit)
with(binding) {
if (mainTablayout.visibility != View.GONE) {
mainTablayout.startAnimation(tabHide)
mainTablayout.visibility = View.GONE
}
mainViewpager.isUserInputEnabled = false
}
}
private fun showTab() {
val tabShow = AnimationUtils.loadAnimation(requireActivity(), R.anim.tablayout_enter)
with(binding) {
if (mainTablayout.visibility != View.VISIBLE) {
mainTablayout.visibility = View.VISIBLE
mainTablayout.startAnimation(tabShow)
}
mainViewpager.isUserInputEnabled = true
}
}
// private fun hideTab() {
// val tabHide = AnimationUtils.loadAnimation(requireActivity(), R.anim.tablayout_exit)
// with(binding) {
// if (mainTablayout.visibility != View.GONE) {
// mainTablayout.startAnimation(tabHide)
// mainTablayout.visibility = View.GONE
// }
// mainViewpager.isUserInputEnabled = false
// }
// }
//
// private fun showTab() {
// val tabShow = AnimationUtils.loadAnimation(requireActivity(), R.anim.tablayout_enter)
// with(binding) {
// if (mainTablayout.visibility != View.VISIBLE) {
// mainTablayout.visibility = View.VISIBLE
// mainTablayout.startAnimation(tabShow)
// }
// mainViewpager.isUserInputEnabled = true
// }
// }
private fun registerReceivers() {
val intentFilter = IntentFilter()

View File

@ -0,0 +1,53 @@
package com.vanced.manager.ui.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.LinearLayoutManager
import com.vanced.manager.R
import com.vanced.manager.adapter.SelectAppsAdapter
import com.vanced.manager.databinding.FragmentSelectAppsBinding
class SelectAppsFragment : Fragment() {
private lateinit var binding: FragmentSelectAppsBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_select_apps, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val selectAdapter = SelectAppsAdapter(requireActivity())
val prefs = getDefaultSharedPreferences(requireActivity())
binding.selectAppsRecycler.apply {
layoutManager = LinearLayoutManager(requireActivity())
setHasFixedSize(true)
adapter = selectAdapter
}
binding.selectAppsFab.setOnClickListener {
if (selectAdapter.apps.all { app -> !app.isChecked }) {
Toast.makeText(requireActivity(), R.string.select_at_least_one_app, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
selectAdapter.apps.forEach { app ->
prefs.edit().putBoolean("enable_${app.tag}", app.isChecked).apply()
}
findNavController().navigate(SelectAppsFragmentDirections.selectAppsToGrantRoot())
}
}
}

View File

@ -1,134 +1,113 @@
package com.vanced.manager.ui.fragments
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.*
import android.widget.Toast
import androidx.preference.*
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.messaging.FirebaseMessaging
import com.google.firebase.perf.FirebasePerformance
import com.vanced.manager.BuildConfig.MANAGER_LANGUAGES
import com.vanced.manager.BuildConfig.MANAGER_LANGUAGE_NAMES
import com.vanced.manager.R
import com.vanced.manager.adapter.GetNotifAdapter
import com.vanced.manager.databinding.FragmentSettingsBinding
import com.vanced.manager.ui.dialogs.*
import com.vanced.manager.utils.LanguageHelper.getLanguageFormat
import java.io.File
class SettingsFragment : PreferenceFragmentCompat() {
class SettingsFragment : Fragment() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
private lateinit var binding: FragmentSettingsBinding
private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) }
activity?.title = getString(R.string.title_settings)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
setHasOptionsMenu(true)
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_settings, container, false)
return binding.root
}
findPreference<Preference>("update_check")?.setOnPreferenceClickListener {
UpdateCheckFragment().show(childFragmentManager.beginTransaction(), "Update Center")
true
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.notificationsRecycler.apply {
layoutManager = LinearLayoutManager(requireActivity())
adapter = GetNotifAdapter(requireActivity())
}
findPreference<SwitchPreference>("vanced_notifs")?.apply {
title = getString(R.string.push_notifications, "Vanced")
summary = getString(R.string.push_notifications_summary, "Vanced")
setOnPreferenceChangeListener { _, newValue ->
when (newValue) {
true -> FirebaseMessaging.getInstance().subscribeToTopic("Vanced-Update")
false -> FirebaseMessaging.getInstance().unsubscribeFromTopic("Vanced-Update")
}
true
binding.firebase.setOnCheckedListener { _, isChecked ->
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(isChecked)
FirebasePerformance.getInstance().isPerformanceCollectionEnabled = isChecked
FirebaseAnalytics.getInstance(requireActivity()).setAnalyticsCollectionEnabled(isChecked)
}
binding.managerVariant.apply {
prefs.getString("vanced_variant", "nonrooot")?.let { setSummary(it) }
setOnClickListener {
ManagerVariantDialog().show(requireActivity().supportFragmentManager, "")
}
}
findPreference<SwitchPreference>("microg_notifs")?.apply {
title = getString(R.string.push_notifications, "microG")
summary = getString(R.string.push_notifications_summary, "microG")
setOnPreferenceChangeListener { _, newValue ->
when (newValue) {
true -> FirebaseMessaging.getInstance().subscribeToTopic("MicroG-Update")
false -> FirebaseMessaging.getInstance().unsubscribeFromTopic("MicroG-Update")
}
true
}
}
findPreference<SwitchPreference>("firebase_analytics")?.setOnPreferenceChangeListener { _, newValue ->
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(newValue as Boolean)
FirebasePerformance.getInstance().isPerformanceCollectionEnabled = newValue
FirebaseAnalytics.getInstance(requireActivity()).setAnalyticsCollectionEnabled(newValue)
true
}
val themePref = preferenceScreen.sharedPreferences.getString("theme_mode", "Follow System")
findPreference<ListPreference>("theme_mode")?.apply {
summary = when (themePref) {
"Light" -> getString(R.string.theme_light)
"Dark" -> getString(R.string.theme_dark)
else -> getString(R.string.theme_follow)
}
setOnPreferenceChangeListener { _, newValue ->
if (themePref != newValue) {
requireActivity().recreate()
return@setOnPreferenceChangeListener true
}
false
}
}
val accentPref = preferenceScreen.sharedPreferences.getString("accent_color", "Blue")
findPreference<ListPreference>("accent_color")?.apply {
summary = when (accentPref) {
"Blue" -> getString(R.string.accent_blue)
"Red" -> getString(R.string.accent_red)
"Green" -> getString(R.string.accent_green)
"Yellow" -> getString(R.string.accent_yellow)
else -> getString(R.string.accent_purple)
}
setOnPreferenceChangeListener { _, newValue ->
if (accentPref != newValue) {
requireActivity().recreate()
return@setOnPreferenceChangeListener true
}
false
}
}
val langPref = preferenceScreen.sharedPreferences.getString("manager_lang", "System Default")
preferenceScreen.findPreference<ListPreference>("manager_lang")?.apply {
summary = langPref?.let { getLanguageFormat(requireActivity(), it) }
entries = arrayOf(getString(R.string.system_default)) + MANAGER_LANGUAGE_NAMES
entryValues = arrayOf("System Default") + MANAGER_LANGUAGES
setOnPreferenceChangeListener { _, newValue ->
if (langPref != newValue) {
requireActivity().recreate()
return@setOnPreferenceChangeListener true
}
false
}
}
findPreference<Preference>("vanced_chosen_modes")?.setOnPreferenceClickListener {
ChosenPreferenceDialogFragment().show(childFragmentManager.beginTransaction(), "Chosen Preferences")
true
}
findPreference<Preference>("clear_files")?.setOnPreferenceClickListener {
binding.clearFiles.setOnClickListener {
with(requireActivity()) {
listOf("apk", "apks").forEach { dir ->
File(getExternalFilesDir(dir)?.path as String).deleteRecursively()
}
Toast.makeText(this, getString(R.string.cleared_files), Toast.LENGTH_SHORT).show()
}
true
}
val themePref = prefs.getString("manager_theme", "System Default")
binding.managerTheme.apply {
setSummary(
when (themePref) {
"Light" -> getString(R.string.theme_light)
"Dark" -> getString(R.string.theme_dark)
else -> getString(R.string.system_default)
}
)
setOnClickListener {
ManagerThemeDialog().show(requireActivity().supportFragmentManager, "")
}
}
val accentPref = prefs.getString("manager_accent", "Blue")
binding.managerAccentColor.apply {
setSummary(
when (accentPref) {
"Blue" -> getString(R.string.accent_blue)
"Red" -> getString(R.string.accent_red)
"Green" -> getString(R.string.accent_green)
"Yellow" -> getString(R.string.accent_yellow)
else -> getString(R.string.accent_purple)
}
)
setOnClickListener {
ManagerAccentColorDialog().show(requireActivity().supportFragmentManager, "")
}
}
val langPref = prefs.getString("manager_lang", "System Default")
binding.managerLanguage.apply {
setSummary(getLanguageFormat(requireActivity(), langPref!!))
setOnClickListener {
ManagerLanguageDialog().show(requireActivity().supportFragmentManager, "")
}
}
binding.selectApps.setOnClickListener {
SelectAppsDialog().show(requireActivity().supportFragmentManager, "")
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
val devSettings = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean("devSettings", false)
val devSettings = getDefaultSharedPreferences(requireActivity()).getBoolean("devSettings", false)
if (devSettings) {
inflater.inflate(R.menu.dev_settings_menu, menu)
}

View File

@ -1,66 +0,0 @@
package com.vanced.manager.ui.fragments
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.fragment.app.DialogFragment
import com.google.android.material.button.MaterialButton
import com.vanced.manager.R
import com.vanced.manager.utils.DownloadHelper.downloadManager
import com.vanced.manager.utils.InternetTools.isUpdateAvailable
class UpdateCheckFragment : DialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (dialog != null && dialog?.window != null) {
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
}
return inflater.inflate(R.layout.fragment_update_check, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
checkUpdates()
view.findViewById<Button>(R.id.update_center_dismiss).setOnClickListener { dismiss() }
view.findViewById<MaterialButton>(R.id.update_center_recheck).setOnClickListener{ checkUpdates() }
downLoadingState(false)
}
private fun checkUpdates() {
val updatebtn = view?.findViewById<Button>(R.id.update_center_update)
val checkingTxt = view?.findViewById<TextView>(R.id.update_center_checking)
if (isUpdateAvailable(requireActivity())) {
view?.findViewById<Button>(R.id.update_center_recheck)?.visibility = View.GONE
checkingTxt?.text = getString(R.string.update_found)
updatebtn?.setOnClickListener {
downLoadingState(true)
downloadManager(false, requireActivity(), view?.findViewById(R.id.update_center_progressbar))
downLoadingState(false)
}
} else
checkingTxt?.text = getString(R.string.update_notfound)
}
private fun downLoadingState(isDownloading: Boolean) {
if (isDownloading) {
dialog?.setCancelable(false)
view?.findViewById<MaterialButton>(R.id.update_center_update)?.isEnabled = false
}
else {
dialog?.setCancelable(true)
view?.findViewById<MaterialButton>(R.id.update_center_update)?.isEnabled = true
}
}
}

View File

@ -1,40 +0,0 @@
package com.vanced.manager.ui.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.RadioGroup
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import com.google.android.material.radiobutton.MaterialRadioButton
import com.vanced.manager.R
class VancedThemeSelectionFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
activity?.title = getString(R.string.install)
return inflater.inflate(R.layout.fragment_vanced_theme_selection, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val nextButton = view.findViewById<Button>(R.id.vanced_next_to_variant)
val themeGroup = view.findViewById<RadioGroup>(R.id.theme_radiogroup)
val prefs = activity?.getSharedPreferences("installPrefs", Context.MODE_PRIVATE)
themeGroup.findViewWithTag<MaterialRadioButton>(prefs?.getString("theme", "dark")).isChecked = true
nextButton.setOnClickListener {
val selectedButton = view.findViewById<MaterialRadioButton>(themeGroup.checkedRadioButtonId)
prefs?.edit()?.putString("theme", selectedButton.tag.toString())?.apply()
view.findNavController().navigate(R.id.toInstallLanguageFragment)
}
}
}

View File

@ -0,0 +1,32 @@
package com.vanced.manager.ui.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.vanced.manager.R
import com.vanced.manager.databinding.FragmentWelcomeBinding
class WelcomeFragment : Fragment() {
private lateinit var binding: FragmentWelcomeBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_welcome, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.welcomeGetStarted.setOnClickListener {
findNavController().navigate(WelcomeFragmentDirections.welcomeToSelectApps())
}
}
}

View File

@ -1,50 +1,57 @@
package com.vanced.manager.ui.viewmodels
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.startActivity
import androidx.databinding.ObservableBoolean
import androidx.databinding.ObservableField
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
import com.crowdin.platform.Crowdin
import com.downloader.PRDownloader
import com.downloader.Status
import com.topjohnwu.superuser.Shell
import com.google.android.material.button.MaterialButton
import com.vanced.manager.R
import com.vanced.manager.core.App
import com.vanced.manager.core.downloader.MicrogDownloader.downloadMicrog
import com.vanced.manager.core.downloader.MusicDownloader.downloadMusic
import com.vanced.manager.core.downloader.VancedDownloader.downloadVanced
import com.vanced.manager.model.DataModel
import com.vanced.manager.model.ProgressModel
import com.vanced.manager.ui.dialogs.AppDownloadDialog
import com.vanced.manager.ui.dialogs.InstallationFilesDetectedDialog
import com.vanced.manager.ui.dialogs.VancedPreferencesDialog
import com.vanced.manager.ui.events.Event
import com.vanced.manager.utils.AppUtils.installing
import com.vanced.manager.utils.AppUtils.managerPkg
import com.vanced.manager.utils.AppUtils.microgPkg
import com.vanced.manager.utils.AppUtils.musicPkg
import com.vanced.manager.utils.AppUtils.musicRootPkg
import com.vanced.manager.utils.AppUtils.vancedPkg
import com.vanced.manager.utils.AppUtils.vancedRootPkg
import com.vanced.manager.utils.Extensions.show
import com.vanced.manager.utils.InternetTools
import com.vanced.manager.utils.PackageHelper.apkExist
import com.vanced.manager.utils.PackageHelper.musicApkExists
import com.vanced.manager.utils.PackageHelper.musicRootApkExists
import com.vanced.manager.utils.PackageHelper.uninstallApk
import com.vanced.manager.utils.PackageHelper.vancedInstallFilesExist
import com.vanced.manager.utils.PackageHelper.vancedRootInstallFilesExist
open class HomeViewModel(private val activity: Activity): ViewModel() {
open class HomeViewModel(private val activity: FragmentActivity): ViewModel() {
private val app = activity.application as App
//val variant = getDefaultSharedPreferences(activity).getString("vanced_variant", "nonroot")
private val prefs = getDefaultSharedPreferences(activity)
val vanced = ObservableField<DataModel>()
val vancedRoot = ObservableField<DataModel>()
val microg = ObservableField<DataModel>()
val music = ObservableField<DataModel>()
val musicRoot = ObservableField<DataModel>()
val manager = ObservableField<DataModel>()
val fetching = ObservableBoolean()
val fetching = ObservableBoolean(true)
private var _navigateDestination = MutableLiveData<Event<Int>>()
@ -53,11 +60,6 @@ open class HomeViewModel(private val activity: Activity): ViewModel() {
fun fetchData() {
fetching.set(true)
app.loadJsonAsync()
vanced.get()?.fetch()
vancedRoot.get()?.fetch()
music.get()?.fetch()
microg.get()?.fetch()
manager.get()?.fetch()
Crowdin.forceUpdate(activity)
fetching.set(false)
}
@ -94,76 +96,53 @@ open class HomeViewModel(private val activity: Activity): ViewModel() {
InternetTools.openUrl(url, color, activity)
}
fun installVanced(variant: String) {
if (!installing.value!!) {
if (!fetching.get()) {
when {
variant == "nonroot" && !microg.get()?.isAppInstalled?.get()!! -> microgToast.show()
variant == "root" && !Shell.rootAccess() -> Toast.makeText(activity, R.string.root_not_granted, Toast.LENGTH_SHORT).show()
else -> {
if (activity.getSharedPreferences("installPrefs", Context.MODE_PRIVATE).getBoolean("valuesModified", false)) {
downloadVanced(activity)
} else {
_navigateDestination.value = Event(R.id.toInstallThemeFragment)
}
}
fun openInstallDialog(view: View, app: String) {
val variant = prefs.getString("vanced_variant", "nonroot")
if (variant == "nonroot" && app != activity.getString(R.string.microg) && !microg.get()?.isAppInstalled?.get()!!) {
microgToast.show()
return
}
if ((view as MaterialButton).text == activity.getString(R.string.update)) {
if (app == activity.getString(R.string.vanced))
VancedPreferencesDialog().show(activity)
else
AppDownloadDialog(app).show(activity)
return
}
when (app) {
activity.getString(R.string.vanced) -> {
when (variant) {
"nonroot" -> if (vancedInstallFilesExist(activity)) InstallationFilesDetectedDialog(app).show(activity) else VancedPreferencesDialog().show(activity)
"root" -> VancedPreferencesDialog().show(activity)
}
}
} else
Toast.makeText(activity, R.string.installation_wait, Toast.LENGTH_SHORT).show()
}
fun installMusic() {
if (!installing.value!!) {
if (!fetching.get()) {
if (!microg.get()?.isAppInstalled?.get()!!) {
microgToast.show()
} else {
downloadMusic(activity)
activity.getString(R.string.music) -> {
when (variant) {
"nonroot" -> if (musicApkExists(activity)) InstallationFilesDetectedDialog(app).show(activity) else AppDownloadDialog(app).show(activity)
"root" -> AppDownloadDialog(app).show(activity)
}
}
} else
Toast.makeText(activity, R.string.installation_wait, Toast.LENGTH_SHORT).show()
}
fun installMicrog() {
if (!installing.value!!)
downloadMicrog(activity)
else
Toast.makeText(activity, R.string.installation_wait, Toast.LENGTH_SHORT).show()
}
fun uninstallVanced(variant: String) = uninstallApk(if (variant == "root") vancedRootPkg else vancedPkg, activity)
fun uninstallMusic() = uninstallApk(musicPkg, activity)
fun uninstallMicrog() = uninstallApk(microgPkg, activity)
activity.getString(R.string.microg) -> {
Log.d("test", apkExist(activity, "microg.apk").toString())
if (apkExist(activity, "microg.apk")) InstallationFilesDetectedDialog(app).show(activity) else AppDownloadDialog(app).show(activity)
}
}
fun cancelDownload(downloadId: Int) {
PRDownloader.cancel(downloadId)
}
fun pauseResumeDownload(downloadId: Int) {
if (PRDownloader.getStatus(downloadId) == Status.PAUSED)
PRDownloader.resume(downloadId)
else
PRDownloader.pause(downloadId)
}
companion object {
val vancedProgress = ObservableField<ProgressModel>()
val musicProgress = ObservableField<ProgressModel>()
val microgProgress = ObservableField<ProgressModel>()
}
fun uninstallPackage(pkg: String) = uninstallApk(pkg, activity)
init {
fetching.set(true)
vanced.set(DataModel(app.vanced, vancedPkg, activity))
vancedRoot.set(DataModel(app.vanced, vancedRootPkg, activity))
music.set(DataModel(app.music, musicPkg, activity))
microg.set(DataModel(app.microg, microgPkg, activity))
manager.set(DataModel(app.manager, managerPkg, activity))
vancedProgress.set(ProgressModel())
musicProgress.set(ProgressModel())
microgProgress.set(ProgressModel())
vanced.set(DataModel(app.vanced, activity, vancedPkg, activity.getString(R.string.vanced), ContextCompat.getDrawable(activity, R.drawable.ic_vanced)))
vancedRoot.set(DataModel(app.vanced, activity, vancedRootPkg, activity.getString(R.string.vanced), ContextCompat.getDrawable(activity, R.drawable.ic_vanced)))
music.set(DataModel(app.music, activity, musicPkg, activity.getString(R.string.music), ContextCompat.getDrawable(activity, R.drawable.ic_music)))
musicRoot.set(DataModel(app.music, activity, musicRootPkg, activity.getString(R.string.music), ContextCompat.getDrawable(activity, R.drawable.ic_music)))
microg.set(DataModel(app.microg, activity, microgPkg, activity.getString(R.string.microg), ContextCompat.getDrawable(activity, R.drawable.ic_microg)))
manager.set(DataModel(app.manager, activity, managerPkg, activity.getString(R.string.app_name), ContextCompat.getDrawable(activity, R.mipmap.ic_launcher)))
fetching.set(false)
}

View File

@ -1,10 +1,10 @@
package com.vanced.manager.ui.viewmodels
import android.app.Activity
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class HomeViewModelFactory(private val activity: Activity) : ViewModelProvider.Factory {
class HomeViewModelFactory(private val activity: FragmentActivity) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return HomeViewModel(activity) as T

View File

@ -0,0 +1,10 @@
package com.vanced.manager.ui.viewmodels
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
class SettingsViewModel(activity: FragmentActivity) : ViewModel() {
}

View File

@ -0,0 +1,13 @@
package com.vanced.manager.ui.viewmodels
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class SettingsViewModelFactory(private val activity: FragmentActivity) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return SettingsViewModel(activity) as T
}
}

View File

@ -3,12 +3,12 @@ package com.vanced.manager.utils
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.vanced.manager.BuildConfig.APPLICATION_ID
import com.vanced.manager.R
import com.vanced.manager.ui.dialogs.AppDownloadDialog
import com.vanced.manager.ui.fragments.HomeFragment
import com.vanced.manager.utils.DownloadHelper.downloadProgress
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@ -16,19 +16,13 @@ import kotlinx.coroutines.launch
object AppUtils {
val mutableInstall = MutableLiveData<Boolean>()
val installing: LiveData<Boolean> = mutableInstall
const val vancedPkg = "com.vanced.android.youtube"
const val vancedRootPkg = "com.google.android.youtube"
const val musicPkg = "com.vanced.android.apps.youtube.music"
const val musicRootPkg = "com.google.android.apps.youtube.music"
const val microgPkg = "com.mgoogle.android.gms"
const val managerPkg = APPLICATION_ID
init {
mutableInstall.value = false
}
fun sendRefresh(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
delay(500)
@ -36,8 +30,16 @@ object AppUtils {
}
}
fun sendCloseDialog(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
delay(500)
LocalBroadcastManager.getInstance(context).sendBroadcast(Intent(AppDownloadDialog.CLOSE_DIALOG))
downloadProgress.get()?.installing?.set(false)
}
}
fun sendFailure(status: Int, context: Context) {
mutableInstall.value = false
downloadProgress.get()?.installing?.set(false)
//Delay error broadcast until activity (and fragment) get back to the screen
CoroutineScope(Dispatchers.IO).launch {
delay(500)

View File

@ -6,13 +6,14 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.util.Log
import android.view.View
import android.widget.ProgressBar
import android.widget.Toast
import androidx.core.content.FileProvider
import androidx.databinding.ObservableField
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.vanced.manager.R
import com.vanced.manager.model.ProgressModel
import com.vanced.manager.utils.AppUtils.sendCloseDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@ -32,47 +33,49 @@ object DownloadHelper {
return downloadManager.enqueue(request)
}
fun downloadManager(forceUpdate: Boolean, context: Context, loadBar: ProgressBar? = null) {
CoroutineScope(if (forceUpdate) Dispatchers.IO else Dispatchers.Main).launch {
val downloadProgress = ObservableField<ProgressModel>()
init {
downloadProgress.set(ProgressModel())
}
fun downloadManager(context: Context) {
CoroutineScope(Dispatchers.IO).launch {
val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk"
//downloadId = activity?.let { download(url, "apk", "manager.apk", it) }!!
PRDownloader.download(url, context.getExternalFilesDir("apk")?.path, "manager.apk")
.build().apply{
if (!forceUpdate) setOnProgressListener {progress ->
val mProgress = progress.currentBytes * 100 / progress.totalBytes
loadBar?.visibility = View.VISIBLE
loadBar?.progress = mProgress.toInt()
downloadProgress.get()?.currentDownload = PRDownloader.download(url, context.getExternalFilesDir("apk")?.path, "manager.apk")
.build()
.setOnProgressListener { progress ->
val mProgress = progress.currentBytes * 100 / progress.totalBytes
downloadProgress.get()?.downloadProgress?.set(mProgress.toInt())
}
.start(object : OnDownloadListener {
override fun onDownloadComplete() {
val apk =
File("${context.getExternalFilesDir("apk")?.path}/manager.apk")
val uri =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
FileProvider.getUriForFile(
context,
"${context.packageName}.provider",
apk
)
else
Uri.fromFile(apk)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(intent)
sendCloseDialog(context)
}
start(object : OnDownloadListener {
override fun onDownloadComplete() {
context.let {
val apk =
File("${context.getExternalFilesDir("apk")?.path}/manager.apk")
val uri =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
FileProvider.getUriForFile(
context,
"${context.packageName}.provider",
apk
)
else
Uri.fromFile(apk)
val intent = Intent(Intent.ACTION_VIEW)
intent.setDataAndType(uri, "application/vnd.android.package-archive")
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
context.startActivity(intent)
}
}
override fun onError(error: com.downloader.Error?) {
Toast.makeText(context, error.toString(), Toast.LENGTH_SHORT).show()
Log.e("VMUpgrade", error.toString())
}
override fun onError(error: com.downloader.Error?) {
Toast.makeText(context, error.toString(), Toast.LENGTH_SHORT).show()
Log.e("VMUpgrade", error.toString())
}
})
}
})
}
}

View File

@ -0,0 +1,18 @@
package com.vanced.manager.utils
import android.widget.RadioGroup
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentActivity
import com.google.android.material.radiobutton.MaterialRadioButton
object Extensions {
fun RadioGroup.getCheckedButtonTag(): String {
return findViewById<MaterialRadioButton>(checkedRadioButtonId).tag.toString()
}
fun DialogFragment.show(activity: FragmentActivity) {
this.show(activity.supportFragmentManager, "")
}
}

View File

@ -21,9 +21,10 @@ class LanguageContextWrapper(base: Context?) : ContextWrapper(base) {
private fun setLocale(config: Configuration, context: Context): Configuration {
val pref = PreferenceManager.getDefaultSharedPreferences(context).getString("manager_lang", "System Default")
val sysLocale = Resources.getSystem().configuration.locale
val locale =
when {
pref == "System Default" -> Locale(Resources.getSystem().configuration.locale.language)
pref == "System Default" -> Locale(sysLocale.language, sysLocale.country)
pref?.length!! > 2 -> Locale(pref.substring(0, pref.length - 3), pref.substring(pref.length - 2))
else -> Locale(pref)
}

View File

@ -1,7 +1,14 @@
package com.vanced.manager.utils
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.os.Build
import android.os.LocaleList
import android.util.Log
import androidx.annotation.RequiresApi
import com.vanced.manager.R
import com.vanced.manager.core.App
import java.util.*
object LanguageHelper {
@ -11,17 +18,54 @@ object LanguageHelper {
language == "System Default" -> context.getString(R.string.system_default)
language.length > 2 -> {
val loc = Locale(
language.substring(0, language.length - 3),
language.substring(language.length - 2)
language.substring(0, language.length - 3),
language.substring(language.length - 2)
)
loc.getDisplayName(loc)
loc.getDisplayName(loc).capitalize(Locale.ENGLISH)
}
else -> {
val loc = Locale(language)
loc.getDisplayName(loc)
loc.getDisplayName(loc).capitalize(Locale.ENGLISH)
}
}
}
fun getDefaultVancedLanguages(activity: Activity): String {
val serverLangs = (activity.applicationContext as App).vanced.get()!!.array<String>("langs")
val sysLocales = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) Resources.getSystem().configuration.locales.toLangTags() else arrayOf(Resources.getSystem().configuration.locale.language)
val finalLangs = mutableListOf<String>()
sysLocales.forEach { sysLocale ->
if (sysLocale == "en")
finalLangs.add(sysLocale)
else if (serverLangs != null && serverLangs.contains(sysLocale))
finalLangs.add(sysLocale)
}
return finalLangs.distinct().sorted().joinToString(", ")
}
fun getDefaultVancedLanguages(app: App): String {
val serverLangs = app.vanced.get()!!.array<String>("langs")
val sysLocales = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) Resources.getSystem().configuration.locales.toLangTags() else arrayOf(Resources.getSystem().configuration.locale.language)
val finalLangs = mutableListOf<String>()
sysLocales.forEach { sysLocale ->
if (sysLocale == "en")
finalLangs.add(sysLocale)
else if (serverLangs != null && serverLangs.contains(sysLocale))
finalLangs.add(sysLocale)
}
return finalLangs.distinct().sorted().joinToString(", ")
}
@RequiresApi(Build.VERSION_CODES.N)
fun LocaleList.toLangTags(): Array<String> {
val langTags: Array<String> = this.toLanguageTags().split(",").toTypedArray()
for (i in 0 until this.size()) {
langTags[i] = langTags[i].substring(0, 2)
}
return langTags
}
}

View File

@ -14,9 +14,7 @@ import com.vanced.manager.BuildConfig
import com.vanced.manager.core.App
import com.vanced.manager.core.installer.AppInstallerService
import com.vanced.manager.core.installer.AppUninstallerService
import com.vanced.manager.core.installer.SplitInstallerService
import com.vanced.manager.ui.viewmodels.HomeViewModel.Companion.vancedProgress
import com.vanced.manager.utils.AppUtils.mutableInstall
import com.vanced.manager.utils.AppUtils.sendCloseDialog
import com.vanced.manager.utils.AppUtils.sendFailure
import com.vanced.manager.utils.AppUtils.sendRefresh
import com.vanced.manager.utils.AppUtils.vancedRootPkg
@ -56,6 +54,103 @@ object PackageHelper {
}
fun apkExist(context: Context, apk: String): Boolean {
val apkPath = File(context.getExternalFilesDir(apk.substring(0, apk.length - 4))?.path, apk)
if (apkPath.exists())
return true
return false
}
fun musicApkExists(context: Context): Boolean {
val apkPath = File(context.getExternalFilesDir("music/nonroot")?.path, "music.apk")
if (apkPath.exists()) {
return true
}
return false
}
fun musicRootApkExists(context: Context): Boolean {
val apkPath = File(context.getExternalFilesDir("music/root")?.path as String)
val apkList = mutableListOf<String>()
if (apkPath.exists()) {
val files = apkPath.listFiles()
if (files?.isNotEmpty() == true) {
for (file in files) {
if (apkList.size == 2)
return true
when (file.name) {
"music.apk" -> apkList.add("music")
"stock.apk" -> apkList.add("stock")
}
}
}
}
return false
}
fun vancedInstallFilesExist(context: Context): Boolean {
val apksPath = File(context.getExternalFilesDir("vanced/nonroot")?.path.toString())
val splitFiles = mutableListOf<String>()
if (apksPath.exists()) {
val files = apksPath.listFiles()
if (files?.isNotEmpty() == true) {
for (file in files) {
when {
(file.name == "black.apk" || file.name == "dark.apk") && !splitFiles.contains("base") -> splitFiles.add("base")
file.name.matches(Regex("split_config\\.(..)\\.apk")) && !splitFiles.contains("lang") -> splitFiles.add("lang")
(file.name.startsWith("split_config.arm") || file.name.startsWith("split_config.x86")) && !splitFiles.contains("arch") -> splitFiles.add("arch")
}
Log.d("test", splitFiles.joinToString())
if (splitFiles.size == 3) {
return true
}
}
}
return false
}
return false
}
fun vancedRootInstallFilesExist(context: Context): Boolean {
val apksPath = File(context.getExternalFilesDir("vanced/root")?.path.toString())
val splitFiles = mutableListOf<String>()
if (apksPath.exists()) {
val files = apksPath.listFiles()
if (files?.isNotEmpty() == true) {
for (file in files) {
when {
(file.name == "black.apk" || file.name == "dark.apk") && !splitFiles.contains("base") -> splitFiles.add("base")
file.name == "stock.apk" && !splitFiles.contains("stock") -> splitFiles.add("stock")
file.name == "dpi.apk" && !splitFiles.contains("dpi") -> splitFiles.add("dpi")
file.name.matches(Regex("split_config\\.(..)\\.apk")) && !splitFiles.contains("lang") -> splitFiles.add("lang")
(file.name.startsWith("split_config.arm") || file.name.startsWith("split_config.x86")) && !splitFiles.contains("arch") -> splitFiles.add("arch")
}
Log.d("test", splitFiles.joinToString())
if (splitFiles.size == 5) {
return true
}
}
}
return false
}
return false
}
fun uninstallApk(pkg: String, context: Context): Boolean {
val callbackIntent = Intent(context, AppUninstallerService::class.java)
callbackIntent.putExtra("pkg", pkg)
@ -69,12 +164,11 @@ object PackageHelper {
}
}
fun install(app: String, path: String, context: Context){
val callbackIntent = Intent(context, AppInstallerService::class.java).putExtra("app", app)
fun install(path: String, context: Context) {
val callbackIntent = Intent(context, AppInstallerService::class.java)
val pendingIntent = PendingIntent.getService(context, 0, callbackIntent, 0)
val packageInstaller = context.packageManager.packageInstaller
val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
params.setAppPackageName(if (app == "microg") "com.mgoogle.android.gms" else "com.vanced.android.apps.youtube.music")
val sessionId = packageInstaller.createSession(params)
val session = packageInstaller.openSession(sessionId)
val inputStream: InputStream = FileInputStream(path)
@ -91,7 +185,7 @@ object PackageHelper {
}
fun installVanced(context: Context): Int {
val apkFolderPath = context.getExternalFilesDir("apks")?.path + "/"
val apkFolderPath = context.getExternalFilesDir("vanced/nonroot")?.path.toString() + "/"
val nameSizeMap = HashMap<String, Long>()
var totalSize: Long = 0
var sessionId = 0
@ -176,7 +270,7 @@ object PackageHelper {
try {
try {
session = context.packageManager.packageInstaller.openSession(sessionId)
val callbackIntent = Intent(context, SplitInstallerService::class.java)
val callbackIntent = Intent(context, AppInstallerService::class.java)
val pendingIntent = PendingIntent.getService(context, 0, callbackIntent, 0)
session.commit(pendingIntent.intentSender)
session.close()
@ -204,7 +298,7 @@ object PackageHelper {
val application = context.applicationContext as App
val vancedApplication = application.vanced.get()?.int("versionCode")
val vancedVersionCode = if (vancedApplication != null) vancedApplication else { application.loadJsonAsync(); vancedApplication }
val apkFilesPath = context.getExternalFilesDir("apks")?.path
val apkFilesPath = context.getExternalFilesDir("vanced/root")?.path
val fileInfoList = apkFilesPath?.let { it1 -> getFileInfoList(it1) }
if (fileInfoList != null) {
var modApk: FileInfo? = null
@ -216,8 +310,7 @@ object PackageHelper {
if (modApk != null) {
if (overwriteBase(modApk, fileInfoList, vancedVersionCode!!, context)) {
sendRefresh(context)
vancedProgress.get()?.showInstallCircle?.set(false)
mutableInstall.value = false
sendCloseDialog(context)
}
}
else {

View File

@ -8,18 +8,18 @@ import com.vanced.manager.R
object ThemeHelper {
fun setFinalTheme(activity: Activity) {
val currentAccent = PreferenceManager.getDefaultSharedPreferences(activity).getString("accent_color", "Blue")
val currentAccent = PreferenceManager.getDefaultSharedPreferences(activity).getString("manager_accent", "Blue")
when (PreferenceManager.getDefaultSharedPreferences(activity)
.getString("theme_mode", "Follow System")) {
.getString("manager_theme", "System Default")) {
"Light" -> activity.setTheme(getLightAccent(currentAccent))
"Dark" -> activity.setTheme(getDarkAccent(currentAccent))
"Follow System" -> {
"System Default" -> {
when (activity.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_YES -> activity.setTheme(getDarkAccent(currentAccent))
Configuration.UI_MODE_NIGHT_NO -> activity.setTheme(getLightAccent(currentAccent))
}
}
else -> getLightAccent("Blue")
else -> activity.setTheme(getLightAccent("Blue"))
}
}

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="800"
android:fromYDelta="-100%p"
android:toYDelta="0"
/>
</set>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="800"
android:fromYDelta="0"
android:toYDelta="-100%p"
/>
</set>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@android:integer/config_longAnimTime"
android:valueType="floatType"
android:valueFrom="0"
android:valueTo="-0.3"
android:propertyName="xFraction" />
<objectAnimator
android:duration="@android:integer/config_longAnimTime"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0.3"
android:valueType="floatType" />
</set>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="@android:integer/config_longAnimTime"
android:valueType="floatType"
android:valueFrom="-0.3"
android:valueTo="0"
android:propertyName="xFraction" />
<objectAnimator
android:duration="@android:integer/config_longAnimTime"
android:propertyName="alpha"
android:valueFrom="0.3"
android:valueTo="1"
android:valueType="floatType" />
</set>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/colorOnSurfaceVariant"
android:pathData="M7.41,7.84L12,12.42l4.59,-4.58L18,9.25l-6,6 -6,-6z"/>
</vector>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:topRightRadius="8dp"
android:topLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:bottomLeftRadius="8dp" />
<solid
android:color="?colorLinkBG" />
</shape>

View File

@ -1,8 +0,0 @@
<!-- drawable/discord.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="34dp"
android:width="34dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M22,24L16.75,19L17.38,21H4.5A2.5,2.5 0 0,1 2,18.5V3.5A2.5,2.5 0 0,1 4.5,1H19.5A2.5,2.5 0 0,1 22,3.5V24M12,6.8C9.32,6.8 7.44,7.95 7.44,7.95C8.47,7.03 10.27,6.5 10.27,6.5L10.1,6.33C8.41,6.36 6.88,7.53 6.88,7.53C5.16,11.12 5.27,14.22 5.27,14.22C6.67,16.03 8.75,15.9 8.75,15.9L9.46,15C8.21,14.73 7.42,13.62 7.42,13.62C7.42,13.62 9.3,14.9 12,14.9C14.7,14.9 16.58,13.62 16.58,13.62C16.58,13.62 15.79,14.73 14.54,15L15.25,15.9C15.25,15.9 17.33,16.03 18.73,14.22C18.73,14.22 18.84,11.12 17.12,7.53C17.12,7.53 15.59,6.36 13.9,6.33L13.73,6.5C13.73,6.5 15.53,7.03 16.56,7.95C16.56,7.95 14.68,6.8 12,6.8M9.93,10.59C10.58,10.59 11.11,11.16 11.1,11.86C11.1,12.55 10.58,13.13 9.93,13.13C9.29,13.13 8.77,12.55 8.77,11.86C8.77,11.16 9.28,10.59 9.93,10.59M14.1,10.59C14.75,10.59 15.27,11.16 15.27,11.86C15.27,12.55 14.75,13.13 14.1,13.13C13.46,13.13 12.94,12.55 12.94,11.86C12.94,11.16 13.45,10.59 14.1,10.59Z" />
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="33.408dp"
android:height="34.294dp"
android:viewportWidth="33.408"
android:viewportHeight="34.294">
<path
android:strokeWidth="1"
android:pathData="M16.7,0.5A36.932,36.932 0,0 0,0.5 4.292c0,5.689 -0.057,19.767 16.2,29.42 16.261,-9.653 16.2,-23.789 16.2,-29.42A36.932,36.932 0,0 0,16.7 0.5Z"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:fillType="evenOdd"/>
<path
android:pathData="M16.13,22.678l9.826,-13.216a1.223,1.223 0,0 0,-1.724 0.172h0l-8.159,8.5 -3.1,-3.735c-1.494,-1.724 -3.448,-0.4 -3.907,-0.057L16.13,22.678"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

View File

@ -1,10 +1,10 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="29dp"
android:height="29dp"
android:width="25dp"
android:height="25dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?colorPrimary"
android:fillColor="#000000"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>
</vector>

View File

@ -1,13 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorOnSurfaceVariant">
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@ -1,10 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:width="36dp"
android:height="36dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorOnSurfaceVariant">
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M8,5v14l11,-7z"/>
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
</vector>

View File

@ -1,13 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorOnSurfaceVariant">
<path
android:fillColor="@android:color/white"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="37.319dp"
android:height="43.642dp"
android:viewportWidth="37.319"
android:viewportHeight="43.642">
<path
android:strokeWidth="1"
android:pathData="M36.796,14.32l-1.329,-3.587 0.93,-2.059a0.707,0.707 0,0 0,-0.133 -0.8L33.807,5.352a4.063,4.063 0,0 0,-4.185 -1l-0.664,0.266L25.171,0.502l-6.51,0.066L12.216,0.635 8.43,4.754l-0.664,-0.266a3.933,3.933 0,0 0,-4.185 1L1.055,8.009A0.637,0.637 0,0 0,0.924 8.602l0.93,2.126L0.524,14.32l4.717,17.8a7.7,7.7 0,0 0,2.857 4.185l9.3,6.311a2.1,2.1 0,0 0,2.591 0l9.3,-6.311a7.162,7.162 0,0 0,2.857 -4.185l3.853,-14.615Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M19.723,26.942a3.239,3.239 0,0 0,-0.731 -0.266h-0.465a2.38,2.38 0,0 0,-0.731 0.266l-1.129,0.465 -1.329,0.6L13.209,29.135a0.441,0.441 0,0 0,-0.266 0.332,0.473 0.473,0 0,0 0.2,0.4l1.86,1.262c0.4,0.266 0.8,0.6 1.129,0.864l0.531,0.465 1.063,0.93 0.465,0.465a0.807,0.807 0,0 0,1.063 0l2.126,-1.86 1.129,-0.864 1.86,-1.329a0.418,0.418 0,0 0,0.2 -0.531c-0.066,-0.133 -0.133,-0.2 -0.266,-0.2L22.181,28.004l-1.329,-0.6ZM32.744,15.117l0.066,-0.2a2.491,2.491 0,0 0,-0.066 -0.731,7.572 7.572,0 0,0 -0.664,-1.262l-1.2,-1.727 -0.864,-1.129 -1.594,-1.993a3.8,3.8 0,0 0,-0.465 -0.531h0l-0.731,0.133L23.709,8.341a5.815,5.815 0,0 1,-1.063 -0.133l-1.927,-0.6 -1.4,-0.531a3.612,3.612 0,0 0,-1.2 0l-1.4,0.4 -1.927,0.6a1.894,1.894 0,0 1,-1.063 0.133l-3.521,-0.664 -0.731,-0.133h0a3.327,3.327 0,0 0,-0.465 0.531l-1.594,1.993c-0.266,0.4 -0.6,0.731 -0.864,1.129l-1.2,1.86 -0.531,0.93A2.926,2.926 0,0 0,4.709 14.918l0.066,0.2a0.507,0.507 0,0 0,0.133 0.332l0.93,1.063 4.185,4.451a1.288,1.288 0,0 1,0.2 1.2l-0.731,1.661a1.831,1.831 0,0 0,0 1.329l0.133,0.4a3.193,3.193 0,0 0,1.129 1.528l0.664,0.531a1.116,1.116 0,0 0,1.2 0.133l2.325,-1.129a6.239,6.239 0,0 0,1.2 -0.8l1.86,-1.661a0.82,0.82 0,0 0,0.266 -0.531,0.754 0.754,0 0,0 -0.2,-0.531l-4.185,-2.857a0.833,0.833 0,0 1,-0.266 -1.063l1.661,-3.056a1.5,1.5 0,0 0,0.066 -1.2,1.959 1.959,0 0,0 -0.93,-0.864l-5.115,-1.927c-0.4,-0.133 -0.332,-0.332 0.066,-0.332l2.989,-0.332a4.974,4.974 0,0 1,1.4 0.133l2.591,0.731a0.777,0.777 0,0 1,0.531 0.864l-1,5.58a4.386,4.386 0,0 0,-0.066 0.93,1.252 1.252,0 0,0 0.8,0.4l1.594,0.332a4.908,4.908 0,0 0,1.4 0l1.462,-0.332a1.252,1.252 0,0 0,0.8 -0.4,2.133 2.133,0 0,0 -0.066,-0.93L20.719,13.124a0.762,0.762 0,0 1,0.531 -0.864l2.591,-0.731a4.974,4.974 0,0 1,1.4 -0.133l2.989,0.266c0.4,0.066 0.4,0.2 0.066,0.332l-5.115,1.927a1.687,1.687 0,0 0,-0.93 0.864,1.487 1.487,0 0,0 0.066,1.2l1.661,3.056A0.851,0.851 0,0 1,23.709 20.104l-4.185,2.857a0.807,0.807 0,0 0,0 1.063h0l1.86,1.661a4.7,4.7 0,0 0,1.2 0.8L24.909,27.604a1.271,1.271 0,0 0,1.2 -0.133l0.664,-0.531a3.685,3.685 0,0 0,1.129 -1.528l0.066,-0.266a2.261,2.261 0,0 0,0 -1.329l-0.664,-1.594a1.288,1.288 0,0 1,0.2 -1.2l4.185,-4.451 0.93,-1.063a0.712,0.712 0,0 1,0.133 -0.4Z"
android:fillColor="#000000"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="?attr/iconColor"
android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM14,13v4h-4v-4H7l5,-5 5,5h-3z"/>
</vector>

View File

@ -1,6 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="29dp"
android:height="29dp"
android:width="25dp"
android:height="25dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path

View File

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="29.605dp"
android:height="34.271dp"
android:viewportWidth="29.605"
android:viewportHeight="34.271">
<path
android:strokeWidth="1"
android:pathData="M25.766,0.5h-21.9a3.352,3.352 0,0 0,-3.361 3.361v22.087a3.373,3.373 0,0 0,3.361 3.361h18.522l-0.859,-3.028 2.1,1.954 1.954,1.825 3.522,3.1v-29.3A3.334,3.334 0,0 0,25.766 0.5Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M22.055,9.782a7.865,7.865 0,0 0,-4.56 -1.737l-0.235,0.26a10.6,10.6 0,0 1,4.037 2.106,13.138 13.138,0 0,0 -4.87,-1.607 13.679,13.679 0,0 0,-3.289 0.054,1.292 1.292,0 0,0 -0.288,0.022 12.15,12.15 0,0 0,-3.674 1.031,6.119 6.119,0 0,0 -0.908,0.478 10.878,10.878 0,0 1,4.218 -2.16l-0.182,-0.185a7.864,7.864 0,0 0,-4.56 1.737,22.555 22.555,0 0,0 -2.328,9.64 5.871,5.871 0,0 0,4.944 2.5s0.6,-0.738 1.089,-1.368a5.13,5.13 0,0 1,-2.819 -1.921,2.3 2.3,0 0,1 0.438,0.239c0.021,0.022 0.021,0.054 0.053,0.054a0.361,0.361 0,0 0,0.16 0.076,8.514 8.514,0 0,0 1.2,0.575 13.145,13.145 0,0 0,2.381 0.706,10.773 10.773,0 0,0 4.218,0 10.444,10.444 0,0 0,2.36 -0.706,9.122 9.122,0 0,0 1.869,-0.977 5.206,5.206 0,0 1,-2.958 1.976c0.491,0.63 1.089,1.346 1.089,1.346a6.013,6.013 0,0 0,4.976 -2.5A22.319,22.319 0,0 0,22.055 9.782ZM11.878,17.869a1.838,1.838 0,1 1,1.655 -1.813A1.745,1.745 0,0 1,11.878 17.866ZM17.805,17.869a1.838,1.838 0,1 1,1.655 -1.813A1.718,1.718 0,0 1,17.805 17.866Z"
android:fillColor="#000000"/>
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</vector>

View File

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="36.367dp"
android:height="35.5dp"
android:viewportWidth="36.367"
android:viewportHeight="35.5">
<path
android:strokeWidth="1"
android:pathData="M18.183,0.5a17.687,17.687 0,0 0,-5.59 34.466c0.879,0.163 1.2,-0.38 1.2,-0.858 0,-0.423 -0.011,-1.531 -0.022,-3.007 -4.917,1.064 -5.96,-2.366 -5.96,-2.366a4.67,4.67 0,0 0,-1.965 -2.584c-1.607,-1.1 0.119,-1.075 0.119,-1.075a3.758,3.758 0,0 1,2.714 1.824,3.758 3.758,0 0,0 5.145,1.465 3.843,3.843 0,0 1,1.118 -2.366c-3.93,-0.445 -8.055,-1.965 -8.055,-8.739a6.8,6.8 0,0 1,1.824 -4.744,6.321 6.321,0 0,1 0.174,-4.679s1.487,-0.478 4.863,1.813a16.727,16.727 0,0 1,8.858 0c3.376,-2.29 4.863,-1.813 4.863,-1.813a6.321,6.321 0,0 1,0.174 4.679,6.836 6.836,0 0,1 1.813,4.744c0,6.8 -4.136,8.283 -8.076,8.728a4.243,4.243 0,0 1,1.2 3.278c0,2.366 -0.022,4.266 -0.022,4.852 0,0.478 0.315,1.02 1.216,0.847a17.689,17.689 0,0 0,-5.6 -34.466Z"
android:fillColor="#00000000"
android:fillType="evenOdd"
android:strokeColor="#000000"/>
</vector>

View File

@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="33.543dp"
android:height="33.543dp"
android:viewportWidth="33.543"
android:viewportHeight="33.543">
<path
android:pathData="M24.522,1.086a7.945,7.945 0,0 1,7.935 7.935v15.5a7.945,7.945 0,0 1,-7.935 7.935h-15.5a7.945,7.945 0,0 1,-7.935 -7.935v-15.5a7.945,7.945 0,0 1,7.935 -7.935h15.5m0,-1.086h-15.5a9.02,9.02 0,0 0,-9.021 9.021v15.5a9.02,9.02 0,0 0,9.021 9.021h15.5a9.02,9.02 0,0 0,9.021 -9.021v-15.5a9.02,9.02 0,0 0,-9.021 -9.021Z"
android:fillColor="#000000"/>
<path
android:pathData="M16.674,9.282a7.686,7.686 0,1 1,-7.686 7.686,7.7 7.7,0 0,1 7.686,-7.686m0,-1.086a8.771,8.771 0,1 0,8.771 8.771,8.775 8.775,0 0,0 -8.771,-8.771Z"
android:fillColor="#000000"/>
<path
android:pathData="M25.879,7.794m-1.541,0a1.541,1.541 0,1 1,3.082 0a1.541,1.541 0,1 1,-3.082 0"
android:fillColor="#000000"/>
</vector>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
<vector android:height="24dp" android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M10.857,14.458s0.155,0.921 -0.034,2.952c-0.236,2.546 0.97,6.59 0.97,6.59s1.645,-4.052 1.358,-6.67c-0.236,-2.152 0.107,-2.904 0.034,-2.803 -1.264,1.746 -2.328,-0.069 -2.328,-0.069zM13.939,16.643c0.206,1.591 -0.023,2.462 -0.32,4.164 -0.15,0.861 3.068,-2.589 4.302,-4.645 0.206,-0.343 -1.18,1.337 -2.551,0.137 -0.951,-0.832 -1.114,-1.085 -1.853,-1.808 -0.249,-0.244 0.277,1.014 0.423,2.151zM10.427,14.618c-0.739,0.723 -0.903,0.976 -1.853,1.808 -1.371,1.2 -2.757,-0.48 -2.551,-0.137 1.234,2.057 4.452,5.506 4.302,4.645 -0.297,-1.703 -0.526,-2.574 -0.32,-4.164 0.147,-1.137 0.673,-2.395 0.423,-2.151zM13.593,11.779c1.504,0.434 2.088,2.523 3.606,2.781 0.314,0.053 0.667,0.148 1.079,0.128 0.77,-0.037 1.744,-0.472 3.045,-2.318 0.385,-0.546 -0.955,3.514 -4.313,3.563 -2.46,0.036 -2.747,-2.408 -4.387,-2.482 -0.592,-0.027 -0.629,-1.156 -0.629,-1.156s0.706,-0.774 1.598,-0.517zM10.407,11.767c-1.504,0.434 -2.088,2.523 -3.606,2.781 -0.314,0.053 -0.667,0.148 -1.079,0.128 -0.77,-0.037 -1.744,-0.472 -3.045,-2.318 -0.385,-0.546 0.955,3.514 4.313,3.563 2.46,0.036 2.747,-2.408 4.387,-2.482 0.592,-0.027 0.629,-1.156 0.629,-1.156s-0.706,-0.774 -1.598,-0.517zM16.033,11.747c1.513,1.146 1.062,2.408 1.911,2.048 2.859,-1.212 2.359,-7.434 2.128,-6.682 -1.303,4.242 -4.143,4.48 -6.876,2.528 -0.534,-0.381 1.985,1.459 2.837,2.105zM10.793,9.641C8.06,11.592 5.22,11.355 3.917,7.113c-0.231,-0.752 -0.731,5.469 2.128,6.682 0.849,0.36 0.398,-0.902 1.911,-2.048 0.852,-0.646 3.371,-2.486 2.837,-2.105zM16.319,10.225c3.3,-0.136 3.909,-5.545 3.65,-4.885 -1.165,2.963 -5.574,1.848 -5.995,3.718 -0.083,0.367 0.747,1.233 2.345,1.167zM10.015,9.058c-0.421,-1.87 -4.831,-0.755 -5.995,-3.718 -0.259,-0.66 0.35,4.749 3.65,4.885 1.599,0.066 2.428,-0.8 2.345,-1.167zM13.768,8.234s1.794,-0.964 3.33,-1.384c1.435,-0.393 2.512,-1.359 2.631,-2.38 0.089,-0.76 -1.11,-2.197 -1.11,-2.197s-0.841,2.334 -1.945,3.501c-1.201,1.27 -0.745,1.099 -2.906,2.46zM7.315,5.774C6.211,4.607 5.37,2.273 5.37,2.273S4.171,3.709 4.26,4.47c0.12,1.021 1.196,1.987 2.631,2.38 1.536,0.421 3.33,1.384 3.33,1.384 -2.162,-1.361 -1.705,-1.19 -2.906,-2.46zM13.55,8.086c1.943,-1.594 2.976,-3.673 4.657,-5.949 0.317,-0.429 -1.419,-1.465 -2.105,-1.533S14.84,3.057 14.775,4.54c-0.059,1.354 -1.486,3.761 -1.224,3.547zM9.214,4.539C9.149,3.056 8.573,0.535 7.887,0.603S5.465,1.707 5.782,2.136c1.681,2.276 2.713,4.356 4.657,5.949 0.261,0.214 -1.165,-2.193 -1.224,-3.547zM13.745,2.937c0.137,-1.098 0.631,-1.9 1.613,-2.574 -0.868,-0.29 -1.591,-0.526 -1.968,-0.217s-1.403,1.342 -1.266,3.023 0.007,7.962 0.305,7.846c0.16,-4.302 1.522,-5.538 1.316,-8.077zM11.559,11.014c0.297,0.116 0.167,-6.165 0.305,-7.846S10.976,0.454 10.598,0.145C10.221,-0.164 9.499,0.072 8.63,0.362c0.983,0.674 1.476,1.476 1.613,2.574 -0.206,2.539 1.156,3.775 1.316,8.077z"/>
</vector>

View File

@ -1,5 +1,5 @@
<vector android:height="30dp" android:viewportHeight="1775.6"
android:viewportWidth="1775.6" android:width="30dp"
<vector android:height="63dp" android:viewportHeight="1775.6"
android:viewportWidth="1775.6" android:width="63dp"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#0c0c0f"
android:pathData="M887.8,887.8m-852.8,0a852.8,852.8 0,1 1,1705.6 0a852.8,852.8 0,1 1,-1705.6 0" android:strokeWidth="70">

View File

@ -1,5 +1,7 @@
<vector android:height="30dp" android:viewportHeight="2000"
android:viewportWidth="2000" android:width="30dp"
<vector android:height="63dp"
android:viewportHeight="2000"
android:viewportWidth="2000"
android:width="63dp"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#0C0C0F" android:pathData="M1000,1000m-900,0a900,900 0,1 1,1800 0a900,900 0,1 1,-1800 0"/>
<path android:fillColor="#FFFFFF" android:pathData="M1297.99,934.95L913.69,687c-16.68,-9.72 -38.08,-4.08 -47.8,12.59l-0.75,1.28c-9.72,16.67 -4.09,38.07 12.59,47.79l367.49,221.11c23.91,14.39 23.77,49.1 -0.25,63.29l-369.18,218.11c-16.76,9.58 -22.58,30.93 -13,47.69l0.73,1.29c9.58,16.76 30.93,22.57 47.69,12.99l386.24,-244.83C1346.25,1037.38 1346.54,966.28 1297.99,934.95z"/>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_baseline_resume_24"
android:state_checked="true" />
<item
android:drawable="@drawable/ic_baseline_pause_24"
android:state_checked="false" />
</selector>

View File

@ -1,9 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="34dp"
android:height="34dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:width="38.94dp"
android:height="38.918dp"
android:viewportWidth="38.94"
android:viewportHeight="38.918">
<path
android:fillColor="#FF000000"
android:pathData="M14.5,15.41C14.58,15.5 14.58,15.69 14.5,15.8C13.77,16.5 12.41,16.56 12,16.56C11.61,16.56 10.25,16.5 9.54,15.8C9.44,15.69 9.44,15.5 9.54,15.41C9.65,15.31 9.82,15.31 9.92,15.41C10.38,15.87 11.33,16 12,16C12.69,16 13.66,15.87 14.1,15.41C14.21,15.31 14.38,15.31 14.5,15.41M10.75,13.04C10.75,12.47 10.28,12 9.71,12C9.14,12 8.67,12.47 8.67,13.04C8.67,13.61 9.14,14.09 9.71,14.08C10.28,14.08 10.75,13.61 10.75,13.04M14.29,12C13.72,12 13.25,12.5 13.25,13.05S13.72,14.09 14.29,14.09C14.86,14.09 15.33,13.61 15.33,13.05C15.33,12.5 14.86,12 14.29,12M22,12C22,17.5 17.5,22 12,22S2,17.5 2,12C2,6.5 6.5,2 12,2S22,6.5 22,12M18.67,12C18.67,11.19 18,10.54 17.22,10.54C16.82,10.54 16.46,10.7 16.2,10.95C15.2,10.23 13.83,9.77 12.3,9.71L12.97,6.58L15.14,7.05C15.16,7.6 15.62,8.04 16.18,8.04C16.75,8.04 17.22,7.57 17.22,7C17.22,6.43 16.75,5.96 16.18,5.96C15.77,5.96 15.41,6.2 15.25,6.55L12.82,6.03C12.75,6 12.68,6.03 12.63,6.07C12.57,6.11 12.54,6.17 12.53,6.24L11.79,9.72C10.24,9.77 8.84,10.23 7.82,10.96C7.56,10.71 7.2,10.56 6.81,10.56C6,10.56 5.35,11.21 5.35,12C5.35,12.61 5.71,13.11 6.21,13.34C6.19,13.5 6.18,13.62 6.18,13.78C6.18,16 8.79,17.85 12,17.85C15.23,17.85 17.85,16.03 17.85,13.78C17.85,13.64 17.84,13.5 17.81,13.34C18.31,13.11 18.67,12.6 18.67,12Z"/>
android:strokeWidth="1"
android:pathData="M0.5,20.212v-1.485c0.022,-0.177 0.055,-0.366 0.078,-0.543 0.111,-0.842 0.155,-1.7 0.332,-2.526A18.737,18.737 0,0 1,8.82 3.802a18.168,18.168 0,0 1,7.989 -3.08c0.632,-0.089 1.274,-0.155 1.906,-0.222h1.485c0.177,0.022 0.366,0.055 0.543,0.078 0.842,0.111 1.7,0.155 2.526,0.332a18.757,18.757 0,0 1,11.834 7.878,18.1 18.1,0 0,1 3.1,7.989c0.089,0.643 0.155,1.3 0.233,1.939v1.485c-0.022,0.177 -0.055,0.366 -0.078,0.543 -0.111,0.842 -0.155,1.7 -0.332,2.526A18.685,18.685 0,0 1,30.12 35.12a18.168,18.168 0,0 1,-7.989 3.08c-0.632,0.089 -1.274,0.155 -1.906,0.222h-1.485c-0.177,-0.022 -0.366,-0.055 -0.543,-0.078 -0.842,-0.111 -1.7,-0.155 -2.526,-0.332a18.7,18.7 0,0 1,-11.823 -7.878,18.1 18.1,0 0,1 -3.1,-7.989C0.644,21.509 0.578,20.866 0.5,20.212Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:pathData="M11.412,17.386c0.616,-0.337 1.2,-0.7 1.813,-1a14.065,14.065 0,0 1,5.406 -1.314c0.291,-0.011 0.392,-0.124 0.459,-0.4 0.414,-2.044 0.851,-4.078 1.276,-6.122 0.112,-0.517 0.336,-0.663 0.862,-0.55 1.377,0.292 2.753,0.584 4.119,0.887a0.367,0.367 0,0 0,0.459 -0.168,1.948 1.948,0 0,1 2.373,-0.741 2.029,2.029 0,0 1,1.254 2.235,2 2,0 0,1 -3.85,0.4c-0.078,-0.2 -0.123,-0.4 -0.19,-0.629 -1.276,-0.27 -2.563,-0.55 -3.85,-0.82a0.326,0.326 0,0 0,-0.257 0.191c-0.414,1.876 -0.806,3.752 -1.22,5.7a14.049,14.049 0,0 1,7.421 2.381,2.845 2.845,0 0,1 4.69,1.37 2.857,2.857 0,0 1,-1.287 3.112,0.579 0.579,0 0,0 -0.257,0.382 6.564,6.564 0,0 1,-2.966 5.92,12.364 12.364,0 0,1 -5.686,2.314 15.04,15.04 0,0 1,-7.622 -0.663,9.809 9.809,0 0,1 -5.1,-3.741 5.634,5.634 0,0 1,-0.974 -3.7,0.459 0.459,0 0,0 -0.224,-0.528 2.818,2.818 0,1 1,3.179 -4.639C11.311,17.319 11.367,17.353 11.412,17.386ZM13.112,21.486a1.953,1.953 0,0 0,1.97 1.966,1.984 1.984,0 0,0 1.959,-1.955 2.026,2.026 0,0 0,-1.97 -2A2,2 0,0 0,13.113 21.487ZM25.812,21.497a1.984,1.984 0,0 0,-1.959 -1.988,2.026 2.026,0 0,0 -1.981,1.988 1.97,1.97 0,0 0,3.94 0ZM19.802,28.226c0.358,-0.045 1.063,-0.09 1.757,-0.213a5.008,5.008 0,0 0,2.5 -1.123c0.3,-0.258 0.358,-0.55 0.168,-0.775s-0.481,-0.2 -0.795,0.022a5.492,5.492 0,0 1,-0.951 0.573,7.7 7.7,0 0,1 -3.626,0.517 5.622,5.622 0,0 1,-3.436 -1.168,0.458 0.458,0 0,0 -0.672,0.056 0.431,0.431 0,0 0,0.045 0.663,6.376 6.376,0 0,0 1.242,0.809A9.241,9.241 0,0 0,19.806 28.227Z"
android:fillColor="#000000"/>
</vector>

View File

@ -1,10 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?attr/colorSurface"
android:pathData="M19.1,12.9a2.8,2.8 0,0 0,0.1 -0.9,2.8 2.8,0 0,0 -0.1,-0.9l2.1,-1.6a0.7,0.7 0,0 0,0.1 -0.6L19.4,5.5a0.7,0.7 0,0 0,-0.6 -0.2l-2.4,1a6.5,6.5 0,0 0,-1.6 -0.9l-0.4,-2.6a0.5,0.5 0,0 0,-0.5 -0.4H10.1a0.5,0.5 0,0 0,-0.5 0.4L9.3,5.4a5.6,5.6 0,0 0,-1.7 0.9l-2.4,-1a0.4,0.4 0,0 0,-0.5 0.2l-2,3.4c-0.1,0.2 0,0.4 0.2,0.6l2,1.6a2.8,2.8 0,0 0,-0.1 0.9,2.8 2.8,0 0,0 0.1,0.9L2.8,14.5a0.7,0.7 0,0 0,-0.1 0.6l1.9,3.4a0.7,0.7 0,0 0,0.6 0.2l2.4,-1a6.5,6.5 0,0 0,1.6 0.9l0.4,2.6a0.5,0.5 0,0 0,0.5 0.4h3.8a0.5,0.5 0,0 0,0.5 -0.4l0.3,-2.6a5.6,5.6 0,0 0,1.7 -0.9l2.4,1a0.4,0.4 0,0 0,0.5 -0.2l2,-3.4c0.1,-0.2 0,-0.4 -0.2,-0.6ZM12,15.6A3.6,3.6 0,1 1,15.6 12,3.6 3.6,0 0,1 12,15.6Z"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40.292dp"
android:height="33.56dp"
android:viewportWidth="40.292"
android:viewportHeight="33.56">
<path
android:strokeWidth="1"
android:pathData="M3.187,14.514q15.815,-6.9 21.1,-9.084c10.043,-4.18 12.134,-4.9 13.5,-4.93a2.4,2.4 0,0 1,1.407 0.421,1.479 1.479,0 0,1 0.513,0.986 6.517,6.517 0,0 1,0.066 1.42c-0.539,5.719 -2.905,19.614 -4.1,26.016 -0.513,2.708 -1.512,3.615 -2.471,3.707 -2.1,0.2 -3.694,-1.393 -5.732,-2.721 -3.181,-2.09 -4.982,-3.392 -8.072,-5.429 -3.576,-2.353 -1.262,-3.655 0.776,-5.758 0.539,-0.552 9.794,-8.979 9.978,-9.741a0.75,0.75 0,0 0,-0.171 -0.644,0.888 0.888,0 0,0 -0.749,-0.079q-0.473,0.118 -15.262,10.083a6.892,6.892 0,0 1,-3.931 1.446,26.376 26.376,0 0,1 -5.626,-1.328c-2.261,-0.736 -4.062,-1.131 -3.9,-2.379C0.571,15.854 1.478,15.184 3.187,14.514Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="44.312dp"
android:height="34.207dp"
android:viewportWidth="44.312"
android:viewportHeight="34.207">
<path
android:strokeWidth="1"
android:pathData="M42.935,4.43a16.967,16.967 0,0 1,-4.809 1.324,8.373 8.373,0 0,0 3.68,-4.635 16.688,16.688 0,0 1,-5.319 2.03,8.381 8.381,0 0,0 -14.275,7.642 23.792,23.792 0,0 1,-17.271 -8.749,8.4 8.4,0 0,0 2.594,11.192 8.276,8.276 0,0 1,-3.789 -1.053,8.4 8.4,0 0,0 6.719,8.326 8.524,8.524 0,0 1,-3.789 0.141,8.373 8.373,0 0,0 7.827,5.818 16.888,16.888 0,0 1,-12.408 3.474,23.747 23.747,0 0,0 12.842,3.767c15.556,0 24.349,-13.146 23.817,-24.924A17.317,17.317 0,0 0,42.935 4.43Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="36.68dp"
android:height="28dp"
android:width="73.36dp"
android:height="56dp"
android:viewportWidth="506.854"
android:viewportHeight="385.268">
<path

View File

@ -1,6 +0,0 @@
<vector android:height="30dp" android:viewportHeight="385.265"
android:viewportWidth="506.854" android:width="40dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FFFFFF" android:pathData="M496.496,69.709c-7.661,-28.84 -30.24,-51.548 -58.94,-59.265c-6.213,-1.68 -25.124,-6.773 -108,-9.24C289.744,0.014 253.792,0 253.434,0s-36.311,0.014 -76.124,1.204C94.431,3.682 75.525,8.781 69.33,10.444c-28.695,7.72 -51.3,30.426 -58.955,59.265C0.294,107.577 0,183.781 0,192.349c0,8.625 0.28,85.365 10.36,123.213c7.658,28.843 30.24,51.55 58.94,59.267c6.213,1.68 25.125,6.771 107.999,9.238c39.824,1.197 75.774,1.197 76.135,1.197s36.312,0 76.122,-1.202c82.879,-2.479 101.787,-7.573 107.986,-9.237c28.703,-7.727 51.296,-30.434 58.951,-59.25c10.078,-37.871 10.356,-114.609 10.356,-123.235C506.867,183.767 506.576,107.562 496.496,69.709zM470.714,308.698c-5.217,19.637 -20.583,35.098 -40.095,40.348c-35.362,9.537 -177.174,9.537 -177.174,9.537s-141.809,0 -177.172,-9.537c-19.51,-5.25 -34.877,-20.721 -40.093,-40.348c-9.475,-35.588 -9.475,-116.366 -9.475,-116.366s0,-80.185 9.475,-115.771c5.216,-19.636 20.583,-35.101 40.093,-40.348c35.351,-9.537 177.159,-9.537 177.159,-9.537s141.809,0 177.173,9.537c19.511,5.248 34.877,20.72 40.093,40.348c9.478,35.588 9.478,115.771 9.478,115.771S480.175,273.11 470.714,308.698z"/>
<path android:fillColor="#FFFFFF" android:pathData="M328.099,174.927l-107.603,-69.423c-4.666,-2.723 -10.656,-1.147 -13.381,3.521c-0.002,0.002 -0.003,0.004 -0.004,0.006l-0.21,0.354c-2.715,4.67 -1.138,10.657 3.525,13.384l102.896,61.911c6.695,4.026 6.656,13.745 -0.065,17.721L209.883,263.47c-4.688,2.688 -6.314,8.66 -3.643,13.354l0.207,0.356c2.688,4.688 8.66,6.313 13.354,3.641l108.146,-68.555C341.614,203.608 341.692,183.701 328.099,174.927z"/>
<path android:fillColor="#FFFFFF" android:pathData="M273.159,183.669l-52.979,-29.846c-6.859,-3.863 -15.338,1.09 -15.338,8.961v59.689c0,7.869 8.479,12.822 15.338,8.961l52.979,-29.848C280.144,197.669 280.144,187.589 273.159,183.669z"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="34.652dp"
android:height="34.651dp"
android:viewportWidth="34.652"
android:viewportHeight="34.651">
<path
android:strokeWidth="1"
android:pathData="M17.239,0.5a16.826,16.826 0,1 0,0.173 0Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:strokeWidth="1"
android:pathData="M17.326,0.5L17.326,34.152M34.152,17.326L0.5,17.326m3.8,-10.354a22.434,22.434 0,0 0,26.058 0m0,20.709a22.434,22.434 0,0 0,-26.058 0M16.031,0.931a21.572,21.572 0,0 0,0 32.961m2.589,0a21.572,21.572 0,0 0,0 -32.961"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48.432dp"
android:height="35.715dp"
android:viewportWidth="48.432"
android:viewportHeight="35.715">
<path
android:strokeWidth="1"
android:pathData="M47.93,17.827s0,8.449 -0.991,12.171a5.959,5.959 0,0 1,-4.194 4.22c-3.7,1 -18.531,1 -18.531,1s-14.832,0 -18.531,-1a5.959,5.959 0,0 1,-4.194 -4.22c-0.991,-3.722 -0.991,-12.171 -0.991,-12.171s0,-8.387 0.991,-12.109a5.959,5.959 0,0 1,4.194 -4.22c3.7,-1 18.531,-1 18.531,-1s4.032,0 8.415,0.141l0.166,0.005 1.081,0.039c0.756,0.029 1.512,0.062 2.25,0.1 1.894,0.1 3.668,0.233 5.008,0.414l0.075,0.01 0.174,0.025c0.249,0.036 0.481,0.073 0.693,0.114 0.251,0.047 0.475,0.1 0.668,0.148a5.959,5.959 0,0 1,4.194 4.22C47.93,9.44 47.93,17.827 47.93,17.827Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
<path
android:strokeWidth="1"
android:pathData="M29.95,16.666l-7.86,-4.538A1.37,1.37 0,0 0,20.034 13.319v9.076a1.37,1.37 0,0 0,2.056 1.187l7.86,-4.538A1.37,1.37 0,0 0,29.95 16.666Z"
android:fillColor="#00000000"
android:strokeColor="#000000"/>
</vector>

View File

@ -1,8 +0,0 @@
<!-- drawable/telegram.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="34dp"
android:width="34dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M9.78,18.65L10.06,14.42L17.74,7.5C18.08,7.19 17.67,7.04 17.22,7.31L7.74,13.3L3.64,12C2.76,11.75 2.75,11.14 3.84,10.7L19.81,4.54C20.54,4.21 21.24,4.72 20.96,5.84L18.24,18.65C18.05,19.56 17.5,19.78 16.74,19.36L12.6,16.3L10.61,18.23C10.38,18.46 10.19,18.65 9.78,18.65Z" />
</vector>

View File

@ -1,8 +0,0 @@
<!-- drawable/twitter.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="34dp"
android:width="34dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M22.46,6C21.69,6.35 20.86,6.58 20,6.69C20.88,6.16 21.56,5.32 21.88,4.31C21.05,4.81 20.13,5.16 19.16,5.36C18.37,4.5 17.26,4 16,4C13.65,4 11.73,5.92 11.73,8.29C11.73,8.63 11.77,8.96 11.84,9.27C8.28,9.09 5.11,7.38 3,4.79C2.63,5.42 2.42,6.16 2.42,6.94C2.42,8.43 3.17,9.75 4.33,10.5C3.62,10.5 2.96,10.3 2.38,10C2.38,10 2.38,10 2.38,10.03C2.38,12.11 3.86,13.85 5.82,14.24C5.46,14.34 5.08,14.39 4.69,14.39C4.42,14.39 4.15,14.36 3.89,14.31C4.43,16 6,17.26 7.89,17.29C6.43,18.45 4.58,19.13 2.56,19.13C2.22,19.13 1.88,19.11 1.54,19.07C3.44,20.29 5.7,21 8.12,21C16,21 20.33,14.46 20.33,8.79C20.33,8.6 20.33,8.42 20.32,8.23C21.16,7.63 21.88,6.87 22.46,6Z" />
</vector>

Some files were not shown because too many files have changed in this diff Show More