diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ba277b1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# DemoModeTile
+
+> Moved to [this repository](https://github.com/AlirezaIvaz/DemoMode).
+
+You get a screenshot, you get a screenshot, everygets a screenshot!
+
+It's a very simple tool presented as a Quick Tile to simplify the process of setting up and activating Demo Mode. It's already pre-configured out of the box with perfect 7:00 clock, full WiFi, full signal and full battery icons for stunning clutter-free screenshots.
+
+For it to work you need to grant it two permissions through adb shell from your computer:
+
+```
+adb -d shell pm grant ir.alirezaivaz.demo_mode android.permission.DUMP
+adb -d shell pm grant ir.alirezaivaz.demo_mode android.permission.WRITE_SECURE_SETTINGS
+```
+
+The `DUMP` permission is required for the Demo Mode to actually work, and the `WRITE_SECURE_SETTINGS` is necessary for the Quick Tile to read the setting and present the correct icon depending on its state.
+
+Since these permissions can be a little scary, for transparency sake I've open sourced it https://github.com/franciscofranco/Demo-Mode-tile.
diff --git a/app/build.gradle b/app/build.gradle
deleted file mode 100644
index 88f9d8b..0000000
--- a/app/build.gradle
+++ /dev/null
@@ -1,96 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-
-android {
- compileSdkVersion 30
- buildToolsVersion "30.0.2"
-
- defaultConfig {
- applicationId "com.franco.demomode"
- minSdkVersion 24
- targetSdkVersion 30
- versionName "1.6"
- versionCode 1910030257
- archivesBaseName = "DemoModeTile-${android.defaultConfig.versionName}"
- }
-
- signingConfigs {
- release {
- readKeystoreProperties('release')
- }
-
- debug {
- readKeystoreProperties('debug')
- }
- }
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- lintOptions {
- abortOnError false
- checkAllWarnings false
- disable 'InvalidPackage'
- }
-
- packagingOptions {
- exclude 'META-INF/LICENSE.txt'
- exclude 'META-INF/NOTICE.txt'
- }
-
- buildTypes {
- release {
- debuggable false
- minifyEnabled true
- shrinkResources true
- signingConfig signingConfigs.release
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
-
- debug {
- minifyEnabled false
- shrinkResources false
- }
- }
-
- buildFeatures {
- viewBinding = true
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-def readKeystoreProperties(def configName) {
- def propsFile = rootProject.file('../../keystore.properties')
-
- if (propsFile.exists()) {
- def props = new Properties()
- props.load(new FileInputStream(propsFile))
- android.signingConfigs[configName].storeFile = file(props['storeFile'])
- android.signingConfigs[configName].storePassword = props['storePassword']
- android.signingConfigs[configName].keyAlias = props['keyAlias']
- android.signingConfigs[configName].keyPassword = props['keyPassword']
- }
-}
-
-dependencies {
- implementation 'androidx.appcompat:appcompat:1.2.0'
- implementation 'com.google.android.material:material:1.2.1'
- implementation 'androidx.preference:preference-ktx:1.1.1'
- implementation "androidx.fragment:fragment-ktx:1.2.5"
- implementation "androidx.core:core-ktx:1.3.1"
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
-
- def lifecycle_version = "2.3.0-alpha07"
- implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
- implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
-}
-
-repositories {
- mavenCentral()
-}
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..e5bc0c6
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,143 @@
+plugins {
+ alias(libs.plugins.application)
+ alias(libs.plugins.kotlin)
+ kotlin("kapt")
+}
+
+val githubUrl = "https://github.com/AlirezaIvaz/DemoMode"
+
+android {
+ namespace = "ir.alirezaivaz.demo_mode"
+ compileSdk = 33
+
+ defaultConfig {
+ applicationId = "ir.alirezaivaz.demo_mode"
+ minSdk = 24
+ targetSdk = 33
+ versionName = "1.0.0"
+ versionCode = 100
+ resourceConfigurations += arrayOf(
+ "en", "fa"
+ )
+ buildConfigField(
+ "String",
+ "GITHUB_REPO_URL",
+ "\"$githubUrl\""
+ )
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+
+ lint {
+ abortOnError = false
+ checkAllWarnings = false
+ disable += "InvalidPackage"
+ }
+
+ packaging {
+ resources {
+ excludes += listOf(
+ "META-INF/LICENSE.txt",
+ "META-INF/NOTICE.txt"
+ )
+ }
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = true
+ isShrinkResources = true
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+
+ flavorDimensions += "distributor"
+ productFlavors {
+ create("github") {
+ dimension = "distributor"
+ versionNameSuffix = "-GH"
+ buildConfigField(
+ "String",
+ "DOWNLOAD_LINK",
+ "\"$githubUrl\""
+ )
+ buildConfigField(
+ "String",
+ "RATE_INTENT",
+ "\"$githubUrl/issues\""
+ )
+ buildConfigField(
+ "String",
+ "APPS_INTENT",
+ "\"https://github.com/AlirezaIvaz\""
+ )
+ }
+ create("cafebazaar") {
+ dimension = "distributor"
+ versionNameSuffix = "-CB"
+ buildConfigField(
+ "String",
+ "DOWNLOAD_LINK",
+ "\"https://cafebazaar.ir/app/${defaultConfig.applicationId}\""
+ )
+ buildConfigField(
+ "String",
+ "RATE_INTENT",
+ "\"bazaar://details?id=${defaultConfig.applicationId}\""
+ )
+ buildConfigField(
+ "String",
+ "APPS_INTENT",
+ "\"bazaar://collection?slug=by_author&aid=alirezaivaz\""
+ )
+ }
+ create("myket") {
+ dimension = "distributor"
+ versionNameSuffix = "-MK"
+ buildConfigField(
+ "String",
+ "DOWNLOAD_LINK",
+ "\"https://myket.ir/app/${defaultConfig.applicationId}\""
+ )
+ buildConfigField(
+ "String",
+ "RATE_INTENT",
+ "\"myket://comment?id=${defaultConfig.applicationId}\""
+ )
+ buildConfigField(
+ "String",
+ "APPS_INTENT",
+ "\"myket://developer/${defaultConfig.applicationId}\""
+ )
+ }
+ }
+
+ buildFeatures {
+ buildConfig = true
+ viewBinding = true
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
+dependencies {
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.core.splashscreen)
+ implementation(libs.androidx.appcompat)
+ implementation(libs.androidx.browser)
+ implementation(libs.androidx.fragment.ktx)
+ implementation(libs.androidx.lifecycle.livedata.ktx)
+ implementation(libs.androidx.lifecycle.viewmodel.ktx)
+ implementation(libs.androidx.preference.ktx)
+ implementation(libs.kotlinx.coroutines.core)
+ implementation(libs.material)
+ implementation(libs.tablericons)
+ kapt(libs.androidx.lifecycle.compiler)
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index a965f92..61d27cc 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -2,7 +2,7 @@
# By default, the flags in this file are appended to flags specified
# in /usr/local/opt/android-sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
+# directive in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
diff --git a/app/src/github/res/menu/main.xml b/app/src/github/res/menu/main.xml
new file mode 100644
index 0000000..fc50ccd
--- /dev/null
+++ b/app/src/github/res/menu/main.xml
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 59f7652..74e4cf1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,6 +1,5 @@
+ xmlns:tools="http://schemas.android.com/tools">
+ android:theme="@style/Theme.DemoModeTile"
+ tools:targetApi="tiramisu">
-
+
-
+
+
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..70e5e71
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/java/com/franco/demomode/activities/MainActivity.kt b/app/src/main/java/com/franco/demomode/activities/MainActivity.kt
deleted file mode 100644
index 4bc9f68..0000000
--- a/app/src/main/java/com/franco/demomode/activities/MainActivity.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.franco.demomode.activities
-
-import android.content.DialogInterface
-import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import androidx.lifecycle.lifecycleScope
-import com.franco.demomode.R
-import com.franco.demomode.Utils
-import com.franco.demomode.databinding.ActivityMainBinding
-import com.google.android.material.snackbar.Snackbar
-import kotlinx.coroutines.launch
-
-class MainActivity : AppCompatActivity() {
- private lateinit var binding: ActivityMainBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding = ActivityMainBinding.inflate(layoutInflater)
-
- setContentView(binding.root)
- setSupportActionBar(binding.toolbar)
- supportActionBar!!.setDisplayShowTitleEnabled(false)
-
- val action = intent?.action ?: ""
- if (action == Utils.MISSING_PERMISSION) {
- Snackbar.make(binding.root, R.string.permissions_need_to_be_granted,
- Snackbar.LENGTH_INDEFINITE).apply {
- setAction(R.string.ok) { dismiss() }
- show()
- }
- }
-
- lifecycleScope.launch {
- val isDemoModeAllowed = Utils().isDemoModeAllowed(this@MainActivity)
-
- if (!isDemoModeAllowed) {
- AlertDialog.Builder(this@MainActivity)
- .setTitle(R.string.demo_mode_allowed_title)
- .setMessage(R.string.demo_mode_allowed_message)
- .setPositiveButton(android.R.string.ok) { dialog: DialogInterface, _: Int -> dialog.dismiss() }
- .show()
- }
- }
- }
-
- override fun onResume() {
- super.onResume()
- Utils().setLightNavBar(binding.root)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt b/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt
deleted file mode 100644
index 86fd6f4..0000000
--- a/app/src/main/java/com/franco/demomode/fragments/SettingsFragment.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-package com.franco.demomode.fragments
-
-import android.os.Bundle
-import android.view.View
-import androidx.appcompat.app.AlertDialog
-import androidx.fragment.app.viewModels
-import androidx.preference.Preference
-import androidx.preference.PreferenceFragmentCompat
-import com.franco.demomode.R
-import kotlin.time.ExperimentalTime
-
-@ExperimentalTime
-class SettingsFragment : PreferenceFragmentCompat(), Preference.OnPreferenceClickListener {
- private lateinit var dumpPermissionPref: Preference
- private lateinit var writeSecureSettingsPref: Preference
-
- private val viewModel by viewModels()
-
- override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {}
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- addPreferencesFromResource(R.xml.settings)
-
- dumpPermissionPref = findPreference(KEY_DUMP)!!
- writeSecureSettingsPref = findPreference(KET_WRITE_SECURE_SETTINGS)!!
-
- dumpPermissionPref.onPreferenceClickListener = this
- writeSecureSettingsPref.onPreferenceClickListener = this
- }
-
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- viewModel.isDumpPermissionUpdates(requireContext()).observe(viewLifecycleOwner, ::renderDump)
- viewModel.isWriteSecureSettingsPermissionUpdates(requireContext())
- .observe(viewLifecycleOwner, ::renderWriteSecureSettings)
- }
-
- private fun renderDump(isGranted: Boolean) {
- dumpPermissionPref.summary = when (isGranted) {
- true -> getString(R.string.granted)
- false -> getString(R.string.not_granted)
- }
- }
-
- private fun renderWriteSecureSettings(isGranted: Boolean) {
- writeSecureSettingsPref.summary = when (isGranted) {
- true -> getString(R.string.granted)
- false -> getString(R.string.not_granted)
- }
- }
-
- override fun onPreferenceClick(preference: Preference): Boolean {
- AlertDialog.Builder(requireActivity())
- .setTitle(R.string.permission_request_title)
- .setMessage(when (preference.key) {
- KEY_DUMP -> R.string.dump_permission_msg
- KET_WRITE_SECURE_SETTINGS -> R.string.write_secure_settings_permission_msg
- else -> throw IllegalArgumentException("well, this shouldn't ever happen")
- })
- .show()
- return false
- }
-
- companion object {
- private const val KEY_DUMP = "dump_permission"
- private const val KET_WRITE_SECURE_SETTINGS = "write_secure_settings"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/franco/demomode/Utils.kt b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/Utils.kt
similarity index 80%
rename from app/src/main/java/com/franco/demomode/Utils.kt
rename to app/src/main/kotlin/ir/alirezaivaz/demo_mode/Utils.kt
index 53523f9..3bfbaa5 100644
--- a/app/src/main/java/com/franco/demomode/Utils.kt
+++ b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/Utils.kt
@@ -1,15 +1,11 @@
-package com.franco.demomode
+package ir.alirezaivaz.demo_mode
import android.Manifest
-import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
-import android.os.Build
import android.provider.Settings
import android.provider.Settings.SettingNotFoundException
-import android.view.View
-import androidx.core.content.ContextCompat
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -109,28 +105,13 @@ class Utils {
== PackageManager.PERMISSION_GRANTED)
}
- suspend fun isWriteSecureSettingsPermissionGranted(context: Context): Boolean = withContext(Dispatchers.IO) {
- (context.packageManager.checkPermission(
- Manifest.permission.WRITE_SECURE_SETTINGS, context.packageName)
- == PackageManager.PERMISSION_GRANTED)
- }
-
- fun setLightNavBar(view: View) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- var flags = view.systemUiVisibility
- flags = flags or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
- view.systemUiVisibility = flags
- (view.context as Activity).window.navigationBarColor = ContextCompat.getColor(view.context, R.color.primary)
- }
- }
-
- fun clearLightNavBar(view: View) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- var flags = view.systemUiVisibility
- flags = flags and View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
- view.systemUiVisibility = flags
+ suspend fun isWriteSecureSettingsPermissionGranted(context: Context): Boolean =
+ withContext(Dispatchers.IO) {
+ (context.packageManager.checkPermission(
+ Manifest.permission.WRITE_SECURE_SETTINGS, context.packageName
+ )
+ == PackageManager.PERMISSION_GRANTED)
}
- }
companion object {
private const val DEMO_MODE_ALLOWED = "sysui_demo_allowed"
diff --git a/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivityMain.kt b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivityMain.kt
new file mode 100644
index 0000000..c49577b
--- /dev/null
+++ b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivityMain.kt
@@ -0,0 +1,277 @@
+package ir.alirezaivaz.demo_mode.activities
+
+import android.Manifest
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.net.Uri
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+import android.util.Log
+import android.view.Menu
+import android.view.MenuItem
+import android.view.View
+import android.widget.Toast
+import androidx.activity.viewModels
+import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
+import androidx.appcompat.app.AppCompatActivity
+import androidx.browser.customtabs.CustomTabColorSchemeParams
+import androidx.browser.customtabs.CustomTabsIntent
+import androidx.core.content.ContextCompat
+import androidx.core.view.isVisible
+import androidx.lifecycle.lifecycleScope
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
+import com.google.android.material.snackbar.BaseTransientBottomBar.Duration
+import com.google.android.material.snackbar.Snackbar
+import ir.alirezaivaz.demo_mode.BuildConfig
+import ir.alirezaivaz.demo_mode.R
+import ir.alirezaivaz.demo_mode.Utils
+import ir.alirezaivaz.demo_mode.databinding.ActivityMainBinding
+import ir.alirezaivaz.demo_mode.viewmodel.MainViewModel
+import kotlinx.coroutines.launch
+import java.io.IOException
+import kotlin.time.ExperimentalTime
+
+@ExperimentalTime
+class ActivityMain : AppCompatActivity() {
+ private val activityMain = this@ActivityMain
+ private lateinit var binding: ActivityMainBinding
+ private val viewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+
+ setContentView(binding.root)
+ setSupportActionBar(binding.toolbar)
+
+ binding.fab.initGitHubFab()
+
+ viewModel.isDumpPermissionUpdates(activityMain)
+ .observe(activityMain, ::renderDump)
+ viewModel.isWriteSecureSettingsPermissionUpdates(activityMain)
+ .observe(activityMain, ::renderWriteSecureSettings)
+
+ binding.dumpGrant.setOnClickListener {
+ showGrantPermissionDialog(
+ ir.alirezaivaz.tablericons.R.drawable.ic_components,
+ R.string.permission_dump,
+ Manifest.permission.DUMP
+ )
+ }
+ binding.writeGrant.setOnClickListener {
+ showGrantPermissionDialog(
+ ir.alirezaivaz.tablericons.R.drawable.ic_settings,
+ R.string.permission_write_secure_settings,
+ Manifest.permission.WRITE_SECURE_SETTINGS
+ )
+ }
+
+// grantPermissions()
+
+ val action = intent?.action ?: ""
+ if (action == Utils.MISSING_PERMISSION) {
+ Snackbar.make(
+ binding.root,
+ R.string.warning_permissions_need_to_be_granted,
+ Snackbar.LENGTH_INDEFINITE
+ ).apply {
+ setAction(R.string.action_ok) { dismiss() }
+ show()
+ }
+ }
+
+ lifecycleScope.launch {
+ val isDemoModeAllowed = Utils().isDemoModeAllowed(activityMain)
+
+ if (!isDemoModeAllowed) {
+ MaterialAlertDialogBuilder(activityMain).apply {
+ setIcon(ir.alirezaivaz.tablericons.R.drawable.ic_progress_alert)
+ setTitle(R.string.warning_demo_mode_allowed_title)
+ setMessage(R.string.warning_demo_mode_allowed_message)
+ setPositiveButton(R.string.action_open_developer) { _, _ ->
+ startActivity(
+ Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
+ )
+ }
+ setNegativeButton(R.string.action_cancel, null)
+ show()
+ }
+ }
+ }
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu?): Boolean {
+ menuInflater.inflate(R.menu.main, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.action_share -> {
+ val shareIntent = Intent(Intent.ACTION_SEND).apply {
+ type = "text/plain"
+ putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name))
+ putExtra(
+ Intent.EXTRA_TEXT,
+ "${getString(R.string.app_name)}\n${BuildConfig.DOWNLOAD_LINK}"
+ )
+ }
+ startActivity(
+ Intent.createChooser(
+ shareIntent,
+ getString(R.string.action_share_chooser)
+ )
+ )
+ }
+
+ R.id.action_rate -> {
+ try {
+ val intentAction = if (BuildConfig.FLAVOR == "cafebazaar")
+ Intent.ACTION_EDIT
+ else
+ Intent.ACTION_VIEW
+ val intent = Intent(intentAction, Uri.parse(BuildConfig.RATE_INTENT))
+ startActivity(intent)
+ } catch (e: Exception) {
+ binding.root.snackBar(R.string.error_action_failure)
+ }
+ }
+
+ R.id.action_apps -> {
+ try {
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.APPS_INTENT))
+ startActivity(intent)
+ } catch (e: Exception) {
+ binding.root.snackBar(R.string.error_action_failure)
+ }
+ }
+ }
+ return true
+ }
+
+ private fun renderDump(isGranted: Boolean) {
+ if (isGranted) {
+ with(binding) {
+ with(dumpStatus) {
+ setImageResource(ir.alirezaivaz.tablericons.R.drawable.ic_circle_check)
+ imageTintList = ContextCompat.getColorStateList(activityMain, R.color.green)
+ }
+ dumpGrant.isVisible = false
+ dumpDescription.isVisible = false
+ dumpDivider.isVisible = false
+ }
+ } else {
+ with(binding) {
+ with(dumpStatus) {
+ setImageResource(ir.alirezaivaz.tablericons.R.drawable.ic_progress_alert)
+ imageTintList = ContextCompat.getColorStateList(activityMain, R.color.orange)
+ }
+ dumpDivider.isVisible = true
+ dumpDescription.isVisible = true
+ dumpGrant.isVisible = true
+ }
+ }
+ }
+
+ private fun renderWriteSecureSettings(isGranted: Boolean) {
+ if (isGranted) {
+ with(binding) {
+ with(writeStatus) {
+ setImageResource(ir.alirezaivaz.tablericons.R.drawable.ic_circle_check)
+ imageTintList = ContextCompat.getColorStateList(activityMain, R.color.green)
+ }
+ writeGrant.isVisible = false
+ writeDescription.isVisible = false
+ writeDivider.isVisible = false
+ }
+ } else {
+ with(binding) {
+ with(writeStatus) {
+ setImageResource(ir.alirezaivaz.tablericons.R.drawable.ic_progress_alert)
+ imageTintList = ContextCompat.getColorStateList(activityMain, R.color.orange)
+ }
+ writeDivider.isVisible = true
+ writeDescription.isVisible = true
+ writeGrant.isVisible = true
+ }
+ }
+ }
+
+ private fun showGrantPermissionDialog(
+ @DrawableRes icon: Int,
+ @StringRes name: Int,
+ permission: String
+ ) {
+ MaterialAlertDialogBuilder(activityMain).apply {
+ setIcon(icon)
+ setTitle(name)
+ setMessage(
+ String.format(
+ getString(R.string.permission_request_description),
+ getString(name),
+ packageName,
+ permission
+ )
+ )
+ setPositiveButton(R.string.action_ok, null)
+ setNeutralButton(R.string.action_grant_root) { _, _ ->
+ grantPermissionWithRoot(permission)
+ }
+ show()
+ }
+ }
+
+ private fun grantPermissionWithRoot(permission: String) {
+ try {
+ val su = Runtime.getRuntime().exec("su")
+ val command = "pm grant $packageName $permission\n"
+ su.outputStream.write(command.toByteArray(charset("UTF-8")))
+ su.outputStream.flush()
+ su.outputStream.write("exit\n".toByteArray(charset("UTF-8")))
+ su.outputStream.flush()
+ } catch (e: IOException) {
+ binding.root.snackBar(R.string.error_root_access)
+ }
+ }
+
+ private fun View.snackBar(message: Int, @Duration length: Int = Snackbar.LENGTH_SHORT) {
+ Snackbar.make(this, message, length)
+ .setAnimationMode(Snackbar.ANIMATION_MODE_SLIDE)
+ .show()
+ }
+
+ private fun ExtendedFloatingActionButton.initGitHubFab() {
+ smoothShrink()
+ this.setOnClickListener {
+ extend()
+ smoothShrink()
+ val params = CustomTabColorSchemeParams.Builder()
+ .setToolbarColor(ContextCompat.getColor(activityMain, R.color.github))
+ .build()
+ CustomTabsIntent.Builder()
+ .setDefaultColorSchemeParams(params)
+ .setShowTitle(true)
+ .build()
+ .launchUrl(
+ activityMain,
+ Uri.parse(BuildConfig.GITHUB_REPO_URL)
+ )
+ }
+ setOnLongClickListener {
+ extend()
+ smoothShrink()
+ true
+ }
+ }
+
+ private fun ExtendedFloatingActionButton.smoothShrink() {
+ Handler(Looper.getMainLooper()).postDelayed({
+ this.shrink()
+ }, 2000)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivitySplash.kt b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivitySplash.kt
new file mode 100644
index 0000000..5f972da
--- /dev/null
+++ b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/activities/ActivitySplash.kt
@@ -0,0 +1,27 @@
+package ir.alirezaivaz.demo_mode.activities
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.splashscreen.SplashScreen
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import kotlin.time.ExperimentalTime
+
+@ExperimentalTime
+class ActivitySplash : AppCompatActivity() {
+ private lateinit var splashScreen: SplashScreen
+ override fun onCreate(savedInstanceState: Bundle?) {
+ splashScreen = installSplashScreen()
+ super.onCreate(savedInstanceState)
+ splashScreen.setOnExitAnimationListener {
+ startActivity(
+ Intent(
+ this@ActivitySplash,
+ ActivityMain::class.java
+ )
+ )
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
+ finish()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/tiles/DemoModeTile.kt
similarity index 51%
rename from app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt
rename to app/src/main/kotlin/ir/alirezaivaz/demo_mode/tiles/DemoModeTile.kt
index 6fdb8c0..616bcaf 100644
--- a/app/src/main/java/com/franco/demomode/tiles/DemoModeTile.kt
+++ b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/tiles/DemoModeTile.kt
@@ -1,15 +1,17 @@
-package com.franco.demomode.tiles
+package ir.alirezaivaz.demo_mode.tiles
import android.content.Intent
import android.graphics.drawable.Icon
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
-import com.franco.demomode.R
-import com.franco.demomode.Utils
-import com.franco.demomode.activities.MainActivity
+import ir.alirezaivaz.demo_mode.Utils
+import ir.alirezaivaz.demo_mode.activities.ActivityMain
+import ir.alirezaivaz.tablericons.R
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
+import kotlin.time.ExperimentalTime
+@ExperimentalTime
class DemoModeTile : TileService() {
override fun onStartListening() {
super.onStartListening()
@@ -18,18 +20,25 @@ class DemoModeTile : TileService() {
val isDemoModeAllowed = Utils().isDemoModeAllowed(applicationContext)
val isDemoMode = Utils().isDemoModeOn(applicationContext)
- qsTile?.state = when {
- !isDemoModeAllowed -> Tile.STATE_UNAVAILABLE
- isDemoMode -> Tile.STATE_ACTIVE
- else -> Tile.STATE_INACTIVE
- }
+ with(qsTile) {
+ state = when {
+ !isDemoModeAllowed -> Tile.STATE_UNAVAILABLE
+ isDemoMode -> Tile.STATE_ACTIVE
+ else -> Tile.STATE_INACTIVE
+ }
+ icon = when {
+ isDemoMode -> Icon.createWithResource(
+ applicationContext,
+ R.drawable.ic_tilt_shift
+ )
- qsTile?.icon = when {
- isDemoMode -> Icon.createWithResource(applicationContext, R.drawable.ic_on)
- else -> Icon.createWithResource(applicationContext, R.drawable.ic_off)
+ else -> Icon.createWithResource(
+ applicationContext,
+ R.drawable.ic_tilt_shift_off
+ )
+ }
+ updateTile()
}
-
- qsTile?.updateTile()
}
}
@@ -38,11 +47,12 @@ class DemoModeTile : TileService() {
GlobalScope.launch {
val hasDumpPermission = Utils().isDumpPermissionGranted(applicationContext)
- val hasWriteSecurePermission = Utils().isWriteSecureSettingsPermissionGranted(applicationContext)
+ val hasWriteSecurePermission =
+ Utils().isWriteSecureSettingsPermissionGranted(applicationContext)
when {
!hasDumpPermission || !hasWriteSecurePermission -> {
- Intent(applicationContext, MainActivity::class.java).apply {
+ Intent(applicationContext, ActivityMain::class.java).apply {
action = Utils.MISSING_PERMISSION
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(this)
@@ -50,17 +60,22 @@ class DemoModeTile : TileService() {
}
else -> {
- qsTile?.apply {
+ with(qsTile) {
if (state == Tile.STATE_ACTIVE) {
state = Tile.STATE_INACTIVE
- icon = Icon.createWithResource(applicationContext, R.drawable.ic_off)
+ icon = Icon.createWithResource(
+ applicationContext,
+ R.drawable.ic_tilt_shift_off
+ )
Utils().disableDemoMode(applicationContext)
} else {
state = Tile.STATE_ACTIVE
- icon = Icon.createWithResource(applicationContext, R.drawable.ic_on)
+ icon = Icon.createWithResource(
+ applicationContext,
+ R.drawable.ic_tilt_shift
+ )
Utils().enableDemoMode(applicationContext)
}
-
updateTile()
}
}
diff --git a/app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/viewmodel/MainViewModel.kt
similarity index 64%
rename from app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt
rename to app/src/main/kotlin/ir/alirezaivaz/demo_mode/viewmodel/MainViewModel.kt
index 0da85de..89a05e8 100644
--- a/app/src/main/java/com/franco/demomode/fragments/SettingsViewModel.kt
+++ b/app/src/main/kotlin/ir/alirezaivaz/demo_mode/viewmodel/MainViewModel.kt
@@ -1,32 +1,30 @@
-package com.franco.demomode.fragments
+package ir.alirezaivaz.demo_mode.viewmodel
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
-import com.franco.demomode.Utils
+import ir.alirezaivaz.demo_mode.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlin.random.Random
+import kotlin.time.Duration.Companion.seconds
import kotlin.time.ExperimentalTime
-import kotlin.time.seconds
@ExperimentalTime
-class SettingsViewModel : ViewModel() {
+class MainViewModel : ViewModel() {
fun isDumpPermissionUpdates(context: Context) = flow {
while (true) {
emit(Utils().isDumpPermissionGranted(context))
- delay(Random.nextLong(1.seconds.toLongMilliseconds(),
- 2.seconds.toLongMilliseconds()))
+ delay(Random.nextLong(1.seconds.inWholeMilliseconds, 2.seconds.inWholeMilliseconds))
}
}.asLiveData(Dispatchers.IO)
fun isWriteSecureSettingsPermissionUpdates(context: Context) = flow {
while (true) {
emit(Utils().isWriteSecureSettingsPermissionGranted(context))
- delay(Random.nextLong(1.seconds.toLongMilliseconds(),
- 2.seconds.toLongMilliseconds()))
+ delay(Random.nextLong(1.seconds.inWholeMilliseconds, 2.seconds.inWholeMilliseconds))
}
}.asLiveData(Dispatchers.IO)
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-xhdpi/ic_off.png b/app/src/main/res/drawable-xhdpi/ic_off.png
deleted file mode 100644
index 034e705..0000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_off.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_on.png b/app/src/main/res/drawable-xhdpi/ic_on.png
deleted file mode 100644
index a9f376d..0000000
Binary files a/app/src/main/res/drawable-xhdpi/ic_on.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_off.png b/app/src/main/res/drawable-xxhdpi/ic_off.png
deleted file mode 100644
index 56eab54..0000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_off.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_on.png b/app/src/main/res/drawable-xxhdpi/ic_on.png
deleted file mode 100644
index 62aef14..0000000
Binary files a/app/src/main/res/drawable-xxhdpi/ic_on.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_off.png b/app/src/main/res/drawable-xxxhdpi/ic_off.png
deleted file mode 100644
index 7e8a298..0000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_off.png and /dev/null differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_on.png b/app/src/main/res/drawable-xxxhdpi/ic_on.png
deleted file mode 100644
index e8870e4..0000000
Binary files a/app/src/main/res/drawable-xxxhdpi/ic_on.png and /dev/null differ
diff --git a/app/src/main/res/drawable/bug.xml b/app/src/main/res/drawable/bug.xml
deleted file mode 100644
index e6bcb4e..0000000
--- a/app/src/main/res/drawable/bug.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/code_braces.xml b/app/src/main/res/drawable/code_braces.xml
deleted file mode 100644
index 50f01a8..0000000
--- a/app/src/main/res/drawable/code_braces.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml
deleted file mode 100644
index 24a5623..0000000
--- a/app/src/main/res/drawable/ic_settings_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/app/src/main/res/drawable/twitter.xml b/app/src/main/res/drawable/twitter.xml
deleted file mode 100644
index ae08ca6..0000000
--- a/app/src/main/res/drawable/twitter.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/font/poppins.xml b/app/src/main/res/font/poppins.xml
new file mode 100644
index 0000000..85d997f
--- /dev/null
+++ b/app/src/main/res/font/poppins.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/font/poppins_bold.ttf b/app/src/main/res/font/poppins_bold.ttf
new file mode 100644
index 0000000..00559ee
Binary files /dev/null and b/app/src/main/res/font/poppins_bold.ttf differ
diff --git a/app/src/main/res/font/poppins_regular.ttf b/app/src/main/res/font/poppins_regular.ttf
new file mode 100644
index 0000000..9f0c71b
Binary files /dev/null and b/app/src/main/res/font/poppins_regular.ttf differ
diff --git a/app/src/main/res/font/vazirmatn.xml b/app/src/main/res/font/vazirmatn.xml
new file mode 100644
index 0000000..05dc3e3
--- /dev/null
+++ b/app/src/main/res/font/vazirmatn.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/font/vazirmatn_bold.ttf b/app/src/main/res/font/vazirmatn_bold.ttf
new file mode 100644
index 0000000..e10be05
Binary files /dev/null and b/app/src/main/res/font/vazirmatn_bold.ttf differ
diff --git a/app/src/main/res/font/vazirmatn_regular.ttf b/app/src/main/res/font/vazirmatn_regular.ttf
new file mode 100644
index 0000000..89a1211
Binary files /dev/null and b/app/src/main/res/font/vazirmatn_regular.ttf differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 056a9b7..e923fed 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,27 +1,218 @@
-
+ android:fitsSystemWindows="true">
-
+ android:layout_height="wrap_content"
+ android:fitsSystemWindows="true">
-
-
+ android:layout_height="?attr/collapsingToolbarLayoutLargeSize"
+ android:fitsSystemWindows="true"
+ app:collapsedTitleTextAppearance="@style/TextAppearance.DemoModeTile.TitleLarge"
+ app:expandedTitleTextAppearance="@style/TextAppearance.DemoModeTile.HeadlineMedium"
+ app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
+
+
-
+
+
+
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ android:overScrollMode="always"
+ app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
new file mode 100644
index 0000000..efae070
--- /dev/null
+++ b/app/src/main/res/menu/main.xml
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..a83cd23
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..a83cd23
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..933d630
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png
new file mode 100644
index 0000000..6f71f2c
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_background.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..9502653
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png
new file mode 100644
index 0000000..8235174
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..3b5d1df
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..ae8ef61
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/app/src/main/res/mipmap-mdpi/ic_launcher_background.png
new file mode 100644
index 0000000..3481a19
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_background.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..ba930f4
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png
new file mode 100644
index 0000000..fe155f2
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..66c0d04
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index f734513..85ed72d 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png
new file mode 100644
index 0000000..e793926
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..cab1634
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png
new file mode 100644
index 0000000..ceb9154
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..e12cfbc
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 6404cbc..7fa9b59 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png
new file mode 100644
index 0000000..d51d521
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..893a935
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png
new file mode 100644
index 0000000..4002d8e
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dc8b203
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index a3eb3f0..d43a4be 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png
new file mode 100644
index 0000000..a567309
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..15f3163
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png
new file mode 100644
index 0000000..70f45a3
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..66aafa1
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml
new file mode 100644
index 0000000..58f7efd
--- /dev/null
+++ b/app/src/main/res/values-fa/strings.xml
@@ -0,0 +1,43 @@
+
+
+ کاشی حالت نمایشی
+ حالت نمایشی
+ گیتهاب
+ ایشوها در گیتهاب
+ نمایهٔ گیتهاب
+ همرسانی
+ همرسانی با…
+ امتیاز به برنامه
+ برنامههای بیشتر
+ بازکردن گزینههای برنامهنویسان
+ اعطای دسترسی
+ اعطا با روت
+ باشه
+ انصراف
+ دسترسیها
+
+ "برای اینکه این برنامه بهدرستی کار کند به دسترسیهای زیر نیاز داریم. از آنجا که این دسترسیها بخشیاز"
+ "دسترسیهای محافظتشده هستند، برای اعطای آنها به برنامه باید از فرمان adb shell در رایانه شخصی "
+ "یا از ترمینال با دسترسی روت استفاده کنید."
+
+ دسترسی به گزارش دامپ سامانه
+ برای شناسایی و تنظیم درست وضعیت کاشی تنظیمات سریع به این دسترسی نیاز داریم.
+ نوشتن تنظیمات امن سامانه
+ برای تغییر تنظیمات حالت نمایشی به این دسترسی نیاز داریم.
+ درخواست دسترسی کاشی حالت نمایشی
+
+ "برای اینکه این برنامه کار کند نیاز دارد که دسترسی %1$s اعطا شود. متاسفانه اعطای این دسترسی "
+ "تنها از طریق دستور adb shell در رایانه شما امکانپذیر است:\n\n"
+ "adb -d shell pm grant %2$s %3$s\n\n"
+ "همچنین اگر دسترسی روت دارید، میتوانید با کلیک روی دکمه «اعطا با روت» این دسترسی را بهصورت "
+ "خودکار به برنامه اعطا کنید."
+
+ برای اینکه کاشی کار کند باید هر دو دسترسی داده شود!
+ حالت نمایشی مجاز نیست!
+
+ "خواهشمندیم مطمئن شوید که حالت نمایشی در گزینههای برنامهنویسان را فعال کردهاید؛ "
+ "زیرا تا زمانی که آنرا فعال نکرده باشید کاشی برنامه بهدرستی کار نخواهد کرد."
+
+ مشکلی در تکمیل این کنش رخ داد!
+ دسترسی روت رد شد!
+
diff --git a/app/src/main/res/values-fa/styles.xml b/app/src/main/res/values-fa/styles.xml
new file mode 100644
index 0000000..c8b9295
--- /dev/null
+++ b/app/src/main/res/values-fa/styles.xml
@@ -0,0 +1,6 @@
+
+
+
+
diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml
new file mode 100644
index 0000000..2375aa2
--- /dev/null
+++ b/app/src/main/res/values-land/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml
new file mode 100644
index 0000000..4436067
--- /dev/null
+++ b/app/src/main/res/values-w1240dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 200dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 0000000..2375aa2
--- /dev/null
+++ b/app/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..bbe9bc0
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index e663c5e..5a86975 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -1,5 +1,6 @@
- #5DE8D0
- #7B1FA2
+ #FF9800
+ #4CAF50
+ #24292F
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..3390183
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+ 8dp
+ 16dp
+ 16dp
+ 16dp
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b636baa..6b3f589 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,18 +1,42 @@
Demo Mode tile
- Demo mode
- Demo mode tile permission request
- For this app to work it needs DUMP permission to be granted. Unfortunately that is only possible through adb shell from your computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.DUMP\n\nFor transparency this app\'s source code is available.
- For this app to work it needs WRITE_SECURE_SETTINGS permission to be granted. Unfortunately that is only possible through adb shell from your computer:\n\nadb -d shell pm grant com.franco.demomode android.permission.WRITE_SECURE_SETTINGS\n\nFor transparency this app\'s source code is available.
- OK
- DUMP
- WRITE_SECURE_SETTINGS
- Not granted
- Permissions
- Granted
- Follow me
- Source code
- Both permissions need to be granted for the tile to work
- Tip!
- Make sure you allow demo mode to run by enabling it on Android settings, otherwise this tile might not work
+ Demo mode
+ GitHub
+ GitHub issues
+ GitHub profile
+ Share
+ Share via…
+ Rate
+ More apps
+ Open developer options
+ Grant permission
+ Grant with root
+ OK
+ Cancel
+ Permissions
+
+ "We need the following permissions for this app to work properly. Since these "
+ "permissions are among the protected permissions, to grant them to the app you "
+ "need to use the adb shell command on the PC or from the terminal with root access."
+
+ Access to system dump report
+ We need this permission to identify and set the status of the tile correctly.
+ Write secure settings
+ We need this permission to change demo mode settings.
+ @string/app_name
+
+ "For this app to work, it needs %1$s permission to be granted. "
+ "Unfortunately that is only possible through adb shell from your PC:\n\n"
+ "adb -d shell pm grant %2$s %3$s\n\n"
+ "Also if you've root access, you can grant it automatically by "
+ "clicking on the 'Grant with root' button at below"
+
+ Both permissions need to be granted for the tile to work
+ Demo mode not allowed!
+
+ "Please make sure you're turned on demo mode in developer options; "
+ "Because the tile won't works properly until you turned it on!"
+
+ Failed to complete this action!
+ Root access denied!
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 7a6748f..5344fd4 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,10 +1,35 @@
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..ca71411
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..d806339
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml
new file mode 100644
index 0000000..7a6ee38
--- /dev/null
+++ b/app/src/main/res/xml/locales_config.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml
deleted file mode 100644
index 1ec91a5..0000000
--- a/app/src/main/res/xml/settings.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index e7166b7..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,22 +0,0 @@
-buildscript {
- ext.kotlin_version = '1.4.10'
- repositories {
- jcenter()
- google()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:4.2.0-alpha12'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
-}
-
-allprojects {
- repositories {
- jcenter()
- google()
- }
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
diff --git a/build.gradle.kts b/build.gradle.kts
new file mode 100644
index 0000000..df60f77
--- /dev/null
+++ b/build.gradle.kts
@@ -0,0 +1,4 @@
+plugins {
+ alias(libs.plugins.application) apply false
+ alias(libs.plugins.kotlin) apply false
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 4fc032a..3e89fcd 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,23 @@
-org.gradle.jvmargs=-Xmx1536m
-android.useAndroidX=true
\ No newline at end of file
+ # Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 0000000..a2b2fd5
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,34 @@
+[versions]
+android = "8.0.2"
+fragment-ktx = "1.5.7"
+kotlin = "1.8.0"
+androidx-core = "1.10.1"
+androidx-core-splashscreen = "1.0.1"
+androidx-appcompat = "1.6.1"
+androidx-browser = "1.5.0"
+androidx-fragment = "1.6.0"
+androidx-lifecycle = "2.6.1"
+androidx-preference = "1.2.0"
+kotlinx-coroutines-core = "1.4.3"
+material = "1.9.0"
+tablericons = "0.9.0"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core" }
+androidx-core-splashscreen = { group = "androidx.core", name = "core-splashscreen", version.ref = "androidx-core-splashscreen" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" }
+androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidx-browser" }
+androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "androidx-fragment" }
+androidx-lifecycle-compiler = { group = "androidx.lifecycle", name = "lifecycle-compiler", version.ref = "androidx-lifecycle" }
+androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "androidx-lifecycle" }
+androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
+androidx-preference-ktx = { group = "androidx.preference", name = "preference-ktx", version.ref = "androidx-preference" }
+kotlinx-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+tablericons = { group = "ir.alirezaivaz", name = "tablericons", version.ref = "tablericons" }
+
+[plugins]
+application = { id = "com.android.application", version.ref = "android" }
+kotlin = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+
+[bundles]
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 83d6bd2..25f7b87 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index e7b4def..0000000
--- a/settings.gradle
+++ /dev/null
@@ -1 +0,0 @@
-include ':app'
diff --git a/settings.gradle.kts b/settings.gradle.kts
new file mode 100644
index 0000000..8d5a641
--- /dev/null
+++ b/settings.gradle.kts
@@ -0,0 +1,16 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://jitpack.io")
+ }
+}
+include(":app")