Compare commits
No commits in common. "ddc3782770dc817658bbb3e42c3476447f531796" and "4856fcc7c59b615ac214e30463c1ab130722987a" have entirely different histories.
ddc3782770
...
4856fcc7c5
|
|
@ -9,8 +9,8 @@ android {
|
||||||
applicationId "org.iiab.controller"
|
applicationId "org.iiab.controller"
|
||||||
minSdkVersion 24
|
minSdkVersion 24
|
||||||
targetSdkVersion 34
|
targetSdkVersion 34
|
||||||
versionCode 32
|
versionCode 28
|
||||||
versionName "v0.2.2beta"
|
versionName "v0.1.32beta"
|
||||||
setProperty("archivesBaseName", "$applicationId-$versionName")
|
setProperty("archivesBaseName", "$applicationId-$versionName")
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
"type": "SINGLE",
|
"type": "SINGLE",
|
||||||
"filters": [],
|
"filters": [],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
"versionCode": 29,
|
"versionCode": 28,
|
||||||
"versionName": "v0.1.33beta",
|
"versionName": "v0.1.32beta",
|
||||||
"outputFile": "org.iiab.controller-v0.1.33beta-release.apk"
|
"outputFile": "org.iiab.controller-v0.1.32beta-release.apk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"elementType": "File",
|
"elementType": "File",
|
||||||
|
|
@ -22,14 +22,14 @@
|
||||||
"minApi": 28,
|
"minApi": 28,
|
||||||
"maxApi": 30,
|
"maxApi": 30,
|
||||||
"baselineProfiles": [
|
"baselineProfiles": [
|
||||||
"baselineProfiles/1/org.iiab.controller-v0.1.33beta-release.dm"
|
"baselineProfiles/1/org.iiab.controller-v0.1.32beta-release.dm"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"minApi": 31,
|
"minApi": 31,
|
||||||
"maxApi": 2147483647,
|
"maxApi": 2147483647,
|
||||||
"baselineProfiles": [
|
"baselineProfiles": [
|
||||||
"baselineProfiles/0/org.iiab.controller-v0.1.33beta-release.dm"
|
"baselineProfiles/0/org.iiab.controller-v0.1.32beta-release.dm"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@
|
||||||
<!-- Android 11+ Package Visibility -->
|
<!-- Android 11+ Package Visibility -->
|
||||||
<queries>
|
<queries>
|
||||||
<package android:name="com.termux" />
|
<package android:name="com.termux" />
|
||||||
<package android:name="com.termux.api" />
|
|
||||||
</queries>
|
</queries>
|
||||||
|
|
||||||
<application android:label="@string/app_name"
|
<application android:label="@string/app_name"
|
||||||
|
|
@ -63,8 +62,7 @@
|
||||||
|
|
||||||
<activity android:name=".MainActivity" android:label="@string/app_name"
|
<activity android:name=".MainActivity" android:label="@string/app_name"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:exported="true"
|
android:exported="true">
|
||||||
android:configChanges="orientation|screenSize|keyboardHidden|screenLayout">
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
|
@ -95,7 +93,4 @@
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
|
||||||
android:minSdkVersion="34" />
|
android:minSdkVersion="34" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
|
|
||||||
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
============================================================================
|
============================================================================
|
||||||
Name : AppListActivity.java
|
Name : AppListActivity.java
|
||||||
Author : hev <r@hev.cc>
|
Author : hev <r@hev.cc>
|
||||||
Contributors: IIAB Project
|
|
||||||
Copyright : Copyright (c) 2025 xyz
|
Copyright : Copyright (c) 2025 xyz
|
||||||
Copyright (c) 2026 IIAB Project
|
|
||||||
Description : App List Activity
|
Description : App List Activity
|
||||||
============================================================================
|
============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : BatteryUtils.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Manage battery permissions
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : BiometricHelper.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Biometrics helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
|
||||||
|
|
@ -1,528 +0,0 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : DashboardFragment.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Initial dasboard status activity
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.BatteryManager;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.text.Html;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.Inet4Address;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.NetworkInterface;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class DashboardFragment extends Fragment {
|
|
||||||
|
|
||||||
private TextView txtDeviceName;
|
|
||||||
private TextView txtWifiIp, txtHotspotIp, txtUptime, txtBattery, badgeStatus, txtStorage, txtRam, txtSwap, txtTermuxState;
|
|
||||||
private TextView modulesTitle;
|
|
||||||
private ProgressBar progStorage, progRam, progSwap;
|
|
||||||
private View ledTermuxState;
|
|
||||||
private LinearLayout modulesContainer;
|
|
||||||
|
|
||||||
private final Handler refreshHandler = new Handler(Looper.getMainLooper());
|
|
||||||
private Runnable refreshRunnable;
|
|
||||||
|
|
||||||
// List of modules to scan (Endpoint, Display Name)
|
|
||||||
private final Object[][] TARGET_MODULES = {
|
|
||||||
{"books", R.string.dash_books},
|
|
||||||
{"code", R.string.dash_code},
|
|
||||||
{"kiwix", R.string.dash_kiwix},
|
|
||||||
{"kolibri", R.string.dash_kolibri},
|
|
||||||
{"maps", R.string.dash_maps},
|
|
||||||
{"matomo", R.string.dash_matomo},
|
|
||||||
{"dashboard", R.string.dash_system}
|
|
||||||
};
|
|
||||||
|
|
||||||
public enum SystemState {
|
|
||||||
ONLINE, OFFLINE, DEBIAN_ONLY, INSTALLER, TERMUX_ONLY, NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
private SystemState currentSystemState = SystemState.NONE;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_dashboard, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
|
|
||||||
// Bindings
|
|
||||||
txtDeviceName = view.findViewById(R.id.dash_text_device_name);
|
|
||||||
txtWifiIp = view.findViewById(R.id.dash_text_wifi_ip);
|
|
||||||
txtHotspotIp = view.findViewById(R.id.dash_text_hotspot_ip);
|
|
||||||
txtUptime = view.findViewById(R.id.dash_text_uptime);
|
|
||||||
txtBattery = view.findViewById(R.id.dash_text_battery);
|
|
||||||
badgeStatus = view.findViewById(R.id.dash_badge_status);
|
|
||||||
|
|
||||||
txtStorage = view.findViewById(R.id.dash_text_storage);
|
|
||||||
txtRam = view.findViewById(R.id.dash_text_ram);
|
|
||||||
txtSwap = view.findViewById(R.id.dash_text_swap);
|
|
||||||
progStorage = view.findViewById(R.id.dash_progress_storage);
|
|
||||||
progRam = view.findViewById(R.id.dash_progress_ram);
|
|
||||||
progSwap = view.findViewById(R.id.dash_progress_swap);
|
|
||||||
|
|
||||||
ledTermuxState = view.findViewById(R.id.led_termux_state);
|
|
||||||
txtTermuxState = view.findViewById(R.id.text_termux_state);
|
|
||||||
modulesContainer = view.findViewById(R.id.modules_container);
|
|
||||||
modulesTitle = view.findViewById(R.id.dash_modules_title);
|
|
||||||
|
|
||||||
modulesContainer.setVisibility(View.GONE);
|
|
||||||
modulesTitle.setText(String.format(getString(R.string.label_separator_up), getString(R.string.dash_installed_modules)));
|
|
||||||
|
|
||||||
// Listener to colapse/expande
|
|
||||||
modulesTitle.setOnClickListener(v -> {
|
|
||||||
boolean isGone = modulesContainer.getVisibility() == View.GONE;
|
|
||||||
modulesContainer.setVisibility(isGone ? View.VISIBLE : View.GONE);
|
|
||||||
modulesTitle.setText(String.format(getString(isGone ? R.string.label_separator_down : R.string.label_separator_up), getString(R.string.dash_installed_modules)));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Generate module views dynamically
|
|
||||||
createModuleViews();
|
|
||||||
|
|
||||||
// Configure refresh timer (every 5 seconds)
|
|
||||||
refreshRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateSystemStats();
|
|
||||||
checkServerAndModules();
|
|
||||||
refreshHandler.postDelayed(this, 5000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
refreshHandler.post(refreshRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
refreshHandler.removeCallbacks(refreshRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSystemStats() {
|
|
||||||
txtDeviceName.setText(getDeviceName());
|
|
||||||
|
|
||||||
// --- 0. CALCULATE SERVER UPTIME ---
|
|
||||||
long uptimeMillis = android.os.SystemClock.elapsedRealtime();
|
|
||||||
long minutes = (uptimeMillis / (1000 * 60)) % 60;
|
|
||||||
long hours = (uptimeMillis / (1000 * 60 * 60)) % 24;
|
|
||||||
long days = (uptimeMillis / (1000 * 60 * 60 * 24));
|
|
||||||
|
|
||||||
// Format: "Uptime: 2d 14h 05m" (Omit days if 0)
|
|
||||||
String timeStr = (days > 0) ?
|
|
||||||
String.format(Locale.US, "%dd %02dh %02dm", days, hours, minutes) :
|
|
||||||
String.format(Locale.US, "%02dh %02dm", hours, minutes);
|
|
||||||
|
|
||||||
txtUptime.setText(Html.fromHtml(getString(R.string.dash_uptime_format, timeStr), Html.FROM_HTML_MODE_LEGACY));
|
|
||||||
|
|
||||||
txtWifiIp.setText(Html.fromHtml(getString(R.string.dash_wifi_format, getWifiIp()), Html.FROM_HTML_MODE_LEGACY));
|
|
||||||
txtHotspotIp.setText(Html.fromHtml(getString(R.string.dash_hotspot_format, getHotspotIp()), Html.FROM_HTML_MODE_LEGACY));
|
|
||||||
|
|
||||||
int batteryLevel = getBatteryPercentage();
|
|
||||||
if (batteryLevel >= 0) {
|
|
||||||
txtBattery.setText(Html.fromHtml(getString(R.string.dash_battery_format, batteryLevel), Html.FROM_HTML_MODE_LEGACY));
|
|
||||||
} else {
|
|
||||||
txtBattery.setText(Html.fromHtml(getString(R.string.dash_battery_no_value), Html.FROM_HTML_MODE_LEGACY));
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 1. GET REAL RAM AND SWAP FROM LINUX ---
|
|
||||||
long memTotal = 0, memAvailable = 0, swapTotal = 0, swapFree = 0;
|
|
||||||
try (BufferedReader br = new BufferedReader(new FileReader("/proc/meminfo"))) {
|
|
||||||
String line;
|
|
||||||
while ((line = br.readLine()) != null) {
|
|
||||||
if (line.startsWith("MemTotal:")) memTotal = parseMemLine(line);
|
|
||||||
else if (line.startsWith("MemAvailable:")) memAvailable = parseMemLine(line);
|
|
||||||
// If phone is old and doesn't have "MemAvailable", use "MemFree"
|
|
||||||
else if (memAvailable == 0 && line.startsWith("MemFree:")) memAvailable = parseMemLine(line);
|
|
||||||
else if (line.startsWith("SwapTotal:")) swapTotal = parseMemLine(line);
|
|
||||||
else if (line.startsWith("SwapFree:")) swapFree = parseMemLine(line);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the values from kB to GB (1 GB = 1048576 kB)
|
|
||||||
double memTotalGb = memTotal / 1048576.0;
|
|
||||||
double memUsedGb = (memTotal - memAvailable) / 1048576.0;
|
|
||||||
int memProgress = memTotal > 0 ? (int) (((memTotal - memAvailable) * 100) / memTotal) : 0;
|
|
||||||
|
|
||||||
double swapTotalGb = swapTotal / 1048576.0;
|
|
||||||
double swapUsedGb = (swapTotal - swapFree) / 1048576.0;
|
|
||||||
int swapProgress = swapTotal > 0 ? (int) (((swapTotal - swapFree) * 100) / swapTotal) : 0;
|
|
||||||
|
|
||||||
// --- UPDATE UI (TEXT AND BARS) ---
|
|
||||||
txtRam.setText(String.format(Locale.US, "%.2f GB / %.2f GB", memUsedGb, memTotalGb));
|
|
||||||
progRam.setProgress(memProgress);
|
|
||||||
|
|
||||||
if (swapTotal > 0) {
|
|
||||||
txtSwap.setText(String.format(Locale.US, "%.2f GB / %.2f GB", swapUsedGb, swapTotalGb));
|
|
||||||
progSwap.setProgress(swapProgress);
|
|
||||||
} else {
|
|
||||||
// If the device does not use Swap
|
|
||||||
txtSwap.setText("-- / --");
|
|
||||||
progSwap.setProgress(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Get Internal Storage
|
|
||||||
File path = android.os.Environment.getDataDirectory();
|
|
||||||
long totalSpace = path.getTotalSpace() / (1024 * 1024 * 1024); // To GB
|
|
||||||
long freeSpace = path.getFreeSpace() / (1024 * 1024 * 1024);
|
|
||||||
long usedSpace = totalSpace - freeSpace;
|
|
||||||
|
|
||||||
txtStorage.setText(usedSpace + " GB / " + totalSpace + " GB");
|
|
||||||
progStorage.setProgress(totalSpace > 0 ? (int) ((usedSpace * 100) / totalSpace) : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createModuleViews() {
|
|
||||||
modulesContainer.removeAllViews();
|
|
||||||
|
|
||||||
int numCols = 3;
|
|
||||||
int numRows = (int) Math.ceil((double) TARGET_MODULES.length / numCols);
|
|
||||||
|
|
||||||
for (int row = 0; row < numRows; row++) {
|
|
||||||
LinearLayout rowLayout = new LinearLayout(requireContext());
|
|
||||||
rowLayout.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
rowLayout.setLayoutParams(new LinearLayout.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
||||||
rowLayout.setBaselineAligned(false);
|
|
||||||
rowLayout.setWeightSum(numCols);
|
|
||||||
rowLayout.setPadding(0, 0, 0, 16);
|
|
||||||
|
|
||||||
for (int col = 0; col < numCols; col++) {
|
|
||||||
int index = (row * numCols) + col;
|
|
||||||
|
|
||||||
LinearLayout cell = new LinearLayout(requireContext());
|
|
||||||
LinearLayout.LayoutParams cellParams = new LinearLayout.LayoutParams(
|
|
||||||
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f);
|
|
||||||
|
|
||||||
// Margins to prevent them from sticking together
|
|
||||||
int margin = 8;
|
|
||||||
if (col == 0) cellParams.setMargins(0, 0, margin, 0); // Left
|
|
||||||
else if (col == 1) cellParams.setMargins(margin/2, 0, margin/2, 0); // Center
|
|
||||||
else cellParams.setMargins(margin, 0, 0, 0); // Right
|
|
||||||
|
|
||||||
cell.setLayoutParams(cellParams);
|
|
||||||
|
|
||||||
if (index < TARGET_MODULES.length) {
|
|
||||||
cell.setOrientation(LinearLayout.HORIZONTAL);
|
|
||||||
cell.setBackgroundResource(R.drawable.rounded_button);
|
|
||||||
cell.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
|
|
||||||
androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_module_bg)));
|
|
||||||
cell.setPadding(16, 24, 16, 24);
|
|
||||||
cell.setGravity(android.view.Gravity.CENTER);
|
|
||||||
|
|
||||||
View led = new View(requireContext());
|
|
||||||
led.setLayoutParams(new LinearLayout.LayoutParams(20, 20));
|
|
||||||
led.setBackgroundResource(R.drawable.led_off);
|
|
||||||
led.setId(View.generateViewId());
|
|
||||||
|
|
||||||
TextView name = new TextView(requireContext());
|
|
||||||
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
|
||||||
textParams.setMargins(12, 0, 0, 0);
|
|
||||||
name.setLayoutParams(textParams);
|
|
||||||
name.setText(getString((Integer) TARGET_MODULES[index][1]));
|
|
||||||
name.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_module_text));
|
|
||||||
name.setTextSize(11f);
|
|
||||||
name.setSingleLine(true);
|
|
||||||
|
|
||||||
cell.addView(led);
|
|
||||||
cell.addView(name);
|
|
||||||
cell.setTag(TARGET_MODULES[index][0]);
|
|
||||||
} else {
|
|
||||||
cell.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
rowLayout.addView(cell);
|
|
||||||
}
|
|
||||||
modulesContainer.addView(rowLayout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkServerAndModules() {
|
|
||||||
new Thread(() -> {
|
|
||||||
// 1. Ping the network once
|
|
||||||
boolean isMainServerAlive = pingUrl("http://localhost:8085/home");
|
|
||||||
|
|
||||||
if (!isAdded() || getActivity() == null) return;
|
|
||||||
|
|
||||||
// 2. Ask the State Machine for the definitive truth
|
|
||||||
currentSystemState = evaluateSystemState(isMainServerAlive);
|
|
||||||
|
|
||||||
// 3. Push the state to MainActivity
|
|
||||||
if (getActivity() instanceof MainActivity) {
|
|
||||||
((MainActivity) getActivity()).currentSystemState = currentSystemState;
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
if (getActivity() instanceof MainActivity) {
|
|
||||||
((MainActivity) getActivity()).updateUIColorsAndVisibility();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- CHECKPOINT 2 ---
|
|
||||||
if (!isAdded() || getActivity() == null) return;
|
|
||||||
|
|
||||||
// 4. Update the UI on the main thread
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
// Configure the Top Traffic Light (Server Status)
|
|
||||||
if (currentSystemState == SystemState.ONLINE) {
|
|
||||||
badgeStatus.setText(R.string.dash_online);
|
|
||||||
badgeStatus.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
|
|
||||||
androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_status_online)));
|
|
||||||
} else {
|
|
||||||
badgeStatus.setText(R.string.dash_offline);
|
|
||||||
badgeStatus.setBackgroundTintList(android.content.res.ColorStateList.valueOf(
|
|
||||||
androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_text_secondary)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure the Bottom LED and Suggestion Message
|
|
||||||
switch (currentSystemState) {
|
|
||||||
case ONLINE:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_on_green);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_online));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_text_primary));
|
|
||||||
break;
|
|
||||||
case OFFLINE:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_off);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_offline));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_text_secondary));
|
|
||||||
break;
|
|
||||||
case DEBIAN_ONLY:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_off);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_debian_only));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_text_primary));
|
|
||||||
break;
|
|
||||||
case INSTALLER:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_off);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_installer));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_text_primary));
|
|
||||||
break;
|
|
||||||
case TERMUX_ONLY:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_off);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_termux_only));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_warning));
|
|
||||||
break;
|
|
||||||
case NONE:
|
|
||||||
ledTermuxState.setBackgroundResource(R.drawable.led_off);
|
|
||||||
txtTermuxState.setText(getString(R.string.dash_state_none));
|
|
||||||
txtTermuxState.setTextColor(androidx.core.content.ContextCompat.getColor(requireContext(), R.color.dash_warning));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 5. Scan individual modules (Only if the system is ONLINE)
|
|
||||||
for (int r = 0; r < modulesContainer.getChildCount(); r++) {
|
|
||||||
LinearLayout row = (LinearLayout) modulesContainer.getChildAt(r);
|
|
||||||
|
|
||||||
for (int c = 0; c < row.getChildCount(); c++) {
|
|
||||||
LinearLayout card = (LinearLayout) row.getChildAt(c);
|
|
||||||
String endpoint = (String) card.getTag();
|
|
||||||
if (endpoint == null) continue;
|
|
||||||
|
|
||||||
View led = card.getChildAt(0);
|
|
||||||
|
|
||||||
// Module ON = (System is ONLINE) AND (URL responds)
|
|
||||||
boolean isModuleAlive = (currentSystemState == SystemState.ONLINE) && pingUrl("http://localhost:8085/" + endpoint);
|
|
||||||
|
|
||||||
if (!isAdded() || getActivity() == null) return;
|
|
||||||
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
led.setBackgroundResource(isModuleAlive ? R.drawable.led_on_green : R.drawable.led_off);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean pingUrl(String urlStr) {
|
|
||||||
try {
|
|
||||||
URL url = new URL(urlStr);
|
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
||||||
conn.setUseCaches(false);
|
|
||||||
conn.setConnectTimeout(1500);
|
|
||||||
conn.setReadTimeout(1500);
|
|
||||||
conn.setRequestMethod("GET");
|
|
||||||
return (conn.getResponseCode() >= 200 && conn.getResponseCode() < 400);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the numbers (in kB) from the lines of /proc/meminfo
|
|
||||||
private long parseMemLine(String line) {
|
|
||||||
try {
|
|
||||||
String[] parts = line.split("\\s+");
|
|
||||||
return Long.parseLong(parts[1]);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// --- METHODS FOR OBTAINING IPs ---
|
|
||||||
private String getWifiIp() {
|
|
||||||
return getIpByInterface("wlan0");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getHotspotIp() {
|
|
||||||
String[] hotspotInterfaces = {"ap0", "wlan1", "swlan0"};
|
|
||||||
for (String iface : hotspotInterfaces) {
|
|
||||||
String ip = getIpByInterface(iface);
|
|
||||||
if (!ip.equals("--")) return ip;
|
|
||||||
}
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getIpByInterface(String interfaceName) {
|
|
||||||
try {
|
|
||||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
|
||||||
for (NetworkInterface intf : interfaces) {
|
|
||||||
if (intf.getName().equalsIgnoreCase(interfaceName)) {
|
|
||||||
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
|
|
||||||
for (InetAddress addr : addrs) {
|
|
||||||
if (!addr.isLoopbackAddress() && addr instanceof Inet4Address) {
|
|
||||||
return addr.getHostAddress();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return "--";
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getBatteryPercentage() {
|
|
||||||
try {
|
|
||||||
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
Intent batteryStatus = requireContext().registerReceiver(null, iFilter);
|
|
||||||
if (batteryStatus != null) {
|
|
||||||
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
|
|
||||||
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
|
|
||||||
return (int) ((level / (float) scale) * 100);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- METHODS FOR OBTAINING THE DEVICE NAME ---
|
|
||||||
private String getDeviceName() {
|
|
||||||
String manufacturer = android.os.Build.MANUFACTURER;
|
|
||||||
String model = android.os.Build.MODEL;
|
|
||||||
|
|
||||||
if (model.toLowerCase().startsWith(manufacturer.toLowerCase())) {
|
|
||||||
return capitalize(model);
|
|
||||||
} else {
|
|
||||||
return capitalize(manufacturer) + " " + model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String capitalize(String s) {
|
|
||||||
if (s == null || s.length() == 0) return "";
|
|
||||||
char first = s.charAt(0);
|
|
||||||
if (Character.isUpperCase(first)) {
|
|
||||||
return s;
|
|
||||||
} else {
|
|
||||||
return Character.toUpperCase(first) + s.substring(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The 5 possible system states
|
|
||||||
// --- MASTER STATE EVALUATOR ---
|
|
||||||
private SystemState evaluateSystemState(boolean isNginxAlive) {
|
|
||||||
// 1. Does the Nginx server respond? (The network doesn't lie)
|
|
||||||
if (isNginxAlive) {
|
|
||||||
return SystemState.ONLINE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Does Termux physically exist on the Android device?
|
|
||||||
boolean isTermuxInstalled = false;
|
|
||||||
try {
|
|
||||||
requireContext().getPackageManager().getPackageInfo("com.termux", 0);
|
|
||||||
isTermuxInstalled = true;
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
isTermuxInstalled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
File stateDir = new File(Environment.getExternalStorageDirectory(), ".iiab_state");
|
|
||||||
|
|
||||||
// Ghost Handling: If Termux is uninstalled, but garbage remains, delete it.
|
|
||||||
if (!isTermuxInstalled) {
|
|
||||||
if (stateDir.exists()) {
|
|
||||||
deleteRecursive(stateDir);
|
|
||||||
}
|
|
||||||
return SystemState.NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Is IIAB fully compiled/restored and ready?
|
|
||||||
File flagIiabReady = new File(stateDir, "flag_iiab_ready");
|
|
||||||
if (flagIiabReady.exists()) {
|
|
||||||
return SystemState.OFFLINE; // The real offline state
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Is the base Debian OS installed, but NO IIAB yet? (The Virgin Debian Trap)
|
|
||||||
File flagSystem = new File(stateDir, "flag_system_installed");
|
|
||||||
if (flagSystem.exists()) {
|
|
||||||
return SystemState.DEBIAN_ONLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Is only the installer ready?
|
|
||||||
File flagInstaller = new File(stateDir, "flag_installer_present");
|
|
||||||
if (flagInstaller.exists()) {
|
|
||||||
return SystemState.INSTALLER;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Only the raw base app is present.
|
|
||||||
return SystemState.TERMUX_ONLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to recursively delete the .iiab_state folder if Termux was uninstalled
|
|
||||||
private void deleteRecursive(File fileOrDirectory) {
|
|
||||||
if (fileOrDirectory.isDirectory()) {
|
|
||||||
File[] children = fileOrDirectory.listFiles();
|
|
||||||
if (children != null) {
|
|
||||||
for (File child : children) {
|
|
||||||
deleteRecursive(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fileOrDirectory.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : DashboardManager.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Initial dasboard status helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
|
@ -27,11 +19,7 @@ public class DashboardManager {
|
||||||
private final View standaloneEspwButton;
|
private final View standaloneEspwButton;
|
||||||
private final View standaloneEspwDescription;
|
private final View standaloneEspwDescription;
|
||||||
|
|
||||||
// Memory variables to avoid freezing the screen
|
// We pass a Callback so the Dashboard can tell MainActivity to start/stop the VPN
|
||||||
private boolean lastTunnelState = false;
|
|
||||||
private boolean lastDegradedState = false;
|
|
||||||
private boolean isFirstRun = true;
|
|
||||||
|
|
||||||
public interface DashboardActionCallback {
|
public interface DashboardActionCallback {
|
||||||
void onToggleEspwRequested();
|
void onToggleEspwRequested();
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +44,7 @@ public class DashboardManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupListeners(DashboardActionCallback callback) {
|
private void setupListeners(DashboardActionCallback callback) {
|
||||||
// Single tap opens Settings directly
|
// Single tap opens Settings directly (No wrench icons needed!)
|
||||||
dashWifi.setOnClickListener(v -> activity.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)));
|
dashWifi.setOnClickListener(v -> activity.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)));
|
||||||
|
|
||||||
dashHotspot.setOnClickListener(v -> {
|
dashHotspot.setOnClickListener(v -> {
|
||||||
|
|
@ -83,15 +71,6 @@ public class DashboardManager {
|
||||||
|
|
||||||
// The Magic Morphing Animation!
|
// The Magic Morphing Animation!
|
||||||
public void setTunnelState(boolean isTunnelActive, boolean isDegraded) {
|
public void setTunnelState(boolean isTunnelActive, boolean isDegraded) {
|
||||||
// ANTI-FREEZE SHIELD!
|
|
||||||
// If the state is exactly the same as 3 seconds ago, abort to avoid blocking the UI
|
|
||||||
if (!isFirstRun && lastTunnelState == isTunnelActive && lastDegradedState == isDegraded) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
isFirstRun = false;
|
|
||||||
lastTunnelState = isTunnelActive;
|
|
||||||
lastDegradedState = isDegraded;
|
|
||||||
|
|
||||||
// Tells Android to smoothly animate any layout changes we make next
|
// Tells Android to smoothly animate any layout changes we make next
|
||||||
TransitionManager.beginDelayedTransition((ViewGroup) dashboardContainer.getParent(), new AutoTransition().setDuration(300));
|
TransitionManager.beginDelayedTransition((ViewGroup) dashboardContainer.getParent(), new AutoTransition().setDuration(300));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : DeployFragment.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Installation / deployment view
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
public class DeployFragment extends Fragment {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_deploy, container, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : IIABWatchdog.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Watchdog activity
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : LogManager.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Watchdog log manager
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@
|
||||||
============================================================================
|
============================================================================
|
||||||
Name : MainActivity.java
|
Name : MainActivity.java
|
||||||
Author : hev <r@hev.cc>
|
Author : hev <r@hev.cc>
|
||||||
Contributors: IIAB Project
|
|
||||||
Copyright : Copyright (c) 2025 hev
|
|
||||||
Copyright (c) 2026 IIAB Project
|
|
||||||
Copyright : Copyright (c) 2023 xyz
|
Copyright : Copyright (c) 2023 xyz
|
||||||
Description : Main Activity
|
Description : Main Activity
|
||||||
============================================================================
|
============================================================================
|
||||||
|
|
@ -30,7 +27,6 @@ import android.content.ComponentName;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageInfo;
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Environment;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
|
@ -59,9 +55,6 @@ import androidx.biometric.BiometricManager;
|
||||||
import androidx.biometric.BiometricPrompt;
|
import androidx.biometric.BiometricPrompt;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.google.android.material.tabs.TabLayout;
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
|
||||||
import androidx.viewpager2.widget.ViewPager2;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
@ -83,26 +76,50 @@ import java.net.InetSocketAddress;
|
||||||
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
|
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
private static final String TAG = "IIAB-MainActivity";
|
private static final String TAG = "IIAB-MainActivity";
|
||||||
private static final String TERMUX_PERMISSION = "com.termux.permission.RUN_COMMAND";
|
private static final String TERMUX_PERMISSION = "com.termux.permission.RUN_COMMAND";
|
||||||
public Preferences prefs;
|
private Preferences prefs;
|
||||||
|
private EditText edittext_socks_addr;
|
||||||
|
private EditText edittext_socks_udp_addr;
|
||||||
|
private EditText edittext_socks_port;
|
||||||
|
private EditText edittext_socks_user;
|
||||||
|
private EditText edittext_socks_pass;
|
||||||
|
private EditText edittext_dns_ipv4;
|
||||||
|
private EditText edittext_dns_ipv6;
|
||||||
|
private CheckBox checkbox_udp_in_tcp;
|
||||||
|
private CheckBox checkbox_remote_dns;
|
||||||
|
private CheckBox checkbox_global;
|
||||||
|
private CheckBox checkbox_maintenance;
|
||||||
|
private TextView textview_maintenance_warning;
|
||||||
|
private CheckBox checkbox_ipv4;
|
||||||
|
private CheckBox checkbox_ipv6;
|
||||||
|
private Button button_apps;
|
||||||
|
private Button button_save;
|
||||||
|
private Button button_control;
|
||||||
|
private Button button_browse_content;
|
||||||
|
private Button watchdogControl;
|
||||||
|
private TextView connectionLog;
|
||||||
|
private LinearLayout logActions;
|
||||||
|
private LinearLayout configLayout;
|
||||||
|
private TextView configLabel;
|
||||||
|
private LinearLayout advancedConfig;
|
||||||
|
private TextView advConfigLabel;
|
||||||
|
private TextView logLabel;
|
||||||
|
private TextView logWarning;
|
||||||
|
private TextView logSizeText;
|
||||||
private ImageButton themeToggle;
|
private ImageButton themeToggle;
|
||||||
private ImageButton btnSettings;
|
private ImageButton btnSettings;
|
||||||
private android.widget.ImageView headerIcon;
|
|
||||||
|
|
||||||
// Tabs UI
|
|
||||||
private TabLayout tabLayout;
|
|
||||||
private ViewPager2 viewPager;
|
|
||||||
private TextView versionFooter;
|
private TextView versionFooter;
|
||||||
public boolean isServerAlive = false;
|
private ProgressBar logProgress;
|
||||||
public boolean isNegotiating = false;
|
|
||||||
public DashboardFragment.SystemState currentSystemState = DashboardFragment.SystemState.NONE;
|
|
||||||
public boolean isProxyDegraded = false;
|
|
||||||
public Boolean targetServerState = null;
|
|
||||||
public String serverTransitionText = "";
|
|
||||||
public UsageFragment usageFragment;
|
|
||||||
|
|
||||||
public void setUsageFragment(UsageFragment fragment) {
|
// Cassette Deck UI
|
||||||
this.usageFragment = fragment;
|
private LinearLayout deckContainer;
|
||||||
}
|
private ProgressButton btnServerControl;
|
||||||
|
private ObjectAnimator fusionAnimator;
|
||||||
|
private android.animation.ObjectAnimator exploreAnimator;
|
||||||
|
private boolean isServerAlive = false;
|
||||||
|
private boolean isNegotiating = false;
|
||||||
|
private boolean isProxyDegraded = false;
|
||||||
|
private Boolean targetServerState = null;
|
||||||
|
private String serverTransitionText = "";
|
||||||
private final Handler timeoutHandler = new Handler(android.os.Looper.getMainLooper());
|
private final Handler timeoutHandler = new Handler(android.os.Looper.getMainLooper());
|
||||||
private Runnable timeoutRunnable;
|
private Runnable timeoutRunnable;
|
||||||
private boolean isWifiActive = false;
|
private boolean isWifiActive = false;
|
||||||
|
|
@ -110,11 +127,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
private String currentTargetUrl = null;
|
private String currentTargetUrl = null;
|
||||||
private long pulseStartTime = 0;
|
private long pulseStartTime = 0;
|
||||||
|
|
||||||
|
private DashboardManager dashboardManager;
|
||||||
|
|
||||||
private ActivityResultLauncher<Intent> vpnPermissionLauncher;
|
private ActivityResultLauncher<Intent> vpnPermissionLauncher;
|
||||||
private ActivityResultLauncher<String[]> requestPermissionsLauncher;
|
private ActivityResultLauncher<String[]> requestPermissionsLauncher;
|
||||||
private ActivityResultLauncher<Intent> batteryOptLauncher;
|
private ActivityResultLauncher<Intent> batteryOptLauncher;
|
||||||
|
|
||||||
public boolean isReadingLogs = false;
|
private boolean isReadingLogs = false;
|
||||||
private final Handler sizeUpdateHandler = new Handler();
|
private final Handler sizeUpdateHandler = new Handler();
|
||||||
private Runnable sizeUpdateRunnable;
|
private Runnable sizeUpdateRunnable;
|
||||||
|
|
||||||
|
|
@ -131,9 +150,10 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
if (IIABWatchdog.ACTION_LOG_MESSAGE.equals(action)) {
|
if (IIABWatchdog.ACTION_LOG_MESSAGE.equals(action)) {
|
||||||
String message = intent.getStringExtra(IIABWatchdog.EXTRA_MESSAGE);
|
String message = intent.getStringExtra(IIABWatchdog.EXTRA_MESSAGE);
|
||||||
addToLog(message);
|
addToLog(message);
|
||||||
if (usageFragment != null) usageFragment.updateLogSizeUI();
|
updateLogSizeUI();
|
||||||
}
|
}
|
||||||
else if (WatchdogService.ACTION_STATE_STARTED.equals(action)) {
|
else if (WatchdogService.ACTION_STATE_STARTED.equals(action)) {
|
||||||
|
// Calculate where we are in the 1200ms cycle (600ms down + 600ms up)
|
||||||
long elapsed = System.currentTimeMillis() - pulseStartTime;
|
long elapsed = System.currentTimeMillis() - pulseStartTime;
|
||||||
long fullCycle = 1200;
|
long fullCycle = 1200;
|
||||||
|
|
||||||
|
|
@ -149,13 +169,13 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
|
|
||||||
// Wait exactly until the wave hits 1.0f alpha, then lock it!
|
// Wait exactly until the wave hits 1.0f alpha, then lock it!
|
||||||
new Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
new Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
||||||
if (usageFragment != null) usageFragment.finalizeEntryPulse();
|
finalizeEntryPulse();
|
||||||
}, timeToNextCycleEnd);
|
}, timeToNextCycleEnd);
|
||||||
}
|
}
|
||||||
else if (WatchdogService.ACTION_STATE_STOPPED.equals(action)) {
|
else if (WatchdogService.ACTION_STATE_STOPPED.equals(action)) {
|
||||||
// Service is down! Give it a 1.5 second visual margin, then stop the exit pulse.
|
// Service is down! Give it a 1.5 second visual margin, then stop the exit pulse.
|
||||||
new Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
new Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
||||||
if (usageFragment != null) usageFragment.finalizeExitPulse();
|
finalizeExitPulse();
|
||||||
}, 1500);
|
}, 1500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,8 +186,8 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
// Intercept launch and redirect to Setup Wizard if first time
|
// Intercept launch and redirect to Setup Wizard if first time
|
||||||
SharedPreferences internalPrefs = getSharedPreferences(getString(R.string.pref_file_internal), Context.MODE_PRIVATE);
|
SharedPreferences internalPrefs = getSharedPreferences("IIAB_Internal", Context.MODE_PRIVATE);
|
||||||
if (!internalPrefs.getBoolean(getString(R.string.pref_key_setup_complete), false)) {
|
if (!internalPrefs.getBoolean("setup_complete", false)) {
|
||||||
startActivity(new Intent(this, SetupActivity.class));
|
startActivity(new Intent(this, SetupActivity.class));
|
||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
|
|
@ -176,24 +196,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
prefs = new Preferences(this);
|
prefs = new Preferences(this);
|
||||||
setContentView(R.layout.main);
|
setContentView(R.layout.main);
|
||||||
|
|
||||||
// --- START TABS & VIEWPAGER ---
|
|
||||||
tabLayout = findViewById(R.id.tab_layout);
|
|
||||||
viewPager = findViewById(R.id.view_pager);
|
|
||||||
|
|
||||||
MainPagerAdapter pagerAdapter = new MainPagerAdapter(this);
|
|
||||||
viewPager.setAdapter(pagerAdapter);
|
|
||||||
|
|
||||||
new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> {
|
|
||||||
switch (position) {
|
|
||||||
case 0: tab.setText(R.string.tab_status); break;
|
|
||||||
case 1: tab.setText(R.string.tab_usage); break;
|
|
||||||
case 2: tab.setText(R.string.tab_deploy); break;
|
|
||||||
}
|
|
||||||
}).attach();
|
|
||||||
versionFooter = findViewById(R.id.version_text);
|
|
||||||
setVersionFooter();
|
|
||||||
viewPager.setCurrentItem(0, false);
|
|
||||||
|
|
||||||
// 1. Initialize Result Launchers
|
// 1. Initialize Result Launchers
|
||||||
vpnPermissionLauncher = registerForActivityResult(
|
vpnPermissionLauncher = registerForActivityResult(
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
|
|
@ -227,14 +229,118 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// UI Bindings
|
||||||
|
edittext_socks_addr = findViewById(R.id.socks_addr);
|
||||||
|
edittext_socks_udp_addr = findViewById(R.id.socks_udp_addr);
|
||||||
|
edittext_socks_port = findViewById(R.id.socks_port);
|
||||||
|
edittext_socks_user = findViewById(R.id.socks_user);
|
||||||
|
edittext_socks_pass = findViewById(R.id.socks_pass);
|
||||||
|
edittext_dns_ipv4 = findViewById(R.id.dns_ipv4);
|
||||||
|
edittext_dns_ipv6 = findViewById(R.id.dns_ipv6);
|
||||||
|
checkbox_ipv4 = findViewById(R.id.ipv4);
|
||||||
|
checkbox_ipv6 = findViewById(R.id.ipv6);
|
||||||
|
checkbox_global = findViewById(R.id.global);
|
||||||
|
checkbox_udp_in_tcp = findViewById(R.id.udp_in_tcp);
|
||||||
|
checkbox_remote_dns = findViewById(R.id.remote_dns);
|
||||||
|
checkbox_maintenance = findViewById(R.id.checkbox_maintenance);
|
||||||
|
checkbox_maintenance.setOnClickListener(this);
|
||||||
|
textview_maintenance_warning = findViewById(R.id.maintenance_warning);
|
||||||
|
button_apps = findViewById(R.id.apps);
|
||||||
|
button_save = findViewById(R.id.save);
|
||||||
|
button_control = findViewById(R.id.control);
|
||||||
|
button_browse_content = findViewById(R.id.btnBrowseContent);
|
||||||
|
watchdogControl = findViewById(R.id.watchdog_control);
|
||||||
|
|
||||||
|
logActions = findViewById(R.id.log_actions);
|
||||||
|
Button btnClearLog = findViewById(R.id.btn_clear_log);
|
||||||
|
Button btnCopyLog = findViewById(R.id.btn_copy_log);
|
||||||
|
connectionLog = findViewById(R.id.connection_log);
|
||||||
|
logProgress = findViewById(R.id.log_progress);
|
||||||
|
logWarning = findViewById(R.id.log_warning_text);
|
||||||
|
logSizeText = findViewById(R.id.log_size_text);
|
||||||
themeToggle = findViewById(R.id.theme_toggle);
|
themeToggle = findViewById(R.id.theme_toggle);
|
||||||
btnSettings = findViewById(R.id.btn_settings);
|
btnSettings = findViewById(R.id.btn_settings);
|
||||||
headerIcon = findViewById(R.id.header_icon);
|
versionFooter = findViewById(R.id.version_text);
|
||||||
|
configLayout = findViewById(R.id.config_layout);
|
||||||
|
configLabel = findViewById(R.id.config_label);
|
||||||
|
advancedConfig = findViewById(R.id.advanced_config);
|
||||||
|
advConfigLabel = findViewById(R.id.adv_config_label);
|
||||||
|
logLabel = findViewById(R.id.log_label);
|
||||||
|
|
||||||
|
deckContainer = findViewById(R.id.deck_container);
|
||||||
|
btnServerControl = findViewById(R.id.btn_server_control);
|
||||||
ImageButton btnShareQr = findViewById(R.id.btn_share_qr);
|
ImageButton btnShareQr = findViewById(R.id.btn_share_qr);
|
||||||
|
|
||||||
|
dashboardManager = new DashboardManager(this, findViewById(android.R.id.content), () -> {
|
||||||
|
handleControlClick();
|
||||||
|
});
|
||||||
|
|
||||||
// Listeners
|
// Listeners
|
||||||
|
watchdogControl.setOnClickListener(v -> {
|
||||||
|
boolean willBeEnabled = !prefs.getWatchdogEnable();
|
||||||
|
setWatchdogState(willBeEnabled);
|
||||||
|
});
|
||||||
|
btnClearLog.setOnClickListener(this);
|
||||||
|
btnCopyLog.setOnClickListener(this);
|
||||||
themeToggle.setOnClickListener(v -> toggleTheme());
|
themeToggle.setOnClickListener(v -> toggleTheme());
|
||||||
btnSettings.setOnClickListener(v -> startActivity(new Intent(MainActivity.this, SetupActivity.class)));
|
btnSettings.setOnClickListener(v -> startActivity(new Intent(MainActivity.this, SetupActivity.class)));
|
||||||
|
configLabel.setOnClickListener(v -> handleConfigToggle());
|
||||||
|
advConfigLabel.setOnClickListener(v -> toggleVisibility(advancedConfig, advConfigLabel, getString(R.string.advanced_settings_label)));
|
||||||
|
logLabel.setOnClickListener(v -> handleLogToggle());
|
||||||
|
checkbox_udp_in_tcp.setOnClickListener(this);
|
||||||
|
checkbox_remote_dns.setOnClickListener(this);
|
||||||
|
checkbox_global.setOnClickListener(this);
|
||||||
|
button_apps.setOnClickListener(this);
|
||||||
|
button_save.setOnClickListener(this);
|
||||||
|
|
||||||
|
btnServerControl.setOnClickListener(v -> {
|
||||||
|
// Ignore clicks if we are already waiting for a state change
|
||||||
|
if (targetServerState != null) return;
|
||||||
|
|
||||||
|
// Freeze the transition text and define the TARGET state
|
||||||
|
serverTransitionText = !isServerAlive ? getString(R.string.server_booting) : getString(R.string.server_shutting_down);
|
||||||
|
targetServerState = !isServerAlive;
|
||||||
|
|
||||||
|
// Lock the UI and start infinite animation
|
||||||
|
updateUIColorsAndVisibility();
|
||||||
|
btnServerControl.startProgress();
|
||||||
|
|
||||||
|
// Set a hard timeout (45 seconds) as a safety net
|
||||||
|
timeoutRunnable = () -> {
|
||||||
|
if (targetServerState != null) {
|
||||||
|
targetServerState = null; // Abort transition
|
||||||
|
btnServerControl.stopProgress();
|
||||||
|
updateUIColorsAndVisibility();
|
||||||
|
addToLog(getString(R.string.server_timeout_warning));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timeoutHandler.postDelayed(timeoutRunnable, getResources().getInteger(R.integer.server_cool_off_duration_ms));
|
||||||
|
|
||||||
|
// Execute the corresponding script command
|
||||||
|
if (!isServerAlive) {
|
||||||
|
startTermuxEnvironmentVisible("--start");
|
||||||
|
} else {
|
||||||
|
startTermuxEnvironmentVisible("--stop");
|
||||||
|
|
||||||
|
// Turn off Watchdog gracefully when stopping the server manually
|
||||||
|
if (prefs.getWatchdogEnable()) {
|
||||||
|
setWatchdogState(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logic to open the WebView (PortalActivity)
|
||||||
|
button_browse_content.setOnClickListener(v -> {
|
||||||
|
if (!isServerAlive) {
|
||||||
|
Snackbar.make(v, R.string.qr_error_no_server, Snackbar.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentTargetUrl != null) {
|
||||||
|
Intent intent = new Intent(MainActivity.this, PortalActivity.class);
|
||||||
|
intent.putExtra("TARGET_URL", currentTargetUrl);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// --- QR Share Button Logic ---
|
// --- QR Share Button Logic ---
|
||||||
btnShareQr.setOnClickListener(v -> {
|
btnShareQr.setOnClickListener(v -> {
|
||||||
|
|
@ -253,7 +359,18 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
startActivity(new Intent(MainActivity.this, QrActivity.class));
|
startActivity(new Intent(MainActivity.this, QrActivity.class));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connectionLog.setMovementMethod(new ScrollingMovementMethod());
|
||||||
|
connectionLog.setTextIsSelectable(true);
|
||||||
|
connectionLog.setOnTouchListener((v, event) -> {
|
||||||
|
v.getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
||||||
|
v.getParent().requestDisallowInterceptTouchEvent(false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
applySavedTheme();
|
applySavedTheme();
|
||||||
|
setVersionFooter();
|
||||||
updateUI();
|
updateUI();
|
||||||
|
|
||||||
addToLog(getString(R.string.app_started));
|
addToLog(getString(R.string.app_started));
|
||||||
|
|
@ -261,7 +378,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
sizeUpdateRunnable = new Runnable() {
|
sizeUpdateRunnable = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (usageFragment != null && usageFragment.isAdded()) usageFragment.updateLogSizeUI();
|
updateLogSizeUI();
|
||||||
sizeUpdateHandler.postDelayed(this, 10000);
|
sizeUpdateHandler.postDelayed(this, 10000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -330,6 +447,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
private void runNegotiationSequence() {
|
private void runNegotiationSequence() {
|
||||||
isNegotiating = true;
|
isNegotiating = true;
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> {
|
||||||
|
startExplorePulse(); // The orange button starts to beat.
|
||||||
updateUIColorsAndVisibility(); // We forced an immediate visual update
|
updateUIColorsAndVisibility(); // We forced an immediate visual update
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -386,21 +504,66 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startLogSizeUpdates() {
|
private void handleLogToggle() {
|
||||||
|
boolean isOpening = connectionLog.getVisibility() == View.GONE;
|
||||||
|
if (isOpening) {
|
||||||
|
if (isReadingLogs) return;
|
||||||
|
isReadingLogs = true;
|
||||||
|
if (logProgress != null) logProgress.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// We delegate the reading to the Manager
|
||||||
|
LogManager.readLogsAsync(this, (logContent, isRapidGrowth) -> {
|
||||||
|
if (connectionLog != null) {
|
||||||
|
connectionLog.setText(logContent);
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
if (logProgress != null) logProgress.setVisibility(View.GONE);
|
||||||
|
if (logWarning != null) logWarning.setVisibility(isRapidGrowth ? View.VISIBLE : View.GONE);
|
||||||
|
updateLogSizeUI();
|
||||||
|
isReadingLogs = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
startLogSizeUpdates();
|
||||||
|
} else {
|
||||||
|
stopLogSizeUpdates();
|
||||||
|
}
|
||||||
|
toggleVisibility(connectionLog, logLabel, getString(R.string.connection_log_label));
|
||||||
|
logActions.setVisibility(connectionLog.getVisibility());
|
||||||
|
if (logSizeText != null) logSizeText.setVisibility(connectionLog.getVisibility());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startLogSizeUpdates() {
|
||||||
sizeUpdateHandler.removeCallbacks(sizeUpdateRunnable);
|
sizeUpdateHandler.removeCallbacks(sizeUpdateRunnable);
|
||||||
sizeUpdateHandler.post(sizeUpdateRunnable);
|
sizeUpdateHandler.post(sizeUpdateRunnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopLogSizeUpdates() {
|
private void stopLogSizeUpdates() {
|
||||||
sizeUpdateHandler.removeCallbacks(sizeUpdateRunnable);
|
sizeUpdateHandler.removeCallbacks(sizeUpdateRunnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateLogSizeUI() {
|
||||||
|
if (logSizeText == null) return;
|
||||||
|
// The LogManager class does the calculation
|
||||||
|
String sizeStr = LogManager.getFormattedSize(this);
|
||||||
|
logSizeText.setText(getString(R.string.log_size_format, sizeStr));
|
||||||
|
}
|
||||||
|
|
||||||
private void connectVpn() {
|
private void connectVpn() {
|
||||||
Intent intent = new Intent(this, TProxyService.class);
|
Intent intent = new Intent(this, TProxyService.class);
|
||||||
startService(intent.setAction(TProxyService.ACTION_CONNECT));
|
startService(intent.setAction(TProxyService.ACTION_CONNECT));
|
||||||
addToLog(getString(R.string.vpn_permission_granted));
|
addToLog(getString(R.string.vpn_permission_granted));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setVersionFooter() {
|
||||||
|
try {
|
||||||
|
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||||
|
String version = pInfo.versionName;
|
||||||
|
versionFooter.setText(version);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
versionFooter.setText(R.string.default_version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPause() {
|
protected void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
@ -411,8 +574,6 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
// Check permissions status
|
|
||||||
updateHeaderIconsOpacity();
|
|
||||||
// Check battery status whenever returning to the app
|
// Check battery status whenever returning to the app
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||||
|
|
@ -429,7 +590,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
startService(vpnIntent.setAction(TProxyService.ACTION_CONNECT));
|
startService(vpnIntent.setAction(TProxyService.ACTION_CONNECT));
|
||||||
setIntent(null);
|
setIntent(null);
|
||||||
}
|
}
|
||||||
if (usageFragment != null && usageFragment.isLogVisible()) {
|
if (connectionLog != null && connectionLog.getVisibility() == View.VISIBLE) {
|
||||||
startLogSizeUpdates();
|
startLogSizeUpdates();
|
||||||
}
|
}
|
||||||
serverCheckHandler.removeCallbacks(serverCheckRunnable);
|
serverCheckHandler.removeCallbacks(serverCheckRunnable);
|
||||||
|
|
@ -465,6 +626,11 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
else themeToggle.setImageResource(R.drawable.ic_theme_system);
|
else themeToggle.setImageResource(R.drawable.ic_theme_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void toggleVisibility(View view, TextView label, String text) {
|
||||||
|
boolean isGone = view.getVisibility() == View.GONE;
|
||||||
|
view.setVisibility(isGone ? View.VISIBLE : View.GONE);
|
||||||
|
label.setText(String.format(getString(isGone ? R.string.label_separator_down : R.string.label_separator_up), text));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onStart() {
|
protected void onStart() {
|
||||||
|
|
@ -486,10 +652,55 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
// Delegated
|
if (view == checkbox_global || view == checkbox_remote_dns || view == checkbox_maintenance) {
|
||||||
|
savePrefs();
|
||||||
|
updateUI();
|
||||||
|
} else if (view == button_apps) {
|
||||||
|
startActivity(new Intent(this, AppListActivity.class));
|
||||||
|
} else if (view.getId() == R.id.save) {
|
||||||
|
savePrefs();
|
||||||
|
Toast.makeText(this, R.string.saved_toast, Toast.LENGTH_SHORT).show();
|
||||||
|
addToLog(getString(R.string.settings_saved));
|
||||||
|
} else if (view.getId() == R.id.control) handleControlClick();
|
||||||
|
else if (view.getId() == R.id.watchdog_control) handleWatchdogClick();
|
||||||
|
else if (view.getId() == R.id.btn_clear_log) showResetLogConfirmation();
|
||||||
|
else if (view.getId() == R.id.btn_copy_log) {
|
||||||
|
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
|
ClipData clip = ClipData.newPlainText("IIAB Log", connectionLog.getText().toString());
|
||||||
|
if (clipboard != null) {
|
||||||
|
clipboard.setPrimaryClip(clip);
|
||||||
|
Toast.makeText(this, R.string.log_copied_toast, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleWatchdogClick() {
|
private void showResetLogConfirmation() {
|
||||||
|
new AlertDialog.Builder(this)
|
||||||
|
.setTitle(R.string.log_reset_confirm_title)
|
||||||
|
.setMessage(R.string.log_reset_confirm_msg)
|
||||||
|
.setPositiveButton(R.string.reset_log, (dialog, which) -> resetLogFile())
|
||||||
|
.setNegativeButton(R.string.cancel, null).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetLogFile() {
|
||||||
|
LogManager.clearLogs(this, new LogManager.LogClearCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
connectionLog.setText("");
|
||||||
|
addToLog(getString(R.string.log_reset_user));
|
||||||
|
if (logWarning != null) logWarning.setVisibility(View.GONE);
|
||||||
|
updateLogSizeUI();
|
||||||
|
Toast.makeText(MainActivity.this, R.string.log_cleared_toast, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(String message) {
|
||||||
|
Toast.makeText(MainActivity.this, getString(R.string.failed_reset_log, message), Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleWatchdogClick() {
|
||||||
setWatchdogState(!prefs.getWatchdogEnable());
|
setWatchdogState(!prefs.getWatchdogEnable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -498,10 +709,9 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
Intent intent = new Intent(this, WatchdogService.class);
|
Intent intent = new Intent(this, WatchdogService.class);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
forceTermuxToForeground();
|
|
||||||
intent.setAction(WatchdogService.ACTION_START);
|
intent.setAction(WatchdogService.ACTION_START);
|
||||||
addToLog(getString(R.string.watchdog_started));
|
addToLog(getString(R.string.watchdog_started));
|
||||||
if (isServerAlive && usageFragment != null) usageFragment.startFusionPulse();
|
if (isServerAlive) startFusionPulse();
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
startForegroundService(intent);
|
startForegroundService(intent);
|
||||||
|
|
@ -510,7 +720,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addToLog(getString(R.string.watchdog_stopped));
|
addToLog(getString(R.string.watchdog_stopped));
|
||||||
if (usageFragment != null) usageFragment.startExitPulse();
|
startExitPulse();
|
||||||
stopService(intent);
|
stopService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -518,7 +728,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
updateUIColorsAndVisibility();
|
updateUIColorsAndVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleControlClick() {
|
private void handleControlClick() {
|
||||||
if (!isServerAlive) {
|
if (!isServerAlive) {
|
||||||
Snackbar.make(findViewById(android.R.id.content), R.string.qr_error_no_server, Snackbar.LENGTH_LONG).show();
|
Snackbar.make(findViewById(android.R.id.content), R.string.qr_error_no_server, Snackbar.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
|
|
@ -541,47 +751,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleBrowseContentClick(View v) {
|
// --- Secure Advanced Settings Menu ---
|
||||||
if (!isServerAlive) {
|
private void handleConfigToggle() {
|
||||||
Snackbar.make(v, R.string.qr_error_no_server, Snackbar.LENGTH_LONG).show();
|
if (configLayout.getVisibility() == View.GONE) {
|
||||||
return;
|
if (BiometricHelper.isDeviceSecure(this)) {
|
||||||
}
|
BiometricHelper.prompt(this,
|
||||||
if (currentTargetUrl != null) {
|
getString(R.string.auth_required_title),
|
||||||
Intent intent = new Intent(this, PortalActivity.class);
|
getString(R.string.auth_required_subtitle),
|
||||||
intent.putExtra("TARGET_URL", currentTargetUrl);
|
() -> toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label)));
|
||||||
startActivity(intent);
|
} else {
|
||||||
}
|
BiometricHelper.showEnrollmentDialog(this);
|
||||||
}
|
|
||||||
public void handleServerLaunchClick(View v) {
|
|
||||||
// Set a hard timeout as a safety net
|
|
||||||
timeoutRunnable = () -> {
|
|
||||||
if (targetServerState != null) {
|
|
||||||
targetServerState = null; // Abort transition
|
|
||||||
if (usageFragment != null) runOnUiThread(() -> usageFragment.stopBtnProgress());
|
|
||||||
updateUIColorsAndVisibility();
|
|
||||||
addToLog(getString(R.string.server_timeout_warning));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
timeoutHandler.postDelayed(timeoutRunnable, getResources().getInteger(R.integer.server_cool_off_duration_ms));
|
|
||||||
|
|
||||||
// Execute the corresponding script command
|
|
||||||
if (!isServerAlive) {
|
|
||||||
startTermuxEnvironmentVisible("--start");
|
|
||||||
|
|
||||||
// Fallback for Oppo/Xiaomi
|
|
||||||
new Handler(android.os.Looper.getMainLooper()).postDelayed(() -> {
|
|
||||||
if (targetServerState != null && !isServerAlive) {
|
|
||||||
Snackbar.make(v, R.string.termux_stuck_warning, Snackbar.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
}, getResources().getInteger(R.integer.server_snackbar_delay_ms));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
startTermuxEnvironmentVisible("--stop");
|
toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
|
||||||
|
|
||||||
// Turn off Watchdog gracefully when stopping the server manually
|
|
||||||
if (prefs.getWatchdogEnable()) {
|
|
||||||
setWatchdogState(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -599,9 +781,45 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUI() {
|
private void updateUI() {
|
||||||
if (usageFragment != null) {
|
boolean vpnActive = prefs.getEnable();
|
||||||
usageFragment.updateUI();
|
boolean watchdogActive = prefs.getWatchdogEnable();
|
||||||
|
|
||||||
|
if (dashboardManager != null) dashboardManager.setTunnelState(vpnActive, isProxyDegraded);
|
||||||
|
|
||||||
|
if (vpnActive) {
|
||||||
|
button_control.setText(R.string.control_disable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_on));
|
||||||
|
} else {
|
||||||
|
button_control.setText(R.string.control_enable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off));
|
||||||
|
}
|
||||||
|
if (watchdogActive) {
|
||||||
|
watchdogControl.setText(R.string.watchdog_disable);
|
||||||
|
} else {
|
||||||
|
watchdogControl.setText(R.string.watchdog_enable);
|
||||||
|
}
|
||||||
|
edittext_socks_addr.setText(prefs.getSocksAddress());
|
||||||
|
edittext_socks_udp_addr.setText(prefs.getSocksUdpAddress());
|
||||||
|
edittext_socks_port.setText(String.valueOf(prefs.getSocksPort()));
|
||||||
|
edittext_socks_user.setText(prefs.getSocksUsername());
|
||||||
|
edittext_socks_pass.setText(prefs.getSocksPassword());
|
||||||
|
edittext_dns_ipv4.setText(prefs.getDnsIpv4());
|
||||||
|
edittext_dns_ipv6.setText(prefs.getDnsIpv6());
|
||||||
|
checkbox_ipv4.setChecked(prefs.getIpv4());
|
||||||
|
checkbox_ipv6.setChecked(prefs.getIpv6());
|
||||||
|
checkbox_global.setChecked(prefs.getGlobal());
|
||||||
|
checkbox_udp_in_tcp.setChecked(prefs.getUdpInTcp());
|
||||||
|
checkbox_remote_dns.setChecked(prefs.getRemoteDns());
|
||||||
|
checkbox_maintenance.setChecked(prefs.getMaintenanceMode());
|
||||||
|
boolean editable = !vpnActive;
|
||||||
|
edittext_socks_addr.setEnabled(editable);
|
||||||
|
edittext_socks_port.setEnabled(editable);
|
||||||
|
button_save.setEnabled(editable);
|
||||||
|
|
||||||
|
checkbox_maintenance.setEnabled(editable);
|
||||||
|
if (textview_maintenance_warning != null) {
|
||||||
|
textview_maintenance_warning.setVisibility(vpnActive ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -627,7 +845,7 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
if (targetServerState != null && isServerAlive == targetServerState) {
|
if (targetServerState != null && isServerAlive == targetServerState) {
|
||||||
targetServerState = null; // Transition complete!
|
targetServerState = null; // Transition complete!
|
||||||
timeoutHandler.removeCallbacks(timeoutRunnable); // Cancel safety net
|
timeoutHandler.removeCallbacks(timeoutRunnable); // Cancel safety net
|
||||||
if (usageFragment != null) runOnUiThread(() -> usageFragment.stopBtnProgress());
|
runOnUiThread(() -> btnServerControl.stopProgress()); // Unlock button
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vpnOn && boxAlive) {
|
if (vpnOn && boxAlive) {
|
||||||
|
|
@ -642,10 +860,163 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUIColorsAndVisibility() {
|
private void updateUIColorsAndVisibility() {
|
||||||
if (usageFragment != null) {
|
boolean isVpnActive = prefs.getEnable();
|
||||||
usageFragment.updateUIColorsAndVisibility();
|
boolean isWatchdogOn = prefs.getWatchdogEnable();
|
||||||
|
|
||||||
|
// Draw island (Tunnel LED colors)
|
||||||
|
if (dashboardManager != null) {
|
||||||
|
dashboardManager.setTunnelState(isVpnActive, isProxyDegraded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw main VPN button (ESPW)
|
||||||
|
if (!isServerAlive) {
|
||||||
|
// Lock and dim the VPN button if there is no server to connect to
|
||||||
|
if (isVpnActive) {
|
||||||
|
button_control.setText(R.string.control_disable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_on_dim));
|
||||||
|
} else {
|
||||||
|
button_control.setText(R.string.control_enable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off_dim));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Unlock if server is alive
|
||||||
|
button_control.setEnabled(true);
|
||||||
|
if (isVpnActive) {
|
||||||
|
button_control.setText(R.string.control_disable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_on));
|
||||||
|
} else {
|
||||||
|
button_control.setText(R.string.control_enable);
|
||||||
|
button_control.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_vpn_off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Explore Content button
|
||||||
|
// Ensure it is ALWAYS visible, never GONE
|
||||||
|
button_browse_content.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (!isServerAlive) {
|
||||||
|
// State 1: Stopped (Greyed out)
|
||||||
|
stopExplorePulse();
|
||||||
|
button_browse_content.setEnabled(true);
|
||||||
|
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_disabled));
|
||||||
|
button_browse_content.setAlpha(1.0f);
|
||||||
|
button_browse_content.setTextColor(Color.parseColor("#888888"));
|
||||||
|
} else if (isNegotiating) {
|
||||||
|
// State 3: Negotiating
|
||||||
|
button_browse_content.setEnabled(true);
|
||||||
|
button_browse_content.setTextColor(Color.WHITE);
|
||||||
|
} else {
|
||||||
|
// State: Alive
|
||||||
|
stopExplorePulse();
|
||||||
|
button_browse_content.setEnabled(true);
|
||||||
|
button_browse_content.setTextColor(Color.WHITE);
|
||||||
|
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_ready));
|
||||||
|
|
||||||
|
if (isVpnActive && !isProxyDegraded) {
|
||||||
|
button_browse_content.setAlpha(1.0f); // 100% Perfect state
|
||||||
|
startExplorePulse();
|
||||||
|
} else {
|
||||||
|
button_browse_content.setAlpha(0.6f); // Watered down fallback state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FUSION LOGIC (Watchdog & Server Control)
|
||||||
|
if (targetServerState != null) {
|
||||||
|
// STATE: COOL-OFF (Locked)
|
||||||
|
btnServerControl.setAlpha(0.6f);
|
||||||
|
btnServerControl.setText(serverTransitionText);
|
||||||
|
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_disabled));
|
||||||
|
} else {
|
||||||
|
// STATE: NORMAL (Unlocked)
|
||||||
|
btnServerControl.setAlpha(1.0f);
|
||||||
|
if (isServerAlive) {
|
||||||
|
btnServerControl.setText(R.string.stop_server);
|
||||||
|
if (isWatchdogOn) {
|
||||||
|
deckContainer.setBackgroundColor(Color.parseColor("#44FF9800"));
|
||||||
|
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on));
|
||||||
|
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_on));
|
||||||
|
} else {
|
||||||
|
if (fusionAnimator == null || !fusionAnimator.isRunning()) deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_danger));
|
||||||
|
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_watchdog_off));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
btnServerControl.setText(R.string.launch_server);
|
||||||
|
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_success));
|
||||||
|
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(this, isWatchdogOn ? R.color.btn_watchdog_on : R.color.btn_watchdog_off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startFusionPulse() {
|
||||||
|
deckContainer.setBackgroundColor(Color.parseColor("#44FF9800"));
|
||||||
|
if (fusionAnimator != null && fusionAnimator.isRunning()) fusionAnimator.cancel();
|
||||||
|
|
||||||
|
pulseStartTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Pulses infinitely until the Service broadcast stops it
|
||||||
|
fusionAnimator = ObjectAnimator.ofFloat(deckContainer, "alpha", 1f, 0.4f);
|
||||||
|
fusionAnimator.setDuration(600);
|
||||||
|
fusionAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
||||||
|
fusionAnimator.setRepeatMode(ObjectAnimator.REVERSE);
|
||||||
|
fusionAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startExitPulse() {
|
||||||
|
if (fusionAnimator != null && fusionAnimator.isRunning()) fusionAnimator.cancel();
|
||||||
|
|
||||||
|
// A slower, deliberate pulse infinitely until the Service + 1.5s delay stops it
|
||||||
|
fusionAnimator = ObjectAnimator.ofFloat(deckContainer, "alpha", deckContainer.getAlpha(), 0.3f);
|
||||||
|
fusionAnimator.setDuration(800);
|
||||||
|
fusionAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
||||||
|
fusionAnimator.setRepeatMode(ObjectAnimator.REVERSE);
|
||||||
|
fusionAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startExplorePulse() {
|
||||||
|
button_browse_content.setAlpha(1.0f); // 100% Bright Orange
|
||||||
|
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_ready));
|
||||||
|
|
||||||
|
if (exploreAnimator == null) {
|
||||||
|
android.animation.PropertyValuesHolder scaleX = android.animation.PropertyValuesHolder.ofFloat(View.SCALE_X, 1.0f, 1.03f);
|
||||||
|
android.animation.PropertyValuesHolder scaleY = android.animation.PropertyValuesHolder.ofFloat(View.SCALE_Y, 1.0f, 1.03f);
|
||||||
|
exploreAnimator = android.animation.ObjectAnimator.ofPropertyValuesHolder(button_browse_content, scaleX, scaleY);
|
||||||
|
exploreAnimator.setDuration(800); // 800ms per heartbeat
|
||||||
|
exploreAnimator.setRepeatCount(android.animation.ObjectAnimator.INFINITE);
|
||||||
|
exploreAnimator.setRepeatMode(android.animation.ObjectAnimator.REVERSE);
|
||||||
|
}
|
||||||
|
if (!exploreAnimator.isRunning()) exploreAnimator.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopExplorePulse() {
|
||||||
|
if (exploreAnimator != null && exploreAnimator.isRunning()) {
|
||||||
|
exploreAnimator.cancel();
|
||||||
|
}
|
||||||
|
// Restore to normal size
|
||||||
|
button_browse_content.setScaleX(1.0f);
|
||||||
|
button_browse_content.setScaleY(1.0f);
|
||||||
|
|
||||||
|
// Diluted orange (ready, but waiting for the tunnel)
|
||||||
|
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(this, R.color.btn_explore_ready));
|
||||||
|
button_browse_content.setAlpha(0.6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finalizeEntryPulse() {
|
||||||
|
if (fusionAnimator != null) fusionAnimator.cancel();
|
||||||
|
deckContainer.setAlpha(1f); // Lock solid instantly
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finalizeExitPulse() {
|
||||||
|
if (fusionAnimator != null) fusionAnimator.cancel();
|
||||||
|
deckContainer.animate()
|
||||||
|
.alpha(1f)
|
||||||
|
.setDuration(300)
|
||||||
|
.withEndAction(() -> {
|
||||||
|
deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
||||||
|
})
|
||||||
|
.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTermuxEnvironmentVisible(String actionFlag) {
|
private void startTermuxEnvironmentVisible(String actionFlag) {
|
||||||
|
|
@ -704,100 +1075,43 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
|
||||||
this.isWifiActive = isWifiOn;
|
this.isWifiActive = isWifiOn;
|
||||||
this.isHotspotActive = isHotspotOn;
|
this.isHotspotActive = isHotspotOn;
|
||||||
|
|
||||||
if (usageFragment != null) {
|
// Let the Dashboard handle the LEDs!
|
||||||
runOnUiThread(() -> usageFragment.updateConnectivityLeds(this.isWifiActive, this.isHotspotActive));
|
if (dashboardManager != null) dashboardManager.updateConnectivityLeds(isWifiOn, isHotspotOn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void savePrefs() {
|
||||||
|
prefs.setSocksAddress("127.0.0.1");
|
||||||
|
prefs.setSocksPort(1080);
|
||||||
|
prefs.setSocksUdpAddress("");
|
||||||
|
prefs.setSocksUsername("");
|
||||||
|
prefs.setSocksPassword("");
|
||||||
|
prefs.setIpv4(true);
|
||||||
|
prefs.setIpv6(true);
|
||||||
|
prefs.setUdpInTcp(false);
|
||||||
|
prefs.setRemoteDns(true);
|
||||||
|
prefs.setGlobal(true);
|
||||||
|
|
||||||
|
prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString());
|
||||||
|
prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString());
|
||||||
|
prefs.setMaintenanceMode(checkbox_maintenance.isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void savePrefs() {
|
private void addToLog(String message) {
|
||||||
if (usageFragment != null) {
|
runOnUiThread(() -> {
|
||||||
usageFragment.savePrefsFromUI();
|
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
|
||||||
}
|
String currentTime = sdf.format(new Date());
|
||||||
}
|
String logEntry = "[" + currentTime + "] " + message + "\n";
|
||||||
|
if (connectionLog != null) {
|
||||||
public void addToLog(String message) {
|
connectionLog.append(logEntry);
|
||||||
if (usageFragment != null) {
|
scrollToBottom();
|
||||||
usageFragment.addToLog(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setVersionFooter() {
|
|
||||||
try {
|
|
||||||
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
|
|
||||||
String version = pInfo.versionName;
|
|
||||||
|
|
||||||
String footerText = getString(R.string.version_footer_format, version);
|
|
||||||
|
|
||||||
versionFooter.setText(footerText);
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
versionFooter.setText(getString(R.string.version_footer_fallback));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void forceTermuxToForeground() {
|
|
||||||
try {
|
|
||||||
Intent intent = getPackageManager().getLaunchIntentForPackage("com.termux");
|
|
||||||
if (intent != null) {
|
|
||||||
// Bring existing activity to the foreground
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
|
||||||
startActivity(intent);
|
|
||||||
addToLog(getString(R.string.force_termux_foreground));
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
});
|
||||||
addToLog(getString(R.string.termux_invocation_error, e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- PERMISSION CHECKERS FOR UI OPACITY ---
|
private void scrollToBottom() {
|
||||||
|
if (connectionLog.getLayout() != null) {
|
||||||
private void updateHeaderIconsOpacity() {
|
int scroll = connectionLog.getLayout().getLineTop(connectionLog.getLineCount()) - connectionLog.getHeight();
|
||||||
boolean hasAllControllerPerms = hasNotifPermission() && hasTermuxPermission() && hasBatteryPermission() && hasStoragePermission();
|
if (scroll > 0) connectionLog.scrollTo(0, scroll);
|
||||||
boolean hasTermuxStorage = hasTermuxStoragePermission();
|
|
||||||
|
|
||||||
// If any vital permission is missing, dim the icons to 40% opacity (0.4f)
|
|
||||||
boolean allPerfect = hasAllControllerPerms && hasTermuxStorage;
|
|
||||||
float targetAlpha = allPerfect ? 1.0f : 0.4f;
|
|
||||||
|
|
||||||
if (btnSettings != null) btnSettings.setAlpha(targetAlpha);
|
|
||||||
if (headerIcon != null) headerIcon.setAlpha(targetAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasNotifPermission() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
||||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasTermuxPermission() {
|
|
||||||
return ContextCompat.checkSelfPermission(this, TERMUX_PERMISSION) == PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasBatteryPermission() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
|
||||||
return pm != null && pm.isIgnoringBatteryOptimizations(getPackageName());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasTermuxStoragePermission() {
|
|
||||||
try {
|
|
||||||
int result = getPackageManager().checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE, "com.termux");
|
|
||||||
if (result == PackageManager.PERMISSION_GRANTED) return true;
|
|
||||||
|
|
||||||
// Fallback: If Android denies the package query, check if the directory actually exists
|
|
||||||
File stateDir = new File(android.os.Environment.getExternalStorageDirectory(), ".iiab_state");
|
|
||||||
return stateDir.exists();
|
|
||||||
} catch (Exception e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasStoragePermission() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
||||||
return Environment.isExternalStorageManager();
|
|
||||||
} else {
|
|
||||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : MainPagerAdapter.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Main Pager Adapter
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
|
||||||
|
|
||||||
public class MainPagerAdapter extends FragmentStateAdapter {
|
|
||||||
|
|
||||||
public MainPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
|
|
||||||
super(fragmentActivity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Fragment createFragment(int position) {
|
|
||||||
switch (position) {
|
|
||||||
case 0:
|
|
||||||
return new DashboardFragment();
|
|
||||||
case 1:
|
|
||||||
return new UsageFragment();
|
|
||||||
case 2:
|
|
||||||
return new DeployFragment();
|
|
||||||
default:
|
|
||||||
return new DashboardFragment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : PortalActivity.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Webview portal activity
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
============================================================================
|
============================================================================
|
||||||
Name : Preferences.java
|
Name : Preferences.java
|
||||||
Author : hev <r@hev.cc>
|
Author : hev <r@hev.cc>
|
||||||
Contributors: IIAB Project
|
|
||||||
Copyright : Copyright (c) 2023 xyz
|
Copyright : Copyright (c) 2023 xyz
|
||||||
Copyright (c) 2026 IIAB Project
|
|
||||||
Description : Preferences
|
Description : Preferences
|
||||||
============================================================================
|
============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : ProgressButton.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Button animation helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : QrActivity.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : QR share content helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
============================================================================
|
============================================================================
|
||||||
Name : ServiceReceiver.java
|
Name : ServiceReceiver.java
|
||||||
Author : hev <r@hev.cc>
|
Author : hev <r@hev.cc>
|
||||||
Contributors: IIAB Project
|
|
||||||
Copyright : Copyright (c) 2023 xyz
|
Copyright : Copyright (c) 2023 xyz
|
||||||
Copyright (c) 2026 IIAB Project
|
|
||||||
Description : ServiceReceiver
|
Description : ServiceReceiver
|
||||||
============================================================================
|
============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : SetupActivity.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Setup permission table helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
|
@ -17,7 +9,6 @@ import android.net.Uri;
|
||||||
import android.net.VpnService;
|
import android.net.VpnService;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -37,15 +28,13 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final String TERMUX_PERMISSION = "com.termux.permission.RUN_COMMAND";
|
private static final String TERMUX_PERMISSION = "com.termux.permission.RUN_COMMAND";
|
||||||
|
|
||||||
private SwitchCompat switchNotif, switchTermux, switchStorage, switchVpn, switchBattery;
|
private SwitchCompat switchNotif, switchTermux, switchVpn, switchBattery;
|
||||||
private Button btnContinue;
|
private Button btnContinue;
|
||||||
private Button btnManageAll;
|
private Button btnManageAll;
|
||||||
private Button btnTermuxOverlay;
|
private Button btnTermuxOverlay;
|
||||||
private Button btnTermuxStorage;
|
|
||||||
private Button btnManageTermux;
|
private Button btnManageTermux;
|
||||||
|
|
||||||
private ActivityResultLauncher<String> requestPermissionLauncher;
|
private ActivityResultLauncher<String> requestPermissionLauncher;
|
||||||
private ActivityResultLauncher<Intent> storageLauncher;
|
|
||||||
private ActivityResultLauncher<Intent> vpnLauncher;
|
private ActivityResultLauncher<Intent> vpnLauncher;
|
||||||
private ActivityResultLauncher<Intent> batteryLauncher;
|
private ActivityResultLauncher<Intent> batteryLauncher;
|
||||||
|
|
||||||
|
|
@ -59,13 +48,11 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
|
|
||||||
switchNotif = findViewById(R.id.switch_perm_notifications);
|
switchNotif = findViewById(R.id.switch_perm_notifications);
|
||||||
switchTermux = findViewById(R.id.switch_perm_termux);
|
switchTermux = findViewById(R.id.switch_perm_termux);
|
||||||
switchStorage = findViewById(R.id.switch_perm_storage);
|
|
||||||
switchVpn = findViewById(R.id.switch_perm_vpn);
|
switchVpn = findViewById(R.id.switch_perm_vpn);
|
||||||
switchBattery = findViewById(R.id.switch_perm_battery);
|
switchBattery = findViewById(R.id.switch_perm_battery);
|
||||||
btnContinue = findViewById(R.id.btn_setup_continue);
|
btnContinue = findViewById(R.id.btn_setup_continue);
|
||||||
btnManageAll = findViewById(R.id.btn_manage_all);
|
btnManageAll = findViewById(R.id.btn_manage_all);
|
||||||
btnTermuxOverlay = findViewById(R.id.btn_termux_overlay);
|
btnTermuxOverlay = findViewById(R.id.btn_termux_overlay);
|
||||||
btnTermuxStorage = findViewById(R.id.btn_termux_storage);
|
|
||||||
btnManageTermux = findViewById(R.id.btn_manage_termux);
|
btnManageTermux = findViewById(R.id.btn_manage_termux);
|
||||||
|
|
||||||
// Hide Notification switch if Android < 13
|
// Hide Notification switch if Android < 13
|
||||||
|
|
@ -78,11 +65,9 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
checkAllPermissions();
|
checkAllPermissions();
|
||||||
|
|
||||||
btnContinue.setOnClickListener(v -> {
|
btnContinue.setOnClickListener(v -> {
|
||||||
// Tell bash that permissions are handled
|
|
||||||
writeTermuxPermissionFlags();
|
|
||||||
// Save flag so we don't show this screen again
|
// Save flag so we don't show this screen again
|
||||||
SharedPreferences prefs = getSharedPreferences(getString(R.string.pref_file_internal), Context.MODE_PRIVATE);
|
SharedPreferences prefs = getSharedPreferences("IIAB_Internal", Context.MODE_PRIVATE);
|
||||||
prefs.edit().putBoolean(getString(R.string.pref_key_setup_complete), true).apply();
|
prefs.edit().putBoolean("setup_complete", true).apply();
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
});
|
});
|
||||||
|
|
@ -94,11 +79,6 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
isGranted -> checkAllPermissions()
|
isGranted -> checkAllPermissions()
|
||||||
);
|
);
|
||||||
|
|
||||||
storageLauncher = registerForActivityResult(
|
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
|
||||||
result -> checkAllPermissions()
|
|
||||||
);
|
|
||||||
|
|
||||||
vpnLauncher = registerForActivityResult(
|
vpnLauncher = registerForActivityResult(
|
||||||
new ActivityResultContracts.StartActivityForResult(),
|
new ActivityResultContracts.StartActivityForResult(),
|
||||||
result -> checkAllPermissions()
|
result -> checkAllPermissions()
|
||||||
|
|
@ -135,30 +115,6 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
switchTermux.setChecked(false);
|
switchTermux.setChecked(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
switchStorage.setOnClickListener(v -> {
|
|
||||||
if (hasStoragePermission()) {
|
|
||||||
handleRevokeAttempt(v);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (switchStorage.isChecked()) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
||||||
try {
|
|
||||||
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
|
|
||||||
intent.addCategory("android.intent.category.DEFAULT");
|
|
||||||
intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName())));
|
|
||||||
storageLauncher.launch(intent);
|
|
||||||
} catch (Exception e) {
|
|
||||||
Intent intent = new Intent();
|
|
||||||
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
|
|
||||||
storageLauncher.launch(intent);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
switchStorage.setChecked(false); // Force visual state back until system confirms
|
|
||||||
});
|
|
||||||
|
|
||||||
switchVpn.setOnClickListener(v -> {
|
switchVpn.setOnClickListener(v -> {
|
||||||
if (hasVpnPermission()) {
|
if (hasVpnPermission()) {
|
||||||
handleRevokeAttempt(v);
|
handleRevokeAttempt(v);
|
||||||
|
|
@ -202,18 +158,6 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Direct access to Termux settings to grant Files/Storage permission
|
|
||||||
btnTermuxStorage.setOnClickListener(v -> {
|
|
||||||
try {
|
|
||||||
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
||||||
intent.setData(Uri.parse("package:com.termux"));
|
|
||||||
startActivity(intent);
|
|
||||||
// Toast.makeText(this, "Please go to Permissions and allow Storage/Files", Toast.LENGTH_LONG).show();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Snackbar.make(v, R.string.termux_not_installed_error, Snackbar.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Direct access to Controller settings (Reuses the method from Phase 1)
|
// Direct access to Controller settings (Reuses the method from Phase 1)
|
||||||
btnManageTermux.setOnClickListener(v -> {
|
btnManageTermux.setOnClickListener(v -> {
|
||||||
try {
|
try {
|
||||||
|
|
@ -258,17 +202,15 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
private void checkAllPermissions() {
|
private void checkAllPermissions() {
|
||||||
boolean notif = hasNotifPermission();
|
boolean notif = hasNotifPermission();
|
||||||
boolean termux = hasTermuxPermission();
|
boolean termux = hasTermuxPermission();
|
||||||
boolean storage = hasStoragePermission();
|
|
||||||
boolean vpn = hasVpnPermission();
|
boolean vpn = hasVpnPermission();
|
||||||
boolean battery = hasBatteryPermission();
|
boolean battery = hasBatteryPermission();
|
||||||
|
|
||||||
switchNotif.setChecked(notif);
|
switchNotif.setChecked(notif);
|
||||||
switchTermux.setChecked(termux);
|
switchTermux.setChecked(termux);
|
||||||
switchStorage.setChecked(storage);
|
|
||||||
switchVpn.setChecked(vpn);
|
switchVpn.setChecked(vpn);
|
||||||
switchBattery.setChecked(battery);
|
switchBattery.setChecked(battery);
|
||||||
|
|
||||||
boolean allGranted = termux && storage && vpn && battery;
|
boolean allGranted = termux && vpn && battery;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
allGranted = allGranted && notif;
|
allGranted = allGranted && notif;
|
||||||
}
|
}
|
||||||
|
|
@ -300,25 +242,4 @@ public class SetupActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasStoragePermission() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
||||||
return Environment.isExternalStorageManager();
|
|
||||||
} else {
|
|
||||||
return ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void writeTermuxPermissionFlags() {
|
|
||||||
java.io.File stateDir = new java.io.File(android.os.Environment.getExternalStorageDirectory(), ".iiab_state");
|
|
||||||
if (!stateDir.exists()) {
|
|
||||||
stateDir.mkdirs();
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
new java.io.File(stateDir, "flag_perm_battery").createNewFile();
|
|
||||||
new java.io.File(stateDir, "flag_perm_overlay").createNewFile();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@
|
||||||
============================================================================
|
============================================================================
|
||||||
Name : TProxyService.java
|
Name : TProxyService.java
|
||||||
Author : hev <r@hev.cc>
|
Author : hev <r@hev.cc>
|
||||||
Contributors: IIAB Project
|
|
||||||
Copyright : Copyright (c) 2024 xyz
|
Copyright : Copyright (c) 2024 xyz
|
||||||
Copyright (c) 2026 IIAB Project
|
|
||||||
Description : TProxy Service with integrated Watchdog
|
Description : TProxy Service with integrated Watchdog
|
||||||
============================================================================
|
============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : TermuxCallbackReceiver.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Termux callback helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
|
|
||||||
|
|
@ -1,495 +0,0 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : UsageFragment.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Usage Fragment Activity
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ClipData;
|
|
||||||
import android.content.ClipboardManager;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.method.ScrollingMovementMethod;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.animation.ObjectAnimator;
|
|
||||||
import android.animation.PropertyValuesHolder;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class UsageFragment extends Fragment implements View.OnClickListener {
|
|
||||||
|
|
||||||
private MainActivity mainActivity;
|
|
||||||
// INTERFACE VARS
|
|
||||||
private EditText edittext_socks_addr, edittext_socks_udp_addr, edittext_socks_port, edittext_socks_user, edittext_socks_pass, edittext_dns_ipv4, edittext_dns_ipv6;
|
|
||||||
private CheckBox checkbox_udp_in_tcp, checkbox_remote_dns, checkbox_global, checkbox_maintenance, checkbox_ipv4, checkbox_ipv6;
|
|
||||||
private TextView textview_maintenance_warning, configLabel, advConfigLabel, logLabel, logWarning, logSizeText, connectionLog;
|
|
||||||
private Button button_apps, button_save, button_control, button_browse_content, watchdogControl, btnClearLog, btnCopyLog;
|
|
||||||
private LinearLayout logActions, configLayout, advancedConfig, deckContainer;
|
|
||||||
private ProgressBar logProgress;
|
|
||||||
private ProgressButton btnServerControl;
|
|
||||||
|
|
||||||
private ObjectAnimator fusionAnimator;
|
|
||||||
private DashboardManager dashboardManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(@NonNull Context context) {
|
|
||||||
super.onAttach(context);
|
|
||||||
if (context instanceof MainActivity) {
|
|
||||||
mainActivity = (MainActivity) context;
|
|
||||||
mainActivity.setUsageFragment(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.fragment_usage, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
|
|
||||||
// UI Bindings
|
|
||||||
edittext_socks_addr = view.findViewById(R.id.socks_addr);
|
|
||||||
edittext_socks_udp_addr = view.findViewById(R.id.socks_udp_addr);
|
|
||||||
edittext_socks_port = view.findViewById(R.id.socks_port);
|
|
||||||
edittext_socks_user = view.findViewById(R.id.socks_user);
|
|
||||||
edittext_socks_pass = view.findViewById(R.id.socks_pass);
|
|
||||||
edittext_dns_ipv4 = view.findViewById(R.id.dns_ipv4);
|
|
||||||
edittext_dns_ipv6 = view.findViewById(R.id.dns_ipv6);
|
|
||||||
checkbox_ipv4 = view.findViewById(R.id.ipv4);
|
|
||||||
checkbox_ipv6 = view.findViewById(R.id.ipv6);
|
|
||||||
checkbox_global = view.findViewById(R.id.global);
|
|
||||||
checkbox_udp_in_tcp = view.findViewById(R.id.udp_in_tcp);
|
|
||||||
checkbox_remote_dns = view.findViewById(R.id.remote_dns);
|
|
||||||
checkbox_maintenance = view.findViewById(R.id.checkbox_maintenance);
|
|
||||||
textview_maintenance_warning = view.findViewById(R.id.maintenance_warning);
|
|
||||||
button_apps = view.findViewById(R.id.apps);
|
|
||||||
button_save = view.findViewById(R.id.save);
|
|
||||||
button_control = view.findViewById(R.id.control);
|
|
||||||
button_browse_content = view.findViewById(R.id.btnBrowseContent);
|
|
||||||
watchdogControl = view.findViewById(R.id.watchdog_control);
|
|
||||||
|
|
||||||
logActions = view.findViewById(R.id.log_actions);
|
|
||||||
btnClearLog = view.findViewById(R.id.btn_clear_log);
|
|
||||||
btnCopyLog = view.findViewById(R.id.btn_copy_log);
|
|
||||||
connectionLog = view.findViewById(R.id.connection_log);
|
|
||||||
logProgress = view.findViewById(R.id.log_progress);
|
|
||||||
logWarning = view.findViewById(R.id.log_warning_text);
|
|
||||||
logSizeText = view.findViewById(R.id.log_size_text);
|
|
||||||
configLayout = view.findViewById(R.id.config_layout);
|
|
||||||
configLabel = view.findViewById(R.id.config_label);
|
|
||||||
advancedConfig = view.findViewById(R.id.advanced_config);
|
|
||||||
advConfigLabel = view.findViewById(R.id.adv_config_label);
|
|
||||||
logLabel = view.findViewById(R.id.log_label);
|
|
||||||
|
|
||||||
deckContainer = view.findViewById(R.id.deck_container);
|
|
||||||
btnServerControl = view.findViewById(R.id.btn_server_control);
|
|
||||||
|
|
||||||
dashboardManager = new DashboardManager(requireActivity(), view, () -> {
|
|
||||||
mainActivity.handleControlClick();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Listeners
|
|
||||||
watchdogControl.setOnClickListener(v -> {
|
|
||||||
if (mainActivity.currentSystemState == DashboardFragment.SystemState.NONE) {
|
|
||||||
Snackbar.make(v, R.string.termux_not_installed_error, Snackbar.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mainActivity.handleWatchdogClick();
|
|
||||||
});
|
|
||||||
button_control.setOnClickListener(v -> mainActivity.handleControlClick());
|
|
||||||
button_browse_content.setOnClickListener(v -> mainActivity.handleBrowseContentClick(v));
|
|
||||||
btnClearLog.setOnClickListener(this);
|
|
||||||
btnCopyLog.setOnClickListener(this);
|
|
||||||
configLabel.setOnClickListener(v -> handleConfigToggle());
|
|
||||||
advConfigLabel.setOnClickListener(v -> toggleVisibility(advancedConfig, advConfigLabel, getString(R.string.advanced_settings_label)));
|
|
||||||
logLabel.setOnClickListener(v -> handleLogToggle());
|
|
||||||
checkbox_udp_in_tcp.setOnClickListener(this);
|
|
||||||
checkbox_remote_dns.setOnClickListener(this);
|
|
||||||
checkbox_global.setOnClickListener(this);
|
|
||||||
checkbox_maintenance.setOnClickListener(this);
|
|
||||||
button_apps.setOnClickListener(this);
|
|
||||||
button_save.setOnClickListener(this);
|
|
||||||
|
|
||||||
btnServerControl.setOnClickListener(v -> {
|
|
||||||
// --- Intercept based on State Machine ---
|
|
||||||
DashboardFragment.SystemState state = mainActivity.currentSystemState;
|
|
||||||
boolean isFullyInstalled = (state == DashboardFragment.SystemState.ONLINE || state == DashboardFragment.SystemState.OFFLINE);
|
|
||||||
|
|
||||||
if (!isFullyInstalled) {
|
|
||||||
Snackbar.make(v, R.string.server_not_installed_warning, 6000).show();
|
|
||||||
return; // Stop execution here
|
|
||||||
}
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
if (mainActivity.targetServerState != null) return;
|
|
||||||
|
|
||||||
mainActivity.serverTransitionText = !mainActivity.isServerAlive ? getString(R.string.server_booting) : getString(R.string.server_shutting_down);
|
|
||||||
mainActivity.targetServerState = !mainActivity.isServerAlive;
|
|
||||||
|
|
||||||
updateUIColorsAndVisibility();
|
|
||||||
btnServerControl.startProgress();
|
|
||||||
|
|
||||||
mainActivity.handleServerLaunchClick(v);
|
|
||||||
});
|
|
||||||
|
|
||||||
connectionLog.setMovementMethod(new ScrollingMovementMethod());
|
|
||||||
connectionLog.setTextIsSelectable(true);
|
|
||||||
connectionLog.setOnTouchListener((v, event) -> {
|
|
||||||
v.getParent().requestDisallowInterceptTouchEvent(true);
|
|
||||||
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
|
||||||
v.getParent().requestDisallowInterceptTouchEvent(false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
updateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (v == checkbox_global || v == checkbox_remote_dns || v == checkbox_maintenance) {
|
|
||||||
mainActivity.savePrefs();
|
|
||||||
updateUI();
|
|
||||||
} else if (v == button_apps) {
|
|
||||||
startActivity(new Intent(requireContext(), AppListActivity.class));
|
|
||||||
} else if (v.getId() == R.id.save) {
|
|
||||||
mainActivity.savePrefs();
|
|
||||||
Toast.makeText(requireContext(), R.string.saved_toast, Toast.LENGTH_SHORT).show();
|
|
||||||
addToLog(getString(R.string.settings_saved));
|
|
||||||
} else if (v.getId() == R.id.btn_clear_log) {
|
|
||||||
showResetLogConfirmation();
|
|
||||||
} else if (v.getId() == R.id.btn_copy_log) {
|
|
||||||
ClipboardManager clipboard = (ClipboardManager) requireContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
|
||||||
ClipData clip = ClipData.newPlainText("IIAB Log", connectionLog.getText().toString());
|
|
||||||
if (clipboard != null) {
|
|
||||||
clipboard.setPrimaryClip(clip);
|
|
||||||
Toast.makeText(requireContext(), R.string.log_copied_toast, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateUI() {
|
|
||||||
if (button_control == null) return;
|
|
||||||
|
|
||||||
boolean vpnActive = mainActivity.prefs.getEnable();
|
|
||||||
boolean watchdogActive = mainActivity.prefs.getWatchdogEnable();
|
|
||||||
|
|
||||||
if (dashboardManager != null) dashboardManager.setTunnelState(vpnActive, mainActivity.isProxyDegraded);
|
|
||||||
|
|
||||||
if (vpnActive) {
|
|
||||||
button_control.setText(R.string.control_disable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_on));
|
|
||||||
} else {
|
|
||||||
button_control.setText(R.string.control_enable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_off));
|
|
||||||
}
|
|
||||||
if (watchdogActive) {
|
|
||||||
watchdogControl.setText(R.string.watchdog_disable);
|
|
||||||
} else {
|
|
||||||
watchdogControl.setText(R.string.watchdog_enable);
|
|
||||||
}
|
|
||||||
edittext_socks_addr.setText(mainActivity.prefs.getSocksAddress());
|
|
||||||
edittext_socks_udp_addr.setText(mainActivity.prefs.getSocksUdpAddress());
|
|
||||||
edittext_socks_port.setText(String.valueOf(mainActivity.prefs.getSocksPort()));
|
|
||||||
edittext_socks_user.setText(mainActivity.prefs.getSocksUsername());
|
|
||||||
edittext_socks_pass.setText(mainActivity.prefs.getSocksPassword());
|
|
||||||
edittext_dns_ipv4.setText(mainActivity.prefs.getDnsIpv4());
|
|
||||||
edittext_dns_ipv6.setText(mainActivity.prefs.getDnsIpv6());
|
|
||||||
checkbox_ipv4.setChecked(mainActivity.prefs.getIpv4());
|
|
||||||
checkbox_ipv6.setChecked(mainActivity.prefs.getIpv6());
|
|
||||||
checkbox_global.setChecked(mainActivity.prefs.getGlobal());
|
|
||||||
checkbox_udp_in_tcp.setChecked(mainActivity.prefs.getUdpInTcp());
|
|
||||||
checkbox_remote_dns.setChecked(mainActivity.prefs.getRemoteDns());
|
|
||||||
checkbox_maintenance.setChecked(mainActivity.prefs.getMaintenanceMode());
|
|
||||||
boolean editable = !vpnActive;
|
|
||||||
edittext_socks_addr.setEnabled(editable);
|
|
||||||
edittext_socks_port.setEnabled(editable);
|
|
||||||
button_save.setEnabled(editable);
|
|
||||||
|
|
||||||
checkbox_maintenance.setEnabled(editable);
|
|
||||||
if (textview_maintenance_warning != null) {
|
|
||||||
textview_maintenance_warning.setVisibility(vpnActive ? View.VISIBLE : View.GONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateUIColorsAndVisibility() {
|
|
||||||
if (!isAdded() || getContext() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (button_control == null) return;
|
|
||||||
|
|
||||||
boolean isVpnActive = mainActivity.prefs.getEnable();
|
|
||||||
boolean isWatchdogOn = mainActivity.prefs.getWatchdogEnable();
|
|
||||||
|
|
||||||
if (dashboardManager != null) {
|
|
||||||
dashboardManager.setTunnelState(isVpnActive, mainActivity.isProxyDegraded);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Main VPN Button
|
|
||||||
if (!mainActivity.isServerAlive) {
|
|
||||||
if (isVpnActive) {
|
|
||||||
button_control.setText(R.string.control_disable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_on_dim));
|
|
||||||
} else {
|
|
||||||
button_control.setText(R.string.control_enable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_off_dim));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
button_control.setEnabled(true);
|
|
||||||
if (isVpnActive) {
|
|
||||||
button_control.setText(R.string.control_disable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_on));
|
|
||||||
} else {
|
|
||||||
button_control.setText(R.string.control_enable);
|
|
||||||
button_control.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_vpn_off));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Explore Button
|
|
||||||
button_browse_content.setVisibility(View.VISIBLE);
|
|
||||||
if (!mainActivity.isServerAlive) {
|
|
||||||
button_browse_content.setEnabled(true);
|
|
||||||
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_explore_disabled));
|
|
||||||
button_browse_content.setAlpha(1.0f);
|
|
||||||
button_browse_content.setTextColor(Color.parseColor("#888888"));
|
|
||||||
} else if (mainActivity.isNegotiating) {
|
|
||||||
button_browse_content.setEnabled(true);
|
|
||||||
button_browse_content.setTextColor(Color.WHITE);
|
|
||||||
} else {
|
|
||||||
button_browse_content.setEnabled(true);
|
|
||||||
button_browse_content.setTextColor(Color.WHITE);
|
|
||||||
button_browse_content.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_explore_ready));
|
|
||||||
|
|
||||||
if (isVpnActive && !mainActivity.isProxyDegraded) {
|
|
||||||
button_browse_content.setAlpha(1.0f);
|
|
||||||
} else {
|
|
||||||
button_browse_content.setAlpha(0.6f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server Control Logic
|
|
||||||
DashboardFragment.SystemState state = mainActivity.currentSystemState;
|
|
||||||
boolean isFullyInstalled = (state == DashboardFragment.SystemState.ONLINE || state == DashboardFragment.SystemState.OFFLINE);
|
|
||||||
|
|
||||||
if (!isFullyInstalled) {
|
|
||||||
// SYSTEM NOT READY: Gray out the button
|
|
||||||
btnServerControl.setAlpha(0.6f);
|
|
||||||
btnServerControl.setText(R.string.launch_server);
|
|
||||||
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_explore_disabled));
|
|
||||||
|
|
||||||
// Also gray out the watchdog since the server isn't installed
|
|
||||||
deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_watchdog_off));
|
|
||||||
|
|
||||||
} else if (mainActivity.targetServerState != null) {
|
|
||||||
// TRANSITIONING STATE
|
|
||||||
btnServerControl.setAlpha(0.6f);
|
|
||||||
btnServerControl.setText(mainActivity.serverTransitionText);
|
|
||||||
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_explore_disabled));
|
|
||||||
} else {
|
|
||||||
// SYSTEM READY: Normal behavior
|
|
||||||
btnServerControl.setAlpha(1.0f);
|
|
||||||
if (mainActivity.isServerAlive) {
|
|
||||||
btnServerControl.setText(R.string.stop_server);
|
|
||||||
if (isWatchdogOn) {
|
|
||||||
deckContainer.setBackgroundColor(Color.parseColor("#44FF9800"));
|
|
||||||
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_watchdog_on));
|
|
||||||
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_watchdog_on));
|
|
||||||
} else {
|
|
||||||
if (fusionAnimator == null || !fusionAnimator.isRunning()) deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_danger));
|
|
||||||
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_watchdog_off));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deckContainer.setBackgroundColor(Color.TRANSPARENT);
|
|
||||||
btnServerControl.setText(R.string.launch_server);
|
|
||||||
btnServerControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), R.color.btn_success));
|
|
||||||
watchdogControl.setBackgroundTintList(ContextCompat.getColorStateList(requireContext(), isWatchdogOn ? R.color.btn_watchdog_on : R.color.btn_watchdog_off));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopBtnProgress() {
|
|
||||||
btnServerControl.stopProgress();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startFusionPulse() {
|
|
||||||
deckContainer.setBackgroundColor(Color.parseColor("#44FF9800"));
|
|
||||||
if (fusionAnimator != null && fusionAnimator.isRunning()) fusionAnimator.cancel();
|
|
||||||
fusionAnimator = ObjectAnimator.ofFloat(deckContainer, "alpha", 1f, 0.4f);
|
|
||||||
fusionAnimator.setDuration(600);
|
|
||||||
fusionAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
|
||||||
fusionAnimator.setRepeatMode(ObjectAnimator.REVERSE);
|
|
||||||
fusionAnimator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startExitPulse() {
|
|
||||||
if (fusionAnimator != null && fusionAnimator.isRunning()) fusionAnimator.cancel();
|
|
||||||
fusionAnimator = ObjectAnimator.ofFloat(deckContainer, "alpha", deckContainer.getAlpha(), 0.3f);
|
|
||||||
fusionAnimator.setDuration(800);
|
|
||||||
fusionAnimator.setRepeatCount(ObjectAnimator.INFINITE);
|
|
||||||
fusionAnimator.setRepeatMode(ObjectAnimator.REVERSE);
|
|
||||||
fusionAnimator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finalizeEntryPulse() {
|
|
||||||
if (fusionAnimator != null) fusionAnimator.cancel();
|
|
||||||
deckContainer.setAlpha(1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finalizeExitPulse() {
|
|
||||||
if (fusionAnimator != null) fusionAnimator.cancel();
|
|
||||||
deckContainer.animate().alpha(1f).setDuration(300).withEndAction(() -> deckContainer.setBackgroundColor(Color.TRANSPARENT)).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addToLog(String message) {
|
|
||||||
requireActivity().runOnUiThread(() -> {
|
|
||||||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
|
|
||||||
String currentTime = sdf.format(new Date());
|
|
||||||
String logEntry = "[" + currentTime + "] " + message + "\n";
|
|
||||||
if (connectionLog != null) {
|
|
||||||
connectionLog.append(logEntry);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scrollToBottom() {
|
|
||||||
if (connectionLog != null && connectionLog.getLayout() != null) {
|
|
||||||
int scroll = connectionLog.getLayout().getLineTop(connectionLog.getLineCount()) - connectionLog.getHeight();
|
|
||||||
if (scroll > 0) connectionLog.scrollTo(0, scroll);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateLogSizeUI() {
|
|
||||||
if (logSizeText == null) return;
|
|
||||||
String sizeStr = LogManager.getFormattedSize(requireContext());
|
|
||||||
logSizeText.setText(getString(R.string.log_size_format, sizeStr));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateConnectivityLeds(boolean wifiOn, boolean hotspotOn) {
|
|
||||||
if (dashboardManager != null) {
|
|
||||||
dashboardManager.updateConnectivityLeds(wifiOn, hotspotOn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLogVisible() {
|
|
||||||
return connectionLog != null && connectionLog.getVisibility() == View.VISIBLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleLogToggle() {
|
|
||||||
boolean isOpening = connectionLog.getVisibility() == View.GONE;
|
|
||||||
if (isOpening) {
|
|
||||||
if (mainActivity.isReadingLogs) return;
|
|
||||||
mainActivity.isReadingLogs = true;
|
|
||||||
if (logProgress != null) logProgress.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
LogManager.readLogsAsync(requireContext(), (logContent, isRapidGrowth) -> {
|
|
||||||
if (connectionLog != null) {
|
|
||||||
connectionLog.setText(logContent);
|
|
||||||
scrollToBottom();
|
|
||||||
}
|
|
||||||
if (logProgress != null) logProgress.setVisibility(View.GONE);
|
|
||||||
if (logWarning != null) logWarning.setVisibility(isRapidGrowth ? View.VISIBLE : View.GONE);
|
|
||||||
updateLogSizeUI();
|
|
||||||
mainActivity.isReadingLogs = false;
|
|
||||||
});
|
|
||||||
mainActivity.startLogSizeUpdates();
|
|
||||||
} else {
|
|
||||||
mainActivity.stopLogSizeUpdates();
|
|
||||||
}
|
|
||||||
toggleVisibility(connectionLog, logLabel, getString(R.string.connection_log_label));
|
|
||||||
logActions.setVisibility(connectionLog.getVisibility());
|
|
||||||
if (logSizeText != null) logSizeText.setVisibility(connectionLog.getVisibility());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleConfigToggle() {
|
|
||||||
if (configLayout.getVisibility() == View.GONE) {
|
|
||||||
if (BiometricHelper.isDeviceSecure(requireContext())) {
|
|
||||||
BiometricHelper.prompt((androidx.appcompat.app.AppCompatActivity) requireActivity(),
|
|
||||||
getString(R.string.auth_required_title),
|
|
||||||
getString(R.string.auth_required_subtitle),
|
|
||||||
() -> toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label)));
|
|
||||||
} else {
|
|
||||||
BiometricHelper.showEnrollmentDialog(requireContext());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
toggleVisibility(configLayout, configLabel, getString(R.string.advanced_settings_label));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void toggleVisibility(View view, TextView label, String text) {
|
|
||||||
boolean isGone = view.getVisibility() == View.GONE;
|
|
||||||
view.setVisibility(isGone ? View.VISIBLE : View.GONE);
|
|
||||||
label.setText(String.format(getString(isGone ? R.string.label_separator_down : R.string.label_separator_up), text));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showResetLogConfirmation() {
|
|
||||||
new AlertDialog.Builder(requireContext())
|
|
||||||
.setTitle(R.string.log_reset_confirm_title)
|
|
||||||
.setMessage(R.string.log_reset_confirm_msg)
|
|
||||||
.setPositiveButton(R.string.reset_log, (dialog, which) -> {
|
|
||||||
LogManager.clearLogs(requireContext(), new LogManager.LogClearCallback() {
|
|
||||||
@Override
|
|
||||||
public void onSuccess() {
|
|
||||||
connectionLog.setText("");
|
|
||||||
addToLog(getString(R.string.log_reset_user));
|
|
||||||
if (logWarning != null) logWarning.setVisibility(View.GONE);
|
|
||||||
updateLogSizeUI();
|
|
||||||
Toast.makeText(requireContext(), R.string.log_cleared_toast, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void onError(String message) {
|
|
||||||
Toast.makeText(requireContext(), getString(R.string.failed_reset_log, message), Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.setNegativeButton(R.string.cancel, null).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void savePrefsFromUI() {
|
|
||||||
mainActivity.prefs.setSocksAddress("127.0.0.1");
|
|
||||||
mainActivity.prefs.setSocksPort(1080);
|
|
||||||
mainActivity.prefs.setSocksUdpAddress("");
|
|
||||||
mainActivity.prefs.setSocksUsername("");
|
|
||||||
mainActivity.prefs.setSocksPassword("");
|
|
||||||
mainActivity.prefs.setIpv4(true);
|
|
||||||
mainActivity.prefs.setIpv6(true);
|
|
||||||
mainActivity.prefs.setUdpInTcp(false);
|
|
||||||
mainActivity.prefs.setRemoteDns(true);
|
|
||||||
mainActivity.prefs.setGlobal(true);
|
|
||||||
|
|
||||||
mainActivity.prefs.setDnsIpv4(edittext_dns_ipv4.getText().toString());
|
|
||||||
mainActivity.prefs.setDnsIpv6(edittext_dns_ipv6.getText().toString());
|
|
||||||
mainActivity.prefs.setMaintenanceMode(checkbox_maintenance.isChecked());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : VpnRecoveryReceiver
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Button Tunnel helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,3 @@
|
||||||
/*
|
|
||||||
* ============================================================================
|
|
||||||
* Name : WatchdogService.java
|
|
||||||
* Author : IIAB Project
|
|
||||||
* Copyright : Copyright (c) 2026 IIAB Project
|
|
||||||
* Description : Watchdog service helper
|
|
||||||
* ============================================================================
|
|
||||||
*/
|
|
||||||
package org.iiab.controller;
|
package org.iiab.controller;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="960" android:viewportWidth="960" android:width="24dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M40,680L40,520L368,520L120,324L120,440L40,440L40,200L80,200L520,442L520,160L720,160L920,400L920,680L820,680Q820,730 785,765Q750,800 700,800Q650,800 615,765Q580,730 580,680L360,680Q360,730 325,765Q290,800 240,800Q190,800 155,765Q120,730 120,680L40,680ZM283,723Q300,706 300,680Q300,654 283,637Q266,620 240,620Q214,620 197,637Q180,654 180,680Q180,706 197,723Q214,740 240,740Q266,740 283,723ZM743,723Q760,706 760,680Q760,654 743,637Q726,620 700,620Q674,620 657,637Q640,654 640,680Q640,706 657,723Q674,740 700,740Q726,740 743,723ZM600,400L816,400L682,240L600,240L600,400Z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp" android:height="24dp"
|
|
||||||
android:viewportWidth="24" android:viewportHeight="24"
|
|
||||||
android:tint="?attr/colorPrimary">
|
|
||||||
<path android:fillColor="@android:color/white"
|
|
||||||
android:pathData="M12,2a3,3 0 0,0 -3,3v2L6.5,7a1.5,1.5 0 0,0 -1.5,1.5v1h14v-1A1.5,1.5 0 0,0 17.5,7L15,7V5A3,3 0 0,0 12,2M12,4a1,1 0 0,1 1,1v2h-2V5A1,1 0 0,1 12,4M4,11v9a2,2 0 0,0 2,2h12a2,2 0 0,0 2,-2v-9H4M11,13h2v7h-2v-7M7.5,13h1.5v5H7.5v-5M15,13h1.5v5H15v-5z"/>
|
|
||||||
</vector>
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<item android:id="@android:id/background">
|
|
||||||
<shape>
|
|
||||||
<corners android:radius="6dp" />
|
|
||||||
<solid android:color="@color/dash_bar_bg" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item android:id="@android:id/progress">
|
|
||||||
<clip>
|
|
||||||
<shape>
|
|
||||||
<corners android:radius="6dp" />
|
|
||||||
<solid android:color="#FFFFFF" /> </shape>
|
|
||||||
</clip>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
</layer-list>
|
|
||||||
|
|
@ -5,6 +5,8 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:attr/windowBackground">
|
android:background="?android:attr/windowBackground">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btn_setup_continue"
|
android:id="@+id/btn_setup_continue"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -71,17 +73,6 @@
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:theme="@style/PurpleSwitchTheme"/>
|
android:theme="@style/PurpleSwitchTheme"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
|
||||||
android:id="@+id/switch_perm_storage"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/setup_perm_storage"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:paddingVertical="12dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:theme="@style/PurpleSwitchTheme"/>
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<androidx.appcompat.widget.SwitchCompat
|
||||||
android:id="@+id/switch_perm_vpn"
|
android:id="@+id/switch_perm_vpn"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -107,7 +98,7 @@
|
||||||
android:id="@+id/btn_manage_all"
|
android:id="@+id/btn_manage_all"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/setup_manage_all_permissions"
|
android:text="Manage All Permissions"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:gravity="start|center_vertical"
|
android:gravity="start|center_vertical"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
|
@ -122,7 +113,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/setup_termux_custom_permissions"
|
android:text="Termux custom permissions"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
|
@ -132,17 +123,7 @@
|
||||||
android:id="@+id/btn_termux_overlay"
|
android:id="@+id/btn_termux_overlay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/setup_display_over_other_apps"
|
android:text="Display over other apps"
|
||||||
android:textAllCaps="false"
|
|
||||||
style="?android:attr/borderlessButtonStyle"
|
|
||||||
android:gravity="start|center_vertical"
|
|
||||||
android:textColor="@color/lightGray66" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_termux_storage"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/setup_termux_storage_btn"
|
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle"
|
||||||
android:gravity="start|center_vertical"
|
android:gravity="start|center_vertical"
|
||||||
|
|
@ -152,7 +133,7 @@
|
||||||
android:id="@+id/btn_manage_termux"
|
android:id="@+id/btn_manage_termux"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/setup_manage_termux_permissions"
|
android:text="Manage Termux permissions"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
style="?android:attr/borderlessButtonStyle"
|
style="?android:attr/borderlessButtonStyle"
|
||||||
android:gravity="start|center_vertical"
|
android:gravity="start|center_vertical"
|
||||||
|
|
|
||||||
|
|
@ -1,299 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="@color/dash_bg_main">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_device_name"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_device"
|
|
||||||
android:textSize="22sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/dash_text_primary"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/dash_module_bg"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:layout_marginBottom="0dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_wifi_ip"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_hotspot_ip"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_uptime"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_battery"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@color/dash_divider"
|
|
||||||
android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_marginBottom="8dp">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/dash_main_storage"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_storage"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="-- GB / -- GB"
|
|
||||||
android:textColor="@color/dash_text_secondary"
|
|
||||||
android:textSize="12sp"/>
|
|
||||||
</LinearLayout>
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/dash_progress_storage"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="12dp"
|
|
||||||
android:progressDrawable="@drawable/rounded_progress_bar"
|
|
||||||
android:progressTint="@color/dash_bar_storage"
|
|
||||||
android:progressBackgroundTint="@color/dash_bar_bg"
|
|
||||||
android:progress="0"
|
|
||||||
android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:baselineAligned="false">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginEnd="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_ram_memory"
|
|
||||||
android:textColor="@color/dash_text_primary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="1" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_ram"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="-- / --"
|
|
||||||
android:textColor="@color/dash_text_secondary"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_marginTop="2dp" />
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/dash_progress_ram"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:progressDrawable="@drawable/rounded_progress_bar"
|
|
||||||
android:progressTint="@color/dash_bar_ram"
|
|
||||||
android:progressBackgroundTint="@color/dash_bar_bg"
|
|
||||||
android:progress="0"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_marginStart="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_swap_virtual"
|
|
||||||
android:textColor="@color/dash_text_primary"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:maxLines="1" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_text_swap"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="-- / --"
|
|
||||||
android:textColor="@color/dash_text_secondary"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_marginTop="2dp" />
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/dash_progress_swap"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="8dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:progressDrawable="@drawable/rounded_progress_bar"
|
|
||||||
android:progressTint="@color/dash_bar_swap"
|
|
||||||
android:progressBackgroundTint="@color/dash_bar_bg"
|
|
||||||
android:progress="0"/>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_iiab_system"
|
|
||||||
android:textSize="22sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/dash_text_primary"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginBottom="8dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/dash_module_bg"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:layout_marginBottom="0dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:layout_marginBottom="12dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/dash_server_status"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_badge_status"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_offline"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="#555555"
|
|
||||||
android:textColor="@color/dash_text_primary"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:paddingHorizontal="8dp"
|
|
||||||
android:paddingVertical="4dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@color/dash_divider"
|
|
||||||
android:layout_marginBottom="12dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/dash_card_termux_state"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:gravity="center_vertical">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/led_termux_state"
|
|
||||||
android:layout_width="12dp"
|
|
||||||
android:layout_height="12dp"
|
|
||||||
android:background="@drawable/led_off"
|
|
||||||
android:layout_marginEnd="12dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/text_termux_state"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_termux_searching"
|
|
||||||
android:textColor="@color/dash_text_primary" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/dash_modules_title"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dash_installed_modules"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:paddingVertical="8dp"
|
|
||||||
android:paddingHorizontal="0dp"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/modules_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical">
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="24dp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
android:padding="24dp">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="120dp"
|
|
||||||
android:layout_height="120dp"
|
|
||||||
android:src="@drawable/ic_auto_towing"
|
|
||||||
app:tint="?android:attr/textColorPrimary" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/deploy_wip_title"
|
|
||||||
android:textSize="24sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:layout_marginTop="16dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/deploy_wip_desc"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:layout_marginTop="8dp"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
@ -1,411 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/dashboard_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="60dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_marginBottom="16dp"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/dash_module_bg" android:paddingHorizontal="8dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:baselineAligned="false">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/dash_wifi"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:padding="12dp">
|
|
||||||
<View
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:id="@+id/led_wifi"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@drawable/led_off" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/wifi"
|
|
||||||
android:textColor="@color/dash_text_primary" android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/dash_hotspot"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:padding="12dp">
|
|
||||||
<View
|
|
||||||
android:id="@+id/led_hotspot"
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@drawable/led_off" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/hotspot"
|
|
||||||
android:textColor="@color/dash_text_primary" android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/dash_tunnel"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:padding="12dp"
|
|
||||||
android:visibility="gone">
|
|
||||||
<View
|
|
||||||
android:id="@+id/led_tunnel"
|
|
||||||
android:layout_width="10dp"
|
|
||||||
android:layout_height="10dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:background="@drawable/led_on_green" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/tunnel"
|
|
||||||
android:textColor="@color/dash_text_primary" android:textStyle="bold" />
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/control"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="90dp"
|
|
||||||
android:layout_marginHorizontal="12dp"
|
|
||||||
android:text="@string/control_enable"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/btn_vpn_off"
|
|
||||||
android:textAllCaps="false"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/control_description"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="12dp"
|
|
||||||
android:text="@string/vpn_description"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="12dp"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btnBrowseContent"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="90dp"
|
|
||||||
android:layout_marginHorizontal="12dp" android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:text="@string/browse_content"
|
|
||||||
android:textSize="21sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/btn_explore_disabled"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:elevation="4dp"
|
|
||||||
android:enabled="false" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/config_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/advanced_settings_label"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:layout_marginTop="24dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:paddingVertical="8dp"
|
|
||||||
android:paddingHorizontal="0dp"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/config_layout"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:padding="16dp"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/dash_bg_card">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/apps"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/apps"
|
|
||||||
android:layout_marginBottom="12dp"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="#673AB7"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textAllCaps="false"/>
|
|
||||||
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/dns_ipv4" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
|
||||||
<EditText android:id="@+id/dns_ipv4" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/dns_ipv6" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
|
||||||
<EditText android:id="@+id/dns_ipv6" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/checkbox_maintenance"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/maintenance_mode"
|
|
||||||
android:checked="true" />
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/maintenance_warning"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/maintenance_warning_msg"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
android:textColor="#FF9800"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<Button android:id="@+id/save"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/save"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="#555555"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textAllCaps="false"/>
|
|
||||||
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_addr" android:textColor="?android:attr/textColorSecondary" android:textSize="12sp" android:visibility="gone"/>
|
|
||||||
<EditText android:id="@+id/socks_addr" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary" android:visibility="gone"/>
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_port" android:textColor="?android:attr/textColorSecondary" android:textSize="12sp" android:visibility="gone"/>
|
|
||||||
<EditText android:id="@+id/socks_port" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:inputType="number" android:textColor="?android:attr/textColorPrimary" android:visibility="gone"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/adv_config_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/advanced_settings_label"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/advanced_config"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_udp_addr" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
|
||||||
<EditText android:id="@+id/socks_udp_addr" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_user" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
|
||||||
<EditText android:id="@+id/socks_user" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
|
||||||
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_pass" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
|
||||||
<EditText android:id="@+id/socks_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:inputType="textPassword" android:textColor="?android:attr/textColorPrimary"/>
|
|
||||||
<CheckBox android:id="@+id/udp_in_tcp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/udp_in_tcp" android:textColor="?android:attr/textColorSecondary"/>
|
|
||||||
<CheckBox android:id="@+id/ipv4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/ipv4" android:textColor="?android:attr/textColorSecondary"/>
|
|
||||||
<CheckBox android:id="@+id/ipv6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/ipv6" android:textColor="?android:attr/textColorSecondary"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:visibility="gone">
|
|
||||||
|
|
||||||
<CheckBox android:id="@+id/remote_dns" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/remote_dns" android:textColor="?android:attr/textColorSecondary"/>
|
|
||||||
<CheckBox android:id="@+id/global" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/global" android:textColor="?android:attr/textColorSecondary"/>
|
|
||||||
</LinearLayout>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/deck_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="12dp"
|
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:background="#00000000"
|
|
||||||
android:padding="3dp"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:weightSum="2">
|
|
||||||
|
|
||||||
<org.iiab.controller.ProgressButton
|
|
||||||
android:id="@+id/btn_server_control"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="80dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginEnd="4dp"
|
|
||||||
android:text="Launch Server"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/btn_success"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
app:progressButtonHeight="6dp"
|
|
||||||
app:progressButtonDuration="@integer/server_cool_off_duration_ms"
|
|
||||||
app:progressButtonColor="#FF9800" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/watchdog_control"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="80dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:layout_marginStart="4dp"
|
|
||||||
android:text="@string/watchdog_enable"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:background="@drawable/rounded_button"
|
|
||||||
android:backgroundTint="@color/btn_watchdog_off"
|
|
||||||
android:textAllCaps="false"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/watchdog_description"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:layout_marginBottom="0dp"/>
|
|
||||||
|
|
||||||
<View android:layout_width="match_parent"
|
|
||||||
android:layout_height="1dp"
|
|
||||||
android:background="@color/divider_color"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:layout_marginBottom="0dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/log_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/connection_log_label"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textSize="18sp"
|
|
||||||
android:textColor="?android:attr/textColorPrimary"
|
|
||||||
android:layout_marginTop="24dp" android:layout_marginBottom="8dp"
|
|
||||||
android:paddingVertical="8dp"
|
|
||||||
android:paddingHorizontal="0dp"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/log_warning_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="@color/text_warning"
|
|
||||||
android:textSize="11sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:text="@string/log_warning_rapid_growth" />
|
|
||||||
|
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/log_progress"
|
|
||||||
style="?android:attr/progressBarStyleHorizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:indeterminate="true"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/connection_log"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="250dp"
|
|
||||||
android:background="#000000"
|
|
||||||
android:textColor="#00FF00"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
android:fadeScrollbars="false"
|
|
||||||
android:scrollbarSize="10dp"
|
|
||||||
android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
|
|
||||||
android:text="@string/system_ready"
|
|
||||||
android:textSize="11sp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/log_size_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="end"
|
|
||||||
android:textColor="?android:attr/textColorSecondary"
|
|
||||||
android:textSize="10sp"
|
|
||||||
android:paddingEnd="8dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:text="Size: 0KB / 10MB" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/log_actions"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:layout_marginTop="4dp">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_clear_log"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/reset_log"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:backgroundTint="@color/btn_danger"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:layout_marginEnd="4dp"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/btn_copy_log"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/copy_all"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:backgroundTint="@color/btn_success"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:layout_marginStart="4dp"/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="32dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?android:attr/windowBackground">
|
android:background="?android:attr/windowBackground">
|
||||||
|
|
||||||
|
<!-- Custom Header/Toolbar -->
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?android:attr/actionBarSize"
|
android:layout_height="?android:attr/actionBarSize"
|
||||||
|
|
@ -37,7 +38,7 @@
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:src="@drawable/ic_center_focus_strong"
|
android:src="@drawable/ic_center_focus_strong"
|
||||||
android:contentDescription="Share via QR"
|
android:contentDescription="Share via QR"
|
||||||
android:padding="12dp"
|
android:padding="10dp"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:tint="#FFFFFF" />
|
android:tint="#FFFFFF" />
|
||||||
|
|
||||||
|
|
@ -48,10 +49,11 @@
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:src="@drawable/ic_menu_preferences"
|
android:src="@drawable/ic_menu_preferences"
|
||||||
android:contentDescription="Settings"
|
android:contentDescription="Settings"
|
||||||
android:padding="12dp"
|
android:padding="10dp"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:tint="#FFFFFF" />
|
android:tint="#FFFFFF" />
|
||||||
|
|
||||||
|
<!-- Triple Toggle Theme ImageButton -->
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/theme_toggle"
|
android:id="@+id/theme_toggle"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
|
|
@ -59,37 +61,448 @@
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||||
android:src="@drawable/ic_theme_system"
|
android:src="@drawable/ic_theme_system"
|
||||||
android:contentDescription="Toggle Theme"
|
android:contentDescription="Toggle Theme"
|
||||||
android:padding="12dp"
|
android:padding="10dp"
|
||||||
android:scaleType="fitCenter"
|
android:scaleType="fitCenter"
|
||||||
android:tint="#FFFFFF" />
|
android:tint="#FFFFFF" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<ScrollView
|
||||||
android:id="@+id/tab_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:tabMode="fixed"
|
|
||||||
app:tabGravity="fill"
|
|
||||||
app:tabIndicatorColor="#FFFFFF"
|
|
||||||
app:tabIndicatorHeight="3dp"
|
|
||||||
app:tabSelectedTextColor="#FFFFFF"
|
|
||||||
app:tabTextColor="#888888"
|
|
||||||
app:tabTextAppearance="@style/CustomTabTextStyle"
|
|
||||||
android:background="#1A1A1A"/>
|
|
||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
|
||||||
android:id="@+id/view_pager"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1" />
|
android:layout_weight="1">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:id="@+id/version_text"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
android:padding="16dp">
|
||||||
android:text="v0.1.x"
|
|
||||||
android:textColor="@color/footer_text_color" android:textSize="11sp"
|
<LinearLayout
|
||||||
android:padding="8dp"
|
android:id="@+id/dashboard_container"
|
||||||
android:background="#1A1A1A" />
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="#1A1A1A"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/dash_wifi"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="12dp">
|
||||||
|
<View
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:id="@+id/led_wifi"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/led_off" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Wi-Fi"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/dash_hotspot"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="12dp">
|
||||||
|
<View
|
||||||
|
android:id="@+id/led_hotspot"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/led_off" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Hotspot"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/dash_tunnel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="?android:attr/selectableItemBackground"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
<View
|
||||||
|
android:id="@+id/led_tunnel"
|
||||||
|
android:layout_width="10dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:background="@drawable/led_on_green" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Tunnel"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- VPN Control Section -->
|
||||||
|
<Button
|
||||||
|
android:id="@+id/control"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:text="@string/control_enable"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="@color/btn_vpn_off"
|
||||||
|
android:textAllCaps="false"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/control_description"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/vpn_description"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="12dp"/>
|
||||||
|
|
||||||
|
<!-- Local WebView -->
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnBrowseContent"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:text="@string/browse_content"
|
||||||
|
android:textSize="21sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="@color/btn_explore_disabled"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:elevation="4dp"
|
||||||
|
android:enabled="false" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/config_label"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/advanced_settings_label"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:background="?attr/sectionHeaderBackground"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:layout_marginTop="20dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/config_layout"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:background="?attr/sectionBackground">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/apps"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/apps"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="#673AB7"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAllCaps="false"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/dns_ipv4"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="11sp"/>
|
||||||
|
<EditText android:id="@+id/dns_ipv4"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/dns_ipv6"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="11sp"/>
|
||||||
|
<EditText android:id="@+id/dns_ipv6"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/checkbox_maintenance"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:text="Maintenance Mode"
|
||||||
|
android:checked="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/maintenance_warning"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Disable Safe Pocket Web in order to modify"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<Button android:id="@+id/save"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/save"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="#555555"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAllCaps="false"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_addr" android:textColor="?android:attr/textColorSecondary" android:textSize="12sp" android:visibility="gone"/>
|
||||||
|
<EditText android:id="@+id/socks_addr" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary" android:visibility="gone"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_port" android:textColor="?android:attr/textColorSecondary" android:textSize="12sp" android:visibility="gone"/>
|
||||||
|
<EditText android:id="@+id/socks_port" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:inputType="number" android:textColor="?android:attr/textColorPrimary" android:visibility="gone"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/adv_config_label"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/advanced_settings_label"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/advanced_config"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_udp_addr" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
||||||
|
<EditText android:id="@+id/socks_udp_addr" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_user" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
||||||
|
<EditText android:id="@+id/socks_user" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/socks_pass" android:textColor="?android:attr/textColorSecondary" android:textSize="11sp"/>
|
||||||
|
<EditText android:id="@+id/socks_pass" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:inputType="textPassword" android:textColor="?android:attr/textColorPrimary"/>
|
||||||
|
|
||||||
|
<CheckBox android:id="@+id/udp_in_tcp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/udp_in_tcp" android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
<CheckBox android:id="@+id/ipv4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/ipv4" android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
<CheckBox android:id="@+id/ipv6" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/ipv6" android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
<CheckBox android:id="@+id/remote_dns" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/remote_dns" android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
<CheckBox android:id="@+id/global" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/global" android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- HR above Watchdog -->
|
||||||
|
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<!-- Watchdog Control Section -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/deck_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:background="#00000000"
|
||||||
|
android:padding="3dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<org.iiab.controller.ProgressButton
|
||||||
|
android:id="@+id/btn_server_control"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:text="Launch Server"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="@color/btn_success"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
|
||||||
|
app:progressButtonHeight="6dp"
|
||||||
|
app:progressButtonDuration="@integer/server_cool_off_duration_ms"
|
||||||
|
app:progressButtonColor="#FF9800" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/watchdog_control"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="80dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:text="@string/watchdog_enable"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:background="@drawable/rounded_button"
|
||||||
|
android:backgroundTint="@color/btn_watchdog_off"
|
||||||
|
android:textAllCaps="false"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/watchdog_description"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginVertical="20dp"/>
|
||||||
|
|
||||||
|
<!-- Log Section (Collapsible) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/log_label"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/connection_log_label"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:background="?attr/sectionHeaderBackground"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"/>
|
||||||
|
|
||||||
|
<!-- Log Warnings (Growth rate warning) -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/log_warning_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="@color/text_warning"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text="@string/log_warning_rapid_growth" />
|
||||||
|
|
||||||
|
<!-- Loading Indicator for Logs -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/log_progress"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/connection_log"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="250dp"
|
||||||
|
android:background="#000000"
|
||||||
|
android:textColor="#00FF00"
|
||||||
|
android:fontFamily="monospace"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:fadeScrollbars="false"
|
||||||
|
android:scrollbarSize="10dp"
|
||||||
|
android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
|
||||||
|
android:text="@string/system_ready"
|
||||||
|
android:textSize="11sp"/>
|
||||||
|
|
||||||
|
<!-- Log Size Indicator -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/log_size_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="end"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:text="Size: 0KB / 10MB" />
|
||||||
|
|
||||||
|
<!-- Log Actions Bar -->
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/log_actions"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginTop="4dp">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_clear_log"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/reset_log"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:backgroundTint="@color/btn_danger"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_marginEnd="4dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_copy_log"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/copy_all"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:backgroundTint="@color/btn_success"
|
||||||
|
android:textColor="#FFFFFF"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_marginStart="4dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Version Footer -->
|
||||||
|
<View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/divider_color" android:layout_marginTop="32dp" android:layout_marginBottom="8dp"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/version_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="v0.1.17alpha"
|
||||||
|
android:textColor="@color/text_muted"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:paddingBottom="16dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
@ -1,233 +1,155 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- General App -->
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
<string name="app_name">IIAB-oA Controller</string>
|
||||||
<string name="default_version">v0.1.x</string>
|
<string name="default_version">v0.1.x</string>
|
||||||
|
|
||||||
<string name="cancel">Cancelar</string>
|
|
||||||
<string name="copy_all">Copiar Todo</string>
|
|
||||||
<string name="fix_action">CORREGIR</string>
|
|
||||||
<string name="save">Guardar</string>
|
<string name="save">Guardar</string>
|
||||||
|
<string name="cancel">Cancelar</string>
|
||||||
<string name="advanced_settings_label">Ajustes del Túnel</string>
|
|
||||||
<string name="configuration_label">Configuración</string>
|
|
||||||
<string name="connection_log_label">Log de Conexión</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">AJUSTES</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">Instalación</string>
|
|
||||||
<string name="tab_status">Estado</string>
|
|
||||||
<string name="tab_usage">Uso</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">Configuración Inicial</string>
|
|
||||||
<string name="setup_welcome">Bienvenido al asistente de configuración de %1$s.\n\nPara funcionar correctamente, necesitamos los siguientes permisos:</string>
|
|
||||||
<string name="setup_continue">Continuar</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">Desactivar Optimización de Batería</string>
|
|
||||||
<string name="setup_perm_notifications">Notificaciones Push</string>
|
|
||||||
<string name="setup_perm_storage">Acceso al almacenamiento local</string>
|
|
||||||
<string name="setup_perm_termux">Ejecución de Termux</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
<string name="setup_manage_all_permissions">Administrar todos los permisos</string>
|
|
||||||
<string name="setup_display_over_other_apps">Mostrar sobre otras aplicaciones</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Administrar permisos de Termux</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">Archivos y medios (Almacenamiento)</string>
|
|
||||||
<string name="termux_not_installed">Termux no está instalado.</string>
|
|
||||||
<string name="termux_not_installed_error">Termux no está instalado o el dispositivo no es compatible.</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">Permiso de notificaciones denegado</string>
|
|
||||||
<string name="notif_perm_granted">Permiso de notificaciones concedido</string>
|
|
||||||
<string name="revoke_permission_warning">Para revocar permisos, debe hacerlo desde los ajustes del sistema.</string>
|
|
||||||
<string name="termux_perm_denied">Permiso de Termux denegado</string>
|
|
||||||
<string name="termux_perm_granted">Permiso de Termux concedido</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">Cargando el dispositivo...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">Activo: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>Batería:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>Batería:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>Hotspot:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>Activo:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">Almacenamiento principal</string>
|
|
||||||
<string name="dash_ram_memory">Memoria RAM</string>
|
|
||||||
<string name="dash_swap_virtual">Swap (Virtual)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">Estado del Servidor:</string>
|
|
||||||
<string name="dash_offline">Desconectado</string>
|
|
||||||
<string name="dash_online">En línea</string>
|
|
||||||
<string name="dash_system_state">Estado del Sistema</string>
|
|
||||||
<string name="dash_iiab_system">Sistema IIAB-oA</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">OS base instalado. Proceda a instalar IIAB.</string>
|
|
||||||
<string name="dash_state_installer">Instalador encontrado, abra la pestaña de instalación para más información.</string>
|
|
||||||
<string name="dash_state_none">No se identificó ningún componente, ni siquiera Termux.</string>
|
|
||||||
<string name="dash_state_offline">IIAB-oA parece estar desconectado, intente lanzarlo.</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA esta en línea.</string>
|
|
||||||
<string name="dash_state_termux_only">Termux encontrado, vaya a la pestaña de Instalación para operarlo.</string>
|
|
||||||
<string name="dash_termux_searching">Buscando instalación...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">Módulos Instalados</string>
|
|
||||||
<string name="dash_books">Libros</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">Mapas</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">Sistema</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">Aplicaciones</string>
|
|
||||||
<string name="browse_content">🚀 Explorar Contenido</string>
|
|
||||||
<string name="launch_server">🚀 Iniciar Servidor</string>
|
|
||||||
<string name="stop_server">🛑 Detener Servidor</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">El sistema IIAB-oA no parece estar (completamente) instalado. Por favor, verifique la pestaña de Estado o Instalación para más información.</string>
|
|
||||||
<string name="server_booting">Iniciando...</string>
|
|
||||||
<string name="server_shutting_down">Apagando...</string>
|
|
||||||
<string name="server_timeout_warning">Advertencia: Tiempo de espera agotado en la transición de estado del servidor.</string>
|
|
||||||
<string name="system_ready">Sistema listo...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">Hotspot</string>
|
|
||||||
<string name="tunnel">Túnel</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">Active Wi-Fi o Hotspot para compartir contenido a través de la red.</string>
|
|
||||||
<string name="qr_error_no_server">Inicie el servidor para compartir contenido a través de la red.</string>
|
|
||||||
<string name="qr_flip_network">Cambiar Red</string>
|
|
||||||
<string name="qr_title_hotspot">Red Hotspot</string>
|
|
||||||
<string name="qr_title_wifi">Red Wi-Fi</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Desactivar Safe Pocket Web</string>
|
|
||||||
<string name="control_enable">Activar Safe Pocket Web</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">Global</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">Modo Mantenimiento</string>
|
|
||||||
<string name="maintenance_warning_msg">Desactive Safe Pocket Web para poder modificar</string>
|
|
||||||
<string name="remote_dns">DNS Remoto</string>
|
|
||||||
<string name="socks_addr">Dirección Socks:</string>
|
|
||||||
<string name="socks_pass">Contraseña Socks:</string>
|
|
||||||
<string name="socks_port">Puerto Socks:</string>
|
|
||||||
<string name="socks_udp_addr">Dirección UDP Socks:</string>
|
|
||||||
<string name="socks_user">Usuario Socks:</string>
|
|
||||||
<string name="udp_in_tcp">Relé UDP sobre TCP</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">Recuperación VPN</string>
|
|
||||||
<string name="recovery_notif_text">Toque para restaurar el entorno seguro inmediatamente.</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web Interrumpido</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">Conexión iniciada por el usuario</string>
|
|
||||||
<string name="vpn_description">Habilite URLs amigables. Bloquee las amenazas.</string>
|
|
||||||
<string name="vpn_permission_granted">Permiso de VPN concedido. Conectando...</string>
|
|
||||||
<string name="vpn_starting">Iniciando VPN...</string>
|
|
||||||
<string name="vpn_stopping">Deteniendo VPN...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">Desactivar\nWatchdog Maestro</string>
|
|
||||||
<string name="watchdog_enable">Activar\nWatchdog Maestro</string>
|
|
||||||
<string name="watchdog_description">Protege Termux del Doze y mantiene el Wi-Fi activo.</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">Asegura que los servicios permanezcan activos cuando la pantalla está apagada.</string>
|
|
||||||
<string name="watchdog_channel_name">Servicio IIAB Watchdog</string>
|
|
||||||
<string name="watchdog_notif_text">Protegiendo el entorno Termux...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB Watchdog Activo</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">CPU WakeLock adquirido bajo protección VPN</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock liberado</string>
|
|
||||||
<string name="error_acquiring_locks">Error al adquirir bloqueos</string>
|
|
||||||
<string name="syncing_watchdog">Sincronizando estado del Watchdog. Activado: %b</string>
|
|
||||||
<string name="watchdog_started">Watchdog Iniciado</string>
|
|
||||||
<string name="watchdog_stopped">Watchdog Detenido</string>
|
|
||||||
<string name="watchdog_thread_ended">Watchdog Thread: Bucle finalizado</string>
|
|
||||||
<string name="watchdog_thread_error">Watchdog Thread: Error en el bucle</string>
|
|
||||||
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrumpido, deteniéndose...</string>
|
|
||||||
<string name="watchdog_thread_started">Watchdog Thread: Bucle iniciado</string>
|
|
||||||
<string name="wifi_lock_acquired">Wi-Fi Lock adquirido bajo protección VPN</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock liberado</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">CRÍTICO: El SO bloqueó el estímulo a Termux (SecurityException).</string>
|
|
||||||
<string name="failed_termux_intent">CRÍTICO: Fallo en el Intent de Termux: %s</string>
|
|
||||||
<string name="force_termux_foreground">Forzar a Termux a pasar a primer plano...</string>
|
|
||||||
<string name="maintenance_mode_enabled">Modo de mantenimiento activado: Termux tiene acceso directo a Internet</string>
|
|
||||||
<string name="maintenance_write_failed">Fallo en la escritura de mantenimiento</string>
|
|
||||||
<string name="permission_denied_log">Permiso denegado: Asegúrese de que el manifiesto tiene RUN_COMMAND y la app no está restringida.</string>
|
|
||||||
<string name="ping_fail">PING 8085: FALLO (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">Error de Pulso: %s</string>
|
|
||||||
<string name="pulse_stimulating">Pulso: Estimulando Termux...</string>
|
|
||||||
<string name="recovery_pulse_received">Pulso de recuperación recibido del sistema. Forzando VPN...</string>
|
|
||||||
<string name="sent_to_termux">Enviado a Termux: %s</string>
|
|
||||||
<string name="session_started">SESIÓN DE LATIDO INICIADA</string>
|
|
||||||
<string name="session_stopped">SESIÓN DE LATIDO DETENIDA</string>
|
|
||||||
<string name="termux_invocation_error">Error al invocar Termux: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] Error de pulso (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] Estímulo OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">¿Termux no abre? Habilite Watchdog Maestro para forzar que obtenga el foco.</string>
|
|
||||||
<string name="unexpected_error_termux">Error inesperado enviando intent a Termux</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- Fin del Historial ---</string>
|
|
||||||
<string name="error_reading_history">Error al leer el historial: %s</string>
|
|
||||||
<string name="failed_write_blackbox">Fallo al escribir en BlackBox</string>
|
|
||||||
<string name="loading_history">--- Cargando Historial ---</string>
|
|
||||||
<string name="log_cleared_toast">Log borrado</string>
|
|
||||||
<string name="log_copied_toast">Log copiado al portapapeles</string>
|
|
||||||
<string name="log_reset_confirm_msg">Esto borrará permanentemente todos los logs de conexión guardados. Esta acción no se puede deshacer.</string>
|
|
||||||
<string name="log_reset_confirm_title">¿Reiniciar historial de log?</string>
|
|
||||||
<string name="failed_reset_log">Fallo al reiniciar el log: %s</string>
|
|
||||||
<string name="log_reset_log">Log reiniciado</string>
|
|
||||||
<string name="log_reset_user">Log reiniciado por el usuario</string>
|
|
||||||
<string name="log_size_bytes">%d B</string>
|
|
||||||
<string name="log_size_format">Tamaño: %1$s / 10MB</string>
|
|
||||||
<string name="log_size_kb">%.1f KB</string>
|
|
||||||
<string name="log_size_mb">%.2f MB</string>
|
|
||||||
<string name="log_warning_rapid_growth">El archivo de log está creciendo demasiado rápido, verifique si algo está fallando</string>
|
|
||||||
<string name="no_blackbox_found">--- No se encontró el archivo BlackBox ---</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">Autentíquese para desactivar el entorno seguro</string>
|
|
||||||
<string name="auth_required_title">Autenticación requerida</string>
|
|
||||||
<string name="auth_success_disconnect">Autenticación exitosa. Desconectando...</string>
|
|
||||||
<string name="security_required_msg">Debe configurar un PIN, Patrón o Huella digital en su dispositivo antes de activar el entorno seguro.</string>
|
|
||||||
<string name="security_required_title">Seguridad Requerida</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Se requiere autenticación para detener la protección de Termux</string>
|
|
||||||
<string name="unlock_watchdog_title">Desbloquear Watchdog Maestro</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">Para que la app funcione al 100%, desactive la optimización de batería.</string>
|
|
||||||
<string name="battery_opt_msg">Para que el Watchdog funcione de manera confiable, desactive las optimizaciones de batería para esta aplicación.</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detectado: Asegúrese de activar \'Permitir actividad en segundo plano\' en los ajustes de esta aplicación.</string>
|
|
||||||
<string name="battery_opt_title">Optimización de Batería</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detectado: Establezca el ahorro de batería a \'Sin restricciones\' en los ajustes.</string>
|
|
||||||
<string name="go_to_settings">Ir a Ajustes</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">Aplicación Iniciada</string>
|
|
||||||
<string name="deploy_wip_desc">El módulo Termux y el instalador de entorno estarán disponibles aquí pronto.</string>
|
|
||||||
<string name="deploy_wip_title">WIP - En construcción</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Batería: "</string>
|
|
||||||
<string name="battery_no_value">Batería: --%</string>
|
|
||||||
<string name="hotspot_fdash">Hotspot: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">Guardado</string>
|
<string name="saved_toast">Guardado</string>
|
||||||
<string name="settings_saved">Ajustes Guardados</string>
|
<string name="settings_saved">Ajustes Guardados</string>
|
||||||
<string name="uptime_no_value">Tiempo de actividad: --</string>
|
<string name="fix_action">CORREGIR</string>
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
<string name="configuration_label">Configuración</string>
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
<string name="advanced_settings_label">Ajustes del Túnel</string>
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
<string name="connection_log_label">Log de Conexión</string>
|
||||||
<string name="setup_termux_custom_permissions">Ajuste de permisos Termux</string>
|
<string name="settings_label">AJUSTES</string>
|
||||||
|
|
||||||
|
<!-- SetupActivity -->
|
||||||
|
<string name="setup_title">Configuración Inicial</string>
|
||||||
|
<string name="setup_welcome">Bienvenido al asistente de configuración de %1$s.\n\nPara funcionar correctamente, necesitamos los siguientes permisos:</string>
|
||||||
|
<string name="setup_perm_notifications">Notificaciones Push</string>
|
||||||
|
<string name="setup_perm_termux">Ejecución de Termux</string>
|
||||||
|
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
||||||
|
<string name="setup_perm_battery">Desactivar Optimización de Batería</string>
|
||||||
|
<string name="setup_continue">Continuar</string>
|
||||||
|
<string name="revoke_permission_warning">Para revocar permisos, debe hacerlo desde los ajustes del sistema.</string>
|
||||||
|
<string name="termux_not_installed_error">Termux no está instalado o el dispositivo no es compatible.</string>
|
||||||
|
<string name="termux_not_installed">Termux no está instalado.</string>
|
||||||
|
|
||||||
|
<!-- VPN / Socks -->
|
||||||
|
<string name="control_enable">Activar Safe Pocket Web</string>
|
||||||
|
<string name="control_disable">Desactivar Safe Pocket Web</string>
|
||||||
|
<string name="vpn_description">Habilite URLs amigables. Bloquee las amenazas.</string>
|
||||||
|
<string name="socks_addr">Dirección Socks:</string>
|
||||||
|
<string name="socks_udp_addr">Dirección UDP Socks:</string>
|
||||||
|
<string name="socks_port">Puerto Socks:</string>
|
||||||
|
<string name="socks_user">Usuario Socks:</string>
|
||||||
|
<string name="socks_pass">Contraseña Socks:</string>
|
||||||
|
<string name="dns_ipv4">DNS IPv4:</string>
|
||||||
|
<string name="dns_ipv6">DNS IPv6:</string>
|
||||||
|
<string name="udp_in_tcp">Relé UDP sobre TCP</string>
|
||||||
|
<string name="remote_dns">DNS Remoto</string>
|
||||||
|
<string name="ipv4">IPv4</string>
|
||||||
|
<string name="ipv6">IPv6</string>
|
||||||
|
<string name="global">Global</string>
|
||||||
|
<string name="apps">Aplicaciones</string>
|
||||||
|
<string name="vpn_stopping">Deteniendo VPN...</string>
|
||||||
|
<string name="vpn_starting">Iniciando VPN...</string>
|
||||||
|
<string name="user_initiated_conn">Conexión iniciada por el usuario</string>
|
||||||
|
<string name="vpn_permission_granted">Permiso de VPN concedido. Conectando...</string>
|
||||||
|
<string name="tproxy_channel_name">socks5</string>
|
||||||
|
|
||||||
|
<!-- WatchdogService / IIABWatchdog -->
|
||||||
|
<string name="watchdog_enable">Activar\nWatchdog Maestro</string>
|
||||||
|
<string name="watchdog_disable">Desactivar\nWatchdog Maestro</string>
|
||||||
|
<string name="watchdog_description">Protege Termux del modo Doze y mantiene el Wi-Fi activo.</string>
|
||||||
|
<string name="watchdog_stopped">Watchdog Detenido</string>
|
||||||
|
<string name="watchdog_started">Watchdog Iniciado</string>
|
||||||
|
<string name="watchdog_channel_name">Servicio IIAB Watchdog</string>
|
||||||
|
<string name="watchdog_channel_desc">Asegura que los servicios permanezcan activos cuando la pantalla está apagada.</string>
|
||||||
|
<string name="watchdog_notif_title">IIAB Watchdog Activo</string>
|
||||||
|
<string name="watchdog_notif_text">Protegiendo el entorno Termux...</string>
|
||||||
|
<string name="syncing_watchdog">Sincronizando estado del Watchdog. Activado: %b</string>
|
||||||
|
<string name="watchdog_thread_started">Watchdog Thread: Bucle iniciado</string>
|
||||||
|
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrumpido, deteniéndose...</string>
|
||||||
|
<string name="watchdog_thread_error">Watchdog Thread: Error en el bucle</string>
|
||||||
|
<string name="watchdog_thread_ended">Watchdog Thread: Bucle finalizado</string>
|
||||||
|
<string name="cpu_wakelock_acquired">CPU WakeLock adquirido bajo protección VPN</string>
|
||||||
|
<string name="wifi_lock_acquired">Wi-Fi Lock adquirido bajo protección VPN</string>
|
||||||
|
<string name="error_acquiring_locks">Error al adquirir bloqueos</string>
|
||||||
|
<string name="cpu_wakelock_released">CPU WakeLock liberado</string>
|
||||||
|
<string name="wifi_lock_released">Wi-Fi Lock liberado</string>
|
||||||
|
|
||||||
|
<!-- Pulse / Heartbeat -->
|
||||||
|
<string name="pulse_stimulating">Pulso: Estimulando Termux...</string>
|
||||||
|
<string name="critical_os_blocked">CRÍTICO: El SO bloqueó el estímulo a Termux (SecurityException).</string>
|
||||||
|
<string name="ping_ok">PING 8085: OK</string>
|
||||||
|
<string name="ping_fail">PING 8085: FALLO (%s)</string>
|
||||||
|
<string name="session_started">SESIÓN DE LATIDO INICIADA</string>
|
||||||
|
<string name="session_stopped">SESIÓN DE LATIDO DETENIDA</string>
|
||||||
|
<string name="permission_denied_log">Permiso denegado: Asegúrese de que el manifiesto tiene RUN_COMMAND y la app no está restringida.</string>
|
||||||
|
<string name="unexpected_error_termux">Error inesperado enviando intent a Termux</string>
|
||||||
|
<string name="pulse_error_log">Error de Pulso: %s</string>
|
||||||
|
<string name="maintenance_write_failed">Fallo en la escritura de mantenimiento</string>
|
||||||
|
<string name="failed_write_blackbox">Fallo al escribir en BlackBox</string>
|
||||||
|
<string name="recovery_pulse_received">Pulso de recuperación recibido del sistema. Forzando VPN...</string>
|
||||||
|
|
||||||
|
<!-- TermuxCallbackReceiver / Operations -->
|
||||||
|
<string name="termux_stimulus_ok">[Termux] Estímulo OK (exit 0)</string>
|
||||||
|
<string name="termux_pulse_error">[Termux] Error de pulso (exit %1$d): %2$s</string>
|
||||||
|
<string name="server_timeout_warning">Advertencia: Tiempo de espera agotado en la transición de estado del servidor.</string>
|
||||||
|
<string name="server_booting">Iniciando...</string>
|
||||||
|
<string name="server_shutting_down">Apagando...</string>
|
||||||
|
<string name="failed_termux_intent">CRÍTICO: Fallo en el Intent de Termux: %s</string>
|
||||||
|
<string name="sent_to_termux">Enviado a Termux: %s</string>
|
||||||
|
<string name="maintenance_mode_enabled">Modo de mantenimiento activado: Termux tiene acceso directo a Internet</string>
|
||||||
|
<string name="stop_server">🛑 Detener Servidor</string>
|
||||||
|
<string name="launch_server">🚀 Iniciar Servidor</string>
|
||||||
|
<string name="termux_perm_granted">Permiso de Termux concedido</string>
|
||||||
|
<string name="termux_perm_denied">Permiso de Termux denegado</string>
|
||||||
|
<string name="notif_perm_granted">Permiso de notificaciones concedido</string>
|
||||||
|
<string name="notif_perm_denied">Permiso de notificaciones denegado</string>
|
||||||
|
|
||||||
|
<!-- Logs -->
|
||||||
|
<string name="log_reset_confirm_title">¿Reiniciar historial de log?</string>
|
||||||
|
<string name="log_reset_confirm_msg">Esto borrará permanentemente todos los logs de conexión guardados. Esta acción no se puede deshacer.</string>
|
||||||
|
<string name="log_warning_rapid_growth">El archivo de log está creciendo demasiado rápido, verifique si algo está fallando</string>
|
||||||
|
<string name="reset_log">Reiniciar Log</string>
|
||||||
|
<string name="copy_all">Copiar Todo</string>
|
||||||
|
<string name="log_reset_log">Log reiniciado</string>
|
||||||
|
<string name="log_reset_user">Log reiniciado por el usuario</string>
|
||||||
|
<string name="log_copied_toast">Log copiado al portapapeles</string>
|
||||||
|
<string name="log_cleared_toast">Log borrado</string>
|
||||||
|
<string name="failed_reset_log">Fallo al reiniciar el log: %s</string>
|
||||||
|
<string name="log_size_format">Tamaño: %1$s / 10MB</string>
|
||||||
|
<string name="log_size_bytes">%d B</string>
|
||||||
|
<string name="log_size_kb">%.1f KB</string>
|
||||||
|
<string name="log_size_mb">%.2f MB</string>
|
||||||
|
<string name="no_blackbox_found">--- No se encontró el archivo BlackBox ---</string>
|
||||||
|
<string name="loading_history">--- Cargando Historial ---</string>
|
||||||
|
<string name="error_reading_history">Error al leer el historial: %s</string>
|
||||||
|
<string name="end_of_history">--- Fin del Historial ---</string>
|
||||||
|
|
||||||
|
<!-- Battery Optimizations -->
|
||||||
|
<string name="battery_opt_title">Optimización de Batería</string>
|
||||||
|
<string name="battery_opt_msg">Para que el Watchdog funcione de manera confiable, desactive las optimizaciones de batería para esta aplicación.</string>
|
||||||
|
<string name="go_to_settings">Ir a Ajustes</string>
|
||||||
|
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detectado: Asegúrese de activar \'Permitir actividad en segundo plano\' en los ajustes de esta aplicación.</string>
|
||||||
|
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detectado: Establezca el ahorro de batería a \'Sin restricciones\' en los ajustes.</string>
|
||||||
|
<string name="battery_opt_denied">Para que la app funcione al 100%, desactive la optimización de batería.</string>
|
||||||
|
|
||||||
|
<!-- UI / Misc -->
|
||||||
|
<string name="browse_content">🚀 Explorar Contenido</string>
|
||||||
|
<string name="system_ready">Sistema listo...\n</string>
|
||||||
|
<string name="app_started">Aplicación Iniciada</string>
|
||||||
|
<string name="label_separator_down">▼ %s</string>
|
||||||
|
<string name="label_separator_up">▶ %s</string>
|
||||||
|
<string name="qr_error_no_server">Inicie el servidor para compartir contenido a través de la red.</string>
|
||||||
|
<string name="qr_error_no_network">Active Wi-Fi o Hotspot para compartir contenido a través de la red.</string>
|
||||||
|
<string name="qr_title_wifi">Red Wi-Fi</string>
|
||||||
|
<string name="qr_title_hotspot">Red Hotspot</string>
|
||||||
|
<string name="qr_flip_network">Cambiar Red</string>
|
||||||
|
|
||||||
|
<!-- Authentication / Security -->
|
||||||
|
<string name="unlock_watchdog_title">Desbloquear Watchdog Maestro</string>
|
||||||
|
<string name="unlock_watchdog_subtitle">Se requiere autenticación para detener la protección de Termux</string>
|
||||||
|
<string name="auth_success_disconnect">Autenticación exitosa. Desconectando...</string>
|
||||||
|
<string name="auth_required_title">Autenticación requerida</string>
|
||||||
|
<string name="auth_required_subtitle">Autentíquese para desactivar el entorno seguro</string>
|
||||||
|
<string name="security_required_title">Seguridad Requerida</string>
|
||||||
|
<string name="security_required_msg">Debe configurar un PIN, Patrón o Huella digital en su dispositivo antes de activar el entorno seguro.</string>
|
||||||
|
|
||||||
|
<!-- VPN Recovery Service -->
|
||||||
|
<string name="recovery_channel_name">Recuperación VPN</string>
|
||||||
|
<string name="recovery_notif_title">Safe Pocket Web Interrumpido</string>
|
||||||
|
<string name="recovery_notif_text">Toque para restaurar el entorno seguro inmediatamente.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
|
||||||
<string name="default_version">v0.1.x</string>
|
|
||||||
|
|
||||||
<string name="cancel">Annuler</string>
|
|
||||||
<string name="copy_all">Tout copier</string>
|
|
||||||
<string name="fix_action">CORRIGER</string>
|
|
||||||
<string name="save">Enregistrer</string>
|
|
||||||
|
|
||||||
<string name="advanced_settings_label">Paramètres du tunnel</string>
|
|
||||||
<string name="configuration_label">Configuration</string>
|
|
||||||
<string name="connection_log_label">Journal de connexion</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">PARAMÈTRES</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">Installation</string>
|
|
||||||
<string name="tab_status">Statut</string>
|
|
||||||
<string name="tab_usage">Utilisation</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">Configuration initiale</string>
|
|
||||||
<string name="setup_welcome">Bienvenue dans l\'assistant de configuration de %1$s.\n\nPour fonctionner correctement, nous avons besoin des autorisations suivantes :</string>
|
|
||||||
<string name="setup_continue">Continuer</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">Désactiver l\'optimisation de la batterie</string>
|
|
||||||
<string name="setup_perm_notifications">Notifications Push</string>
|
|
||||||
<string name="setup_perm_storage">Accès au stockage local</string>
|
|
||||||
<string name="setup_perm_termux">Exécution de Termux</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">Fichiers et médias (Stockage)</string>
|
|
||||||
<string name="termux_not_installed">Termux n\'est pas installé.</string>
|
|
||||||
<string name="termux_not_installed_error">Termux n\'est pas installé ou l\'appareil n\'est pas pris en charge.</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">Autorisation de notification refusée</string>
|
|
||||||
<string name="notif_perm_granted">Autorisation de notification accordée</string>
|
|
||||||
<string name="revoke_permission_warning">Pour révoquer des autorisations, vous devez le faire depuis les paramètres système.</string>
|
|
||||||
<string name="termux_perm_denied">Autorisation Termux refusée</string>
|
|
||||||
<string name="termux_perm_granted">Autorisation Termux accordée</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">Chargement de l\'appareil...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">Temps de fonctionnement: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>Batterie:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>Batterie:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>Point d\'accès:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>Temps de fonctionnement:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">Stockage principal</string>
|
|
||||||
<string name="dash_ram_memory">Mémoire RAM</string>
|
|
||||||
<string name="dash_swap_virtual">Swap (virtuel)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">Statut du serveur:</string>
|
|
||||||
<string name="dash_offline">Hors ligne</string>
|
|
||||||
<string name="dash_online">En ligne</string>
|
|
||||||
<string name="dash_system_state">État du système</string>
|
|
||||||
<string name="dash_iiab_system">Système IIAB-oA</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">OS de base installé. Procédez à l\'installation de IIAB.</string>
|
|
||||||
<string name="dash_state_installer">Installateur trouvé, ouvrez l\'onglet installation pour plus d\'informations.</string>
|
|
||||||
<string name="dash_state_none">Aucun composant identifié, même pas Termux.</string>
|
|
||||||
<string name="dash_state_offline">IIAB-oA semble hors ligne, essayez de le lancer.</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA est en ligne.</string>
|
|
||||||
<string name="dash_state_termux_only">Termux trouvé, allez dans l\'onglet Installation pour le gérer.</string>
|
|
||||||
<string name="dash_termux_searching">Recherche d\'installation...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">Modules installés</string>
|
|
||||||
<string name="dash_books">Livres</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">Cartes</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">Système</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">Applications</string>
|
|
||||||
<string name="browse_content">🚀 Explorer le contenu</string>
|
|
||||||
<string name="launch_server">🚀 Lancer le serveur</string>
|
|
||||||
<string name="stop_server">🛑 Arrêter le serveur</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">Le système IIAB-oA ne semble pas être (entièrement) installé. Veuillez vérifier l\'onglet Statut ou Installation pour plus d\'informations.</string>
|
|
||||||
<string name="server_booting">Démarrage...</string>
|
|
||||||
<string name="server_shutting_down">Arrêt en cours...</string>
|
|
||||||
<string name="server_timeout_warning">Avertissement: Le délai de transition de l\'état du serveur a expiré.</string>
|
|
||||||
<string name="system_ready">Système prêt...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">Point d\'accès</string>
|
|
||||||
<string name="tunnel">Tunnel</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">Activez le Wi-Fi ou le point d\'accès pour partager du contenu sur le réseau.</string>
|
|
||||||
<string name="qr_error_no_server">Lancez le serveur pour partager du contenu sur le réseau.</string>
|
|
||||||
<string name="qr_flip_network">Changer de réseau</string>
|
|
||||||
<string name="qr_title_hotspot">Réseau point d\'accès</string>
|
|
||||||
<string name="qr_title_wifi">Réseau Wi-Fi</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Désactiver Safe Pocket Web</string>
|
|
||||||
<string name="control_enable">Activer Safe Pocket Web</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">Global</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">Mode de maintenance</string>
|
|
||||||
<string name="maintenance_warning_msg">Désactivez Safe Pocket Web pour pouvoir modifier</string>
|
|
||||||
<string name="remote_dns">DNS distant</string>
|
|
||||||
<string name="socks_addr">Adresse Socks:</string>
|
|
||||||
<string name="socks_pass">Mot de passe Socks:</string>
|
|
||||||
<string name="socks_port">Port Socks:</string>
|
|
||||||
<string name="socks_udp_addr">Adresse UDP Socks:</string>
|
|
||||||
<string name="socks_user">Nom d\'utilisateur Socks:</string>
|
|
||||||
<string name="udp_in_tcp">Relais UDP sur TCP</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">Récupération VPN</string>
|
|
||||||
<string name="recovery_notif_text">Appuyez pour restaurer immédiatement l\'environnement sécurisé.</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web interrompu</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">Connexion initiée par l\'utilisateur</string>
|
|
||||||
<string name="vpn_description">Activez des URL conviviales. Bloquez les menaces.</string>
|
|
||||||
<string name="vpn_permission_granted">Autorisation VPN accordée. Connexion...</string>
|
|
||||||
<string name="vpn_starting">Démarrage VPN...</string>
|
|
||||||
<string name="vpn_stopping">Arrêt VPN...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">Désactiver\nle Watchdog maître</string>
|
|
||||||
<string name="watchdog_enable">Activer\nle Watchdog maître</string>
|
|
||||||
<string name="watchdog_description">Protège Termux du mode Doze et maintient le Wi-Fi actif.</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">Garantit que les services restent actifs lorsque l\'écran est éteint.</string>
|
|
||||||
<string name="watchdog_channel_name">Service IIAB Watchdog</string>
|
|
||||||
<string name="watchdog_notif_text">Protection de l\'environnement Termux...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB Watchdog actif</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">CPU WakeLock acquis sous protection VPN</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock libéré</string>
|
|
||||||
<string name="error_acquiring_locks">Erreur lors de l\'acquisition des verrous</string>
|
|
||||||
<string name="syncing_watchdog">Synchronisation de l\'état du Watchdog. Activé: %b</string>
|
|
||||||
<string name="watchdog_started">Watchdog démarré</string>
|
|
||||||
<string name="watchdog_stopped">Watchdog arrêté</string>
|
|
||||||
<string name="watchdog_thread_ended">Watchdog Thread: Boucle terminée</string>
|
|
||||||
<string name="watchdog_thread_error">Watchdog Thread: Erreur dans la boucle</string>
|
|
||||||
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrompu, arrêt en cours...</string>
|
|
||||||
<string name="watchdog_thread_started">Watchdog Thread: Boucle démarrée</string>
|
|
||||||
<string name="wifi_lock_acquired">Wi-Fi Lock acquis sous protection VPN</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock libéré</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">CRITIQUE: Le système d\'exploitation a bloqué la stimulation de Termux (SecurityException).</string>
|
|
||||||
<string name="failed_termux_intent">CRITIQUE: Échec de l\'intention Termux: %s</string>
|
|
||||||
<string name="force_termux_foreground">Forcer Termux au premier plan...</string>
|
|
||||||
<string name="maintenance_mode_enabled">Mode de maintenance activé: Termux a un accès direct à Internet</string>
|
|
||||||
<string name="maintenance_write_failed">Échec de l\'écriture de maintenance</string>
|
|
||||||
<string name="permission_denied_log">Autorisation refusée: Assurez-vous que le manifeste contient RUN_COMMAND et que l\'application n\'est pas restreinte.</string>
|
|
||||||
<string name="ping_fail">PING 8085: ÉCHEC (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">Erreur de Pulse: %s</string>
|
|
||||||
<string name="pulse_stimulating">Pulse: Stimulation de Termux...</string>
|
|
||||||
<string name="recovery_pulse_received">Pulse de récupération reçu du système. VPN en cours d\'application...</string>
|
|
||||||
<string name="sent_to_termux">Envoyé à Termux: %s</string>
|
|
||||||
<string name="session_started">SESSION DE HEARTBEAT DÉMARRÉE</string>
|
|
||||||
<string name="session_stopped">SESSION DE HEARTBEAT ARRÊTÉE</string>
|
|
||||||
<string name="termux_invocation_error">Erreur lors de l\'invocation de Termux: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] Erreur de Pulse (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">Termux ne s\'ouvre pas? Activez le Watchdog maître pour le forcer à prendre le focus.</string>
|
|
||||||
<string name="unexpected_error_termux">Erreur inattendue lors de l\'envoi de l\'intention vers Termux</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- Fin de l\'historique ---</string>
|
|
||||||
<string name="error_reading_history">Erreur lors de la lecture de l\'historique: %s</string>
|
|
||||||
<string name="failed_write_blackbox">Échec de l\'écriture dans BlackBox</string>
|
|
||||||
<string name="loading_history">--- Chargement de l\'historique ---</string>
|
|
||||||
<string name="log_cleared_toast">Journal effacé</string>
|
|
||||||
<string name="log_copied_toast">Journal copié dans le presse-papier</string>
|
|
||||||
<string name="log_reset_confirm_msg">Cela supprimera définitivement tous les journaux de connexion enregistrés. Cette action ne peut pas être annulée.</string>
|
|
||||||
<string name="log_reset_confirm_title">Réinitialiser l\'historique des journaux?</string>
|
|
||||||
<string name="failed_reset_log">Échec de la réinitialisation du journal: %s</string>
|
|
||||||
<string name="log_reset_log">Journal réinitialisé</string>
|
|
||||||
<string name="log_reset_user">Journal réinitialisé par l\'utilisateur</string>
|
|
||||||
<string name="log_size_bytes">%d o</string>
|
|
||||||
<string name="log_size_format">Taille: %1$s / 10 Mo</string>
|
|
||||||
<string name="log_size_kb">%.1f Ko</string>
|
|
||||||
<string name="log_size_mb">%.2f Mo</string>
|
|
||||||
<string name="log_warning_rapid_growth">Le fichier de journalisation croît trop rapidement, vérifiez si quelque chose échoue</string>
|
|
||||||
<string name="no_blackbox_found">--- Aucun fichier BlackBox trouvé ---</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">Authentifiez-vous pour désactiver l\'environnement sécurisé</string>
|
|
||||||
<string name="auth_required_title">Authentification requise</string>
|
|
||||||
<string name="auth_success_disconnect">Authentification réussie. Déconnexion...</string>
|
|
||||||
<string name="security_required_msg">Vous devez définir un code PIN, un schéma ou une empreinte digitale sur votre appareil avant d\'activer l\'environnement sécurisé.</string>
|
|
||||||
<string name="security_required_title">Sécurité requise</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Authentification requise pour arrêter la protection Termux</string>
|
|
||||||
<string name="unlock_watchdog_title">Déverrouiller le Watchdog maître</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">Pour que l\'application fonctionne à 100%, veuillez désactiver l\'optimisation de la batterie.</string>
|
|
||||||
<string name="battery_opt_msg">Pour que le Watchdog fonctionne de manière fiable, veuillez désactiver les optimisations de batterie pour cette application.</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme détecté: Veuillez vous assurer d\'activer \'Autoriser l\'activité en arrière-plan\' dans les paramètres de cette application.</string>
|
|
||||||
<string name="battery_opt_title">Optimisation de la batterie</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi détecté: Veuillez régler l\'économie de batterie sur \'Aucune restriction\' dans les paramètres.</string>
|
|
||||||
<string name="go_to_settings">Aller aux paramètres</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">Application démarrée</string>
|
|
||||||
<string name="deploy_wip_desc">Le module Termux et l\'installateur d\'environnement seront disponibles ici prochainement.</string>
|
|
||||||
<string name="deploy_wip_title">WIP - En construction</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Batterie: "</string>
|
|
||||||
<string name="battery_no_value">Batterie: --%</string>
|
|
||||||
<string name="hotspot_fdash">Point d\'accès: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">Enregistré</string>
|
|
||||||
<string name="settings_saved">Paramètres enregistrés</string>
|
|
||||||
<string name="uptime_no_value">Temps de fonctionnement: --</string>
|
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
|
||||||
<string name="setup_display_over_other_apps">Display over other apps</string>
|
|
||||||
<string name="setup_manage_all_permissions">Manage All Permissions</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Manage Termux permissions</string>
|
|
||||||
<string name="setup_termux_custom_permissions">Termux custom permissions</string>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
|
||||||
<string name="default_version">v0.1.x</string>
|
|
||||||
|
|
||||||
<string name="cancel">रद्द करें</string>
|
|
||||||
<string name="copy_all">सभी कॉपी करें</string>
|
|
||||||
<string name="fix_action">ठीक करें</string>
|
|
||||||
<string name="save">सहेजें</string>
|
|
||||||
|
|
||||||
<string name="advanced_settings_label">टनल सेटिंग्स</string>
|
|
||||||
<string name="configuration_label">कॉन्फ़िगरेशन</string>
|
|
||||||
<string name="connection_log_label">कनेक्शन लॉग</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">सेटिंग्स</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">इंस्टालेशन</string>
|
|
||||||
<string name="tab_status">स्थिति</string>
|
|
||||||
<string name="tab_usage">उपयोग</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">प्रारंभिक सेटअप</string>
|
|
||||||
<string name="setup_welcome">%1$s सेटअप विज़ार्ड में आपका स्वागत है।\n\nठीक से काम करने के लिए, हमें निम्नलिखित अनुमतियों की आवश्यकता है:</string>
|
|
||||||
<string name="setup_continue">जारी रखें</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">बैटरी अनुकूलन अक्षम करें</string>
|
|
||||||
<string name="setup_perm_notifications">पुश सूचनाएं</string>
|
|
||||||
<string name="setup_perm_storage">स्थानीय स्टोरेज एक्सेस</string>
|
|
||||||
<string name="setup_perm_termux">Termux निष्पादन</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">फ़ाइलें और मीडिया (स्टोरेज)</string>
|
|
||||||
<string name="termux_not_installed">Termux इंस्टॉल नहीं है।</string>
|
|
||||||
<string name="termux_not_installed_error">Termux इंस्टॉल नहीं है या डिवाइस समर्थित नहीं है।</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">सूचना अनुमति अस्वीकार</string>
|
|
||||||
<string name="notif_perm_granted">सूचना अनुमति दी गई</string>
|
|
||||||
<string name="revoke_permission_warning">अनुमतियां रद्द करने के लिए, आपको सिस्टम सेटिंग्स में जाना होगा।</string>
|
|
||||||
<string name="termux_perm_denied">Termux अनुमति अस्वीकार</string>
|
|
||||||
<string name="termux_perm_granted">Termux अनुमति दी गई</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">डिवाइस लोड हो रहा है...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">अपटाइम: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>बैटरी:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>बैटरी:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>हॉटस्पॉट:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>अपटाइम:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">मुख्य स्टोरेज</string>
|
|
||||||
<string name="dash_ram_memory">RAM मेमोरी</string>
|
|
||||||
<string name="dash_swap_virtual">स्वैप (वर्चुअल)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">सर्वर स्थिति:</string>
|
|
||||||
<string name="dash_offline">ऑफ़लाइन</string>
|
|
||||||
<string name="dash_online">ऑनलाइन</string>
|
|
||||||
<string name="dash_system_state">सिस्टम स्थिति</string>
|
|
||||||
<string name="dash_iiab_system">सिस्टम IIAB-oA</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">बेस OS इंस्टॉल है। IIAB इंस्टॉल करना जारी रखें।</string>
|
|
||||||
<string name="dash_state_installer">इंस्टॉलर मिला, अधिक जानकारी के लिए इंस्टालेशन टैब खोलें।</string>
|
|
||||||
<string name="dash_state_none">कोई घटक नहीं मिला, यहाँ तक कि Termux भी नहीं।</string>
|
|
||||||
<string name="dash_state_offline">IIAB-oA ऑफ़लाइन लग रहा है, इसे लॉन्च करने का प्रयास करें।</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA ऑनलाइन है।</string>
|
|
||||||
<string name="dash_state_termux_only">Termux मिला, इसे प्रबंधित करने के लिए इंस्टालेशन टैब पर जाएं।</string>
|
|
||||||
<string name="dash_termux_searching">इंस्टालेशन खोज रहा है...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">इंस्टॉल किए गए मॉड्यूल</string>
|
|
||||||
<string name="dash_books">पुस्तकें</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">मानचित्र</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">सिस्टम</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">ऐप्स</string>
|
|
||||||
<string name="browse_content">🚀 सामग्री देखें</string>
|
|
||||||
<string name="launch_server">🚀 सर्वर लॉन्च करें</string>
|
|
||||||
<string name="stop_server">🛑 सर्वर बंद करें</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">IIAB-oA सिस्टम (पूरी तरह से) इंस्टॉल नहीं लग रहा है। कृपया अधिक जानकारी के लिए स्थिति या इंस्टालेशन टैब देखें।</string>
|
|
||||||
<string name="server_booting">बूट हो रहा है...</string>
|
|
||||||
<string name="server_shutting_down">बंद हो रहा है...</string>
|
|
||||||
<string name="server_timeout_warning">चेतावनी: सर्वर स्थिति परिवर्तन का समय समाप्त हो गया।</string>
|
|
||||||
<string name="system_ready">सिस्टम तैयार...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">हॉटस्पॉट</string>
|
|
||||||
<string name="tunnel">टनल</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">नेटवर्क पर सामग्री साझा करने के लिए Wi-Fi या हॉटस्पॉट सक्षम करें।</string>
|
|
||||||
<string name="qr_error_no_server">नेटवर्क पर सामग्री साझा करने के लिए सर्वर लॉन्च करें।</string>
|
|
||||||
<string name="qr_flip_network">नेटवर्क स्विच करें</string>
|
|
||||||
<string name="qr_title_hotspot">हॉटस्पॉट नेटवर्क</string>
|
|
||||||
<string name="qr_title_wifi">Wi-Fi नेटवर्क</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Safe Pocket Web अक्षम करें</string>
|
|
||||||
<string name="control_enable">Safe Pocket Web सक्षम करें</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">ग्लोबल</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">रखरखाव मोड</string>
|
|
||||||
<string name="maintenance_warning_msg">संशोधन करने के लिए Safe Pocket Web अक्षम करें</string>
|
|
||||||
<string name="remote_dns">रिमोट DNS</string>
|
|
||||||
<string name="socks_addr">Socks पता:</string>
|
|
||||||
<string name="socks_pass">Socks पासवर्ड:</string>
|
|
||||||
<string name="socks_port">Socks पोर्ट:</string>
|
|
||||||
<string name="socks_udp_addr">Socks UDP पता:</string>
|
|
||||||
<string name="socks_user">Socks उपयोगकर्ता नाम:</string>
|
|
||||||
<string name="udp_in_tcp">TCP पर UDP रिले</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">VPN रिकवरी</string>
|
|
||||||
<string name="recovery_notif_text">सुरक्षित वातावरण को तुरंत बहाल करने के लिए टैप करें।</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web बाधित</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">उपयोगकर्ता द्वारा शुरू किया गया कनेक्शन</string>
|
|
||||||
<string name="vpn_description">अनुकूल URL सक्षम करें। खतरों को ब्लॉक करें।</string>
|
|
||||||
<string name="vpn_permission_granted">VPN अनुमति दी गई। कनेक्ट हो रहा है...</string>
|
|
||||||
<string name="vpn_starting">VPN शुरू हो रहा है...</string>
|
|
||||||
<string name="vpn_stopping">VPN बंद हो रहा है...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">मास्टर वॉचडॉग\nअक्षम करें</string>
|
|
||||||
<string name="watchdog_enable">मास्टर वॉचडॉग\nसक्षम करें</string>
|
|
||||||
<string name="watchdog_description">Termux को Doze मोड से बचाता है और Wi-Fi को सक्रिय रखता है।</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">यह सुनिश्चित करता है कि स्क्रीन बंद होने पर भी सेवाएं सक्रिय रहें।</string>
|
|
||||||
<string name="watchdog_channel_name">IIAB वॉचडॉग सेवा</string>
|
|
||||||
<string name="watchdog_notif_text">Termux वातावरण की सुरक्षा...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB वॉचडॉग सक्रिय</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">VPN सुरक्षा के तहत CPU WakeLock प्राप्त</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock जारी</string>
|
|
||||||
<string name="error_acquiring_locks">लॉक प्राप्त करने में त्रुटि</string>
|
|
||||||
<string name="syncing_watchdog">वॉचडॉग स्थिति सिंक हो रही है। सक्षम: %b</string>
|
|
||||||
<string name="watchdog_started">वॉचडॉग शुरू</string>
|
|
||||||
<string name="watchdog_stopped">वॉचडॉग बंद</string>
|
|
||||||
<string name="watchdog_thread_ended">वॉचडॉग थ्रेड: लूप समाप्त</string>
|
|
||||||
<string name="watchdog_thread_error">वॉचडॉग थ्रेड: लूप में त्रुटि</string>
|
|
||||||
<string name="watchdog_thread_interrupted">वॉचडॉग थ्रेड: बाधित, बंद हो रहा है...</string>
|
|
||||||
<string name="watchdog_thread_started">वॉचडॉग थ्रेड: लूप शुरू हुआ</string>
|
|
||||||
<string name="wifi_lock_acquired">VPN सुरक्षा के तहत Wi-Fi Lock प्राप्त</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock जारी</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">क्रिटिकल: OS ने Termux उत्तेजना को ब्लॉक कर दिया (SecurityException)।</string>
|
|
||||||
<string name="failed_termux_intent">क्रिटिकल: Termux इंटेंट विफल: %s</string>
|
|
||||||
<string name="force_termux_foreground">Termux को फॉरग्राउंड में मजबूर किया जा रहा है...</string>
|
|
||||||
<string name="maintenance_mode_enabled">रखरखाव मोड सक्षम: Termux के पास सीधा इंटरनेट एक्सेस है</string>
|
|
||||||
<string name="maintenance_write_failed">रखरखाव लेखन विफल</string>
|
|
||||||
<string name="permission_denied_log">अनुमति अस्वीकार: सुनिश्चित करें कि मैनिफ़ेस्ट में RUN_COMMAND है और ऐप प्रतिबंधित नहीं है।</string>
|
|
||||||
<string name="ping_fail">PING 8085: विफल (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">पल्स त्रुटि: %s</string>
|
|
||||||
<string name="pulse_stimulating">पल्स: Termux को उत्तेजित करना...</string>
|
|
||||||
<string name="recovery_pulse_received">सिस्टम से रिकवरी पल्स प्राप्त। VPN लागू किया जा रहा है...</string>
|
|
||||||
<string name="sent_to_termux">Termux को भेजा गया: %s</string>
|
|
||||||
<string name="session_started">हार्टबीट सत्र शुरू हुआ</string>
|
|
||||||
<string name="session_stopped">हार्टबीट सत्र बंद हुआ</string>
|
|
||||||
<string name="termux_invocation_error">Termux को बुलाने में त्रुटि: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] पल्स त्रुटि (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] स्टिमुलस OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">Termux नहीं खुल रहा है? फोकस पाने के लिए मास्टर वॉचडॉग सक्षम करें।</string>
|
|
||||||
<string name="unexpected_error_termux">Termux पर इंटेंट भेजने में अनपेक्षित त्रुटि</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- इतिहास का अंत ---</string>
|
|
||||||
<string name="error_reading_history">इतिहास पढ़ने में त्रुटि: %s</string>
|
|
||||||
<string name="failed_write_blackbox">BlackBox में लिखने में विफल</string>
|
|
||||||
<string name="loading_history">--- इतिहास लोड हो रहा है ---</string>
|
|
||||||
<string name="log_cleared_toast">लॉग साफ़ किया गया</string>
|
|
||||||
<string name="log_copied_toast">लॉग क्लिपबोर्ड पर कॉपी किया गया</string>
|
|
||||||
<string name="log_reset_confirm_msg">यह सभी संग्रहीत कनेक्शन लॉग को स्थायी रूप से हटा देगा। यह कार्रवाई पूर्ववत नहीं की जा सकती।</string>
|
|
||||||
<string name="log_reset_confirm_title">लॉग इतिहास रीसेट करें?</string>
|
|
||||||
<string name="failed_reset_log">लॉग रीसेट करने में विफल: %s</string>
|
|
||||||
<string name="log_reset_log">लॉग रीसेट किया गया</string>
|
|
||||||
<string name="log_reset_user">उपयोगकर्ता द्वारा लॉग रीसेट</string>
|
|
||||||
<string name="log_size_bytes">%d B</string>
|
|
||||||
<string name="log_size_format">आकार: %1$s / 10MB</string>
|
|
||||||
<string name="log_size_kb">%.1f KB</string>
|
|
||||||
<string name="log_size_mb">%.2f MB</string>
|
|
||||||
<string name="log_warning_rapid_growth">लॉग फ़ाइल बहुत तेज़ी से बढ़ रही है, आपको जांचना चाहिए कि क्या कुछ विफल हो रहा है</string>
|
|
||||||
<string name="no_blackbox_found">--- कोई BlackBox फ़ाइल नहीं मिली ---</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">सुरक्षित वातावरण को अक्षम करने के लिए प्रमाणित करें</string>
|
|
||||||
<string name="auth_required_title">प्रमाणीकरण आवश्यक है</string>
|
|
||||||
<string name="auth_success_disconnect">प्रमाणीकरण सफल। डिस्कनेक्ट हो रहा है...</string>
|
|
||||||
<string name="security_required_msg">सुरक्षित वातावरण को सक्षम करने से पहले आपको अपने डिवाइस पर PIN, पैटर्न या फ़िंगरप्रिंट सेट करना होगा।</string>
|
|
||||||
<string name="security_required_title">सुरक्षा आवश्यक</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Termux सुरक्षा को रोकने के लिए प्रमाणीकरण आवश्यक है</string>
|
|
||||||
<string name="unlock_watchdog_title">मास्टर वॉचडॉग अनलॉक करें</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">ऐप को 100% काम करने के लिए, कृपया बैटरी अनुकूलन को अक्षम करें।</string>
|
|
||||||
<string name="battery_opt_msg">वॉचडॉग के विश्वसनीय रूप से काम करने के लिए, कृपया इस ऐप के लिए बैटरी अनुकूलन को अक्षम करें।</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme पहचाना गया: कृपया सुनिश्चित करें कि आप इस ऐप की सेटिंग्स में \'Allow background activity\' सक्षम करें।</string>
|
|
||||||
<string name="battery_opt_title">बैटरी अनुकूलन</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi पहचाना गया: कृपया सेटिंग्स में बैटरी सेवर को \'No restrictions\' पर सेट करें।</string>
|
|
||||||
<string name="go_to_settings">सेटिंग्स पर जाएं</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">एप्लिकेशन शुरू हुआ</string>
|
|
||||||
<string name="deploy_wip_desc">Termux मॉड्यूल और वातावरण इंस्टॉलर जल्द ही यहां उपलब्ध होंगे।</string>
|
|
||||||
<string name="deploy_wip_title">WIP - निर्माणाधीन</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Battery: "</string>
|
|
||||||
<string name="battery_no_value">Battery: --%</string>
|
|
||||||
<string name="hotspot_fdash">हॉटस्पॉट: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">सहेजा गया</string>
|
|
||||||
<string name="settings_saved">सेटिंग्स सहेजी गईं</string>
|
|
||||||
<string name="uptime_no_value">अपटाइम: --</string>
|
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
|
||||||
<string name="setup_display_over_other_apps">Display over other apps</string>
|
|
||||||
<string name="setup_manage_all_permissions">Manage All Permissions</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Manage Termux permissions</string>
|
|
||||||
<string name="setup_termux_custom_permissions">Termux custom permissions</string>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<color name="dash_bg_main">#121212</color>
|
|
||||||
<color name="dash_bg_card">#242424</color>
|
|
||||||
<color name="dash_text_primary">#FAFAFA</color>
|
|
||||||
<color name="dash_text_secondary">#BDBDBD</color>
|
|
||||||
<color name="dash_module_bg">#242424</color>
|
|
||||||
<color name="dash_module_text">#FFFFFF</color>
|
|
||||||
<color name="dash_divider">#333333</color>
|
|
||||||
<color name="dash_warning">#FFB300</color>
|
|
||||||
<color name="dash_status_online">#4CAF50</color>
|
|
||||||
|
|
||||||
<color name="footer_text_color">#888888</color>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,231 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
|
||||||
<string name="default_version">v0.1.x</string>
|
|
||||||
|
|
||||||
<string name="cancel">Cancelar</string>
|
|
||||||
<string name="copy_all">Copiar Tudo</string>
|
|
||||||
<string name="fix_action">CORRIGIR</string>
|
|
||||||
<string name="save">Salvar</string>
|
|
||||||
|
|
||||||
<string name="advanced_settings_label">Configurações do Túnel</string>
|
|
||||||
<string name="configuration_label">Configuração</string>
|
|
||||||
<string name="connection_log_label">Log de Conexão</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">CONFIGURAÇÕES</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">Instalação</string>
|
|
||||||
<string name="tab_status">Status</string>
|
|
||||||
<string name="tab_usage">Uso</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">Configuração Inicial</string>
|
|
||||||
<string name="setup_welcome">Bem-vindo ao assistente de configuração do %1$s.\n\nPara funcionar corretamente, precisamos das seguintes permissões:</string>
|
|
||||||
<string name="setup_continue">Continuar</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">Desativar Otimização de Bateria</string>
|
|
||||||
<string name="setup_perm_notifications">Notificações Push</string>
|
|
||||||
<string name="setup_perm_storage">Acesso ao armazenamento local</string>
|
|
||||||
<string name="setup_perm_termux">Execução do Termux</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">Arquivos e mídia (Armazenamento)</string>
|
|
||||||
<string name="termux_not_installed">O Termux não está instalado.</string>
|
|
||||||
<string name="termux_not_installed_error">O Termux não está instalado ou o dispositivo não é compatível.</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">Permissão de notificação negada</string>
|
|
||||||
<string name="notif_perm_granted">Permissão de notificação concedida</string>
|
|
||||||
<string name="revoke_permission_warning">Para revogar permissões, você deve fazê-lo nas configurações do sistema.</string>
|
|
||||||
<string name="termux_perm_denied">Permissão do Termux negada</string>
|
|
||||||
<string name="termux_perm_granted">Permissão do Termux concedida</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">Carregando o dispositivo...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">Tempo de atividade: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>Bateria:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>Bateria:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>Hotspot:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>Tempo de atividade:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">Armazenamento principal</string>
|
|
||||||
<string name="dash_ram_memory">Memória RAM</string>
|
|
||||||
<string name="dash_swap_virtual">Swap (Virtual)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">Status do Servidor:</string>
|
|
||||||
<string name="dash_offline">Offline</string>
|
|
||||||
<string name="dash_online">Online</string>
|
|
||||||
<string name="dash_system_state">Estado do Sistema</string>
|
|
||||||
<string name="dash_iiab_system">Sistema IIAB-oA</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">SO base instalado. Prossiga com a instalação do IIAB.</string>
|
|
||||||
<string name="dash_state_installer">Instalador encontrado, abra a aba de instalação para mais informações.</string>
|
|
||||||
<string name="dash_state_none">Nenhum componente identificado, nem mesmo o Termux.</string>
|
|
||||||
<string name="dash_state_offline">O IIAB-oA parece estar offline, tente iniciá-lo.</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA está online.</string>
|
|
||||||
<string name="dash_state_termux_only">Termux encontrado, vá para a aba Instalação para gerenciá-lo.</string>
|
|
||||||
<string name="dash_termux_searching">Buscando instalação...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">Módulos Instalados</string>
|
|
||||||
<string name="dash_books">Livros</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">Mapas</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">Sistema</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">Aplicativos</string>
|
|
||||||
<string name="browse_content">🚀 Explorar Conteúdo</string>
|
|
||||||
<string name="launch_server">🚀 Iniciar Servidor</string>
|
|
||||||
<string name="stop_server">🛑 Parar Servidor</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">O sistema IIAB-oA não parece estar (totalmente) instalado. Verifique a aba Status ou Instalação para mais informações.</string>
|
|
||||||
<string name="server_booting">Inicializando...</string>
|
|
||||||
<string name="server_shutting_down">Desligando...</string>
|
|
||||||
<string name="server_timeout_warning">Aviso: Tempo limite de transição de estado do servidor excedido.</string>
|
|
||||||
<string name="system_ready">Sistema pronto...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">Hotspot</string>
|
|
||||||
<string name="tunnel">Túnel</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">Ative o Wi-Fi ou Hotspot para compartilhar conteúdo pela rede.</string>
|
|
||||||
<string name="qr_error_no_server">Inicie o servidor para compartilhar conteúdo pela rede.</string>
|
|
||||||
<string name="qr_flip_network">Trocar Rede</string>
|
|
||||||
<string name="qr_title_hotspot">Rede Hotspot</string>
|
|
||||||
<string name="qr_title_wifi">Rede Wi-Fi</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Desativar Safe Pocket Web</string>
|
|
||||||
<string name="control_enable">Ativar Safe Pocket Web</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">Global</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">Modo de Manutenção</string>
|
|
||||||
<string name="maintenance_warning_msg">Desative o Safe Pocket Web para poder modificar</string>
|
|
||||||
<string name="remote_dns">DNS Remoto</string>
|
|
||||||
<string name="socks_addr">Endereço Socks:</string>
|
|
||||||
<string name="socks_pass">Senha Socks:</string>
|
|
||||||
<string name="socks_port">Porta Socks:</string>
|
|
||||||
<string name="socks_udp_addr">Endereço UDP Socks:</string>
|
|
||||||
<string name="socks_user">Usuário Socks:</string>
|
|
||||||
<string name="udp_in_tcp">Relé UDP sobre TCP</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">Recuperação de VPN</string>
|
|
||||||
<string name="recovery_notif_text">Toque para restaurar o ambiente seguro imediatamente.</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web Interrompido</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">Conexão iniciada pelo usuário</string>
|
|
||||||
<string name="vpn_description">Ative URLs amigáveis. Bloqueie as ameaças.</string>
|
|
||||||
<string name="vpn_permission_granted">Permissão de VPN concedida. Conectando...</string>
|
|
||||||
<string name="vpn_starting">Iniciando VPN...</string>
|
|
||||||
<string name="vpn_stopping">Parando VPN...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">Desativar\nWatchdog Mestre</string>
|
|
||||||
<string name="watchdog_enable">Ativar\nWatchdog Mestre</string>
|
|
||||||
<string name="watchdog_description">Protege o Termux do modo Doze e mantém o Wi-Fi ativo.</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">Garante que os serviços permaneçam ativos quando a tela estiver desligada.</string>
|
|
||||||
<string name="watchdog_channel_name">Serviço IIAB Watchdog</string>
|
|
||||||
<string name="watchdog_notif_text">Protegendo o ambiente Termux...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB Watchdog Ativo</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">CPU WakeLock adquirido sob proteção VPN</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock liberado</string>
|
|
||||||
<string name="error_acquiring_locks">Erro ao adquirir bloqueios</string>
|
|
||||||
<string name="syncing_watchdog">Sincronizando estado do Watchdog. Ativado: %b</string>
|
|
||||||
<string name="watchdog_started">Watchdog Iniciado</string>
|
|
||||||
<string name="watchdog_stopped">Watchdog Parado</string>
|
|
||||||
<string name="watchdog_thread_ended">Watchdog Thread: Loop encerrado</string>
|
|
||||||
<string name="watchdog_thread_error">Watchdog Thread: Erro no loop</string>
|
|
||||||
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrompido, parando...</string>
|
|
||||||
<string name="watchdog_thread_started">Watchdog Thread: Loop iniciado</string>
|
|
||||||
<string name="wifi_lock_acquired">Wi-Fi Lock adquirido sob proteção VPN</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock liberado</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">CRÍTICO: O SO bloqueou o estímulo do Termux (SecurityException).</string>
|
|
||||||
<string name="failed_termux_intent">CRÍTICO: Falha no Intent do Termux: %s</string>
|
|
||||||
<string name="force_termux_foreground">Forçando o Termux para o primeiro plano...</string>
|
|
||||||
<string name="maintenance_mode_enabled">Modo de manutenção ativado: Termux tem acesso direto à Internet</string>
|
|
||||||
<string name="maintenance_write_failed">Falha na escrita de manutenção</string>
|
|
||||||
<string name="permission_denied_log">Permissão Negada: Certifique-se de que o manifesto tem RUN_COMMAND e o aplicativo não está restrito.</string>
|
|
||||||
<string name="ping_fail">PING 8085: FALHA (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">Erro de Pulso: %s</string>
|
|
||||||
<string name="pulse_stimulating">Pulso: Estimulando o Termux...</string>
|
|
||||||
<string name="recovery_pulse_received">Pulso de recuperação recebido do sistema. Forçando VPN...</string>
|
|
||||||
<string name="sent_to_termux">Enviado para o Termux: %s</string>
|
|
||||||
<string name="session_started">SESSÃO DE BATIMENTO CARDÍACO INICIADA</string>
|
|
||||||
<string name="session_stopped">SESSÃO DE BATIMENTO CARDÍACO PARADA</string>
|
|
||||||
<string name="termux_invocation_error">Erro ao invocar Termux: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] Erro de Pulso (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] Estímulo OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">Termux não abre? Ative o Watchdog Mestre para forçá-lo a ganhar foco.</string>
|
|
||||||
<string name="unexpected_error_termux">Erro inesperado ao enviar intent para o Termux</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- Fim do Histórico ---</string>
|
|
||||||
<string name="error_reading_history">Erro ao ler histórico: %s</string>
|
|
||||||
<string name="failed_write_blackbox">Falha ao escrever no BlackBox</string>
|
|
||||||
<string name="loading_history">--- Carregando Histórico ---</string>
|
|
||||||
<string name="log_cleared_toast">Log limpo</string>
|
|
||||||
<string name="log_copied_toast">Log copiado para a área de transferência</string>
|
|
||||||
<string name="log_reset_confirm_msg">Isso apagará permanentemente todos os logs de conexão armazenados. Esta ação não pode ser desfeita.</string>
|
|
||||||
<string name="log_reset_confirm_title">Redefinir Histórico de Log?</string>
|
|
||||||
<string name="failed_reset_log">Falha ao redefinir log: %s</string>
|
|
||||||
<string name="log_reset_log">Log redefinido</string>
|
|
||||||
<string name="log_reset_user">Log redefinido pelo usuário</string>
|
|
||||||
<string name="log_size_bytes">%d B</string>
|
|
||||||
<string name="log_size_format">Tamanho: %1$s / 10MB</string>
|
|
||||||
<string name="log_size_kb">%.1f KB</string>
|
|
||||||
<string name="log_size_mb">%.2f MB</string>
|
|
||||||
<string name="log_warning_rapid_growth">O arquivo de log está crescendo muito rapidamente, verifique se algo está falhando</string>
|
|
||||||
<string name="no_blackbox_found">--- Nenhum arquivo BlackBox encontrado ---</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">Autentique-se para desativar o ambiente seguro</string>
|
|
||||||
<string name="auth_required_title">Autenticação necessária</string>
|
|
||||||
<string name="auth_success_disconnect">Autenticação bem-sucedida. Desconectando...</string>
|
|
||||||
<string name="security_required_msg">Você deve definir um PIN, Padrão ou Impressão Digital no seu dispositivo antes de ativar o ambiente seguro.</string>
|
|
||||||
<string name="security_required_title">Segurança Necessária</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Autenticação necessária para parar a proteção do Termux</string>
|
|
||||||
<string name="unlock_watchdog_title">Desbloquear Watchdog Mestre</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">Para que o app funcione 100%, desative a otimização de bateria.</string>
|
|
||||||
<string name="battery_opt_msg">Para que o Watchdog funcione de forma confiável, desative as otimizações de bateria para este aplicativo.</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detectado: Certifique-se de ativar \'Permitir atividade em segundo plano\' nas configurações deste aplicativo.</string>
|
|
||||||
<string name="battery_opt_title">Otimização de Bateria</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detectado: Defina a economia de bateria para \'Sem restrições\' nas configurações.</string>
|
|
||||||
<string name="go_to_settings">Ir para Configurações</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">Aplicativo Iniciado</string>
|
|
||||||
<string name="deploy_wip_desc">O módulo Termux e o instalador de ambiente estarão disponíveis aqui em breve.</string>
|
|
||||||
<string name="deploy_wip_title">WIP - Em Construção</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Bateria: "</string>
|
|
||||||
<string name="battery_no_value">Bateria: --%</string>
|
|
||||||
<string name="hotspot_fdash">Hotspot: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">Salvo</string>
|
|
||||||
<string name="settings_saved">Configurações salvas</string>
|
|
||||||
<string name="uptime_no_value">Tempo de atividade: --</string>
|
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
|
||||||
<string name="setup_display_over_other_apps">Display over other apps</string>
|
|
||||||
<string name="setup_manage_all_permissions">Manage All Permissions</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Manage Termux permissions</string>
|
|
||||||
<string name="setup_termux_custom_permissions">Termux custom permissions</string>
|
|
||||||
</resources>
|
|
||||||
|
|
@ -1,231 +1,155 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- General App -->
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
<string name="app_name">IIAB-oA Controller</string>
|
||||||
<string name="default_version">v0.1.x</string>
|
<string name="default_version">v0.1.x</string>
|
||||||
|
|
||||||
<string name="cancel">Отмена</string>
|
|
||||||
<string name="copy_all">Скопировать все</string>
|
|
||||||
<string name="fix_action">ИСПРАВИТЬ</string>
|
|
||||||
<string name="save">Сохранить</string>
|
<string name="save">Сохранить</string>
|
||||||
|
<string name="cancel">Отмена</string>
|
||||||
<string name="advanced_settings_label">Настройки туннеля</string>
|
|
||||||
<string name="configuration_label">Конфигурация</string>
|
|
||||||
<string name="connection_log_label">Журнал подключений</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">НАСТРОЙКИ</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">Установка</string>
|
|
||||||
<string name="tab_status">Статус</string>
|
|
||||||
<string name="tab_usage">Использование</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">Начальная настройка</string>
|
|
||||||
<string name="setup_welcome">Добро пожаловать в мастер настройки %1$s.\n\nДля правильной работы нам нужны следующие разрешения:</string>
|
|
||||||
<string name="setup_continue">Продолжить</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">Отключить оптимизацию батареи</string>
|
|
||||||
<string name="setup_perm_notifications">Push-уведомления</string>
|
|
||||||
<string name="setup_perm_storage">Доступ к локальному хранилищу</string>
|
|
||||||
<string name="setup_perm_termux">Выполнение Termux</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">Файлы и медиа (Хранилище)</string>
|
|
||||||
<string name="termux_not_installed">Termux не установлен.</string>
|
|
||||||
<string name="termux_not_installed_error">Termux не установлен или устройство не поддерживается.</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">Разрешение на уведомления отклонено</string>
|
|
||||||
<string name="notif_perm_granted">Разрешение на уведомления предоставлено</string>
|
|
||||||
<string name="revoke_permission_warning">Чтобы отозвать разрешения, это нужно сделать в настройках системы.</string>
|
|
||||||
<string name="termux_perm_denied">Разрешение Termux отклонено</string>
|
|
||||||
<string name="termux_perm_granted">Разрешение Termux предоставлено</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">Загрузка устройства...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">Время работы: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>Батарея:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>Батарея:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>Точка доступа:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>Время работы:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">Основная память</string>
|
|
||||||
<string name="dash_ram_memory">ОЗУ</string>
|
|
||||||
<string name="dash_swap_virtual">Swap (Виртуальная)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">Статус сервера:</string>
|
|
||||||
<string name="dash_offline">Оффлайн</string>
|
|
||||||
<string name="dash_online">В сети</string>
|
|
||||||
<string name="dash_system_state">Состояние системы</string>
|
|
||||||
<string name="dash_iiab_system">Система IIAB-oA</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">ОС установлена. Перейдите к установке IIAB.</string>
|
|
||||||
<string name="dash_state_installer">Установщик найден, откройте вкладку установки для получения подробной информации.</string>
|
|
||||||
<string name="dash_state_none">Компоненты не найдены, даже Termux.</string>
|
|
||||||
<string name="dash_state_offline">IIAB-oA оффлайн, попробуйте запустить его.</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA доступен онлайн.</string>
|
|
||||||
<string name="dash_state_termux_only">Termux найден, перейдите на вкладку Установка, чтобы управлять им.</string>
|
|
||||||
<string name="dash_termux_searching">Поиск установки...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">Установленные модули</string>
|
|
||||||
<string name="dash_books">Книги</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">Карты</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">Система</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">Приложения</string>
|
|
||||||
<string name="browse_content">🚀 Исследовать контент</string>
|
|
||||||
<string name="launch_server">🚀 Запустить сервер</string>
|
|
||||||
<string name="stop_server">🛑 Остановить сервер</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">Система IIAB-oA (полностью) не установлена. Проверьте вкладку Статус или Установка для получения подробной информации.</string>
|
|
||||||
<string name="server_booting">Загрузка...</string>
|
|
||||||
<string name="server_shutting_down">Выключение...</string>
|
|
||||||
<string name="server_timeout_warning">Предупреждение: Время ожидания перехода состояния сервера истекло.</string>
|
|
||||||
<string name="system_ready">Система готова...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">Точка доступа</string>
|
|
||||||
<string name="tunnel">Туннель</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">Включите Wi-Fi или точку доступа, чтобы поделиться контентом по сети.</string>
|
|
||||||
<string name="qr_error_no_server">Запустите сервер, чтобы поделиться контентом по сети.</string>
|
|
||||||
<string name="qr_flip_network">Переключить сеть</string>
|
|
||||||
<string name="qr_title_hotspot">Сеть точки доступа</string>
|
|
||||||
<string name="qr_title_wifi">Сеть Wi-Fi</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Выключить Safe Pocket Web</string>
|
|
||||||
<string name="control_enable">Включить Safe Pocket Web</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">Глобально</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">Режим обслуживания</string>
|
|
||||||
<string name="maintenance_warning_msg">Отключите Safe Pocket Web для внесения изменений</string>
|
|
||||||
<string name="remote_dns">Удаленный DNS</string>
|
|
||||||
<string name="socks_addr">Адрес Socks:</string>
|
|
||||||
<string name="socks_pass">Пароль Socks:</string>
|
|
||||||
<string name="socks_port">Порт Socks:</string>
|
|
||||||
<string name="socks_udp_addr">UDP адрес Socks:</string>
|
|
||||||
<string name="socks_user">Имя пользователя Socks:</string>
|
|
||||||
<string name="udp_in_tcp">UDP ретрансляция через TCP</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">Восстановление VPN</string>
|
|
||||||
<string name="recovery_notif_text">Нажмите, чтобы немедленно восстановить безопасное окружение.</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web прерван</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">Соединение инициировано пользователем</string>
|
|
||||||
<string name="vpn_description">Включить дружественные URL. Блокировать угрозы.</string>
|
|
||||||
<string name="vpn_permission_granted">Разрешение VPN получено. Подключение...</string>
|
|
||||||
<string name="vpn_starting">Запуск VPN...</string>
|
|
||||||
<string name="vpn_stopping">Остановка VPN...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">Выключить\nМастер Watchdog</string>
|
|
||||||
<string name="watchdog_enable">Включить\nМастер Watchdog</string>
|
|
||||||
<string name="watchdog_description">Защищает Termux от режима Doze и поддерживает Wi-Fi активным.</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">Гарантирует, что службы остаются активными при выключенном экране.</string>
|
|
||||||
<string name="watchdog_channel_name">Служба IIAB Watchdog</string>
|
|
||||||
<string name="watchdog_notif_text">Защита окружения Termux...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB Watchdog активен</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">CPU WakeLock получен под защитой VPN</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock освобожден</string>
|
|
||||||
<string name="error_acquiring_locks">Ошибка получения блокировок</string>
|
|
||||||
<string name="syncing_watchdog">Синхронизация состояния Watchdog. Включено: %b</string>
|
|
||||||
<string name="watchdog_started">Watchdog запущен</string>
|
|
||||||
<string name="watchdog_stopped">Watchdog остановлен</string>
|
|
||||||
<string name="watchdog_thread_ended">Watchdog Thread: Цикл завершен</string>
|
|
||||||
<string name="watchdog_thread_error">Watchdog Thread: Ошибка в цикле</string>
|
|
||||||
<string name="watchdog_thread_interrupted">Watchdog Thread: Прервано, остановка...</string>
|
|
||||||
<string name="watchdog_thread_started">Watchdog Thread: Цикл запущен</string>
|
|
||||||
<string name="wifi_lock_acquired">Wi-Fi Lock получен под защитой VPN</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock освобожден</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">КРИТИЧЕСКАЯ ОШИБКА: ОС заблокировала стимуляцию Termux (SecurityException).</string>
|
|
||||||
<string name="failed_termux_intent">КРИТИЧЕСКАЯ ОШИБКА: Ошибка Intent Termux: %s</string>
|
|
||||||
<string name="force_termux_foreground">Принудительно перевести Termux на передний план...</string>
|
|
||||||
<string name="maintenance_mode_enabled">Режим обслуживания включен: Termux имеет прямой доступ в Интернет</string>
|
|
||||||
<string name="maintenance_write_failed">Ошибка записи обслуживания</string>
|
|
||||||
<string name="permission_denied_log">В доступе отказано: убедитесь, что в манифесте есть RUN_COMMAND и приложение не ограничено.</string>
|
|
||||||
<string name="ping_fail">PING 8085: ОШИБКА (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">Ошибка пульса: %s</string>
|
|
||||||
<string name="pulse_stimulating">Пульс: Стимуляция Termux...</string>
|
|
||||||
<string name="recovery_pulse_received">Пульс восстановления получен от системы. Принудительный VPN...</string>
|
|
||||||
<string name="sent_to_termux">Отправлено в Termux: %s</string>
|
|
||||||
<string name="session_started">СЕАНС СЕРДЦЕБИЕНИЯ ЗАПУЩЕН</string>
|
|
||||||
<string name="session_stopped">СЕАНС СЕРДЦЕБИЕНИЯ ОСТАНОВЛЕН</string>
|
|
||||||
<string name="termux_invocation_error">Ошибка вызова Termux: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] Ошибка пульса (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] Стимул OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">Termux не открывается? Включите Мастер Watchdog, чтобы принудительно вывести его на передний план.</string>
|
|
||||||
<string name="unexpected_error_termux">Непредвиденная ошибка при отправке intent в Termux</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- Конец истории ---</string>
|
|
||||||
<string name="error_reading_history">Ошибка чтения истории: %s</string>
|
|
||||||
<string name="failed_write_blackbox">Ошибка записи в BlackBox</string>
|
|
||||||
<string name="loading_history">--- Загрузка истории ---</string>
|
|
||||||
<string name="log_cleared_toast">Журнал очищен</string>
|
|
||||||
<string name="log_copied_toast">Журнал скопирован в буфер обмена</string>
|
|
||||||
<string name="log_reset_confirm_msg">Это безвозвратно удалит все сохраненные журналы подключений. Это действие нельзя отменить.</string>
|
|
||||||
<string name="log_reset_confirm_title">Сбросить историю журнала?</string>
|
|
||||||
<string name="failed_reset_log">Ошибка сброса журнала: %s</string>
|
|
||||||
<string name="log_reset_log">Журнал сброшен</string>
|
|
||||||
<string name="log_reset_user">Журнал сброшен пользователем</string>
|
|
||||||
<string name="log_size_bytes">%d B</string>
|
|
||||||
<string name="log_size_format">Размер: %1$s / 10MB</string>
|
|
||||||
<string name="log_size_kb">%.1f KB</string>
|
|
||||||
<string name="log_size_mb">%.2f MB</string>
|
|
||||||
<string name="log_warning_rapid_growth">Файл журнала растет слишком быстро, возможно, стоит проверить, нет ли ошибки</string>
|
|
||||||
<string name="no_blackbox_found">--- Файл BlackBox не найден ---</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">Пройдите аутентификацию, чтобы отключить безопасное окружение</string>
|
|
||||||
<string name="auth_required_title">Требуется аутентификация</string>
|
|
||||||
<string name="auth_success_disconnect">Аутентификация успешна. Отключение...</string>
|
|
||||||
<string name="security_required_msg">Перед активацией безопасного окружения необходимо установить PIN-код, графический ключ или отпечаток пальца на устройстве.</string>
|
|
||||||
<string name="security_required_title">Требуется безопасность</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Требуется аутентификация для остановки защиты Termux</string>
|
|
||||||
<string name="unlock_watchdog_title">Разблокировать Мастер Watchdog</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">Для 100% работы приложения, пожалуйста, отключите оптимизацию батареи.</string>
|
|
||||||
<string name="battery_opt_msg">Для надежной работы Watchdog, пожалуйста, отключите оптимизацию батареи для этого приложения.</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme обнаружен: Пожалуйста, убедитесь, что вы включили "Разрешить фоновую активность" в настройках этого приложения.</string>
|
|
||||||
<string name="battery_opt_title">Оптимизация батареи</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi обнаружен: Пожалуйста, установите экономию заряда батареи на "Без ограничений" в настройках.</string>
|
|
||||||
<string name="go_to_settings">Перейти к настройкам</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">Приложение запущено</string>
|
|
||||||
<string name="deploy_wip_desc">Модуль Termux и установщик окружения скоро будут доступны здесь.</string>
|
|
||||||
<string name="deploy_wip_title">WIP - В разработке</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Батарея: "</string>
|
|
||||||
<string name="battery_no_value">Батарея: --%</string>
|
|
||||||
<string name="hotspot_fdash">Точка доступа: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">Сохранено</string>
|
<string name="saved_toast">Сохранено</string>
|
||||||
<string name="settings_saved">Настройки сохранены</string>
|
<string name="settings_saved">Настройки сохранены</string>
|
||||||
<string name="uptime_no_value">Время работы: --</string>
|
<string name="fix_action">ИСПРАВИТЬ</string>
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
<string name="configuration_label">Конфигурация</string>
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
<string name="advanced_settings_label">Настройки туннеля</string>
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
<string name="connection_log_label">Журнал подключений</string>
|
||||||
<string name="setup_display_over_other_apps">Display over other apps</string>
|
<string name="settings_label">НАСТРОЙКИ</string>
|
||||||
<string name="setup_manage_all_permissions">Manage All Permissions</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Manage Termux permissions</string>
|
<!-- SetupActivity -->
|
||||||
<string name="setup_termux_custom_permissions">Termux custom permissions</string>
|
<string name="setup_title">Начальная настройка</string>
|
||||||
|
<string name="setup_welcome">Добро пожаловать в мастер настройки %1$s.\n\nДля правильной работы нам нужны следующие разрешения:</string>
|
||||||
|
<string name="setup_perm_notifications">Push-уведомления</string>
|
||||||
|
<string name="setup_perm_termux">Выполнение Termux</string>
|
||||||
|
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
||||||
|
<string name="setup_perm_battery">Отключить оптимизацию батареи</string>
|
||||||
|
<string name="setup_continue">Продолжить</string>
|
||||||
|
<string name="revoke_permission_warning">Чтобы отозвать разрешения, это нужно сделать в настройках системы.</string>
|
||||||
|
<string name="termux_not_installed_error">Termux не установлен или устройство не поддерживается.</string>
|
||||||
|
<string name="termux_not_installed">Termux не установлен.</string>
|
||||||
|
|
||||||
|
<!-- VPN / Socks -->
|
||||||
|
<string name="control_enable">Включить Safe Pocket Web</string>
|
||||||
|
<string name="control_disable">Выключить Safe Pocket Web</string>
|
||||||
|
<string name="vpn_description">Включить дружественные URL. Блокировать угрозы.</string>
|
||||||
|
<string name="socks_addr">Адрес Socks:</string>
|
||||||
|
<string name="socks_udp_addr">UDP адрес Socks:</string>
|
||||||
|
<string name="socks_port">Порт Socks:</string>
|
||||||
|
<string name="socks_user">Имя пользователя Socks:</string>
|
||||||
|
<string name="socks_pass">Пароль Socks:</string>
|
||||||
|
<string name="dns_ipv4">DNS IPv4:</string>
|
||||||
|
<string name="dns_ipv6">DNS IPv6:</string>
|
||||||
|
<string name="udp_in_tcp">UDP ретрансляция через TCP</string>
|
||||||
|
<string name="remote_dns">Удаленный DNS</string>
|
||||||
|
<string name="ipv4">IPv4</string>
|
||||||
|
<string name="ipv6">IPv6</string>
|
||||||
|
<string name="global">Глобально</string>
|
||||||
|
<string name="apps">Приложения</string>
|
||||||
|
<string name="vpn_stopping">Остановка VPN...</string>
|
||||||
|
<string name="vpn_starting">Запуск VPN...</string>
|
||||||
|
<string name="user_initiated_conn">Соединение инициировано пользователем</string>
|
||||||
|
<string name="vpn_permission_granted">Разрешение VPN получено. Подключение...</string>
|
||||||
|
<string name="tproxy_channel_name">socks5</string>
|
||||||
|
|
||||||
|
<!-- WatchdogService / IIABWatchdog -->
|
||||||
|
<string name="watchdog_enable">Включить\nМастер Watchdog</string>
|
||||||
|
<string name="watchdog_disable">Выключить\nМастер Watchdog</string>
|
||||||
|
<string name="watchdog_description">Защищает Termux от режима Doze и поддерживает Wi-Fi активным.</string>
|
||||||
|
<string name="watchdog_stopped">Watchdog остановлен</string>
|
||||||
|
<string name="watchdog_started">Watchdog запущен</string>
|
||||||
|
<string name="watchdog_channel_name">Служба IIAB Watchdog</string>
|
||||||
|
<string name="watchdog_channel_desc">Гарантирует, что службы остаются активными при выключенном экране.</string>
|
||||||
|
<string name="watchdog_notif_title">IIAB Watchdog активен</string>
|
||||||
|
<string name="watchdog_notif_text">Защита окружения Termux...</string>
|
||||||
|
<string name="syncing_watchdog">Синхронизация состояния Watchdog. Включено: %b</string>
|
||||||
|
<string name="watchdog_thread_started">Watchdog Thread: Цикл запущен</string>
|
||||||
|
<string name="watchdog_thread_interrupted">Watchdog Thread: Прервано, остановка...</string>
|
||||||
|
<string name="watchdog_thread_error">Watchdog Thread: Ошибка в цикле</string>
|
||||||
|
<string name="watchdog_thread_ended">Watchdog Thread: Цикл завершен</string>
|
||||||
|
<string name="cpu_wakelock_acquired">CPU WakeLock получен под защитой VPN</string>
|
||||||
|
<string name="wifi_lock_acquired">Wi-Fi Lock получен под защитой VPN</string>
|
||||||
|
<string name="error_acquiring_locks">Ошибка получения блокировок</string>
|
||||||
|
<string name="cpu_wakelock_released">CPU WakeLock освобожден</string>
|
||||||
|
<string name="wifi_lock_released">Wi-Fi Lock освобожден</string>
|
||||||
|
|
||||||
|
<!-- Pulse / Heartbeat -->
|
||||||
|
<string name="pulse_stimulating">Пульс: Стимуляция Termux...</string>
|
||||||
|
<string name="critical_os_blocked">КРИТИЧЕСКАЯ ОШИБКА: ОС заблокировала стимуляцию Termux (SecurityException).</string>
|
||||||
|
<string name="ping_ok">PING 8085: OK</string>
|
||||||
|
<string name="ping_fail">PING 8085: ОШИБКА (%s)</string>
|
||||||
|
<string name="session_started">СЕАНС СЕРДЦЕБИЕНИЯ ЗАПУЩЕН</string>
|
||||||
|
<string name="session_stopped">СЕАНС СЕРДЦЕБИЕНИЯ ОСТАНОВЛЕН</string>
|
||||||
|
<string name="permission_denied_log">В доступе отказано: убедитесь, что в манифесте есть RUN_COMMAND и приложение не ограничено.</string>
|
||||||
|
<string name="unexpected_error_termux">Непредвиденная ошибка при отправке intent в Termux</string>
|
||||||
|
<string name="pulse_error_log">Ошибка пульса: %s</string>
|
||||||
|
<string name="maintenance_write_failed">Ошибка записи обслуживания</string>
|
||||||
|
<string name="failed_write_blackbox">Ошибка записи в BlackBox</string>
|
||||||
|
<string name="recovery_pulse_received">Пульс восстановления получен от системы. Принудительный VPN...</string>
|
||||||
|
|
||||||
|
<!-- TermuxCallbackReceiver / Operations -->
|
||||||
|
<string name="termux_stimulus_ok">[Termux] Стимул OK (exit 0)</string>
|
||||||
|
<string name="termux_pulse_error">[Termux] Ошибка пульса (exit %1$d): %2$s</string>
|
||||||
|
<string name="server_timeout_warning">Предупреждение: Время ожидания перехода состояния сервера истекло.</string>
|
||||||
|
<string name="server_booting">Загрузка...</string>
|
||||||
|
<string name="server_shutting_down">Выключение...</string>
|
||||||
|
<string name="failed_termux_intent">КРИТИЧЕСКАЯ ОШИБКА: Ошибка Intent Termux: %s</string>
|
||||||
|
<string name="sent_to_termux">Отправлено в Termux: %s</string>
|
||||||
|
<string name="maintenance_mode_enabled">Режим обслуживания включен: Termux имеет прямой доступ в Интернет</string>
|
||||||
|
<string name="stop_server">🛑 Остановить сервер</string>
|
||||||
|
<string name="launch_server">🚀 Запустить сервер</string>
|
||||||
|
<string name="termux_perm_granted">Разрешение Termux предоставлено</string>
|
||||||
|
<string name="termux_perm_denied">Разрешение Termux отклонено</string>
|
||||||
|
<string name="notif_perm_granted">Разрешение на уведомления предоставлено</string>
|
||||||
|
<string name="notif_perm_denied">Разрешение на уведомления отклонено</string>
|
||||||
|
|
||||||
|
<!-- Logs -->
|
||||||
|
<string name="log_reset_confirm_title">Сбросить историю журнала?</string>
|
||||||
|
<string name="log_reset_confirm_msg">Это безвозвратно удалит все сохраненные журналы подключений. Это действие нельзя отменить.</string>
|
||||||
|
<string name="log_warning_rapid_growth">Файл журнала растет слишком быстро, возможно, стоит проверить, нет ли ошибки</string>
|
||||||
|
<string name="reset_log">Сбросить журнал</string>
|
||||||
|
<string name="copy_all">Скопировать все</string>
|
||||||
|
<string name="log_reset_log">Журнал сброшен</string>
|
||||||
|
<string name="log_reset_user">Журнал сброшен пользователем</string>
|
||||||
|
<string name="log_copied_toast">Журнал скопирован в буфер обмена</string>
|
||||||
|
<string name="log_cleared_toast">Журнал очищен</string>
|
||||||
|
<string name="failed_reset_log">Ошибка сброса журнала: %s</string>
|
||||||
|
<string name="log_size_format">Размер: %1$s / 10MB</string>
|
||||||
|
<string name="log_size_bytes">%d B</string>
|
||||||
|
<string name="log_size_kb">%.1f KB</string>
|
||||||
|
<string name="log_size_mb">%.2f MB</string>
|
||||||
|
<string name="no_blackbox_found">--- Файл BlackBox не найден ---</string>
|
||||||
|
<string name="loading_history">--- Загрузка истории ---</string>
|
||||||
|
<string name="error_reading_history">Ошибка чтения истории: %s</string>
|
||||||
|
<string name="end_of_history">--- Конец истории ---</string>
|
||||||
|
|
||||||
|
<!-- Battery Optimizations -->
|
||||||
|
<string name="battery_opt_title">Оптимизация батареи</string>
|
||||||
|
<string name="battery_opt_msg">Для надежной работы Watchdog, пожалуйста, отключите оптимизацию батареи для этого приложения.</string>
|
||||||
|
<string name="go_to_settings">Перейти к настройкам</string>
|
||||||
|
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme обнаружен: Пожалуйста, убедитесь, что вы включили "Разрешить фоновую активность" в настройках этого приложения.</string>
|
||||||
|
<string name="battery_opt_xiaomi_extra">\n\nXiaomi обнаружен: Пожалуйста, установите экономию заряда батареи на "Без ограничений" в настройках.</string>
|
||||||
|
<string name="battery_opt_denied">Для 100% работы приложения, пожалуйста, отключите оптимизацию батареи.</string>
|
||||||
|
|
||||||
|
<!-- UI / Misc -->
|
||||||
|
<string name="browse_content">🚀 Исследовать контент</string>
|
||||||
|
<string name="system_ready">Система готова...\n</string>
|
||||||
|
<string name="app_started">Приложение запущено</string>
|
||||||
|
<string name="label_separator_down">▼ %s</string>
|
||||||
|
<string name="label_separator_up">▶ %s</string>
|
||||||
|
<string name="qr_error_no_server">Запустите сервер, чтобы поделиться контентом по сети.</string>
|
||||||
|
<string name="qr_error_no_network">Включите Wi-Fi или точку доступа, чтобы поделиться контентом по сети.</string>
|
||||||
|
<string name="qr_title_wifi">Сеть Wi-Fi</string>
|
||||||
|
<string name="qr_title_hotspot">Сеть точки доступа</string>
|
||||||
|
<string name="qr_flip_network">Переключить сеть</string>
|
||||||
|
|
||||||
|
<!-- Authentication / Security -->
|
||||||
|
<string name="unlock_watchdog_title">Разблокировать Мастер Watchdog</string>
|
||||||
|
<string name="unlock_watchdog_subtitle">Требуется аутентификация для остановки защиты Termux</string>
|
||||||
|
<string name="auth_success_disconnect">Аутентификация успешна. Отключение...</string>
|
||||||
|
<string name="auth_required_title">Требуется аутентификация</string>
|
||||||
|
<string name="auth_required_subtitle">Пройдите аутентификацию, чтобы отключить безопасное окружение</string>
|
||||||
|
<string name="security_required_title">Требуется безопасность</string>
|
||||||
|
<string name="security_required_msg">Перед активацией безопасного окружения необходимо установить PIN-код, графический ключ или отпечаток пальца на устройстве.</string>
|
||||||
|
|
||||||
|
<!-- VPN Recovery Service -->
|
||||||
|
<string name="recovery_channel_name">Восстановление VPN</string>
|
||||||
|
<string name="recovery_notif_title">Safe Pocket Web прерван</string>
|
||||||
|
<string name="recovery_notif_text">Нажмите, чтобы немедленно восстановить безопасное окружение.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -28,28 +28,4 @@
|
||||||
<color name="divider_color">#444444</color>
|
<color name="divider_color">#444444</color>
|
||||||
<color name="btn_danger">#D32F2F</color>
|
<color name="btn_danger">#D32F2F</color>
|
||||||
<color name="btn_success">#388E3C</color>
|
<color name="btn_success">#388E3C</color>
|
||||||
|
|
||||||
<color name="bar_storage">#4DB6AC</color>
|
|
||||||
<color name="bar_ram">#FFB300</color>
|
|
||||||
<color name="bar_swap">#7986CB</color>
|
|
||||||
<color name="bar_background">#333333</color>
|
|
||||||
|
|
||||||
<!-- Landing -->
|
|
||||||
<color name="dash_bar_storage">#4DB6AC</color>
|
|
||||||
<color name="dash_bar_ram">#FFB300</color>
|
|
||||||
<color name="dash_bar_swap">#7986CB</color>
|
|
||||||
<color name="dash_badge_online">#2E7D32</color>
|
|
||||||
<color name="dash_bar_bg">#333333</color>
|
|
||||||
|
|
||||||
<color name="dash_bg_main">#F4F5F7</color>
|
|
||||||
<color name="dash_bg_card">#FFFFFF</color>
|
|
||||||
<color name="dash_text_primary">#202124</color>
|
|
||||||
<color name="dash_text_secondary">#5F6368</color>
|
|
||||||
<color name="dash_module_bg">#E8EAED</color>
|
|
||||||
<color name="dash_module_text">#202124</color>
|
|
||||||
<color name="dash_divider">#E0E0E0</color>
|
|
||||||
<color name="dash_warning">#E65100</color>
|
|
||||||
<color name="dash_status_online">#2E7D32</color>
|
|
||||||
|
|
||||||
<color name="footer_text_color">#FFFFFF</color>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<integer name="server_cool_off_duration_ms">60000</integer>
|
<integer name="server_cool_off_duration_ms">60000</integer>
|
||||||
<integer name="server_snackbar_delay_ms">20000</integer>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -1,233 +1,155 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- General App -->
|
||||||
<string name="app_name">IIAB-oA Controller</string>
|
<string name="app_name">IIAB-oA Controller</string>
|
||||||
<string name="default_version">v0.1.x</string>
|
<string name="default_version">v0.1.x</string>
|
||||||
|
|
||||||
<string name="cancel">Cancel</string>
|
|
||||||
<string name="copy_all">Copy All</string>
|
|
||||||
<string name="fix_action">FIX</string>
|
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
<string name="advanced_settings_label">Tunnel Settings</string>
|
|
||||||
<string name="configuration_label">Configuration</string>
|
|
||||||
<string name="connection_log_label">Connection Log</string>
|
|
||||||
<string name="label_separator_down">▼ %s</string>
|
|
||||||
<string name="label_separator_up">▶ %s</string>
|
|
||||||
<string name="settings_label">SETTINGS</string>
|
|
||||||
|
|
||||||
<string name="tab_deploy">Installation</string>
|
|
||||||
<string name="tab_status">Status</string>
|
|
||||||
<string name="tab_usage">Usage</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="setup_title">Initial Setup</string>
|
|
||||||
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string>
|
|
||||||
<string name="setup_continue">Continue</string>
|
|
||||||
|
|
||||||
<string name="setup_perm_battery">Disable Battery Optimization</string>
|
|
||||||
<string name="setup_perm_notifications">Push Notifications</string>
|
|
||||||
<string name="setup_perm_storage">Local Storage Access</string>
|
|
||||||
<string name="setup_perm_termux">Termux Execution</string>
|
|
||||||
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
|
||||||
|
|
||||||
<string name="setup_termux_storage_btn">Files and media (Storage)</string>
|
|
||||||
<string name="termux_not_installed">Termux is not installed.</string>
|
|
||||||
<string name="termux_not_installed_error">Termux is not installed or device not supported.</string>
|
|
||||||
|
|
||||||
<string name="notif_perm_denied">Notification permission denied</string>
|
|
||||||
<string name="notif_perm_granted">Notification permission granted</string>
|
|
||||||
<string name="revoke_permission_warning">To revoke permissions, you must do it from system settings.</string>
|
|
||||||
<string name="termux_perm_denied">Termux permission denied</string>
|
|
||||||
<string name="termux_perm_granted">Termux permission granted</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="dash_title">IIAB-oA Controller</string>
|
|
||||||
<string name="dash_subtitle_localhost">localhost</string>
|
|
||||||
|
|
||||||
<string name="dash_device">Loading device...</string>
|
|
||||||
<string name="dash_ip">IP: %1$s</string>
|
|
||||||
<string name="dash_uptime">Uptime: %1$s</string>
|
|
||||||
<string name="dash_battery_format"><b>Battery:</b> %1$d%%</string>
|
|
||||||
<string name="dash_battery_no_value"><b>Battery:</b> --%%</string>
|
|
||||||
<string name="dash_hotspot_format"><b>Hotspot:</b> %1$s</string>
|
|
||||||
<string name="dash_uptime_format"><b>Uptime:</b> %1$s</string>
|
|
||||||
<string name="dash_wifi_format"><b>Wi-Fi:</b> %1$s</string>
|
|
||||||
<string name="dash_main_storage">Main Storage</string>
|
|
||||||
<string name="dash_ram_memory">RAM Memory</string>
|
|
||||||
<string name="dash_swap_virtual">Swap (Virtual)</string>
|
|
||||||
|
|
||||||
<string name="dash_server_status">Server Status:</string>
|
|
||||||
<string name="dash_offline">Offline</string>
|
|
||||||
<string name="dash_online">Online</string>
|
|
||||||
<string name="dash_system_state">System State</string>
|
|
||||||
<string name="dash_iiab_system">IIAB-oA System</string>
|
|
||||||
|
|
||||||
<string name="dash_state_debian_only">Base OS installed. Proceed to install IIAB.</string>
|
|
||||||
<string name="dash_state_installer">Installer found, open the installation tab for more info.</string>
|
|
||||||
<string name="dash_state_none">No component identified, not even Termux.</string>
|
|
||||||
<string name="dash_state_offline">IIAB-oA seems offline, try launching it.</string>
|
|
||||||
<string name="dash_state_online">IIAB-oA is online.</string>
|
|
||||||
<string name="dash_state_termux_only">Termux found, go to Installation tab to manage it.</string>
|
|
||||||
<string name="dash_termux_searching">Searching for installation...</string>
|
|
||||||
|
|
||||||
<string name="dash_installed_modules">Installed Modules</string>
|
|
||||||
<string name="dash_books">Books</string>
|
|
||||||
<string name="dash_kiwix">Kiwix</string>
|
|
||||||
<string name="dash_kolibri">Kolibri</string>
|
|
||||||
<string name="dash_maps">Maps</string>
|
|
||||||
<string name="dash_matomo">Matomo</string>
|
|
||||||
<string name="dash_system">System</string>
|
|
||||||
<string name="dash_code">Code</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="apps">Apps</string>
|
|
||||||
<string name="browse_content">🚀 Explore Content</string>
|
|
||||||
<string name="launch_server">🚀 Launch Server</string>
|
|
||||||
<string name="stop_server">🛑 Stop Server</string>
|
|
||||||
|
|
||||||
<string name="server_not_installed_warning">The IIAB-oA system does not seem to be (fully) installed. Please check the Status or Installation tab for more info.</string>
|
|
||||||
<string name="server_booting">Booting...</string>
|
|
||||||
<string name="server_shutting_down">Shutting down...</string>
|
|
||||||
<string name="server_timeout_warning">Warning: Server state transition timed out.</string>
|
|
||||||
<string name="system_ready">System ready...\n</string>
|
|
||||||
|
|
||||||
<string name="hotspot">Hotspot</string>
|
|
||||||
<string name="tunnel">Tunnel</string>
|
|
||||||
<string name="wifi">Wi-Fi</string>
|
|
||||||
|
|
||||||
<string name="qr_error_no_network">Enable Wi-Fi or Hotspot to share content over the network.</string>
|
|
||||||
<string name="qr_error_no_server">Launch the server to share content over the network.</string>
|
|
||||||
<string name="qr_flip_network">Switch Network</string>
|
|
||||||
<string name="qr_title_hotspot">Hotspot Network</string>
|
|
||||||
<string name="qr_title_wifi">Wi-Fi Network</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="control_disable">Disable Safe Pocket Web</string>
|
|
||||||
<string name="control_enable">Enable Safe Pocket Web</string>
|
|
||||||
|
|
||||||
<string name="dns_ipv4">DNS IPv4:</string>
|
|
||||||
<string name="dns_ipv6">DNS IPv6:</string>
|
|
||||||
<string name="global">Global</string>
|
|
||||||
<string name="ipv4">IPv4</string>
|
|
||||||
<string name="ipv6">IPv6</string>
|
|
||||||
<string name="maintenance_mode">Maintenance Mode</string>
|
|
||||||
<string name="maintenance_warning_msg">Disable Safe Pocket Web in order to modify</string>
|
|
||||||
<string name="remote_dns">Remote DNS</string>
|
|
||||||
<string name="socks_addr">Socks Address:</string>
|
|
||||||
<string name="socks_pass">Socks Password:</string>
|
|
||||||
<string name="socks_port">Socks Port:</string>
|
|
||||||
<string name="socks_udp_addr">Socks UDP Address:</string>
|
|
||||||
<string name="socks_user">Socks Username:</string>
|
|
||||||
<string name="udp_in_tcp">UDP relay over TCP</string>
|
|
||||||
|
|
||||||
<string name="recovery_channel_name">VPN Recovery</string>
|
|
||||||
<string name="recovery_notif_text">Tap to restore secure environment immediately.</string>
|
|
||||||
<string name="recovery_notif_title">Safe Pocket Web Interrupted</string>
|
|
||||||
<string name="tproxy_channel_name">socks5</string>
|
|
||||||
<string name="user_initiated_conn">User initiated connection</string>
|
|
||||||
<string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
|
|
||||||
<string name="vpn_permission_granted">VPN Permission Granted. Connecting...</string>
|
|
||||||
<string name="vpn_starting">VPN Starting...</string>
|
|
||||||
<string name="vpn_stopping">VPN Stopping...</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="watchdog_disable">Disable\nMaster Watchdog</string>
|
|
||||||
<string name="watchdog_enable">Enable\nMaster Watchdog</string>
|
|
||||||
<string name="watchdog_description">Protects Termux from Doze mode and keeps Wi-Fi active.</string>
|
|
||||||
|
|
||||||
<string name="watchdog_channel_desc">Ensures services remain active when screen is off.</string>
|
|
||||||
<string name="watchdog_channel_name">IIAB Watchdog Service</string>
|
|
||||||
<string name="watchdog_notif_text">Protecting Termux environment...</string>
|
|
||||||
<string name="watchdog_notif_title">IIAB Watchdog Active</string>
|
|
||||||
|
|
||||||
<string name="cpu_wakelock_acquired">CPU WakeLock acquired under VPN shield</string>
|
|
||||||
<string name="cpu_wakelock_released">CPU WakeLock released</string>
|
|
||||||
<string name="error_acquiring_locks">Error acquiring locks</string>
|
|
||||||
<string name="syncing_watchdog">Syncing Watchdog state. Enabled: %b</string>
|
|
||||||
<string name="watchdog_started">Watchdog Started</string>
|
|
||||||
<string name="watchdog_stopped">Watchdog Stopped</string>
|
|
||||||
<string name="watchdog_thread_ended">Watchdog Thread: Loop ended</string>
|
|
||||||
<string name="watchdog_thread_error">Watchdog Thread: Error in loop</string>
|
|
||||||
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrupted, stopping...</string>
|
|
||||||
<string name="watchdog_thread_started">Watchdog Thread: Started loop</string>
|
|
||||||
<string name="wifi_lock_acquired">Wi-Fi Lock acquired under VPN shield</string>
|
|
||||||
<string name="wifi_lock_released">Wi-Fi Lock released</string>
|
|
||||||
|
|
||||||
<string name="critical_os_blocked">CRITICAL: OS blocked Termux stimulus (SecurityException).</string>
|
|
||||||
<string name="failed_termux_intent">CRITICAL: Failed Termux Intent: %s</string>
|
|
||||||
<string name="force_termux_foreground">Forcing Termux to the foreground...</string>
|
|
||||||
<string name="maintenance_mode_enabled">Maintenance mode enabled: Termux has direct Internet access</string>
|
|
||||||
<string name="maintenance_write_failed">Maintenance write failed</string>
|
|
||||||
<string name="permission_denied_log">Permission Denied: Ensure manifest has RUN_COMMAND and app is not restricted.</string>
|
|
||||||
<string name="ping_fail">PING 8085: FAIL (%s)</string>
|
|
||||||
<string name="ping_ok">PING 8085: OK</string>
|
|
||||||
<string name="pulse_error_log">Pulse Error: %s</string>
|
|
||||||
<string name="pulse_stimulating">Pulse: Stimulating Termux...</string>
|
|
||||||
<string name="recovery_pulse_received">Recovery Pulse Received from System. Enforcing VPN...</string>
|
|
||||||
<string name="sent_to_termux">Sent to Termux: %s</string>
|
|
||||||
<string name="session_started">HEARTBEAT SESSION STARTED</string>
|
|
||||||
<string name="session_stopped">HEARTBEAT SESSION STOPPED</string>
|
|
||||||
<string name="termux_invocation_error">Error invoking Termux: %1$s</string>
|
|
||||||
<string name="termux_pulse_error">[Termux] Pulse Error (exit %1$d): %2$s</string>
|
|
||||||
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string>
|
|
||||||
<string name="termux_stuck_warning">Termux not opening? Enable Master Watchdog to force it to gain focus.</string>
|
|
||||||
<string name="unexpected_error_termux">Unexpected error sending intent to Termux</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="end_of_history">--- End of History ---</string>
|
|
||||||
<string name="error_reading_history">Error reading history: %s</string>
|
|
||||||
<string name="failed_write_blackbox">Failed to write to BlackBox</string>
|
|
||||||
<string name="loading_history">--- Loading History ---</string>
|
|
||||||
<string name="log_cleared_toast">Log cleared</string>
|
|
||||||
<string name="log_copied_toast">Log copied to clipboard</string>
|
|
||||||
<string name="log_reset_confirm_msg">This will permanently delete all stored connection logs. This action cannot be undone.</string>
|
|
||||||
<string name="log_reset_confirm_title">Reset Log History?</string>
|
|
||||||
<string name="failed_reset_log">Failed to reset log: %s</string>
|
|
||||||
<string name="log_reset_log">Log reset</string>
|
|
||||||
<string name="log_reset_user">Log reset by user</string>
|
|
||||||
<string name="log_size_bytes">%d B</string>
|
|
||||||
<string name="log_size_format">Size: %1$s / 10MB</string>
|
|
||||||
<string name="log_size_kb">%.1f KB</string>
|
|
||||||
<string name="log_size_mb">%.2f MB</string>
|
|
||||||
<string name="log_warning_rapid_growth">The logging file is growing too rapidly, you might want to check if something is failing</string>
|
|
||||||
<string name="no_blackbox_found">--- No BlackBox file found ---</string>
|
|
||||||
<string name="reset_log">Reset Log</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="auth_required_subtitle">Authenticate to disable the secure environment</string>
|
|
||||||
<string name="auth_required_title">Authentication required</string>
|
|
||||||
<string name="auth_success_disconnect">Authentication Success. Disconnecting...</string>
|
|
||||||
<string name="security_required_msg">You must set up a PIN, Pattern, or Fingerprint on your device before enabling the secure environment.</string>
|
|
||||||
<string name="security_required_title">Security Required</string>
|
|
||||||
<string name="unlock_watchdog_subtitle">Authentication required to stop Termux protection</string>
|
|
||||||
<string name="unlock_watchdog_title">Unlock Master Watchdog</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string>
|
|
||||||
<string name="battery_opt_msg">For the Watchdog to work reliably, please disable battery optimizations for this app.</string>
|
|
||||||
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detected: Please ensure you also enable \'Allow background activity\' in this app\'s settings.</string>
|
|
||||||
<string name="battery_opt_title">Battery Optimization</string>
|
|
||||||
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detected: Please set battery saver to \'No restrictions\' in settings.</string>
|
|
||||||
<string name="go_to_settings">Go to Settings</string>
|
|
||||||
|
|
||||||
|
|
||||||
<string name="app_started">Application Started</string>
|
|
||||||
<string name="deploy_wip_desc">The Termux module and environment installer will be available here soon.</string>
|
|
||||||
<string name="deploy_wip_title">WIP - Under Construction</string>
|
|
||||||
|
|
||||||
<string name="battery_custom">"Battery: "</string>
|
|
||||||
<string name="battery_no_value">Battery: --%</string>
|
|
||||||
<string name="hotspot_fdash">Hotspot: --</string>
|
|
||||||
<string name="pref_file_internal">IIAB_Internal</string>
|
|
||||||
<string name="pref_key_setup_complete">setup_complete</string>
|
|
||||||
<string name="saved_toast">Saved</string>
|
<string name="saved_toast">Saved</string>
|
||||||
<string name="settings_saved">Settings Saved</string>
|
<string name="settings_saved">Settings Saved</string>
|
||||||
<string name="uptime_no_value">Uptime: --</string>
|
<string name="fix_action">FIX</string>
|
||||||
<string name="version_footer_fallback">IIAB-oA · 2026 · Controller v0.1.xbeta</string>
|
<string name="configuration_label">Configuration</string>
|
||||||
<string name="version_footer_format">IIAB-oA · 2026 · Controller %1$s</string>
|
<string name="advanced_settings_label">Tunnel Settings</string>
|
||||||
<string name="wi_fi_fdash">Wi-Fi: --</string>
|
<string name="connection_log_label">Connection Log</string>
|
||||||
<string name="setup_display_over_other_apps">Display over other apps</string>
|
<string name="settings_label">SETTINGS</string>
|
||||||
<string name="setup_manage_all_permissions">Manage All Permissions</string>
|
|
||||||
<string name="setup_manage_termux_permissions">Manage Termux permissions</string>
|
<!-- SetupActivity -->
|
||||||
<string name="setup_termux_custom_permissions">Termux custom permissions</string>
|
<string name="setup_title">Initial Setup</string>
|
||||||
|
<string name="setup_welcome">Welcome to the %1$s setup wizard.\n\nIn order to work properly, we need the following permissions:</string>
|
||||||
|
<string name="setup_perm_notifications">Push Notifications</string>
|
||||||
|
<string name="setup_perm_termux">Termux Execution</string>
|
||||||
|
<string name="setup_perm_vpn">Safe Pocket Web (VPN)</string>
|
||||||
|
<string name="setup_perm_battery">Disable Battery Optimization</string>
|
||||||
|
<string name="setup_continue">Continue</string>
|
||||||
|
<string name="revoke_permission_warning">To revoke permissions, you must do it from system settings.</string>
|
||||||
|
<string name="termux_not_installed_error">Termux is not installed or device not supported.</string>
|
||||||
|
<string name="termux_not_installed">Termux is not installed.</string>
|
||||||
|
|
||||||
|
<!-- VPN / Socks -->
|
||||||
|
<string name="control_enable">Enable Safe Pocket Web</string>
|
||||||
|
<string name="control_disable">Disable Safe Pocket Web</string>
|
||||||
|
<string name="vpn_description">Enable friendly URLs. Lock out the threats.</string>
|
||||||
|
<string name="socks_addr">Socks Address:</string>
|
||||||
|
<string name="socks_udp_addr">Socks UDP Address:</string>
|
||||||
|
<string name="socks_port">Socks Port:</string>
|
||||||
|
<string name="socks_user">Socks Username:</string>
|
||||||
|
<string name="socks_pass">Socks Password:</string>
|
||||||
|
<string name="dns_ipv4">DNS IPv4:</string>
|
||||||
|
<string name="dns_ipv6">DNS IPv6:</string>
|
||||||
|
<string name="udp_in_tcp">UDP relay over TCP</string>
|
||||||
|
<string name="remote_dns">Remote DNS</string>
|
||||||
|
<string name="ipv4">IPv4</string>
|
||||||
|
<string name="ipv6">IPv6</string>
|
||||||
|
<string name="global">Global</string>
|
||||||
|
<string name="apps">Apps</string>
|
||||||
|
<string name="vpn_stopping">VPN Stopping...</string>
|
||||||
|
<string name="vpn_starting">VPN Starting...</string>
|
||||||
|
<string name="user_initiated_conn">User initiated connection</string>
|
||||||
|
<string name="vpn_permission_granted">VPN Permission Granted. Connecting...</string>
|
||||||
|
<string name="tproxy_channel_name">socks5</string>
|
||||||
|
|
||||||
|
<!-- WatchdogService / IIABWatchdog -->
|
||||||
|
<string name="watchdog_enable">Enable\nMaster Watchdog</string>
|
||||||
|
<string name="watchdog_disable">Disable\nMaster Watchdog</string>
|
||||||
|
<string name="watchdog_description">Protects Termux from Doze mode and keeps Wi-Fi active.</string>
|
||||||
|
<string name="watchdog_stopped">Watchdog Stopped</string>
|
||||||
|
<string name="watchdog_started">Watchdog Started</string>
|
||||||
|
<string name="watchdog_channel_name">IIAB Watchdog Service</string>
|
||||||
|
<string name="watchdog_channel_desc">Ensures services remain active when screen is off.</string>
|
||||||
|
<string name="watchdog_notif_title">IIAB Watchdog Active</string>
|
||||||
|
<string name="watchdog_notif_text">Protecting Termux environment...</string>
|
||||||
|
<string name="syncing_watchdog">Syncing Watchdog state. Enabled: %b</string>
|
||||||
|
<string name="watchdog_thread_started">Watchdog Thread: Started loop</string>
|
||||||
|
<string name="watchdog_thread_interrupted">Watchdog Thread: Interrupted, stopping...</string>
|
||||||
|
<string name="watchdog_thread_error">Watchdog Thread: Error in loop</string>
|
||||||
|
<string name="watchdog_thread_ended">Watchdog Thread: Loop ended</string>
|
||||||
|
<string name="cpu_wakelock_acquired">CPU WakeLock acquired under VPN shield</string>
|
||||||
|
<string name="wifi_lock_acquired">Wi-Fi Lock acquired under VPN shield</string>
|
||||||
|
<string name="error_acquiring_locks">Error acquiring locks</string>
|
||||||
|
<string name="cpu_wakelock_released">CPU WakeLock released</string>
|
||||||
|
<string name="wifi_lock_released">Wi-Fi Lock released</string>
|
||||||
|
|
||||||
|
<!-- Pulse / Heartbeat -->
|
||||||
|
<string name="pulse_stimulating">Pulse: Stimulating Termux...</string>
|
||||||
|
<string name="critical_os_blocked">CRITICAL: OS blocked Termux stimulus (SecurityException).</string>
|
||||||
|
<string name="ping_ok">PING 8085: OK</string>
|
||||||
|
<string name="ping_fail">PING 8085: FAIL (%s)</string>
|
||||||
|
<string name="session_started">HEARTBEAT SESSION STARTED</string>
|
||||||
|
<string name="session_stopped">HEARTBEAT SESSION STOPPED</string>
|
||||||
|
<string name="permission_denied_log">Permission Denied: Ensure manifest has RUN_COMMAND and app is not restricted.</string>
|
||||||
|
<string name="unexpected_error_termux">Unexpected error sending intent to Termux</string>
|
||||||
|
<string name="pulse_error_log">Pulse Error: %s</string>
|
||||||
|
<string name="maintenance_write_failed">Maintenance write failed</string>
|
||||||
|
<string name="failed_write_blackbox">Failed to write to BlackBox</string>
|
||||||
|
<string name="recovery_pulse_received">Recovery Pulse Received from System. Enforcing VPN...</string>
|
||||||
|
|
||||||
|
<!-- TermuxCallbackReceiver / Operations -->
|
||||||
|
<string name="termux_stimulus_ok">[Termux] Stimulus OK (exit 0)</string>
|
||||||
|
<string name="termux_pulse_error">[Termux] Pulse Error (exit %1$d): %2$s</string>
|
||||||
|
<string name="server_timeout_warning">Warning: Server state transition timed out.</string>
|
||||||
|
<string name="server_booting">Booting...</string>
|
||||||
|
<string name="server_shutting_down">Shutting down...</string>
|
||||||
|
<string name="failed_termux_intent">CRITICAL: Failed Termux Intent: %s</string>
|
||||||
|
<string name="sent_to_termux">Sent to Termux: %s</string>
|
||||||
|
<string name="maintenance_mode_enabled">Maintenance mode enabled: Termux has direct Internet access</string>
|
||||||
|
<string name="stop_server">🛑 Stop Server</string>
|
||||||
|
<string name="launch_server">🚀 Launch Server</string>
|
||||||
|
<string name="termux_perm_granted">Termux permission granted</string>
|
||||||
|
<string name="termux_perm_denied">Termux permission denied</string>
|
||||||
|
<string name="notif_perm_granted">Notification permission granted</string>
|
||||||
|
<string name="notif_perm_denied">Notification permission denied</string>
|
||||||
|
|
||||||
|
<!-- Logs -->
|
||||||
|
<string name="log_reset_confirm_title">Reset Log History?</string>
|
||||||
|
<string name="log_reset_confirm_msg">This will permanently delete all stored connection logs. This action cannot be undone.</string>
|
||||||
|
<string name="log_warning_rapid_growth">The logging file is growing too rapidly, you might want to check if something is failing</string>
|
||||||
|
<string name="reset_log">Reset Log</string>
|
||||||
|
<string name="copy_all">Copy All</string>
|
||||||
|
<string name="log_reset_log">Log reset</string>
|
||||||
|
<string name="log_reset_user">Log reset by user</string>
|
||||||
|
<string name="log_copied_toast">Log copied to clipboard</string>
|
||||||
|
<string name="log_cleared_toast">Log cleared</string>
|
||||||
|
<string name="failed_reset_log">Failed to reset log: %s</string>
|
||||||
|
<string name="log_size_format">Size: %1$s / 10MB</string>
|
||||||
|
<string name="log_size_bytes">%d B</string>
|
||||||
|
<string name="log_size_kb">%.1f KB</string>
|
||||||
|
<string name="log_size_mb">%.2f MB</string>
|
||||||
|
<string name="no_blackbox_found">--- No BlackBox file found ---</string>
|
||||||
|
<string name="loading_history">--- Loading History ---</string>
|
||||||
|
<string name="error_reading_history">Error reading history: %s</string>
|
||||||
|
<string name="end_of_history">--- End of History ---</string>
|
||||||
|
|
||||||
|
<!-- Battery Optimizations -->
|
||||||
|
<string name="battery_opt_title">Battery Optimization</string>
|
||||||
|
<string name="battery_opt_msg">For the Watchdog to work reliably, please disable battery optimizations for this app.</string>
|
||||||
|
<string name="go_to_settings">Go to Settings</string>
|
||||||
|
<string name="battery_opt_oppo_extra">\n\nOPPO/Realme detected: Please ensure you also enable \'Allow background activity\' in this app\'s settings.</string>
|
||||||
|
<string name="battery_opt_xiaomi_extra">\n\nXiaomi detected: Please set battery saver to \'No restrictions\' in settings.</string>
|
||||||
|
<string name="battery_opt_denied">For the app to work 100%, please disable battery optimization.</string>
|
||||||
|
|
||||||
|
<!-- UI / Misc -->
|
||||||
|
<string name="browse_content">🚀 Explore Content</string>
|
||||||
|
<string name="system_ready">System ready...\n</string>
|
||||||
|
<string name="app_started">Application Started</string>
|
||||||
|
<string name="label_separator_down">▼ %s</string>
|
||||||
|
<string name="label_separator_up">▶ %s</string>
|
||||||
|
<string name="qr_error_no_server">Launch the server to share content over the network.</string>
|
||||||
|
<string name="qr_error_no_network">Enable Wi-Fi or Hotspot to share content over the network.</string>
|
||||||
|
<string name="qr_title_wifi">Wi-Fi Network</string>
|
||||||
|
<string name="qr_title_hotspot">Hotspot Network</string>
|
||||||
|
<string name="qr_flip_network">Switch Network</string>
|
||||||
|
|
||||||
|
<!-- Authentication / Security -->
|
||||||
|
<string name="unlock_watchdog_title">Unlock Master Watchdog</string>
|
||||||
|
<string name="unlock_watchdog_subtitle">Authentication required to stop Termux protection</string>
|
||||||
|
<string name="auth_success_disconnect">Authentication Success. Disconnecting...</string>
|
||||||
|
<string name="auth_required_title">Authentication required</string>
|
||||||
|
<string name="auth_required_subtitle">Authenticate to disable the secure environment</string>
|
||||||
|
<string name="security_required_title">Security Required</string>
|
||||||
|
<string name="security_required_msg">You must set up a PIN, Pattern, or Fingerprint on your device before enabling the secure environment.</string>
|
||||||
|
|
||||||
|
<!-- VPN Recovery Service -->
|
||||||
|
<string name="recovery_channel_name">VPN Recovery</string>
|
||||||
|
<string name="recovery_notif_title">Safe Pocket Web Interrupted</string>
|
||||||
|
<string name="recovery_notif_text">Tap to restore secure environment immediately.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -20,9 +20,4 @@
|
||||||
<style name="PurpleSwitchTheme" parent="">
|
<style name="PurpleSwitchTheme" parent="">
|
||||||
<item name="colorControlActivated">#8A2BE2</item>
|
<item name="colorControlActivated">#8A2BE2</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="CustomTabTextStyle" parent="TextAppearance.Design.Tab">
|
|
||||||
<item name="android:textStyle">bold</item>
|
|
||||||
<item name="android:textSize">13sp</item>
|
|
||||||
<item name="textAllCaps">true</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue