diff --git a/winboll/build.gradle b/winboll/build.gradle
index 46828ad..f1ca517 100644
--- a/winboll/build.gradle
+++ b/winboll/build.gradle
@@ -31,7 +31,7 @@ android {
// versionName 更新后需要手动设置
// .winboll/winbollBuildProps.properties 文件的 stageCount=0
// Gradle编译环境下合起来的 versionName 就是 "${versionName}.0"
- versionName "15.11"
+ versionName "15.20"
if(true) {
versionName = genVersionName("${versionName}")
}
@@ -50,7 +50,7 @@ android {
}
dependencies {
-
+ api project(':libwinboll')
api 'com.google.code.gson:gson:2.10.1'
// 下拉控件
@@ -67,8 +67,6 @@ dependencies {
api 'io.github.medyo:android-about-page:2.0.0'
// 网络连接类库
api 'com.squareup.okhttp3:okhttp:4.4.1'
- // OkHttp网络请求
- implementation 'com.squareup.okhttp3:okhttp:3.14.9'
// FastJSON解析
implementation 'com.alibaba:fastjson:1.2.76'
@@ -86,7 +84,6 @@ dependencies {
//注意:以下5个库必须要引入
//implementation 'androidx.appcompat:appcompat:1.4.1'
api 'androidx.recyclerview:recyclerview:1.0.0'
- api 'com.google.code.gson:gson:2.8.5'
api 'com.github.bumptech.glide:glide:4.9.0'
//annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
@@ -107,13 +104,5 @@ dependencies {
implementation 'com.termux:terminal-view:0.118.0'
implementation 'com.termux:termux-shared:0.118.0'
- // WinBoLL库 nexus.winboll.cc 地址
- api 'cc.winboll.studio:libaes:15.15.2'
- api 'cc.winboll.studio:libappbase:15.15.11'
-
- // WinBoLL备用库 jitpack.io 地址
- //api 'com.github.ZhanGSKen:AES:aes-v15.15.7'
- //api 'com.github.ZhanGSKen:APPBase:appbase-v15.15.4'
-
api fileTree(dir: 'libs', include: ['*.jar'])
}
diff --git a/winboll/build.properties b/winboll/build.properties
index c7c8cc1..cc56cae 100644
--- a/winboll/build.properties
+++ b/winboll/build.properties
@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
-#Wed May 06 13:39:52 CST 2026
-stageCount=27
-libraryProject=
-baseVersion=15.11
-publishVersion=15.11.26
-buildCount=22
-baseBetaVersion=15.11.27
+#Wed May 13 13:48:00 CST 2026
+stageCount=2
+libraryProject=libwinboll
+baseVersion=15.20
+publishVersion=15.20.1
+buildCount=2
+baseBetaVersion=15.20.2
diff --git a/winboll/src/beta/res/layout/activity_ollama_window.xml b/winboll/src/beta/res/layout/activity_ollama_window.xml
index 34dbfda..86f97cd 100644
--- a/winboll/src/beta/res/layout/activity_ollama_window.xml
+++ b/winboll/src/beta/res/layout/activity_ollama_window.xml
@@ -29,13 +29,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:padding="16dp" android:background="@drawable/bg_container_border">
+ android:padding="16dp">
@@ -43,13 +43,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
- android:orientation="vertical" android:background="@drawable/bg_container_border">
+ android:orientation="vertical">
+ android:textColor="#B0B0B0" />
@@ -67,7 +67,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="模型名称:"
- />
+ android:textColor="#B0B0B0" />
@@ -85,7 +85,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="系统消息:"
- />
+ android:textColor="#B0B0B0" />
+ android:orientation="horizontal">
+ android:textColor="#FFFFFF" />
+ android:textColor="#FF5252" />
diff --git a/winboll/src/main/AndroidManifest.xml b/winboll/src/main/AndroidManifest.xml
index 9c136b1..a949d1a 100644
--- a/winboll/src/main/AndroidManifest.xml
+++ b/winboll/src/main/AndroidManifest.xml
@@ -15,14 +15,13 @@
-
+
-
-
@@ -29,16 +29,11 @@ public abstract class BaseWinBoLLActivity extends AppCompatActivity implements I
}
AESThemeBean.ThemeType getThemeType() {
- /*SharedPreferences sharedPreferences = getSharedPreferences(
- SHAREDPREFERENCES_NAME, MODE_PRIVATE);
- return AESThemeBean.ThemeType.values()[((sharedPreferences.getInt(DRAWER_THEME_TYPE, AESThemeBean.ThemeType.DEFAULT.ordinal())))];
- */
- return AESThemeBean.getThemeStyleType(AESThemeUtil.getThemeTypeID(getApplicationContext()));
+ return WinBoLLThemeUtil.getThemeStyleType(WinBoLLThemeUtil.getThemeTypeID(getApplicationContext()));
}
void setThemeStyle() {
- //setTheme(AESThemeBean.getThemeStyle(getThemeType()));
- setTheme(AESThemeUtil.getThemeTypeID(getApplicationContext()));
+ setTheme(WinBoLLThemeUtil.getThemeTypeID(getApplicationContext()));
}
@Override
diff --git a/winboll/src/main/java/cc/winboll/studio/winboll/applications/MyTermuxActivity.java b/winboll/src/main/java/cc/winboll/studio/winboll/applications/MyTermuxActivity.java
index 5e7bddd..6bd2b29 100644
--- a/winboll/src/main/java/cc/winboll/studio/winboll/applications/MyTermuxActivity.java
+++ b/winboll/src/main/java/cc/winboll/studio/winboll/applications/MyTermuxActivity.java
@@ -1,31 +1,46 @@
package cc.winboll.studio.winboll.applications;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.winboll.R;
+import cc.winboll.studio.winboll.models.TermuxButtonManager;
+import cc.winboll.studio.winboll.models.TermuxButtonModel;
import cc.winboll.studio.winboll.termux.TermuxCommandExecutor;
+import java.util.ArrayList;
public class MyTermuxActivity extends AppCompatActivity {
public static final String TAG = "MyTermuxActivity";
private Toolbar mToolbar;
- private Button mTermuxButton;
- private Button mTermuxWorkSpacesButton;
+ private ListView mListView;
+ private Button mBtnAdd;
+ private ButtonAdapter mAdapter;
+ private ArrayList mButtonList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_termux);
- // 初始化工具栏
initToolbar();
- // 初始化按钮
- initView();
+ initListView();
+ initAddButton();
+ refreshList();
}
private void initToolbar() {
@@ -34,44 +49,189 @@ public class MyTermuxActivity extends AppCompatActivity {
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- LogUtils.d(TAG, "点击返回按钮");
- finish();
- }
- });
- LogUtils.d(TAG, "工具栏初始化完成");
+ @Override
+ public void onClick(View v) {
+ finish();
+ }
+ });
}
}
- private void initView() {
- mTermuxButton = findViewById(R.id.btn_termux);
- if (mTermuxButton != null) {
- mTermuxButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- LogUtils.d(TAG, "点击 Termux 按钮");
- TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~");
- //TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~/TermuxWorkSpaces", "./TermuxWorkSpaces");
- }
- });
- LogUtils.d(TAG, "Termux 按钮初始化完成");
- }
+ private void initListView() {
+ mListView = findViewById(R.id.list_termux_buttons);
+ mButtonList = new ArrayList();
+ mAdapter = new ButtonAdapter();
+ mListView.setAdapter(mAdapter);
- mTermuxWorkSpacesButton = findViewById(R.id.btn_termuxworkspaces);
- if (mTermuxWorkSpacesButton != null) {
- mTermuxWorkSpacesButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- LogUtils.d(TAG, "点击 TermuxWorkSpaces 按钮");
- TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this, "cd ~/TermuxWorkSpaces", "./TermuxWorkSpaces");
- }
- });
- LogUtils.d(TAG, "TermuxWorkSpaces 按钮初始化完成");
- }
+ mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ TermuxButtonModel model = mButtonList.get(position);
+ TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this,
+ model.getExeCommand(), model.getWorkDir());
+ }
+ });
+
+ mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ showContextMenu(position);
+ return true;
+ }
+ });
}
- private boolean isTermuxAvailable() {
- return TermuxCommandExecutor.isTermuxInstalled(this);
+ private void initAddButton() {
+ mBtnAdd = findViewById(R.id.btn_add_termux_button);
+ mBtnAdd.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showButtonDialog(-1, null);
+ }
+ });
+ }
+
+ private void refreshList() {
+ mButtonList.clear();
+ ArrayList loaded = TermuxButtonManager.loadButtons(this);
+ if (loaded != null) {
+ mButtonList.addAll(loaded);
+ }
+ mAdapter.notifyDataSetChanged();
+ }
+
+ private void showContextMenu(final int position) {
+ final TermuxButtonModel model = mButtonList.get(position);
+ String[] items = new String[]{
+ getString(R.string.menu_execute),
+ getString(R.string.menu_edit),
+ getString(R.string.menu_delete),
+ getString(R.string.menu_cancel)
+ };
+ new AlertDialog.Builder(this)
+ .setTitle(model.getButtonName())
+ .setItems(items, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (which == 0) {
+ TermuxCommandExecutor.openTermuxBash(MyTermuxActivity.this,
+ model.getExeCommand(), model.getWorkDir());
+ } else if (which == 1) {
+ showButtonDialog(position, model);
+ } else if (which == 2) {
+ showDeleteConfirmDialog(position);
+ }
+ }
+ })
+ .show();
+ }
+
+ private void showDeleteConfirmDialog(final int position) {
+ new AlertDialog.Builder(this)
+ .setTitle(getString(R.string.dialog_delete_title))
+ .setMessage(getString(R.string.dialog_delete_message) + mButtonList.get(position).getButtonName())
+ .setPositiveButton(getString(R.string.dialog_confirm), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ TermuxButtonManager.deleteButton(MyTermuxActivity.this, mButtonList, position);
+ refreshList();
+ Toast.makeText(MyTermuxActivity.this, R.string.toast_deleted, Toast.LENGTH_SHORT).show();
+ }
+ })
+ .setNegativeButton(getString(R.string.dialog_cancel), null)
+ .show();
+ }
+
+ private void showButtonDialog(final int index, final TermuxButtonModel model) {
+ final boolean isEdit = (model != null);
+
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.setPadding(40, 20, 40, 20);
+
+ final EditText etName = new EditText(this);
+ etName.setHint(R.string.hint_button_name);
+ if (model != null) {
+ etName.setText(model.getButtonName());
+ }
+ layout.addView(etName);
+
+ final EditText etCommand = new EditText(this);
+ etCommand.setHint(R.string.hint_exe_command);
+ if (model != null) {
+ etCommand.setText(model.getExeCommand());
+ }
+ layout.addView(etCommand);
+
+ final EditText etWorkDir = new EditText(this);
+ etWorkDir.setHint(R.string.hint_work_dir);
+ if (model != null) {
+ etWorkDir.setText(model.getWorkDir());
+ }
+ layout.addView(etWorkDir);
+
+ int titleResId = isEdit ? R.string.dialog_edit_title : R.string.dialog_add_title;
+ new AlertDialog.Builder(this)
+ .setTitle(titleResId)
+ .setView(layout)
+ .setPositiveButton(getString(R.string.dialog_save), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String name = etName.getText().toString().trim();
+ String command = etCommand.getText().toString().trim();
+ String workDir = etWorkDir.getText().toString().trim();
+ if (name.isEmpty() || command.isEmpty()) {
+ Toast.makeText(MyTermuxActivity.this, R.string.toast_fields_required, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ TermuxButtonModel newModel = new TermuxButtonModel();
+ newModel.setButtonName(name);
+ newModel.setExeCommand(command);
+ newModel.setWorkDir(workDir);
+ if (isEdit) {
+ TermuxButtonManager.updateButton(MyTermuxActivity.this, mButtonList, index, newModel);
+ } else {
+ TermuxButtonManager.addButton(MyTermuxActivity.this, mButtonList, newModel);
+ }
+ refreshList();
+ }
+ })
+ .setNegativeButton(getString(R.string.dialog_cancel), null)
+ .show();
+ }
+
+ private class ButtonAdapter extends BaseAdapter {
+ @Override
+ public int getCount() {
+ return mButtonList.size();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mButtonList.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ TextView tv;
+ if (convertView == null) {
+ tv = new TextView(MyTermuxActivity.this);
+ tv.setPadding(30, 20, 30, 20);
+ tv.setTextSize(16);
+ tv.setMinHeight(80);
+ } else {
+ tv = (TextView) convertView;
+ }
+
+ TermuxButtonModel model = mButtonList.get(position);
+ tv.setText(model.getButtonName() + "\n" + model.getExeCommand());
+ tv.setTextColor(getResources().getColor(android.R.color.white));
+ return tv;
+ }
}
}
diff --git a/winboll/src/main/java/cc/winboll/studio/winboll/models/TermuxButtonManager.java b/winboll/src/main/java/cc/winboll/studio/winboll/models/TermuxButtonManager.java
new file mode 100644
index 0000000..456a2a2
--- /dev/null
+++ b/winboll/src/main/java/cc/winboll/studio/winboll/models/TermuxButtonManager.java
@@ -0,0 +1,37 @@
+package cc.winboll.studio.winboll.models;
+
+import android.content.Context;
+import cc.winboll.studio.libappbase.BaseBean;
+import java.util.ArrayList;
+
+public class TermuxButtonManager {
+
+ public static ArrayList loadButtons(Context context) {
+ ArrayList list = new ArrayList();
+ BaseBean.loadBeanList(context, list, TermuxButtonModel.class);
+ return list;
+ }
+
+ public static boolean saveButtons(Context context, ArrayList list) {
+ return BaseBean.saveBeanList(context, list, TermuxButtonModel.class);
+ }
+
+ public static void addButton(Context context, ArrayList list, TermuxButtonModel button) {
+ list.add(button);
+ saveButtons(context, list);
+ }
+
+ public static void updateButton(Context context, ArrayList list, int index, TermuxButtonModel button) {
+ if (index >= 0 && index < list.size()) {
+ list.set(index, button);
+ saveButtons(context, list);
+ }
+ }
+
+ public static void deleteButton(Context context, ArrayList list, int index) {
+ if (index >= 0 && index < list.size()) {
+ list.remove(index);
+ saveButtons(context, list);
+ }
+ }
+}
diff --git a/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeBean.java b/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeBean.java
new file mode 100644
index 0000000..1d748d7
--- /dev/null
+++ b/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeBean.java
@@ -0,0 +1,49 @@
+package cc.winboll.studio.winboll.theme;
+
+import cc.winboll.studio.libaes.models.AESThemeBean;
+import cc.winboll.studio.winboll.R;
+
+public class WinBoLLThemeBean {
+
+ public static final String TAG = "WinBoLLThemeBean";
+
+ public static int getDefaultThemeStyleID() {
+ return R.style.MyAppTheme;
+ }
+
+ public static int getThemeStyleID(AESThemeBean.ThemeType themeType) {
+ int themeStyleID = getDefaultThemeStyleID();
+ if (AESThemeBean.ThemeType.DEPTH == themeType) {
+ themeStyleID = R.style.MyDepthAppTheme;
+ } else if (AESThemeBean.ThemeType.SKY == themeType) {
+ themeStyleID = R.style.MySkyAppTheme;
+ } else if (AESThemeBean.ThemeType.GOLDEN == themeType) {
+ themeStyleID = R.style.MyGoldenAppTheme;
+ } else if (AESThemeBean.ThemeType.BEARING == themeType) {
+ themeStyleID = R.style.MyBearingAppTheme;
+ } else if (AESThemeBean.ThemeType.MEMOR == themeType) {
+ themeStyleID = R.style.MyMemorAppTheme;
+ } else if (AESThemeBean.ThemeType.TAO == themeType) {
+ themeStyleID = R.style.MyTaoAppTheme;
+ }
+ return themeStyleID;
+ }
+
+ public static AESThemeBean.ThemeType getThemeStyleType(int nThemeStyleID) {
+ AESThemeBean.ThemeType themeStyle = AESThemeBean.ThemeType.AES;
+ if (R.style.MyDepthAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.DEPTH;
+ } else if (R.style.MySkyAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.SKY;
+ } else if (R.style.MyGoldenAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.GOLDEN;
+ } else if (R.style.MyBearingAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.BEARING;
+ } else if (R.style.MyMemorAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.MEMOR;
+ } else if (R.style.MyTaoAppTheme == nThemeStyleID) {
+ themeStyle = AESThemeBean.ThemeType.TAO;
+ }
+ return themeStyle;
+ }
+}
diff --git a/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeUtil.java b/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeUtil.java
new file mode 100644
index 0000000..1e6640d
--- /dev/null
+++ b/winboll/src/main/java/cc/winboll/studio/winboll/theme/WinBoLLThemeUtil.java
@@ -0,0 +1,36 @@
+package cc.winboll.studio.winboll.theme;
+
+import android.content.Context;
+import cc.winboll.studio.libaes.models.AESThemeBean;
+import cc.winboll.studio.libaes.utils.AESThemeUtil;
+
+public class WinBoLLThemeUtil {
+
+ public static final String TAG = "WinBoLLThemeUtil";
+
+ public static int getThemeTypeID(Context context) {
+ AESThemeBean bean = AESThemeBean.loadBean(context, AESThemeBean.class);
+ int themeTypeID;
+ if (bean == null) {
+ themeTypeID = WinBoLLThemeBean.getDefaultThemeStyleID();
+ } else {
+ int aesStyleID = bean.getCurrentThemeTypeID();
+ AESThemeBean.ThemeType themeType = WinBoLLThemeBean.getThemeStyleType(aesStyleID);
+ themeTypeID = WinBoLLThemeBean.getThemeStyleID(themeType);
+ }
+ return themeTypeID;
+ }
+
+ public static void saveThemeStyleID(Context context, int nThemeTypeID) {
+ AESThemeBean bean = new AESThemeBean(nThemeTypeID);
+ AESThemeBean.saveBean(context, bean);
+ }
+
+ public static AESThemeBean.ThemeType getThemeStyleType(int nThemeStyleID) {
+ return WinBoLLThemeBean.getThemeStyleType(nThemeStyleID);
+ }
+
+ public static int getThemeStyleID(AESThemeBean.ThemeType themeType) {
+ return WinBoLLThemeBean.getThemeStyleID(themeType);
+ }
+}
diff --git a/winboll/src/main/res/drawable/bg_shadow.xml b/winboll/src/main/res/drawable/bg_shadow.xml
index 0cafd81..6d3d898 100644
--- a/winboll/src/main/res/drawable/bg_shadow.xml
+++ b/winboll/src/main/res/drawable/bg_shadow.xml
@@ -12,7 +12,11 @@
android:angle="270"
android:endColor="#0F000000"
android:startColor="#0F000000" />
-
+
@@ -27,7 +31,11 @@
android:angle="270"
android:endColor="@color/colorAccent"
android:startColor="@color/colorAccent" />
-
+
diff --git a/winboll/src/main/res/layout/activity_about.xml b/winboll/src/main/res/layout/activity_about.xml
index 9301de9..b38ba39 100644
--- a/winboll/src/main/res/layout/activity_about.xml
+++ b/winboll/src/main/res/layout/activity_about.xml
@@ -4,7 +4,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent" android:background="@drawable/bg_container_border">
+ android:layout_height="match_parent">
+ android:layout_height="match_parent">
+ android:id="@+id/ll_hostbar">
+ android:onClick="onSwitchHost"/>
+ android:onClick="onSwitchHost"/>
@@ -37,7 +35,7 @@
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="right" android:background="@drawable/bg_container_border">
+ android:gravity="right">