<|start_filename|>app/src/main/java/com/tanish2k09/sce/fragments/containerFragments/CategoryFragment.kt<|end_filename|>
package com.tanish2k09.sce.fragments.containerFragments

import android.graphics.Color
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView

import com.tanish2k09.sce.R

import android.content.Context.MODE_PRIVATE

/**
 * A simple [Fragment] subclass.
 * create an instance of this fragment.
 */
class CategoryFragment : Fragment() {

    private var categoryName = "Not categorized"
    private var dividerTop: View? = null
    private var dividerBottom: View? = null
    private var catText: TextView? = null

    fun setInstanceCategory(category: String) {
        categoryName = category
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val v = inflater.inflate(R.layout.fragment_category, container, false)

        catText = v.findViewById(R.id.categoryTitle)
        catText!!.text = categoryName

        dividerTop = v.findViewById(R.id.catDivTop)
        dividerBottom = v.findViewById(R.id.catDivBottom)

        return v
    }

    override fun onResume() {
        super.onResume()
        val sp = catText!!.context.getSharedPreferences("settings", MODE_PRIVATE)
        val accent = Color.parseColor(sp.getString("accentCol", "#00bfa5"))
        catText!!.setTextColor(accent)
        dividerBottom!!.setBackgroundColor(accent)
        dividerTop!!.setBackgroundColor(accent)
    }

    fun pushConfigVarFragment(`var`: ConfigVar, index: Int) {
        childFragmentManager.beginTransaction().add(R.id.categoryList, `var`, "configCard$index").commit()
    }

    fun popFragment(index: Int): Boolean {
        childFragmentManager.beginTransaction()
                .remove(childFragmentManager.findFragmentByTag("configCard$index")!!)
                .commitNow()
        return childFragmentManager.fragments.size == 0
    }
}// Required empty public constructor


<|start_filename|>app/src/main/java/com/tanish2k09/sce/utils/StringVal.kt<|end_filename|>
package com.tanish2k09.sce.utils

import java.util.ArrayList

class StringVal internal constructor(val name: String) {
    private val options: ArrayList<String> = ArrayList()
    var activeVal = "<no value set>"

    var descriptionString: String? = null
        private set

    var title: String? = null
        internal set

    var category: String? = null
        internal set

    val numOptions: Int
        get() = options.size

    init {
        descriptionString = ""
        title = ""
    }

    internal fun addVal(`val`: String) {
        for (idx in options.indices)
            if (options[idx] == `val`)
                return
        options.add(`val`)
    }

    fun getOption(index: Int): String? {
        return if (index < options.size) options[index] else null
    }

    internal fun clearOptions() {
        options.clear()
    }

    internal fun setDescription(desc: String) {
        descriptionString = desc
    }
}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/fragments/containerFragments/ConfigVar.kt<|end_filename|>
package com.tanish2k09.sce.fragments.containerFragments

import android.app.AlertDialog
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.TextView

import com.tanish2k09.sce.R
import com.tanish2k09.sce.fragments.modals.ConfigOptionsModal
import com.tanish2k09.sce.utils.ConfigCache
import com.tanish2k09.sce.utils.StringVal

import android.content.Context.MODE_PRIVATE
import java.util.*

/**
 * A simple [Fragment] subclass.
 */
class ConfigVar : Fragment(), ConfigOptionsModal.Listener, View.OnClickListener {

    private var curVal: TextView? = null
    private var title: TextView? = null
    private var svc: StringVal? = null
    private var accentCol: Int = 0

    fun setupCardInfo(index: Int): Boolean {
        svc = ConfigCache.getStringVal(index)
        return svc != null
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val v = inflater.inflate(R.layout.fragment_config_var, container, false)

        title = v.findViewById(R.id.title)
        curVal = v.findViewById(R.id.curVal)

        title!!.text = svc!!.name.toUpperCase(Locale.getDefault())
        curVal!!.text = svc!!.activeVal

        val llTopCard = v.findViewById<LinearLayout>(R.id.ll_topCard)
        llTopCard.setOnClickListener(this)

        val infoButton = v.findViewById<ImageButton>(R.id.infoButtonConfig)
        infoButton.setOnClickListener(this)

        return v
    }

    override fun onResume() {
        super.onResume()
        val sp = curVal!!.context.getSharedPreferences("settings", MODE_PRIVATE)
        accentCol = Color.parseColor(sp.getString("accentCol", "#00bfa5"))
        curVal!!.setTextColor(accentCol)

        if (sp.getBoolean("useTitlesOnCards", true)) {
            title!!.text = svc!!.title
            title!!.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f)
            title!!.setTypeface(Typeface.DEFAULT, Typeface.BOLD)
        } else {
            title!!.text = svc!!.name.toUpperCase(Locale.getDefault())
            title!!.setTypeface(Typeface.MONOSPACE, Typeface.BOLD)
        }
    }

    override fun onItemClickedGov(position: Int) {
        svc!!.activeVal = svc!!.getOption(position)!!
        curVal!!.text = svc!!.activeVal
    }

    private fun showInfoDialog(v: View) {
        val builder = AlertDialog.Builder(v.context, R.style.dialogCustomStyle)

        builder.setPositiveButton("Okay") { dialog, _ -> dialog.dismiss() }

        builder.setTitle(svc!!.title)
                .setMessage(svc!!.descriptionString)
                .setCancelable(true)
                .create()
                .show()
    }

    override fun onClick(v: View) {
        if (v.id == R.id.ll_topCard)
            ConfigOptionsModal.newInstance(svc, accentCol).show(childFragmentManager, svc!!.name + " Selector")
        else
            showInfoDialog(v)
    }
}// Required empty public constructor


<|start_filename|>app/src/main/java/com/pes/androidmaterialcolorpickerdialog/MaterialColorPickerTextSeekBar.kt<|end_filename|>
package com.pes.androidmaterialcolorpickerdialog

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.Typeface
import androidx.annotation.ColorInt
import androidx.annotation.Dimension
import androidx.appcompat.widget.AppCompatSeekBar
import android.util.AttributeSet
import android.util.TypedValue

import com.tanish2k09.sce.R

/**
 * Created by <NAME> on 2017-03-04
 *
 * @author <NAME> <github></github><EMAIL>>
 * @since v1.1.0
 */
internal class MaterialColorPickerTextSeekBar : AppCompatSeekBar {

    private var textPaint: Paint? = null
    private var textRect: Rect? = null

    @ColorInt
    private var textColor: Int = 0

    @Dimension(unit = 2)
    private var textSize: Float = 0.toFloat()

    private var text: String? = null

    constructor(context: Context) : super(context) {
        init(null)
    }

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        init(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        textPaint = Paint(Paint.LINEAR_TEXT_FLAG or Paint.ANTI_ALIAS_FLAG)
        textRect = Rect()

        if (attrs != null) {

            val typedArray = context.obtainStyledAttributes(
                    attrs, R.styleable.MaterialColorPickerTextSeekBar
            )

            try {

                textColor = typedArray.getColor(
                        R.styleable.MaterialColorPickerTextSeekBar_android_textColor,
                        -0x1000000
                )

                textSize = typedArray.getDimension(
                        R.styleable.MaterialColorPickerTextSeekBar_android_textSize,
                        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                                18f, resources.displayMetrics)
                )

                text = typedArray.getString(R.styleable
                        .MaterialColorPickerTextSeekBar_android_text)

            } finally {

                typedArray.recycle()

            }

        }

        textPaint!!.color = textColor
        textPaint!!.typeface = Typeface.DEFAULT_BOLD
        textPaint!!.textSize = textSize
        textPaint!!.textAlign = Paint.Align.CENTER

        /* Measures 255 instead of the actual text because otherwise the padding would jump up
         * and down each time the text with its ascender and descenders changes.
         *
         * --
         *
         * Since we're only interested in a roundabout height depending on the text's font size
         * anyway, calculating the text bounds of this value is enough in this case.
         */
        textPaint!!.getTextBounds("255", 0, 3, textRect)

        setPadding(paddingLeft, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                (0.6 * textRect!!.height()).toFloat(), resources.displayMetrics).toInt(),
                paddingRight, paddingBottom)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        canvas.drawText(
                (if (text == null) progress.toString() else text)!!,
                (thumb.bounds.left + paddingLeft).toFloat(),
                (textRect!!.height() + (paddingTop shr 2)).toFloat(),
                textPaint!!
        )

    }
}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/helpers/ConfigImportExport.kt<|end_filename|>
package com.tanish2k09.sce.helpers

import com.tanish2k09.sce.R
import com.tanish2k09.sce.utils.ConfigCache
import com.tanish2k09.sce.utils.TopCommentStore
import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.io.SuFile

import android.content.Context
import android.os.Environment
import android.util.Log
import android.widget.Toast

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.IOException

import com.tanish2k09.sce.R.string.ConfigPath1
import com.tanish2k09.sce.R.string.ConfigPath2

class ConfigImportExport(private val ctx: Context) {
    private var configFile: File? = null

    private fun openConfig(): Int {
        configFile = File(Environment.getExternalStorageDirectory().path + "/SmurfKernel",
                ctx.resources.getString(R.string.configFile))
        return if (configFile!!.exists()) {
            0
        } else {
            -1
        }
    }

    private fun isValidConfigLine(line: String): Boolean {
        return line.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray().size == 2
    }

    /* The config file expects a certain notation/format:
     * The top value must be the profile.version
     *
     *  ##~ - Comment/Description
     *  ##* - Category
     *  ##: - Title
     *  # - Inactive Option (if it has exactly 1 '=')
     *  # - Comment (if not an inactive option)
     *  ##/ - Top comment (should be cached)
     */
    fun configImport(): Boolean {
        if (openConfig() != 0) {
            if (configDumpRoot()) {
                Toast.makeText(ctx, ctx.getString(R.string.importRoot), Toast.LENGTH_SHORT).show()
                return configImport()
            }
            return false
        } else {
            try {
                ConfigCache.clearAll()
                val inBR = BufferedReader(FileReader(configFile!!))
                var cache: String? = inBR.readLine()
                var title = ""
                var category = ""
                var description = StringBuilder()

                while (cache != null) {
                    if (isValidConfigLine(cache)) {
                        val configPair: Array<String>
                        if (cache.startsWith("#")) {
                            cache = cache.substring(1)
                            configPair = cache.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                            ConfigCache.addConfig(configPair[0], configPair[1], false, title, description.toString(), category)
                        } else {
                            configPair = cache.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                            ConfigCache.addConfig(configPair[0], configPair[1], true, title, description.toString(), category)
                        }
                        description = StringBuilder()
                    } else if (cache.startsWith("##:")) {
                        if (cache.length > 3)
                            title = cache.substring(3)
                    } else if (cache.startsWith("##~")) {
                        description.append(cache.substring(3)).append('\n')
                    } else if (cache.startsWith("##*")) {
                        if (cache.length > 3)
                            category = cache.substring(3)
                    } else if (cache.startsWith("##/")) {
                        TopCommentStore.appendLine(cache)
                    }
                    cache = inBR.readLine()
                }
                return true
            } catch (e: IOException) {
                Toast.makeText(ctx, R.string.swwRC, Toast.LENGTH_SHORT).show()
                e.printStackTrace()
                return false
            }

        }
    }

    private fun detectScript(layer: Int): String {
        val maxConfigPoints = 2

        if (layer > maxConfigPoints)
            return ""
        Log.d("SCE-CIE", " -- Checking layer $layer")

        var path = ""

        if (layer == 1)
            path = ctx.resources.getString(ConfigPath1)
        else if (layer == 2)
            path = ctx.resources.getString(ConfigPath2)

        val script = SuFile(path)
        return if (script.exists()) path else detectScript(layer + 1)

    }

    private fun runScript() {
        if (!Shell.rootAccess()) {
            Toast.makeText(ctx, ctx.resources.getString(R.string.noRoot), Toast.LENGTH_LONG).show()
            Log.e("SCE-CIE", "--- NO ROOT ACCESS ---")
            return
        }
        Log.d("SCE-CIE", "--- RunScript true ---")
        val scriptPath = detectScript(1)

        bashSh(scriptPath)
    }

    private fun bashSh(path: String) {
        Log.d("SCE-CIE", "Executing script path: $path")
        Shell.su("sh $path").submit()
    }

    fun saveConfig(runScript: Boolean) {
        try {
            Log.d("SCE-CIE", "New config file created? " + configFile!!.createNewFile())

            val outBW = BufferedWriter(FileWriter(configFile!!))
            outBW.write(TopCommentStore.comment)

            for (idx in 0 until ConfigCache.configListSize) {
                val svc = ConfigCache.getStringVal(idx)!!

                val category = svc.category

                if (category!!.isNotEmpty() && svc.name != ctx.resources.getString(R.string.profileVersion)) {
                    outBW.write("##*$category")
                    outBW.newLine()
                }

                if (svc.title!!.isNotEmpty()) {
                    outBW.write("##:" + svc.title!!)
                    outBW.newLine()
                }

                if (svc.descriptionString!!.isNotEmpty()) {
                    val lines = svc.descriptionString!!.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                    for (string in lines) {
                        outBW.write("##~$string")
                        outBW.newLine()
                    }
                }

                for (option in 0 until svc.numOptions) {
                    val lineToWrite = StringBuilder()

                    if (svc.getOption(option) != svc.activeVal && svc.name != ctx.getString(R.string.profileVersion))
                        lineToWrite.append("#")

                    lineToWrite.append(svc.name).append("=").append(svc.getOption(option))
                    outBW.write(lineToWrite.toString())
                    outBW.newLine()
                }
                outBW.newLine()
                outBW.newLine()
            }
            outBW.flush()
            outBW.close()
            Toast.makeText(ctx, "Saved successfully", Toast.LENGTH_SHORT).show()
            if (runScript)
                runScript()
        } catch (e: IOException) {
            Toast.makeText(ctx, R.string.swwRC, Toast.LENGTH_SHORT).show()
            e.printStackTrace()
        }

    }

    private fun configDumpRoot(): Boolean {
        val filename = ctx.resources.getString(R.string.configFile)
        val rootConfig = SuFile.open("/$filename")
        if (rootConfig.exists())
            Shell.su("cp /" + filename + " " + configFile!!.absolutePath).exec()
        return configFile!!.exists()
    }
}


<|start_filename|>app/src/main/java/com/pes/androidmaterialcolorpickerdialog/ColorFormatHelper.kt<|end_filename|>
package com.pes.androidmaterialcolorpickerdialog

import androidx.annotation.IntRange

internal object ColorFormatHelper {

    /**
     * Checks whether the specified value is between (including bounds) 0 and 255
     *
     * @param colorValue Color value
     * @return Specified input value if between 0 and 255, otherwise 0
     */
    fun assertColorValueInRange(@IntRange(from = 0, to = 255) colorValue: Int): Int {
        return if (colorValue in 0..255) colorValue else 0
    }

