package com.example.FastAdmin // Corrected package name import android.os.Bundle import android.webkit.HttpAuthHandler import android.webkit.WebView import android.webkit.WebViewClient import androidx.appcompat.app.AppCompatActivity import android.app.AlertDialog import android.content.Context import android.content.SharedPreferences import android.widget.EditText import android.widget.LinearLayout import android.widget.TextView import android.widget.Button import android.view.Gravity import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.graphics.Color import android.util.TypedValue import android.view.View import android.graphics.drawable.GradientDrawable class MainActivity : AppCompatActivity() { // --- COLOR CONSTANTS DERIVED FROM styles.css AND colors.xml --- private val COLOR_BG = 0xFF1A1B26.toInt() private val COLOR_CARD = 0xFF24283B.toInt() private val COLOR_PRIMARY_TEXT = 0xFFC0CAF5.toInt() private val COLOR_ACCENT = 0xFF7AA2F7.toInt() private val COLOR_ERROR = 0xFFF7768E.toInt() private val COLOR_BORDER_DARK = 0xFF3A3C4D.toInt() private lateinit var myWebView: WebView private lateinit var sharedPrefs: SharedPreferences // Key for SharedPreferences private val PREFS_NAME = "AdminPrefs" private val DOMAIN_KEY = "TargetDomain" // Currently selected domain private val DOMAIN_LIST_KEY = "SavedDomains" // Key for the list of all domains override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Initialize SharedPreferences sharedPrefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) // Check if the domain is already saved val savedDomain = sharedPrefs.getString(DOMAIN_KEY, null) if (savedDomain.isNullOrEmpty()) { // Domain not set: show the full manager menu showDomainManagerDialog() } else { // Domain is set: proceed to load WebView setupWebView(savedDomain) } } // --- Core WebView Setup Function (NO CHANGE) --- private fun setupWebView(baseUrl: String) { myWebView = findViewById(R.id.webview) val settings = myWebView.settings settings.javaScriptEnabled = true settings.domStorageEnabled = true myWebView.webViewClient = object : WebViewClient() { override fun onReceivedHttpAuthRequest( view: WebView?, handler: HttpAuthHandler?, host: String?, realm: String? ) { if (handler != null) { showHttpAuthDialog(handler, host, realm) } } } val urlToLoad = if (baseUrl.startsWith("http")) baseUrl else "https://$baseUrl" myWebView.loadUrl(urlToLoad) } // --- Domain Manager Menu (STYLED) --- private fun showDomainManagerDialog() { val savedDomains = sharedPrefs.getStringSet(DOMAIN_LIST_KEY, HashSet())?.toList() ?: emptyList() val currentDomain = sharedPrefs.getString(DOMAIN_KEY, null) val managerLayout = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL setPadding(dpToPx(20), dpToPx(10), dpToPx(20), dpToPx(10)) } // 1. Add List of Domains if (savedDomains.isEmpty()) { managerLayout.addView(TextView(this).apply { text = "No domains saved. Tap ADD NEW below." setTextColor(COLOR_PRIMARY_TEXT) setPadding(0, dpToPx(15), 0, dpToPx(15)) }) } else { for (domain in savedDomains) { val isSelected = domain == currentDomain val domainItem = createDomainListItem(domain, isSelected) managerLayout.addView(domainItem) } } // 2. Add Buttons Layout val buttonsLayout = LinearLayout(this).apply { orientation = LinearLayout.HORIZONTAL gravity = Gravity.CENTER_HORIZONTAL setPadding(0, dpToPx(20), 0, 0) } // Add Button val addButton = createStyledButton("ADD NEW", COLOR_ACCENT, COLOR_BG).apply { setOnClickListener { showAddDomainDialog(savedDomains.toSet()) } } buttonsLayout.addView(addButton, LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f).apply { rightMargin = dpToPx(10) }) // Delete Button val deleteButton = createStyledButton("DELETE", COLOR_ERROR, COLOR_BG).apply { isEnabled = savedDomains.isNotEmpty() setOnClickListener { showDeleteDomainDialog(savedDomains) } } buttonsLayout.addView(deleteButton, LinearLayout.LayoutParams(0, WRAP_CONTENT, 1f)) managerLayout.addView(buttonsLayout) // Show the styled AlertDialog AlertDialog.Builder(this, R.style.Theme_App_DarkDialog) // Use the custom dialog theme .setTitle("Manage Admin Boards") .setMessage("Tap to select a board:") .setView(managerLayout) .setNegativeButton("EXIT") { _, _ -> finish() } .show() } // --- Helper function to create a styled button --- private fun createStyledButton(text: String, bgColor: Int, textColor: Int): Button { return Button(this).apply { this.text = text setBackgroundColor(bgColor) setTextColor(textColor) setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) setPadding(dpToPx(15), dpToPx(10), dpToPx(15), dpToPx(10)) elevation = dpToPx(4).toFloat() } } // --- Helper function to create a styled list item --- private fun createDomainListItem(domain: String, isSelected: Boolean): View { val container = LinearLayout(this).apply { orientation = LinearLayout.HORIZONTAL setPadding(dpToPx(15), dpToPx(15), dpToPx(15), dpToPx(15)) layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply { bottomMargin = dpToPx(10) } val drawable = GradientDrawable() drawable.setColor(if (isSelected) COLOR_ACCENT else COLOR_CARD) drawable.cornerRadius = dpToPx(8).toFloat() background = drawable setOnClickListener { sharedPrefs.edit().putString(DOMAIN_KEY, domain).apply() recreate() } } val textView = TextView(this).apply { text = domain setTextColor(if (isSelected) COLOR_BG else COLOR_PRIMARY_TEXT) setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) gravity = Gravity.CENTER_VERTICAL } container.addView(textView, LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 1f)) return container } // --- Add Domain Dialog (STYLED) --- private fun showAddDomainDialog(existingDomains: Set) { val domainInput = EditText(this).apply { hint = "e.g., admin.board.com/panel" setTextColor(COLOR_PRIMARY_TEXT) setHintTextColor(Color.GRAY) setPadding(dpToPx(15), dpToPx(15), dpToPx(15), dpToPx(15)) val borderDrawable = GradientDrawable() borderDrawable.setColor(COLOR_BG) borderDrawable.setStroke(dpToPx(1), COLOR_BORDER_DARK) borderDrawable.cornerRadius = dpToPx(8).toFloat() background = borderDrawable } val layout = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL setPadding(dpToPx(20), dpToPx(20), dpToPx(20), dpToPx(20)) addView(domainInput, LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)) } AlertDialog.Builder(this, R.style.Theme_App_DarkDialog) .setTitle("Add New Domain") .setView(layout) .setPositiveButton("Save") { _, _ -> val newDomain = domainInput.text.toString().trim() if (newDomain.isNotEmpty() && !existingDomains.contains(newDomain)) { val updatedSet = existingDomains.toMutableSet() updatedSet.add(newDomain) sharedPrefs.edit().putStringSet(DOMAIN_LIST_KEY, updatedSet).apply() } showDomainManagerDialog() } .setNegativeButton("Cancel") { _, _ -> showDomainManagerDialog() } .show() } // --- Delete Domain Dialog (Styled) --- private fun showDeleteDomainDialog(domainNames: List) { if (domainNames.isEmpty()) { showDomainManagerDialog() return } val items = domainNames.toTypedArray() AlertDialog.Builder(this, R.style.Theme_App_DarkDialog) .setTitle("Select Domain to DELETE") .setItems(items) { dialog, which -> val domainToDelete = domainNames[which] val currentSet = sharedPrefs.getStringSet(DOMAIN_LIST_KEY, HashSet())?.toMutableSet() if (currentSet != null) { currentSet.remove(domainToDelete) sharedPrefs.edit().putStringSet(DOMAIN_LIST_KEY, currentSet).apply() if (sharedPrefs.getString(DOMAIN_KEY, null) == domainToDelete) { sharedPrefs.edit().remove(DOMAIN_KEY).apply() } } dialog.dismiss() showDomainManagerDialog() } .setNegativeButton("Cancel") { _, _ -> showDomainManagerDialog() } .show() } // --- Utility function for converting DP to PX --- private fun dpToPx(dp: Int): Int { return TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, dp.toFloat(), resources.displayMetrics ).toInt() } // --- HTTP Auth Dialog Function (EXISTING, uses custom theme) --- private fun showHttpAuthDialog(handler: HttpAuthHandler, host: String?, realm: String?) { val usernameInput = EditText(this).apply { hint = "Username" setTextColor(COLOR_PRIMARY_TEXT) setHintTextColor(Color.GRAY) } val passwordInput = EditText(this).apply { hint = "Password" inputType = android.text.InputType.TYPE_CLASS_TEXT or android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD setTextColor(COLOR_PRIMARY_TEXT) setHintTextColor(Color.GRAY) } val layout = LinearLayout(this).apply { orientation = LinearLayout.VERTICAL setPadding(dpToPx(20), dpToPx(10), dpToPx(20), dpToPx(10)) addView(usernameInput, LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)) addView(passwordInput, LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)) } AlertDialog.Builder(this, R.style.Theme_App_DarkDialog) .setTitle("Authentication Required") .setMessage("Please enter credentials for $realm on $host") .setView(layout) .setPositiveButton("Log In") { _, _ -> val username = usernameInput.text.toString() val password = passwordInput.text.toString() handler.proceed(username, password) } .setNegativeButton("Cancel") { _, _ -> handler.cancel() } .setCancelable(false) .show() } // --- Back Button Logic (EXISTING) --- override fun onBackPressed() { if (::myWebView.isInitialized && myWebView.canGoBack()) { myWebView.goBack() } else { if (sharedPrefs.getString(DOMAIN_KEY, null).isNullOrEmpty()) { super.onBackPressed() } else { sharedPrefs.edit().remove(DOMAIN_KEY).apply() setContentView(R.layout.activity_main) showDomainManagerDialog() } } } }