UI: Setup Activity
This commit is contained in:
parent
c354ee703e
commit
e28b12c9fd
@ -133,7 +133,7 @@
|
|||||||
android:theme="@style/AppTheme.NoActionBar.Dark" />
|
android:theme="@style/AppTheme.NoActionBar.Dark" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.setup.SetupActivity"
|
android:name=".ui.setup.SetupActivity"
|
||||||
android:exported="false"
|
android:exported="true"
|
||||||
android:theme="@style/AppTheme.NoActionBar" />
|
android:theme="@style/AppTheme.NoActionBar" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.bonus.BonusActivity"
|
android:name=".ui.bonus.BonusActivity"
|
||||||
|
@ -1,222 +0,0 @@
|
|||||||
package io.neoterm.component.setup;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.system.Os;
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipInputStream;
|
|
||||||
|
|
||||||
import io.neoterm.R;
|
|
||||||
import io.neoterm.backend.EmulatorDebug;
|
|
||||||
import io.neoterm.frontend.logging.NLog;
|
|
||||||
import io.neoterm.frontend.config.NeoPreference;
|
|
||||||
import io.neoterm.frontend.config.NeoTermPath;
|
|
||||||
|
|
||||||
public final class BaseFileInstaller {
|
|
||||||
public interface ResultListener {
|
|
||||||
void onResult(Exception error);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean needSetup() {
|
|
||||||
final File PREFIX_FILE = new File(NeoTermPath.USR_PATH);
|
|
||||||
return !PREFIX_FILE.isDirectory();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void installBaseFiles(final Activity activity, final ResultListener resultListener) {
|
|
||||||
if (!needSetup()) {
|
|
||||||
resultListener.onResult(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final File PREFIX_FILE = new File(NeoTermPath.USR_PATH);
|
|
||||||
|
|
||||||
final ProgressDialog progress = makeProgressDialog(activity);
|
|
||||||
progress.setMax(100);
|
|
||||||
progress.show();
|
|
||||||
new Thread() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
final String STAGING_PREFIX_PATH = NeoTermPath.ROOT_PATH + "/usr-staging";
|
|
||||||
final File STAGING_PREFIX_FILE = new File(STAGING_PREFIX_PATH);
|
|
||||||
|
|
||||||
if (STAGING_PREFIX_FILE.exists()) {
|
|
||||||
deleteFolder(STAGING_PREFIX_FILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalBytes = 0;
|
|
||||||
int totalReadBytes = 0;
|
|
||||||
final byte[] buffer = new byte[8096];
|
|
||||||
final List<Pair<String, String>> symlinks = new ArrayList<>(50);
|
|
||||||
|
|
||||||
HttpURLConnection connection = openBaseFileConnection();
|
|
||||||
connection.setConnectTimeout(8000);
|
|
||||||
connection.setReadTimeout(8000);
|
|
||||||
totalBytes = connection.getContentLength();
|
|
||||||
|
|
||||||
try (ZipInputStream zipInput = new ZipInputStream(connection.getInputStream())) {
|
|
||||||
ZipEntry zipEntry;
|
|
||||||
|
|
||||||
while ((zipEntry = zipInput.getNextEntry()) != null) {
|
|
||||||
totalReadBytes += zipEntry.getCompressedSize();
|
|
||||||
|
|
||||||
final int totalReadBytesFinal = totalReadBytes;
|
|
||||||
final int totalBytesFinal = totalBytes;
|
|
||||||
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
double progressFloat = ((double) totalReadBytesFinal) / ((double) totalBytesFinal) * 100.0;
|
|
||||||
progress.setProgress((int) progressFloat);
|
|
||||||
} catch (RuntimeException ignore) {
|
|
||||||
// activity dismissed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (zipEntry.getName().contains("SYMLINKS.txt")) {
|
|
||||||
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
|
|
||||||
String line;
|
|
||||||
while ((line = symlinksReader.readLine()) != null) {
|
|
||||||
if (line.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
String[] parts = line.split("←");
|
|
||||||
if (parts.length != 2)
|
|
||||||
throw new RuntimeException("Malformed symlink line: " + line);
|
|
||||||
String oldPath = parts[0];
|
|
||||||
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
|
||||||
symlinks.add(Pair.create(oldPath, newPath));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String zipEntryName = zipEntry.getName();
|
|
||||||
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
|
||||||
if (zipEntry.isDirectory()) {
|
|
||||||
if (!targetFile.mkdirs())
|
|
||||||
throw new RuntimeException("Failed to create directory: " + targetFile.getAbsolutePath());
|
|
||||||
} else {
|
|
||||||
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
|
||||||
int readBytes;
|
|
||||||
while ((readBytes = zipInput.read(buffer)) != -1) {
|
|
||||||
outStream.write(buffer, 0, readBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") || zipEntryName.startsWith("lib/apt/methods")) {
|
|
||||||
//noinspection OctalInteger
|
|
||||||
Os.chmod(targetFile.getAbsolutePath(), 0700);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.disconnect();
|
|
||||||
|
|
||||||
if (symlinks.isEmpty())
|
|
||||||
throw new RuntimeException("No SYMLINKS.txt encountered");
|
|
||||||
for (Pair<String, String> symlink : symlinks) {
|
|
||||||
NLog.INSTANCE.e("Setup", "Linking " + symlink.first + " to " + symlink.second);
|
|
||||||
Os.symlink(symlink.first, symlink.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!STAGING_PREFIX_FILE.renameTo(PREFIX_FILE)) {
|
|
||||||
throw new RuntimeException("Unable to rename staging folder");
|
|
||||||
}
|
|
||||||
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
resultListener.onResult(null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (final Exception e) {
|
|
||||||
NLog.INSTANCE.e(EmulatorDebug.LOG_TAG, "Bootstrap error", e);
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
resultListener.onResult(e);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
// Activity already dismissed - ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
activity.runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
progress.dismiss();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
// Activity already dismissed - ignore.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpURLConnection openBaseFileConnection() throws IOException {
|
|
||||||
String arch = determineArchName();
|
|
||||||
String baseUrl = NeoTermPath.INSTANCE.getSERVER_BASE_URL();
|
|
||||||
|
|
||||||
// Use the same source
|
|
||||||
NeoPreference.INSTANCE.store(R.string.key_package_source, baseUrl);
|
|
||||||
|
|
||||||
return (HttpURLConnection) new URL(baseUrl + "/boot/" + arch + ".zip").openConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String determineArchName() {
|
|
||||||
for (String androidArch : Build.SUPPORTED_ABIS) {
|
|
||||||
switch (androidArch) {
|
|
||||||
case "arm64-v8a":
|
|
||||||
return "aarch64";
|
|
||||||
case "armeabi-v7a":
|
|
||||||
return "arm";
|
|
||||||
case "x86_64":
|
|
||||||
return "x86_64";
|
|
||||||
// case "x86":
|
|
||||||
// return "i686";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new RuntimeException("Unable to determine arch from Build.SUPPORTED_ABIS = " +
|
|
||||||
Arrays.toString(Build.SUPPORTED_ABIS));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void deleteFolder(File fileOrDirectory) {
|
|
||||||
File[] children = fileOrDirectory.listFiles();
|
|
||||||
if (children != null) {
|
|
||||||
for (File child : children) {
|
|
||||||
deleteFolder(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!fileOrDirectory.delete()) {
|
|
||||||
throw new RuntimeException("Unable to delete " + (fileOrDirectory.isDirectory() ? "directory " : "file ") + fileOrDirectory.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ProgressDialog makeProgressDialog(Context context) {
|
|
||||||
ProgressDialog dialog = new ProgressDialog(context);
|
|
||||||
dialog.setMessage(context.getString(R.string.installer_message));
|
|
||||||
dialog.setIndeterminate(false);
|
|
||||||
dialog.setCancelable(false);
|
|
||||||
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
|
|
||||||
return dialog;
|
|
||||||
}
|
|
||||||
}
|
|
@ -137,6 +137,8 @@ class PackageManagerActivity : AppCompatActivity(), SearchView.OnQueryTextListen
|
|||||||
|
|
||||||
private fun changeSourceToUserInput(sourceManager: SourceManager) {
|
private fun changeSourceToUserInput(sourceManager: SourceManager) {
|
||||||
val editText = EditText(this)
|
val editText = EditText(this)
|
||||||
|
editText.setSelectAllOnFocus(true)
|
||||||
|
|
||||||
AlertDialog.Builder(this)
|
AlertDialog.Builder(this)
|
||||||
.setTitle(R.string.pref_package_source)
|
.setTitle(R.string.pref_package_source)
|
||||||
.setView(editText)
|
.setView(editText)
|
||||||
|
@ -1,41 +1,109 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:layout_margin="32dp"
|
||||||
android:background="@android:color/white">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/titleTextView"
|
android:id="@+id/setup_title_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginBottom="26dp"
|
||||||
android:layout_marginTop="26dp"
|
android:layout_marginTop="26dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/setup_hello"
|
|
||||||
android:textColor="@color/colorAccent"
|
|
||||||
android:textSize="49sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/subtitleTextView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="-7dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/setup_info"
|
android:text="@string/setup_info"
|
||||||
android:textColor="@color/colorAccent"
|
android:textColor="@color/colorAccent"
|
||||||
android:textSize="16sp" />
|
android:textSize="32sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/setup_next"
|
android:id="@+id/select_method_tip_text"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/preview_layout_margin"
|
android:layout_below="@id/setup_title_text"
|
||||||
android:layout_marginEnd="@dimen/preview_layout_margin"
|
android:text="@string/setup_setup_method" />
|
||||||
android:text="@string/setup_next"
|
|
||||||
android:textColor="#9b9b9b"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
<Button
|
||||||
|
android:id="@+id/setup_next"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:text="@string/setup_next" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@+id/setup_next"
|
||||||
|
android:layout_below="@id/select_method_tip_text"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checkedButton="@id/setup_method_online">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/setup_method_online"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/setup_online" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/setup_method_local"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/setup_local" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/setup_method_assets"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/setup_assets" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/setup_url_tip_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/setup_source_url" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/setup_source_url"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/setup_input_source_url" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/setup_source_url_select"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.2"
|
||||||
|
android:text="@string/setup_dots" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/setup_log_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -48,7 +48,7 @@
|
|||||||
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
<string name="fullscreen_mode_changed">全屏模式已改变,请重启 NeoTerm</string>
|
||||||
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
<string name="permission_denied">NeoTerm 无法取得必需的权限,正在退出</string>
|
||||||
<string name="error">还有这种操作?</string>
|
<string name="error">还有这种操作?</string>
|
||||||
<string name="use_system_shell">使用系统Shell</string>
|
<string name="use_system_shell">使用系统会话</string>
|
||||||
<string name="retry">重试</string>
|
<string name="retry">重试</string>
|
||||||
<string name="source_changed">APT 源已更改,你可能需要执行 apt update 来更新</string>
|
<string name="source_changed">APT 源已更改,你可能需要执行 apt update 来更新</string>
|
||||||
<string name="package_details">软件包: %s\n版本: %s\n依赖: %s\n占用空间: %s\n描述: %s\n主页: %s</string>
|
<string name="package_details">软件包: %s\n版本: %s\n依赖: %s\n占用空间: %s\n描述: %s\n主页: %s</string>
|
||||||
@ -66,15 +66,17 @@
|
|||||||
<string name="package_settings_desc">软件源,更新,升级</string>
|
<string name="package_settings_desc">软件源,更新,升级</string>
|
||||||
<string name="install_font">安装字体</string>
|
<string name="install_font">安装字体</string>
|
||||||
<string name="install_color">安装配色方案</string>
|
<string name="install_color">安装配色方案</string>
|
||||||
<string name="setup_hello">发现</string>
|
|
||||||
<string name="setup_info">你好,NeoTerm</string>
|
<string name="setup_info">你好,NeoTerm</string>
|
||||||
<string name="setup_info2">轻触以选择你的最爱</string>
|
<string name="setup_next">开始!</string>
|
||||||
<string name="setup_next">短暂的安装过程之后,\n即可开始使用NeoTerm</string>
|
<string name="setup_setup_method">选择你的配置方式</string>
|
||||||
<string name="discovery">发现</string>
|
<string name="setup_online">在线设置</string>
|
||||||
|
<string name="setup_local">本地 Zip 文件</string>
|
||||||
|
<string name="setup_assets">软件自带 Zip 文件</string>
|
||||||
|
<string name="setup_source_url">配置地址</string>
|
||||||
|
<string name="setup_input_source_url">输入配置地址</string>
|
||||||
<string name="crash_model">设备: %s</string>
|
<string name="crash_model">设备: %s</string>
|
||||||
<string name="crash_app">应用: %s</string>
|
<string name="crash_app">应用: %s</string>
|
||||||
<string name="crash_stack_trace">堆栈信息</string>
|
<string name="crash_stack_trace">堆栈信息</string>
|
||||||
<string name="crash_tips">我们正努力让这个 Activity 永不见天日…</string>
|
|
||||||
<string name="service_status_text">%d 个会话, %d 个图形会话</string>
|
<string name="service_status_text">%d 个会话, %d 个图形会话</string>
|
||||||
<string name="service_lock_acquired"> (永不休眠)</string>
|
<string name="service_lock_acquired"> (永不休眠)</string>
|
||||||
<string name="service_acquire_lock">取得休眠锁</string>
|
<string name="service_acquire_lock">取得休眠锁</string>
|
||||||
|
@ -61,15 +61,11 @@
|
|||||||
<string name="package_settings_desc">軟體源,更新,升級</string>
|
<string name="package_settings_desc">軟體源,更新,升級</string>
|
||||||
<string name="install_font">安裝字體</string>
|
<string name="install_font">安裝字體</string>
|
||||||
<string name="install_color">安裝色彩主題</string>
|
<string name="install_color">安裝色彩主題</string>
|
||||||
<string name="setup_hello">發現</string>
|
|
||||||
<string name="setup_info">你好,NeoTerm</string>
|
<string name="setup_info">你好,NeoTerm</string>
|
||||||
<string name="setup_info2">輕觸以選擇你的最愛</string>
|
<string name="setup_next">GO</string>
|
||||||
<string name="setup_next">短暫的安裝過程之後,\n即可開始使用NeoTerm</string>
|
|
||||||
<string name="discovery">發現</string>
|
|
||||||
<string name="crash_model">裝置: %s</string>
|
<string name="crash_model">裝置: %s</string>
|
||||||
<string name="crash_app">程式: %s</string>
|
<string name="crash_app">程式: %s</string>
|
||||||
<string name="crash_stack_trace">錯誤訊息</string>
|
<string name="crash_stack_trace">錯誤訊息</string>
|
||||||
<string name="crash_tips">我們正在努力讓這個 Activity 永不見天日…</string>
|
|
||||||
<string name="service_status_text">%d 個會話, %d 個图形會話</string>
|
<string name="service_status_text">%d 個會話, %d 個图形會話</string>
|
||||||
<string name="service_lock_acquired"> (永不休眠)</string>
|
<string name="service_lock_acquired"> (永不休眠)</string>
|
||||||
<string name="service_acquire_lock">開啟休眠鎖</string>
|
<string name="service_acquire_lock">開啟休眠鎖</string>
|
||||||
|
@ -12,13 +12,17 @@
|
|||||||
<string name="service_acquire_lock">Acquire Lock</string>
|
<string name="service_acquire_lock">Acquire Lock</string>
|
||||||
<string name="service_release_lock">Release Lock</string>
|
<string name="service_release_lock">Release Lock</string>
|
||||||
|
|
||||||
<string name="setup_hello">Discovery</string>
|
|
||||||
<string name="setup_info">Hello, NeoTerm</string>
|
<string name="setup_info">Hello, NeoTerm</string>
|
||||||
<string name="setup_info2">Tap to choose your favorites</string>
|
<string name="setup_next">Let\'s Go!</string>
|
||||||
<string name="setup_next">After a short installation process,\nyou can start using NeoTerm</string>
|
<string name="setup_setup_method">Select your setup method</string>
|
||||||
|
<string name="setup_online">Online Setup</string>
|
||||||
|
<string name="setup_local">Local Zip File Setup</string>
|
||||||
|
<string name="setup_assets">Assets Zip File Setup</string>
|
||||||
|
<string name="setup_source_url">Source URL</string>
|
||||||
|
<string name="setup_input_source_url">Input source URL…</string>
|
||||||
|
<string name="setup_dots" translatable="false">…</string>
|
||||||
|
|
||||||
<string name="about">About</string>
|
<string name="about">About</string>
|
||||||
<string name="discovery">Discovery</string>
|
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
<string name="general_settings">General Settings</string>
|
<string name="general_settings">General Settings</string>
|
||||||
<string name="general_settings_desc">Bell, Vibrate, Shell, Initial Command</string>
|
<string name="general_settings_desc">Bell, Vibrate, Shell, Initial Command</string>
|
||||||
@ -50,7 +54,6 @@
|
|||||||
|
|
||||||
<string name="crash_model">Model: %s</string>
|
<string name="crash_model">Model: %s</string>
|
||||||
<string name="crash_app">App: %s</string>
|
<string name="crash_app">App: %s</string>
|
||||||
<string name="crash_tips">We are trying to deprecate this Activity…</string>
|
|
||||||
<string name="crash_stack_trace">Stack Trace</string>
|
<string name="crash_stack_trace">Stack Trace</string>
|
||||||
|
|
||||||
<string name="installer_message">Installing</string>
|
<string name="installer_message">Installing</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user