    /**
     * Formats individual RGB values to be output as a HEX string.
     *
     * Beware: If color value is lower than 0 or higher than 255, it's reset to 0.
     *
     * @param red   Red color value
     * @param green Green color value
     * @param blue  Blue color value
     * @return HEX String containing the three values
     */
    fun formatColorValues(
            @IntRange(from = 0, to = 255) red: Int,
            @IntRange(from = 0, to = 255) green: Int,
            @IntRange(from = 0, to = 255) blue: Int): String {

        return String.format("%02X%02X%02X",
                assertColorValueInRange(red),
                assertColorValueInRange(green),
                assertColorValueInRange(blue)
        )
    }

    /**
     * Formats individual ARGB values to be output as an 8 character HEX string.
     *
     * Beware: If any value is lower than 0 or higher than 255, it's reset to 0.
     *
     * @param alpha Alpha value
     * @param red   Red color value
     * @param green Green color value
     * @param blue  Blue color value
     * @return HEX String containing the three values
     * @since v1.1.0
     */
    fun formatColorValues(
            @IntRange(from = 0, to = 255) alpha: Int,
            @IntRange(from = 0, to = 255) red: Int,
            @IntRange(from = 0, to = 255) green: Int,
            @IntRange(from = 0, to = 255) blue: Int): String {

        return String.format("%02X%02X%02X%02X",
                assertColorValueInRange(alpha),
                assertColorValueInRange(red),
                assertColorValueInRange(green),
                assertColorValueInRange(blue)
        )
    }

}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/utils/ConfigCache.kt<|end_filename|>
package com.tanish2k09.sce.utils

import java.util.ArrayList

class ConfigCache {
    companion object {

        private val configList = ArrayList<StringVal>()

        fun addConfig(name: String,
                      `val`: String,
                      isValActive: Boolean,
                      title: String?,
                      description: String?,
                      category: String?): Int {

            for (idx in configList.indices) {
                val tmp = configList[idx]
                if (tmp.name == name) {
                    tmp.addVal(`val`)

                    if (isValActive)
                        tmp.activeVal = `val`

                    return idx
                }
            }

            val newStringVal = StringVal(name)
            newStringVal.addVal(`val`)

            if (isValActive)
                newStringVal.activeVal = `val`

            if (title != null)
                newStringVal.title = title

            if (description != null)
                newStringVal.setDescription(description)

            if (category != null && category.isNotEmpty())
                newStringVal.category = category
            else
                newStringVal.category = "Not categorized"

            configList.add(newStringVal)
            return configList.size - 1
        }

        val configListSize: Int
            get() = configList.size

        fun getStringVal(index: Int): StringVal? {
            return if (index <= configList.size) configList[index] else null
        }

        fun clearAll() {
            for (idx in 0 until configListSize)
                configList[idx].clearOptions()
        }
    }
}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/fragments/modals/ConfigOptionsModal.java<|end_filename|>
package com.tanish2k09.sce.fragments.modals;

import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import androidx.fragment.app.Fragment;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.tanish2k09.sce.R;
import com.tanish2k09.sce.utils.StringVal;

/**
 * <p>A fragment that shows a list of items as a modal bottom sheet.</p>
 * <p>You can show this modal bottom sheet from your activity like this:</p>
 * <pre>
 *     ConfigOptionsModal.newInstance(30).show(getSupportFragmentManager(), "dialog");
 * </pre>
 * <p>You activity (or fragment) needs to implement {@link ConfigOptionsModal.Listener}.</p>
 */
public class ConfigOptionsModal extends BottomSheetDialogFragment {

    private static StringVal svc;
    private static int color;
    private Listener mListener;

    public static ConfigOptionsModal newInstance(StringVal svc_arg, int accentColor) {
        final ConfigOptionsModal fragment = new ConfigOptionsModal();
        svc = svc_arg;
        color = accentColor;
        return fragment;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme);
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_config_options_dialog, container, false);
        TextView modalTitle = v.findViewById(R.id.modalTitle);
        CardView modalTitleCard = v.findViewById(R.id.modalTopTitleCard);

        modalTitle.setText(getString(R.string.modalTitle, svc.getName(), svc.getActiveVal()));
        modalTitleCard.setCardBackgroundColor(color);
        return v;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        final RecyclerView recyclerView = view.findViewById(R.id.list);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        recyclerView.setAdapter(new ItemAdapter(svc.getNumOptions()));
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        final Fragment parent = getParentFragment();
        if (parent != null) {
            mListener = (Listener) parent;
        } else {
            mListener = (Listener) context;
        }
    }

    @Override
    public void onDetach() {
        mListener = null;
        super.onDetach();
    }

    public interface Listener {
        void onItemClickedGov(int position);
    }

    private class ViewHolder extends RecyclerView.ViewHolder {

        final TextView text, serial;
        final View tapView;

        ViewHolder(LayoutInflater inflater, ViewGroup parent) {
            super(inflater.inflate(R.layout.fragment_list_item_text, parent, false));
            text = itemView.findViewById(R.id.text);
            serial = itemView.findViewById(R.id.serial);
            tapView = itemView.findViewById(R.id.tapView);
            tapView.setOnClickListener(v -> {
                if (mListener != null) {
                    mListener.onItemClickedGov(getAdapterPosition());
                    dismiss();
                }
            });
        }

    }

    private class ItemAdapter extends RecyclerView.Adapter<ViewHolder> {

        private final int mItemCount;
        private int currentNum = 1;

        ItemAdapter(int itemCount) {
            mItemCount = itemCount;
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(parent.getContext()), parent);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.text.setText(svc.getOption(currentNum-1));
            holder.serial.setText(getString(R.string.numSerial,position+1));
            currentNum++;
        }

        @Override
        public int getItemCount() {
            return mItemCount;
        }

    }

}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/InfoActivity.java<|end_filename|>
package com.tanish2k09.sce;

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;

