diff --git a/README.md b/README.md index 3ee09c7..a3618db 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Android APK: - 已生成 Android debug APK:`android/app/build/outputs/apk/debug/app-debug.apk` - 已生成 Android signed release APK:`android/app/build/outputs/apk/release/app-release.apk` - `npm run apk:release` 还会额外产出带版本号的文件:`android/app/build/outputs/apk/release/boss-android-v{versionName}-release.apk` -- 当前最新 release 构建版本:`2.5.2`(`versionCode=15`) +- 当前最新 release 构建版本:`2.5.3`(`versionCode=16`) - 当前 APK 已切到原生 Android 客户端:`MainActivity + BossApiClient + 原生 XML 布局` - 当前原生活动页已经覆盖:会话首页、项目详情、项目目标、版本记录、会话信息、群资料、发起群聊、消息转发、线程详情、设备详情、添加设备、账号与安全、设置、AI 账号、技能、运维中心、关于 - 当前原生一级体验已回退到微信式交互:`会话 / 设备 / 我的` 固定底部 tab,会话首页是简单聊天列表,`主 Agent / 审计对话` 以普通置顶会话样式排在最前;项目详情页是聊天优先,只保留 `项目目标 / 版本记录` 两个轻入口 @@ -112,6 +112,7 @@ Android APK: - `2.5.0` 已补齐聊天附件主链:原生聊天框左侧 `+` 会打开底部抽屉,支持图片 / 视频 / 文件发送;默认走服务器文件存储,`我的 > 附件与存储` 可切到阿里 OSS 私有桶;附件消息已支持下载 / 打开、手动分析、自动分析状态,以及带 task token 的主 Agent 附件分析链接 - `2.5.1` 继续收口微信式原生 UI:聊天页普通态顶部已隐藏刷新按钮,只保留右上角“信息”;发起群聊页顶部说明和选择区已压成更轻的会话式密度,候选线程继续复用微信式会话卡片 - `2.5.2` 继续补齐深层原生页:`项目目标 / 版本迭代记录 / 会话信息 / 群资料` 已进一步向设计图收口;附件消息卡片的分析状态和动作文案也压成了更轻的微信式层级 +- `2.5.3` 继续压缩原生聊天与建群页面:`发起群聊` 页已收成轻量头部 + hint pill + 一层操作区;聊天页里自己发出的消息顶部元信息已收成只显示时间,不再重复 `你 · 时间` ## 本地启动 diff --git a/android/app/build.gradle b/android/app/build.gradle index 60362a8..6e71a71 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -36,8 +36,8 @@ android { applicationId "com.hyzq.boss" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 15 - versionName "2.5.2" + versionCode 16 + versionName "2.5.3" buildConfigField "String", "BOSS_API_BASE_URL", "\"https://boss.hyzq.net\"" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/android/app/src/main/java/com/hyzq/boss/BossUi.java b/android/app/src/main/java/com/hyzq/boss/BossUi.java index a174dd6..08a3c34 100644 --- a/android/app/src/main/java/com/hyzq/boss/BossUi.java +++ b/android/app/src/main/java/com/hyzq/boss/BossUi.java @@ -912,10 +912,7 @@ public final class BossUi { wrapper.setLayoutParams(wrapperParams); TextView metaView = new TextView(context); - String metaText = senderLabel; - if (!TextUtils.isEmpty(meta)) { - metaText = metaText + " · " + meta; - } + String metaText = buildMessageMetaText(senderLabel, meta, outgoing); metaView.setText(metaText); metaView.setTextSize(11); metaView.setTextColor(context.getColor(R.color.boss_text_soft)); @@ -1049,10 +1046,7 @@ public final class BossUi { wrapper.setLayoutParams(wrapperParams); TextView metaView = new TextView(context); - String metaText = senderLabel; - if (!TextUtils.isEmpty(meta)) { - metaText = metaText + " · " + meta; - } + String metaText = buildMessageMetaText(senderLabel, meta, outgoing); metaView.setText(metaText); metaView.setTextSize(11); metaView.setTextColor(context.getColor(R.color.boss_text_soft)); @@ -1061,6 +1055,23 @@ public final class BossUi { return wrapper; } + private static String buildMessageMetaText( + String senderLabel, + @Nullable String meta, + boolean outgoing + ) { + if (outgoing && !TextUtils.isEmpty(meta)) { + return meta; + } + if (TextUtils.isEmpty(meta)) { + return senderLabel; + } + if (TextUtils.isEmpty(senderLabel)) { + return meta; + } + return senderLabel + " · " + meta; + } + private static TextView buildAttachmentPrimaryText(Context context, String text) { TextView primary = new TextView(context); primary.setText(TextUtils.isEmpty(text) ? "未命名附件" : text); diff --git a/android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java b/android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java index f87e217..43bfc5c 100644 --- a/android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java +++ b/android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java @@ -2,8 +2,11 @@ package com.hyzq.boss; import android.content.Intent; import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; import android.widget.Button; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.Nullable; @@ -85,15 +88,13 @@ public class GroupCreateActivity extends BossScreenActivity { ? sourceProjectName : threadMeta.optString("threadDisplayName", sourceProjectName == null ? "当前会话" : sourceProjectName); } - for (SummaryCardSpec cardSpec : buildHeaderCardSpecs( + appendContent(buildHeaderView( hasSourceProject(), sourceProjectId, sourceProjectName, threadMeta, participants - )) { - appendContent(BossUi.buildCard(this, cardSpec.title, cardSpec.body, cardSpec.meta)); - } + )); if (rebuildCandidates) { List selectableConversations = collectSelectableConversationItems(conversationsPayload, sourceProjectId); @@ -121,16 +122,10 @@ public class GroupCreateActivity extends BossScreenActivity { lastCandidateProjectIds.addAll(nextCandidateProjectIds); } - SummaryCardSpec selectionCard = buildSelectionCardSpec( - candidates.size(), - selectedProjectIds.size(), - hasSourceProject() - ); - appendContent(BossUi.buildCard( + appendContent(buildSectionLabel("选择其他线程")); + appendContent(BossUi.buildHintPill( this, - selectionCard.title, - selectionCard.body, - selectionCard.meta + buildSelectionHintText(candidates.size(), selectedProjectIds.size(), hasSourceProject()) )); candidateListLayout = new LinearLayout(this); @@ -145,16 +140,53 @@ public class GroupCreateActivity extends BossScreenActivity { createButton = BossUi.buildPrimaryButton(this, "创建群聊"); createButton.setOnClickListener(v -> createGroupChat()); - appendContent(createButton); - Button cancelButton = BossUi.buildSecondaryButton(this, "取消"); cancelButton.setOnClickListener(v -> finish()); - appendContent(cancelButton); + appendContent(BossUi.buildInlineActionRow(this, cancelButton, createButton)); setRefreshing(false); updateCreateButtonState(); } + private View buildHeaderView( + boolean hasSourceProject, + @Nullable String sourceProjectId, + @Nullable String sourceProjectName, + @Nullable JSONObject threadMeta, + @Nullable JSONArray participants + ) { + if (hasSourceProject) { + return BossUi.buildSimpleProfileHeader( + this, + TextUtils.isEmpty(sourceProjectName) ? "当前会话" : sourceProjectName, + "从当前会话发起群聊", + buildSourceHeaderDetail(sourceProjectId, threadMeta, participants) + ); + } + return BossUi.buildSimpleProfileHeader( + this, + "发起新群聊", + "从会话列表直接建群", + "至少选择 2 个线程后创建新群" + ); + } + + private TextView buildSectionLabel(String text) { + TextView label = new TextView(this); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.leftMargin = BossUi.dp(this, 16); + params.rightMargin = BossUi.dp(this, 16); + params.bottomMargin = BossUi.dp(this, 6); + label.setLayoutParams(params); + label.setText(text); + label.setTextSize(13); + label.setTextColor(getColor(R.color.boss_text_muted)); + return label; + } + static List collectSelectableConversationItems(@Nullable JSONObject conversationsPayload, String sourceProjectId) { List result = new ArrayList<>(); JSONArray conversations = conversationsPayload == null ? null : conversationsPayload.optJSONArray("conversations"); @@ -192,65 +224,39 @@ public class GroupCreateActivity extends BossScreenActivity { ); } - static List buildHeaderCardSpecs( - boolean hasSourceProject, + static String buildSourceHeaderDetail( @Nullable String sourceProjectId, - @Nullable String sourceProjectName, @Nullable JSONObject threadMeta, @Nullable JSONArray participants ) { - List cards = new ArrayList<>(1); - if (hasSourceProject) { - String resolvedSourceProjectName = sourceProjectName == null || sourceProjectName.isEmpty() - ? "当前会话" - : sourceProjectName; - cards.add(new SummaryCardSpec( - resolvedSourceProjectName, - buildSourceBody(sourceProjectId, threadMeta, participants), - "新群会单独创建,原会话保留" - )); - return cards; - } - cards.add(new SummaryCardSpec( - "从会话中发起群聊", - "至少选择 2 个线程,新群会单独创建。", - "原有单线程会话会保留" - )); - return cards; + return buildSourceBody(sourceProjectId, threadMeta, participants); } - static SummaryCardSpec buildSelectionCardSpec( + static String buildSelectionHintText( int candidateCount, int selectedCount, boolean hasSourceProject ) { if (candidateCount <= 0) { - return new SummaryCardSpec( - "选择其他线程", - "当前没有可加入的其他线程", - "候选 0 个 · 已选 0 个" - ); + return "当前没有可加入的其他线程"; } if (selectedCount <= 0) { - return new SummaryCardSpec( - "选择其他线程", - hasSourceProject ? "至少选择 1 个其他线程" : "至少选择 2 个线程", - "候选 " + candidateCount + " 个 · 已选 0 个" - ); + return hasSourceProject ? "至少选择 1 个其他线程" : "至少选择 2 个线程"; } - return new SummaryCardSpec( - "选择其他线程", - "继续点选可调整成员", - "候选 " + candidateCount + " 个 · 已选 " + selectedCount + " 个" - ); + return "已选 " + selectedCount + " 个线程"; } private LinearLayout buildCandidateRow(CandidateConversation candidate) { - return BossUi.buildConversationRow( + LinearLayout row = BossUi.buildConversationRow( this, toCandidateConversationRow(candidate.sourceItem, selectedProjectIds.contains(candidate.projectId)), v -> toggleSelection(candidate.projectId) ); + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) row.getLayoutParams(); + params.bottomMargin = BossUi.dp(this, 8); + row.setLayoutParams(params); + row.setPadding(BossUi.dp(this, 12), BossUi.dp(this, 12), BossUi.dp(this, 12), BossUi.dp(this, 12)); + return row; } private void toggleSelection(String projectId) { @@ -399,7 +405,7 @@ public class GroupCreateActivity extends BossScreenActivity { String folderName = threadMeta == null ? "" : threadMeta.optString("folderName", ""); String resolvedFolderName = folderName.isEmpty() ? "未命名文件夹" : folderName; String resolvedThreadId = threadId == null || threadId.isEmpty() ? "未命名线程" : threadId; - return "来源线程 " + resolvedThreadId + return resolvedThreadId + " · " + resolvedFolderName + " · " @@ -407,18 +413,6 @@ public class GroupCreateActivity extends BossScreenActivity { + " 个参与线程"; } - static final class SummaryCardSpec { - final String title; - final String body; - final String meta; - - SummaryCardSpec(String title, String body, String meta) { - this.title = title; - this.body = body; - this.meta = meta; - } - } - private static final class CandidateConversation { private final String projectId; private final JSONObject sourceItem; diff --git a/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityTest.java b/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityTest.java index 849b49e..2c78ca2 100644 --- a/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityTest.java +++ b/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityTest.java @@ -14,7 +14,7 @@ import static org.junit.Assert.assertTrue; public class GroupCreateActivityTest { @Test - public void buildHeaderCardSpecs_collapsesSourceFlowIntoSingleCompactCard() { + public void buildSourceHeaderDetail_usesCompactWechatSummary() { JSONObject threadMeta = new StubJSONObject() .withString("threadDisplayName", "北区试产线回归") .withString("threadId", "thread-7") @@ -25,27 +25,20 @@ public class GroupCreateActivityTest { new StubJSONObject() ); - List cards = GroupCreateActivity.buildHeaderCardSpecs( - true, + String detail = GroupCreateActivity.buildSourceHeaderDetail( "source-1", - "北区试产线回归", threadMeta, participants ); - assertEquals(1, cards.size()); - assertEquals("北区试产线回归", cards.get(0).title); - assertEquals("来源线程 thread-7 · Mac Studio · 3 个参与线程", cards.get(0).body); - assertEquals("新群会单独创建,原会话保留", cards.get(0).meta); + assertEquals("thread-7 · Mac Studio · 3 个参与线程", detail); } @Test - public void buildSelectionCardSpec_usesCompactWechatStyleHint() { - GroupCreateActivity.SummaryCardSpec card = GroupCreateActivity.buildSelectionCardSpec(5, 0, true); - - assertEquals("选择其他线程", card.title); - assertEquals("至少选择 1 个其他线程", card.body); - assertEquals("候选 5 个 · 已选 0 个", card.meta); + public void buildSelectionHintText_usesCompactWechatStyleHint() { + assertEquals("至少选择 1 个其他线程", GroupCreateActivity.buildSelectionHintText(5, 0, true)); + assertEquals("已选 2 个线程", GroupCreateActivity.buildSelectionHintText(5, 2, true)); + assertEquals("当前没有可加入的其他线程", GroupCreateActivity.buildSelectionHintText(0, 0, true)); } @Test diff --git a/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityUiTest.java b/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityUiTest.java index 03a7a4b..8c4340e 100644 --- a/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityUiTest.java +++ b/android/app/src/test/java/com/hyzq/boss/GroupCreateActivityUiTest.java @@ -40,11 +40,10 @@ public class GroupCreateActivityUiTest { LinearLayout content = activity.findViewById(R.id.screen_content); assertTrue(viewTreeContainsText(content.getChildAt(0), "北区试产线回归")); - assertTrue(viewTreeContainsText(content.getChildAt(0), "来源线程 thread-7 · Mac Studio · 3 个参与线程")); - assertTrue(viewTreeContainsText(content.getChildAt(0), "新群会单独创建,原会话保留")); + assertTrue(viewTreeContainsText(content.getChildAt(0), "从当前会话发起群聊")); + assertTrue(viewTreeContainsText(content.getChildAt(0), "thread-7 · Mac Studio · 3 个参与线程")); assertTrue(viewTreeContainsText(content.getChildAt(1), "选择其他线程")); - assertTrue(viewTreeContainsText(content.getChildAt(1), "继续点选可调整成员")); - assertTrue(viewTreeContainsText(content.getChildAt(1), "候选 2 个 · 已选 2 个")); + assertTrue(viewTreeContainsText(content.getChildAt(2), "已选 2 个线程")); } @Test @@ -77,8 +76,32 @@ public class GroupCreateActivityUiTest { ); LinearLayout content = activity.findViewById(R.id.screen_content); - assertTrue(viewTreeContainsText(content.getChildAt(1), "至少选择 1 个其他线程")); - assertTrue(viewTreeContainsText(content.getChildAt(1), "候选 2 个 · 已选 0 个")); + assertTrue(viewTreeContainsText(content.getChildAt(2), "至少选择 1 个其他线程")); + } + + @Test + public void renderCreatePageUsesInlineActionRowInsteadOfStackedButtons() throws Exception { + Intent intent = new Intent() + .putExtra(GroupCreateActivity.EXTRA_SOURCE_PROJECT_ID, "source-1") + .putExtra(GroupCreateActivity.EXTRA_SOURCE_PROJECT_NAME, "北区试产线回归"); + TestGroupCreateActivity activity = Robolectric + .buildActivity(TestGroupCreateActivity.class, intent) + .setup() + .get(); + + ReflectionHelpers.callInstanceMethod( + activity, + "renderCreatePage", + ReflectionHelpers.ClassParameter.from(JSONObject.class, buildParticipantsPayload()), + ReflectionHelpers.ClassParameter.from(JSONObject.class, buildConversationsPayload()), + ReflectionHelpers.ClassParameter.from(boolean.class, true) + ); + + LinearLayout content = activity.findViewById(R.id.screen_content); + View lastChild = content.getChildAt(content.getChildCount() - 1); + assertTrue(lastChild instanceof LinearLayout); + assertTrue(viewTreeContainsText(lastChild, "取消")); + assertTrue(viewTreeContainsText(lastChild, "创建群聊")); } private static JSONObject buildParticipantsPayload() throws Exception { diff --git a/android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityUiTest.java b/android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityUiTest.java index de8c74c..cf72751 100644 --- a/android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityUiTest.java +++ b/android/app/src/test/java/com/hyzq/boss/ProjectDetailActivityUiTest.java @@ -190,6 +190,42 @@ public class ProjectDetailActivityUiTest { assertFalse(viewTreeContainsText(attachmentView, "已分析")); } + @Test + public void outgoingAttachmentMetaPrefersTimeOnly() throws Exception { + Intent intent = new Intent() + .putExtra(ProjectDetailActivity.EXTRA_PROJECT_ID, "project-1") + .putExtra(ProjectDetailActivity.EXTRA_PROJECT_NAME, "北区试产线回归"); + TestProjectDetailActivity activity = Robolectric + .buildActivity(TestProjectDetailActivity.class, intent) + .setup() + .get(); + + JSONObject attachment = new JSONObject() + .put("attachmentId", "att-meta") + .put("fileName", "现场照片.jpg") + .put("mimeType", "image/jpeg") + .put("attachmentKind", "image") + .put("analysisState", "queued_auto") + .put("fileSizeBytes", 1024); + JSONObject message = new JSONObject() + .put("id", "msg-meta") + .put("kind", "attachment") + .put("body", "已发送附件") + .put("attachments", new JSONArray().put(attachment)); + + View attachmentView = ReflectionHelpers.callInstanceMethod( + activity, + "buildAttachmentMessageView", + ReflectionHelpers.ClassParameter.from(JSONObject.class, message), + ReflectionHelpers.ClassParameter.from(String.class, "你"), + ReflectionHelpers.ClassParameter.from(String.class, "09:26"), + ReflectionHelpers.ClassParameter.from(boolean.class, true) + ); + + assertTrue(viewTreeContainsText(attachmentView, "09:26")); + assertFalse(viewTreeContainsText(attachmentView, "你 · 09:26")); + } + private static View buildBoundMessageView(TestProjectDetailActivity activity, String messageId, String body) { TextView messageView = new TextView(activity); messageView.setText(body); diff --git a/docs/architecture/ai_handoff_index_cn.md b/docs/architecture/ai_handoff_index_cn.md index 3ba22c3..8e2436d 100644 --- a/docs/architecture/ai_handoff_index_cn.md +++ b/docs/architecture/ai_handoff_index_cn.md @@ -153,7 +153,7 @@ - 邮件:`Postfix + Dovecot` - Android:`AppCompatActivity + 原生 XML 布局 + HttpURLConnection` - 原生登录恢复:`SharedPreferences + restore token` -- 当前最新原生 APK:`2.5.2`(`versionCode=15`) +- 当前最新原生 APK:`2.5.3`(`versionCode=16`) 当前不要误判成已经用了: diff --git a/docs/architecture/current_runtime_and_deploy_status_cn.md b/docs/architecture/current_runtime_and_deploy_status_cn.md index 181ab00..3f95752 100644 --- a/docs/architecture/current_runtime_and_deploy_status_cn.md +++ b/docs/architecture/current_runtime_and_deploy_status_cn.md @@ -116,7 +116,7 @@ cd /Users/kris/code/boss - 当前已生成 Android debug APK:`android/app/build/outputs/apk/debug/app-debug.apk` - 当前已生成 Android signed release APK:`android/app/build/outputs/apk/release/app-release.apk` - 当前 release 构建还会额外生成带版本号的 APK:`android/app/build/outputs/apk/release/boss-android-v{versionName}-release.apk` -- 当前最新 release 构建版本:`2.5.2`(`versionCode=15`) +- 当前最新 release 构建版本:`2.5.3`(`versionCode=16`) - 当前 release keystore 位于本机 `android/keystores/boss-release.keystore`,签名参数位于 `android/signing/release-signing.properties` - `2.0.1` 已在本机连接的华为真机上复核通过,修复了 `Theme.SplashScreen` 导致的 `AppCompatActivity` 启动闪退 - `2.1.0` 已把 Web 一级页和主要二级页全部补成原生活动页:`MainActivity / ProjectDetailActivity / ProjectGoalsActivity / ProjectVersionsActivity / ProjectForwardActivity / ThreadDetailActivity / DeviceDetailActivity / DeviceEnrollmentActivity / SkillInventoryActivity / SecurityActivity / SettingsActivity / AiAccountsActivity / OpsCenterActivity / AboutActivity` @@ -132,6 +132,8 @@ cd /Users/kris/code/boss - `2.5.1` 已压缩“发起群聊”页首信息密度:来源会话场景只保留一张紧凑摘要卡,选择区改成更短的微信式提示,同时保留会话卡片式候选列表 - `2.5.2` 已继续回退深层原生页:`会话信息 / 群资料` 改为轻量头部信息 + 菜单式入口 + 线程列表;`项目目标 / 版本迭代记录` 也已按设计图改成轻卡片结构,不再使用厚按钮和说明块 - `2.5.2` 已压缩附件消息卡片的状态层级:`待分析` 收成 `可分析`,`让 AI 分析` 收成 `AI 分析`,有摘要时不再重复显示 `已分析` +- `2.5.3` 已继续压缩“发起群聊”页:来源会话摘要改成轻量 profile header,选择区改成 `选择其他线程 + hint pill`,底部按钮收成同层操作区,候选会话卡片纵向间距进一步压缩 +- `2.5.3` 已把聊天页里自己发出的消息顶部元信息收成只显示时间,不再重复 `你 · 时间`,文本消息、附件卡片和聊天记录卡片都会共用这条规则 - 当前附件分析任务已带受控 `task token` 下载链接和文本摘录:本地开发环境会跟随请求 origin 生成链接,生产环境默认走 `https://boss.hyzq.net` - `2.5.x` 当前已补上会话首页独立建群入口:可以不从单线程聊天内部出发,直接在会话首页右上角 `+` 建立新群聊;同时已把多个原生自定义 top bar 页面统一纳入状态栏安全区处理 diff --git a/public/downloads/boss-android-latest-aab.json b/public/downloads/boss-android-latest-aab.json index ce67b99..4f0ae65 100644 --- a/public/downloads/boss-android-latest-aab.json +++ b/public/downloads/boss-android-latest-aab.json @@ -1,11 +1,11 @@ { "artifactType": "aab", - "fileName": "boss-android-v2.5.2-release.aab", - "urlPath": "/downloads/boss-android-v2.5.2-release.aab", - "sizeBytes": 2912579, - "updatedAt": "2026-03-29T12:26:43Z", - "sha256": "dca2dc0a080bba282505bacf7e8a37e5aca2e695a657b46df0e184c1ff077d6e", - "versionName": "2.5.2", - "versionCode": 15, + "fileName": "boss-android-v2.5.3-release.aab", + "urlPath": "/downloads/boss-android-v2.5.3-release.aab", + "sizeBytes": 2912097, + "updatedAt": "2026-03-29T12:41:56Z", + "sha256": "12b520dba9a9fa3075c374910a595943d3f2a0b9f70a813bdfe8d1546e380d3c", + "versionName": "2.5.3", + "versionCode": 16, "buildFlavor": "release" } diff --git a/public/downloads/boss-android-latest.aab b/public/downloads/boss-android-latest.aab index 5460c67..ce27455 100644 Binary files a/public/downloads/boss-android-latest.aab and b/public/downloads/boss-android-latest.aab differ diff --git a/public/downloads/boss-android-latest.apk b/public/downloads/boss-android-latest.apk index d602cac..befc680 100644 Binary files a/public/downloads/boss-android-latest.apk and b/public/downloads/boss-android-latest.apk differ diff --git a/public/downloads/boss-android-latest.json b/public/downloads/boss-android-latest.json index f4b9d40..7dcac60 100644 --- a/public/downloads/boss-android-latest.json +++ b/public/downloads/boss-android-latest.json @@ -1,10 +1,10 @@ { - "fileName": "boss-android-v2.5.2-release.apk", + "fileName": "boss-android-v2.5.3-release.apk", "urlPath": "/api/v1/user/ota/package", - "sizeBytes": 3089319, - "updatedAt": "2026-03-29T12:26:31Z", - "sha256": "a27be7abe260c42dcd357206adf292f48bdd33bb14e343c25ee38faeebefd97f", - "versionName": "2.5.2", - "versionCode": 15, + "sizeBytes": 3088834, + "updatedAt": "2026-03-29T12:41:51Z", + "sha256": "dd44b6e1228966fbd6e83ab53936393024a76e17f7fe996e15442f4f105a435a", + "versionName": "2.5.3", + "versionCode": 16, "buildFlavor": "release" } diff --git a/public/downloads/boss-android-v2.5.3-release.aab b/public/downloads/boss-android-v2.5.3-release.aab new file mode 100644 index 0000000..ce27455 Binary files /dev/null and b/public/downloads/boss-android-v2.5.3-release.aab differ diff --git a/public/downloads/boss-android-v2.5.3-release.apk b/public/downloads/boss-android-v2.5.3-release.apk new file mode 100644 index 0000000..befc680 Binary files /dev/null and b/public/downloads/boss-android-v2.5.3-release.apk differ