import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Toast;

public class InfoActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_info);

        LinearLayout colorPicker = findViewById(R.id.colorPickerLayout);
        LinearLayout source = findViewById(R.id.sourceCodeLayout);
        Button xda = findViewById(R.id.xdaButton);
        Button telegram = findViewById(R.id.tgButton);
        Button email = findViewById(R.id.emailButton);
        Button discord = findViewById(R.id.discordButton);

        colorPicker.setOnClickListener(view -> {
            Uri uri = Uri.parse(getString(R.string.colorPickerLink));
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });

        source.setOnClickListener(view -> {
            Uri uri = Uri.parse(getString(R.string.SourceCodeLink));
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });

        xda.setOnClickListener(view -> {
            Uri uri = Uri.parse(getString(R.string.xdaLink));
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });

        telegram.setOnClickListener(view -> {
            Uri uri = Uri.parse(getString(R.string.telegramLink));
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });

        email.setOnClickListener(view -> {
            Uri uri = Uri.parse(getString(R.string.emailLink));
            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            startActivity(intent);
        });

        discord.setOnClickListener(view -> Toast.makeText(this, this.getResources().getString(R.string.quantum), Toast.LENGTH_LONG).show());
    }

    @Override
    protected void onResume() {
        super.onResume();
        SharedPreferences sp = getSharedPreferences("settings",MODE_PRIVATE);
        ConstraintLayout infoTopLayout = findViewById(R.id.infoTopLayout);
        String color = "#121212";

        if (sp.getBoolean("useBlackNotDark", false))
            color = "#000000";

        int parsedColor = Color.parseColor(color);

        getWindow().setNavigationBarColor(parsedColor);
        getWindow().setStatusBarColor(parsedColor);
        infoTopLayout.setBackgroundColor(parsedColor);
    }
}


<|start_filename|>app/src/main/java/com/tanish2k09/sce/SettingsActivity.kt<|end_filename|>
package com.tanish2k09.sce

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.cardview.widget.CardView
import android.widget.Switch
import android.widget.Toast
import com.pes.androidmaterialcolorpickerdialog.ColorPicker
import com.pes.androidmaterialcolorpickerdialog.ColorPickerCallback

class SettingsActivity : AppCompatActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)
        window.navigationBarColor = ContextCompat.getColor(this, R.color.black)

        val sp = getSharedPreferences("settings", Context.MODE_PRIVATE)

        val autoImportConfig = findViewById<Switch>(R.id.autoImportConfigSwitch)
        val autoUpdateConfig = findViewById<Switch>(R.id.autoUpdateConfigSwitch)
        val useTitles = findViewById<Switch>(R.id.useTitlesOnCards)
        val useBlackBG = findViewById<Switch>(R.id.useBlackNotDark)
        val colorCard = findViewById<CardView>(R.id.colorCard)

        autoImportConfig.isChecked = sp.getBoolean("autoImportConfig", true)
        autoImportConfig.setOnCheckedChangeListener { _, _ ->
            sp.edit().putBoolean("autoImportConfig", autoImportConfig.isChecked).apply()
            Toast.makeText(this, "autoImportConfig: Restart app to apply", Toast.LENGTH_SHORT).show()
        }

        autoUpdateConfig.isChecked = sp.getBoolean("autoUpdateConfig", true)
        autoUpdateConfig.setOnCheckedChangeListener { _, _ -> sp.edit().putBoolean("autoUpdateConfig", autoUpdateConfig.isChecked).apply() }

        useTitles.isChecked = sp.getBoolean("useTitlesOnCards", true)
        useTitles.setOnCheckedChangeListener { _, isChecked -> sp.edit().putBoolean("useTitlesOnCards", isChecked).apply() }

        useBlackBG.isChecked = sp.getBoolean("useBlackNotDark", false)
        setThemeColor(useBlackBG.isChecked)
        useBlackBG.setOnCheckedChangeListener { _, isChecked ->
            sp.edit().putBoolean("useBlackNotDark", isChecked).apply()

            var color = "#121212"

            if (isChecked)
                color = "#000000"

            setThemeColor(color)
        }

        setColorCard(colorCard, Color.parseColor(sp.getString("accentCol", "#00bfa5")))
        colorCard.setOnClickListener {
            val preColor = Color.parseColor(sp.getString("accentCol", "#00bfa5"))
            val cp = ColorPicker(this, Color.red(preColor), Color.green(preColor), Color.blue(preColor))
            cp.enableAutoClose()
            cp.setCallback(object : ColorPickerCallback {
                override fun onColorChosen(color: Int) {
                    sp.edit().putString("accentCol", String.format("#%06X", 0xFFFFFF and color)).apply()
                    setColorCard(colorCard, color)
                }})
            cp.show()
        }
    }

    fun setColorCard(card: CardView, color: Int) {
        card.setCardBackgroundColor(color)
    }

    private fun setThemeColor(colorHex: String) {
        val settingsLayout = findViewById<ConstraintLayout>(R.id.settingsLayout)

        val themeColor = ColorDrawable(Color.parseColor(colorHex))
        settingsLayout.background = themeColor
        window.statusBarColor = Color.parseColor(colorHex)
        window.navigationBarColor = Color.parseColor(colorHex)
    }

    private fun setThemeColor(isBlackChecked: Boolean) {
        if (isBlackChecked)
            setThemeColor("#000000")
        else
            setThemeColor("#121212")
    }
}


<|start_filename|>app/src/main/java/com/pes/androidmaterialcolorpickerdialog/ColorPickerCallback.kt<|end_filename|>
package com.pes.androidmaterialcolorpickerdialog

import androidx.annotation.ColorInt

/**
 * Created by <NAME> on 2017-03-04
 *
 * @author <NAME>
 */
interface ColorPickerCallback {
    /**
     * Gets called whenever a user chooses a color from the ColorPicker, i.e., presses the
     * "Choose" button.
     *
     * @param color Color chosen
     */

    fun onColorChosen(@ColorInt color: Int)
}



<|start_filename|>app/src/main/java/com/tanish2k09/sce/MainActivity.kt<|end_filename|>
package com.tanish2k09.sce

import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentTransaction
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.appcompat.widget.Toolbar

import android.util.Log
import android.util.TypedValue
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.TextView
import android.widget.Toast

import com.tanish2k09.sce.fragments.containerFragments.CategoryFragment
import com.tanish2k09.sce.fragments.containerFragments.ConfigVar
import com.tanish2k09.sce.helpers.ConfigImportExport
import com.tanish2k09.sce.utils.ConfigCache
import com.tanish2k09.sce.utils.TopCommentStore
import com.topjohnwu.superuser.Shell

import java.io.IOException

class MainActivity : AppCompatActivity() {

    private var noNotesCard: CardView? = null
    private var saveCard: CardView? = null
    private var cig: ConfigImportExport? = null
    private var runScript = true
    private var sp: SharedPreferences? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        setSupportActionBar(toolbar)

        cig = ConfigImportExport(this)

        noNotesCard = findViewById(R.id.no_notes_card)
        noNotesCard!!.setOnClickListener { commenceConfigImport() }

        saveCard = findViewById(R.id.saveButton)
        saveCard!!.setOnClickListener { cig!!.saveConfig(runScript) }

        Shell.su("cd /").submit()

        sp = getSharedPreferences("settings", Context.MODE_PRIVATE)
        if (sp!!.getBoolean("autoImportConfig", true) && ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
            commenceConfigImport()
    }

    override fun onResume() {
        super.onResume()
        val saveTitle = findViewById<TextView>(R.id.saveTitle)

        if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {

            ActivityCompat.requestPermissions(this,
                    arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE),
                    1)
        }

        runScript = sp!!.getBoolean("autoUpdateConfig", true)
        if (runScript) {
            saveTitle.text = resources.getString(R.string.saveAndApply)
            saveTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
        } else {
            saveTitle.text = resources.getString(R.string.save)
            saveTitle.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24f)
        }

        updateTheme()
    }

    private fun updateTheme() {
        val accent = Color.parseColor(sp!!.getString("accentCol", "#00bfa5"))
        val saveTitle = findViewById<TextView>(R.id.saveTitle)
        val toolbar = findViewById<Toolbar>(R.id.toolbar)
        val mainContentLayout = findViewById<ConstraintLayout>(R.id.mainContentLayout)

        saveCard!!.setCardBackgroundColor(accent)
        noNotesCard!!.setCardBackgroundColor(accent)

        var color = "#121212"
        if (sp!!.getBoolean("useBlackNotDark", false))
            color = "#000000"

        val parsedColor = Color.parseColor(color)

        val colDrawable = ColorDrawable(parsedColor)

        toolbar.background = colDrawable
        window.statusBarColor = parsedColor
        window.navigationBarColor = parsedColor
        mainContentLayout.background = colDrawable
        saveTitle.setTextColor(parsedColor)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            noNotesCard!!.outlineAmbientShadowColor = accent
            noNotesCard!!.outlineSpotShadowColor = accent
            saveCard!!.outlineAmbientShadowColor = accent
            saveCard!!.outlineSpotShadowColor = accent
        }
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_main, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.


        when (item.itemId) {
            R.id.action_import_config -> return commenceConfigImport()

            R.id.action_info -> {
                val infoActivityIntent = Intent(this, InfoActivity::class.java)
                startActivity(infoActivityIntent)
            }

            R.id.action_settings -> {
                val settingsActivityIntent = Intent(this, SettingsActivity::class.java)
                startActivity(settingsActivityIntent)
            }
        }

        return super.onOptionsItemSelected(item)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
            Toast.makeText(this, R.string.StoragePermDenied, Toast.LENGTH_LONG).show()
            finish()
            moveTaskToBack(true)
        }
    }

    private fun commenceConfigImport(): Boolean {
        removeConfigFragments()
        TopCommentStore.clear()

        if (!cig!!.configImport()) {
            Toast.makeText(this, resources.getString(R.string.swwImport), Toast.LENGTH_SHORT).show()
            return false
        }

        val size = ConfigCache.configListSize
        Log.d("SCE-CIE", "Found $size values")

        if (size > 0) {
            fillConfigFragments()
            noNotesCard!!.visibility = View.INVISIBLE
            saveCard!!.visibility = View.VISIBLE
            saveCard!!.isEnabled = true
        } else {
            Toast.makeText(this, "No values could be extracted", Toast.LENGTH_SHORT).show()
        }
        return true
    }

    private fun removeConfigFragments() {
        val fm = supportFragmentManager

        for (idx in 1 until ConfigCache.configListSize) {
            val cf = fm.findFragmentByTag("catFrag" + (ConfigCache.getStringVal(idx)?.category ?: "")) as CategoryFragment?
            if (cf != null) {
                if (cf.popFragment(idx))
                    fm.beginTransaction().remove(cf).commitNow()
            }
        }
    }

    private fun fillConfigFragments() {
        val fm = supportFragmentManager
        var ft: FragmentTransaction

        /* Assumes the first config is PROFILE.VERSION, so we skip that for fragment inflation*/
        val pv = "Profile version: " + (ConfigCache.getStringVal(0)?.activeVal ?: "Null?")
        Toast.makeText(this, pv, Toast.LENGTH_SHORT).show()
        Log.d("SCE-CIE", pv)

        for (idx in 1 until ConfigCache.configListSize) {
            val configFragment = ConfigVar()
            val category = ConfigCache.getStringVal(idx)?.category
            var cf = fm.findFragmentByTag("catFrag$category") as CategoryFragment?

            if (cf == null) {
                ft = fm.beginTransaction()
                cf = CategoryFragment()
                cf.setInstanceCategory(category!!)
                ft.add(R.id.listLayout, cf, "catFrag$category").commitNow()
            }

            if (!configFragment.setupCardInfo(idx))
                continue

            cf.pushConfigVarFragment(configFragment, idx)
        }
    }

    public override fun onDestroy() {
        try {
            val shell = Shell.getCachedShell()
            shell?.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }

        super.onDestroy()
    }

    companion object {

        init {
            /* Shell.Config methods shall be called before any shell is created
         * This is the reason why you should call it in a static block
         * The followings are some examples, check Javadoc for more details */
            Shell.Config.setFlags(Shell.FLAG_REDIRECT_STDERR or Shell.FLAG_VERBOSE_LOGGING)
            Shell.Config.setTimeout(5)
        }
    }
}


<|start_filename|>app/src/main/java/com/pes/androidmaterialcolorpickerdialog/ColorPicker.kt<|end_filename|>
package com.pes.androidmaterialcolorpickerdialog

import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.graphics.Color
import android.os.Bundle
import androidx.annotation.ColorInt
import androidx.annotation.IntRange
import android.text.InputFilter
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.Button
import android.widget.EditText
import android.widget.SeekBar

import com.tanish2k09.sce.R

import com.pes.androidmaterialcolorpickerdialog.ColorFormatHelper.assertColorValueInRange
import com.pes.androidmaterialcolorpickerdialog.ColorFormatHelper.formatColorValues

/**
 * This is the only class of the project. It consists in a custom dialog that shows the GUI
 * used for choosing a color using three sliders or an input field.
 *
 * @author <NAME>
 */
class ColorPicker
/**
 * Creator of the class. It will initialize the class with black color as default
 *
 * @param activity The reference to the activity where the color picker is called
 */
private constructor(private val activity: Activity) : Dialog(activity), SeekBar.OnSeekBarChangeListener {

    private var colorView: View? = null
    private var alphaSeekBar: SeekBar? = null
    private var redSeekBar: SeekBar? = null
    private var greenSeekBar: SeekBar? = null
    private var blueSeekBar: SeekBar? = null
    private var hexCode: EditText? = null
    private var alpha: Int = 0
    private var red: Int = 0
    private var green: Int = 0
    private var blue: Int = 0
    private var callback: ColorPickerCallback? = null

    private val withAlpha: Boolean
    private var autoclose: Boolean = false

    /**
     * Getter for the color as Android Color class value.
     *
     * From Android Reference: The Color class defines methods for creating and converting color
     * ints.
     * Colors are represented as packed ints, made up of 4 bytes: alpha, red, green, blue.
     * The values are unpremultiplied, meaning any transparency is stored solely in the alpha
     * component, and not in the color components.
     *
     * @return Selected color as Android Color class value.
     */
    var color: Int
        get() = if (withAlpha) Color.argb(alpha, red, green, blue) else Color.rgb(red, green, blue)
        set(@ColorInt color) {
            alpha = Color.alpha(color)
            red = Color.red(color)
            green = Color.green(color)
            blue = Color.blue(color)
        }

    init {

        if (activity is ColorPickerCallback) {
            callback = activity
        }

        this.alpha = 255
        this.red = 0
        this.green = 0
        this.blue = 0

        this.withAlpha = false
        this.autoclose = false
    }

    /**
     * Creator of the class. It will initialize the class with the rgb color passed as default
     *
     * @param activity The reference to the activity where the color picker is called
     * @param red      Red color for RGB values (0 - 255)
     * @param green    Green color for RGB values (0 - 255)
     * @param blue     Blue color for RGB values (0 - 255)
     *
     * If the value of the colors it's not in the right range (0 - 255) it will
     * be place at 0.
     */
    constructor(activity: Activity,
                @IntRange(from = 0, to = 255) red: Int,
                @IntRange(from = 0, to = 255) green: Int,
                @IntRange(from = 0, to = 255) blue: Int) : this(activity) {

        this.red = assertColorValueInRange(red)
        this.green = assertColorValueInRange(green)
        this.blue = assertColorValueInRange(blue)
    }

    /**
     * Enable auto-dismiss for the dialog
     */
    fun enableAutoClose() {
        this.autoclose = true
    }

    fun setCallback(listener: ColorPickerCallback) {
        callback = listener
    }

    /**
     * Simple onCreate function. Here there is the init of the GUI.
     *
     * @param savedInstanceState As usual ...
     */
    override fun onCreate(savedInstanceState: Bundle) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.materialcolorpicker__layout_color_picker)

        colorView = findViewById(R.id.colorView)

        hexCode = findViewById(R.id.hexCode)

        alphaSeekBar = findViewById(R.id.alphaSeekBar)
        redSeekBar = findViewById(R.id.redSeekBar)
        greenSeekBar = findViewById(R.id.greenSeekBar)
        blueSeekBar = findViewById(R.id.blueSeekBar)

        alphaSeekBar!!.setOnSeekBarChangeListener(this)
        redSeekBar!!.setOnSeekBarChangeListener(this)
        greenSeekBar!!.setOnSeekBarChangeListener(this)
        blueSeekBar!!.setOnSeekBarChangeListener(this)

        hexCode!!.filters = arrayOf<InputFilter>(InputFilter.LengthFilter(if (withAlpha) 8 else 6))

        hexCode!!.setOnEditorActionListener { v, actionId, event ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH ||
                    actionId == EditorInfo.IME_ACTION_DONE ||
                    event.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_ENTER)
            {
                updateColorView(v.text.toString())
                val imm = activity
                        .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(hexCode!!.windowToken, 0)

                return@setOnEditorActionListener true
            }
            false
        }

        val okColor = findViewById<Button>(R.id.okColorButton)
        okColor.setOnClickListener { sendColor() }
    }

    private fun initUi() {
        colorView!!.setBackgroundColor(color)

        alphaSeekBar!!.progress = alpha
        redSeekBar!!.progress = red
        greenSeekBar!!.progress = green
        blueSeekBar!!.progress = blue

        if (!withAlpha) {
            alphaSeekBar!!.visibility = View.GONE
        }

        hexCode!!.setText(if (withAlpha)
            formatColorValues(alpha, red, green, blue)
        else
            formatColorValues(red, green, blue)
        )
    }

    private fun sendColor() {
        if (callback != null)
            callback!!.onColorChosen(color)
        if (autoclose) {
            dismiss()
        }
    }

    /**
     * Method that synchronizes the color between the bars, the view, and the HEX code text.
     *
     * @param input HEX Code of the color.
     */
    private fun updateColorView(input: String) {
        try {
            val color = Color.parseColor("#$input")
            alpha = Color.alpha(color)
            red = Color.red(color)
            green = Color.green(color)
            blue = Color.blue(color)

            colorView!!.setBackgroundColor(color)

            alphaSeekBar!!.progress = alpha
            redSeekBar!!.progress = red
            greenSeekBar!!.progress = green
            blueSeekBar!!.progress = blue
        } catch (ignored: IllegalArgumentException) {
            hexCode!!.error = activity.resources.getText(R.string.materialcolorpicker__errHex)
        }

    }

    /**
     * Method called when the user change the value of the bars. This sync the colors.
     *
     * @param seekBar  SeekBar that has changed
     * @param progress The new progress value
     * @param fromUser Whether the user is the reason for the method call
     */
    override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {

        when {
            seekBar.id == R.id.alphaSeekBar -> alpha = progress
            seekBar.id == R.id.redSeekBar -> red = progress
            seekBar.id == R.id.greenSeekBar -> green = progress
            seekBar.id == R.id.blueSeekBar -> blue = progress
        }

        colorView!!.setBackgroundColor(color)

        //Setting the inputText hex color
        hexCode!!.setText(if (withAlpha)
            formatColorValues(alpha, red, green, blue)
        else
            formatColorValues(red, green, blue)
        )

    }

    override fun onStopTrackingTouch(seekBar: SeekBar) {}

    override fun onStartTrackingTouch(seekBar: SeekBar) {}

    override fun show() {
        super.show()
        initUi()
    }
}

<|start_filename|>app/src/main/java/com/tanish2k09/sce/utils/TopCommentStore.kt<|end_filename|>
package com.tanish2k09.sce.utils

object TopCommentStore {
    private var topComment = StringBuilder()

    val comment: String
        get() = topComment.toString()

    fun appendLine(line: String) {
        topComment.append(line).append('\n')
    }

    fun clear() {
        topComment = StringBuilder()
    }
}
