From 420ca6b1ce029f558892f0da6c6d15842393f335 Mon Sep 17 00:00:00 2001 From: ADSFAaron Date: Sun, 30 Aug 2026 18:23:30 +0800 Subject: [PATCH] feat(execution): show what is running, and stop two silent failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three user reports, one theme: the app was doing the right thing without saying so, or failing without saying so. Running flows are now visible wherever the user looks. The card badge was a three-second timer armed by the Run button alone, so a swipe, an alarm, a geofence or a widget tap lit nothing, while a run blocked by a missing permission lit anyway. Its source is now the engine's own set — the same state that drops overlapping runs, so it cannot drift from what is really executing. The ongoing notification names the flow instead of saying "automation is active", and long-pressing the master switch lists everything in flight. A flow that finishes in 30ms is held on screen for 900ms, because an indicator that appears and vanishes inside one frame is indistinguishable from nothing having happened. Scheduled flows ran late because SCHEDULE_EXACT_ALARM was declared in the manifest and never requested. For a targetSdk 33+ app it is denied by default on a fresh install, so the scheduler fell back to an inexact alarm the system batches into a Doze maintenance window — the documented guarantee there is "within one hour". Devices upgraded from an older version keep the permission, which is why the same build was fine for some users and ten minutes late for others. TIME triggers now report it like any other missing permission, and a receiver re-schedules on grant: precision is fixed when an alarm is set, so without that step the alarms already in flight stay late. NFC was hijacked device-wide whenever the app was open. enableReaderMode is exclusive and FLAG_READER_SKIP_NDEF_CHECK disables NDEF dispatch outright, and onResume enabled it unconditionally — so a URL tag opened nothing and a transit card did nothing, even for users with no NFC flow at all. Reader mode now has one owner and is held only while an enabled NFC flow could use it or a config screen is waiting for a tap. The manifest TAG_DISCOVERED filter goes with it: it is the dispatch system's last resort, which made NexFlow the catch-all for every tag no other app claimed, and it is deprecated as of API 37. Also fixes the volume action summary, which still read the pre-1.4.0 `level` key and rendered every volume action — new ones included — as "Media: ?". Verified on device (XQ-AT52): reader mode off with the app foregrounded and on only during a scan, the card badge lighting from a swipe-triggered run, and the notification naming the flow. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 23 ++ CLAUDE.md | 3 + app/build.gradle.kts | 4 +- app/src/main/AndroidManifest.xml | 21 +- app/src/main/java/com/nexflow/MainActivity.kt | 87 +++- .../java/com/nexflow/event/NfcReaderMode.kt | 67 +++ .../permissions/FlowPermissionChecker.kt | 19 + .../nexflow/permissions/PermissionIntents.kt | 10 + .../receiver/ExactAlarmPermissionReceiver.kt | 64 +++ .../java/com/nexflow/service/FlowEngine.kt | 50 ++- .../nexflow/service/FlowExecutionService.kt | 89 +++- .../nexflow/trigger/NfcTagTriggerHandler.kt | 6 +- .../java/com/nexflow/ui/flows/FlowsScreen.kt | 391 +++++++++++++++--- .../com/nexflow/ui/flows/FlowsViewModel.kt | 8 + .../ui/flows/detail/FlowDetailScreen.kt | 43 +- .../ui/flows/detail/config/ActionConfig.kt | 14 +- app/src/main/res/values-ja/strings.xml | 11 +- app/src/main/res/values-zh-rCN/strings.xml | 11 +- app/src/main/res/values-zh-rTW/strings.xml | 11 +- app/src/main/res/values/strings.xml | 12 +- .../ui/flows/FlowCardScreenshotTest.kt | 28 +- ...rdRunning_en \302\267 dark_e6b9ad11_0.png" | Bin 0 -> 36694 bytes ...dRunning_en \302\267 light_448008dd_0.png" | Bin 0 -> 36803 bytes ...rdRunning_ja \302\267 dark_8f36ad31_0.png" | Bin 0 -> 36704 bytes ...dRunning_ja \302\267 light_c92a17c0_0.png" | Bin 0 -> 36777 bytes ...unning_zh-CN \302\267 dark_a43c20f1_0.png" | Bin 0 -> 36758 bytes ...nning_zh-CN \302\267 light_482c6f89_0.png" | Bin 0 -> 36878 bytes ...unning_zh-TW \302\267 dark_46e4ec12_0.png" | Bin 0 -> 36943 bytes ...nning_zh-TW \302\267 light_c317a2a3_0.png" | Bin 0 -> 37080 bytes .../com/nexflow/event/NfcReaderModeTest.kt | 59 +++ .../permissions/ExactAlarmPermissionTest.kt | 111 +++++ .../service/FlowEngineRunningStateTest.kt | 176 ++++++++ .../flows/detail/config/VolumeSummaryTest.kt | 82 ++++ 33 files changed, 1272 insertions(+), 128 deletions(-) create mode 100644 app/src/main/java/com/nexflow/event/NfcReaderMode.kt create mode 100644 app/src/main/java/com/nexflow/receiver/ExactAlarmPermissionReceiver.kt create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 dark_e6b9ad11_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 light_448008dd_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 dark_8f36ad31_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 light_c92a17c0_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-CN \302\267 dark_a43c20f1_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-CN \302\267 light_482c6f89_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 dark_46e4ec12_0.png" create mode 100644 "app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 light_c317a2a3_0.png" create mode 100644 app/src/test/java/com/nexflow/event/NfcReaderModeTest.kt create mode 100644 app/src/test/java/com/nexflow/permissions/ExactAlarmPermissionTest.kt create mode 100644 app/src/test/java/com/nexflow/service/FlowEngineRunningStateTest.kt create mode 100644 app/src/test/java/com/nexflow/ui/flows/detail/config/VolumeSummaryTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c58cf4..63ade7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ (尚無項目) +## [1.5.0] - 2026-08-30 + +這一版處理的是「我怎麼知道它有沒有在動」,以及兩個安靜到不像故障的故障。執行中的流程現在會在卡片、通知與長按閃電的清單裡同時現身;排程晚到十分鐘的原因是一個從來沒被要求過的權限;而 NexFlow 只要開著,就會把整支手機的 NFC 感應全部吃掉。 + +### 新增(Added) + +- **執行中的流程看得見了,不管是誰啟動的**:卡片右下角在流程執行時轉成轉圈的「執行中」。這裡原本是點下執行鈕才亮三秒的計時器,所以側滑執行、時間到、地理圍欄、小工具啟動的流程一律不亮,而被權限擋下、根本沒開始的執行反而亮著。現在的來源是引擎自己用來擋重複執行的那份狀態,不是另一份會走樣的複本 + - 執行極快的流程會至少顯示 0.9 秒。三十毫秒跑完的流程是使用者真的要求過的一次執行,但指示器在一個影格內閃掉,和什麼都沒發生分不出來——而那正是這個指示器存在的理由 +- **通知會說出正在跑哪一個流程**:常駐通知從「自動化執行中」變成「正在執行:<流程名稱>」,同時跑多個時顯示數量、展開列出名稱。背景觸發的流程原本只有一個容易錯過的 Toast 作為線索 +- **長按右上角的閃電,列出目前執行中的流程**:從膠囊邊緣展開的浮層,每一列帶自己的轉圈指示。膠囊本身也會顯示執行中的數量,所以不長按也看得到 + +### 修正(Fixed) + +- **排程到 9:00 的流程可能 9:10 才跑**:`SCHEDULE_EXACT_ALARM` 在 manifest 裡宣告了,但**沒有任何一處程式碼向使用者要過它**。targetSdk 33 以上的 App 在全新安裝(以及備份還原到新機)時這個權限預設是拒絕的,於是排程器安靜地退回不精確鬧鐘,被系統批次進 Doze 維護視窗——官方文件對不精確鬧鐘的保證是「一小時內」。從舊版一路升級上來的裝置會保留已授予的權限,這是為什麼同一版有人遇到、有人沒有 + - TIME 觸發器納入權限檢查:缺少精確鬧鐘時,流程卡片會亮出警告,設置向導把使用者帶到系統的「鬧鐘和提醒」頁 + - 使用者授予後,`SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED` 會立刻重排所有 TIME 鬧鐘。鬧鐘只在排定當下決定精度,沒有這一步,授權後既有的鬧鐘會繼續遲到,直到使用者重新編輯流程或重開機 +- **NexFlow 開著的時候,整支手機的 NFC 都失效**:`MainActivity` 無條件在 `onResume` 開啟 reader mode。reader mode 是獨占且全裝置生效的,`FLAG_READER_SKIP_NDEF_CHECK` 更直接關掉 NDEF 分派,所以感應網址標籤不會開啟瀏覽器、感應交通卡沒有反應——即使使用者一個 NFC 流程都沒有。現在只有「有啟用中的 NFC 流程且引擎正在執行」或「正在設定頁掃描標籤」時才佔用 + - 一併移除 manifest 的 `TAG_DISCOVERED` 攔截。它是標籤分派的最後手段,等於讓 NexFlow 成為所有其他 App 都不處理的標籤的萬用接收者(門禁卡、交通卡);它在 API 37 也已經被標為 deprecated。NFC 觸發器本來就只在前景有效,從來不需要這個攔截 + - 掃描中讀到的標籤不再同時觸發流程。重新掃描「正在編輯的那個流程」所綁定的標籤,不應該把那個流程跑起來 + - 設定頁的掃描不再自己開關 reader mode。兩個持有者的結果是設定頁關閉掃描時,順手把 `MainActivity` 為了 NFC 觸發器而持有的那份也關掉了 +- **音量動作的摘要顯示成「媒體:?」**:1.4.0 把音量從絕對階數(`level`)改存百分比(`volume_percent`),但流程詳情頁的摘要那一行仍然去讀舊的鍵。所有音量動作——包括用新版編輯器存的——都顯示成問號。摘要現在走與編輯器相同的正規化,1.4.0 之前寫的流程不必重新儲存也會顯示它實際會執行的百分比 + ## [1.4.0] - 2026-08-21 這一版補的是「跑完之後,到底發生了什麼」:執行記錄從一句成敗變成逐個動作的紀錄,HTTP 拿得回資料讓流程能依真實回應分支,而條件判斷不再對「從來沒有的值」下結論。同時把工具鏈與相依套件推到現行 stable,並讓測試從一層變四層、全部在 CI 上把關。 @@ -227,6 +249,7 @@ AI 對話從「能用」變成「好用」:回覆逐字出現而不是等半 - 多語言:繁體中文、簡體中文、日文、英文 - 匯入/匯出 `.flow`(JSON)與 MacroDroid `.mdr` 相容解析 +[1.5.0]: https://github.com/ADSFAaron/NexFlow/releases/tag/v1.5.0 [1.4.0]: https://github.com/ADSFAaron/NexFlow/releases/tag/v1.4.0 [1.3.0]: https://github.com/ADSFAaron/NexFlow/releases/tag/v1.3.0 [1.2.0]: https://github.com/ADSFAaron/NexFlow/releases/tag/v1.2.0 diff --git a/CLAUDE.md b/CLAUDE.md index b84fdbf..c3de9a7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,6 +48,9 @@ core/macrodroid-compat/ # MacroDroid .mdr 格式解析 | `Regex("""\{\{([^}]+)}}""")` | 某些 Android regex engine 對 `))}}` 報 syntax error | 改為 `\}\}` 明確 escape | | `AccessibilityService.dispatchGesture()` | 沒在 accessibility-service XML 宣告 `android:canPerformGestures="true"` 就只會回 `false`,不丟例外、不寫 log,模擬點擊/滑動整個靜默失效 | `nexflow_accessibility_config.xml` 一定要有 `android:canPerformGestures="true"` | | `GestureDescription.StrokeDescription` | 座標超出螢幕範圍會丟 `IllegalArgumentException`;座標來自使用者手打的設定,在 service 的 coroutine 裡丟出去會拖垮整個無障礙服務 | 建 `StrokeDescription` 要包 `runCatching`,失敗就回報 action 失敗。單點 `moveTo`(不 `lineTo`)是合法的「不移動的觸碰」,可直接當點擊用 | +| `NfcAdapter.enableReaderMode()` | **獨占且全裝置生效**:開著的時候所有感應都只進自己的 callback,別的 App 一律看不到標籤;`FLAG_READER_SKIP_NDEF_CHECK` 更直接關掉 NDEF 分派(javadoc 原話「NDEF-based tag dispatch will not be functional」)。在 `onResume` 無條件開啟=只要 App 開著就吃掉使用者的網址標籤與交通卡 | 只在真的要用時開(有啟用中的 NFC 流程、或正在掃描設定),且只能有一個持有者。設定頁想掃卡就向那個持有者提出請求,不要自己 `enableReaderMode`——第二個持有者關閉時會把第一個的也關掉 | +| manifest `android.nfc.action.TAG_DISCOVERED` | 分派順序是 NDEF → TECH → TAG,TAG 是最後手段。若機器上只有你註冊,就成了所有其他 App 不處理的標籤(門禁卡、交通卡)的萬用接收者。API 37 已標 `@Deprecated` | 前景 NFC 用 reader mode 就夠,不要註冊這個 filter。真要背景 NFC 才用 `TECH_DISCOVERED` + 明確 tech-list | +| `SCHEDULE_EXACT_ALARM` | targetSdk 33+ 的 App **全新安裝時預設拒絕**(備份還原到新機也是拒絕),但從舊版升級的裝置會保留已授予的 → 同一版有人正常有人遲到。沒授權時退回不精確鬧鐘,官方保證只有「一小時內」,排 9:00 的流程 9:10 才跑 | 宣告不等於拿到:一定要 `canScheduleExactAlarms()` 檢查 + 用 `ACTION_REQUEST_SCHEDULE_EXACT_ALARM` 引導。並且要收 `ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED` 重排——鬧鐘的精度是排定當下決定的,授權後既有鬧鐘不會自己升級 | ### 3. 測試 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d1543c8..611cd21 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,8 +28,8 @@ android { applicationId = "com.adsf.nexflow" minSdk = 30 targetSdk = 37 - versionCode = 8 - versionName = "1.4.0" + versionCode = 9 + versionName = "1.5.0" testInstrumentationRunner = "com.nexflow.HiltTestRunner" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bb2219c..5fdd45d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -111,11 +111,12 @@ - - - - - + @@ -154,6 +155,16 @@ + + + + + + + dispatchNfcTag(tag) }, - NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or - NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or - NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, - null, - ) + /** + * Hold the NFC controller in reader mode only while something actually needs it. + * + * This used to be an unconditional `enableReaderMode` in `onResume`, which meant that + * merely having NexFlow open swallowed every tap on the device: reader mode is exclusive + * and FLAG_READER_SKIP_NDEF_CHECK disables NDEF dispatch outright, so a URL tag opened + * nothing and a transit card did nothing — even for users with no NFC flow at all. + * + * Collection is scoped to RESUMED because reader mode is only legal for a foreground + * activity, which is also the only time an NFC trigger can fire. + */ + private fun observeReaderModeNeed() { + val adapter = nfcAdapter ?: return + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + combine( + repository.observeEnabled().map { flows -> + flows.any { flow -> flow.triggers.any { it.type == TriggerType.NFC_TAG } } + }, + FlowExecutionService.running, + NfcReaderMode.scanRequests.map { it > 0 }, + ) { hasNfcFlow, engineRunning, scanning -> + // A tag can only start a flow when the engine is actually up, so with the + // master switch off there is nothing to gain from claiming the controller. + // A scan is exempt: naming a tag is how the first NFC flow gets configured. + (hasNfcFlow && engineRunning) || scanning + } + .distinctUntilChanged() + .collect { needed -> + if (needed) { + adapter.enableReaderMode( + this@MainActivity, + { tag -> dispatchNfcTag(tag) }, + NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or + NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or + NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, + null, + ) + } else { + adapter.disableReaderMode(this@MainActivity) + } + } + } + } } override fun onPause() { super.onPause() + // Unconditional, and before onPause returns: the collector above is cancelled by the + // lifecycle without getting a chance to turn reader mode off itself, and leaving it on + // would keep NFC hijacked after the app is no longer in front. A no-op when it was + // never enabled. nfcAdapter?.disableReaderMode(this) } override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - handleNfcIntent(intent) handleShareIntent(intent) handleRunFlowIntent(intent) } @@ -155,13 +205,14 @@ class MainActivity : AppCompatActivity() { } } - private fun handleNfcIntent(intent: Intent?) { - val tag = intent?.getParcelableExtra(NfcAdapter.EXTRA_TAG) ?: return - dispatchNfcTag(tag) - } - private fun dispatchNfcTag(tag: Tag) { val tagId = tag.id.joinToString("") { "%02X".format(it) } - NfcEventSource.emit(tagId) + // A scan in progress claims the tag outright. The user is naming a tag, not asking for + // the flows bound to it to run — and one of those is very likely the flow being edited. + if (NfcReaderMode.scanRequests.value > 0) { + NfcReaderMode.emitScannedTag(tagId) + } else { + NfcEventSource.emit(tagId) + } } } diff --git a/app/src/main/java/com/nexflow/event/NfcReaderMode.kt b/app/src/main/java/com/nexflow/event/NfcReaderMode.kt new file mode 100644 index 0000000..8383093 --- /dev/null +++ b/app/src/main/java/com/nexflow/event/NfcReaderMode.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.event + +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update + +/** + * Lets UI ask for the NFC controller to be put in reader mode without touching the adapter. + * + * Reader mode is exclusive and device-wide: while it is on, every tap goes to this app's + * callback and nothing is dispatched to any other app — a URL tag opens nothing, a transit + * card does nothing. So it must have exactly one owner ([com.nexflow.MainActivity]) that can + * see every reason it is wanted, and it must be off whenever there is no reason at all. + * + * Two things want it: an enabled flow with an NFC trigger (the activity works that out from + * the repository), and a config screen waiting for the user to tap the tag they are naming — + * which has to work even before any NFC flow exists. Requests are counted rather than a plain + * flag so one screen ending its scan cannot switch off another screen's. + */ +object NfcReaderMode { + + private val _scanRequests = MutableStateFlow(0) + + /** How many screens are currently waiting for the user to tap a tag. */ + val scanRequests: StateFlow = _scanRequests.asStateFlow() + + fun beginScan() = _scanRequests.update { it + 1 } + + fun endScan() = _scanRequests.update { (it - 1).coerceAtLeast(0) } + + private val _scannedTags = MutableSharedFlow( + replay = 0, + extraBufferCapacity = 4, + onBufferOverflow = BufferOverflow.DROP_OLDEST, + ) + + /** + * Tags read while a scan is in progress. Separate from [NfcEventSource] on purpose: a tag + * tapped to fill in a config field must not also fire the flows that trigger on it — + * otherwise re-scanning the tag of the flow you are editing runs that very flow. + */ + val scannedTags: SharedFlow = _scannedTags.asSharedFlow() + + fun emitScannedTag(tagId: String) { + _scannedTags.tryEmit(tagId) + } +} diff --git a/app/src/main/java/com/nexflow/permissions/FlowPermissionChecker.kt b/app/src/main/java/com/nexflow/permissions/FlowPermissionChecker.kt index 8d624ed..5d166c3 100644 --- a/app/src/main/java/com/nexflow/permissions/FlowPermissionChecker.kt +++ b/app/src/main/java/com/nexflow/permissions/FlowPermissionChecker.kt @@ -29,6 +29,7 @@ import com.nexflow.core.automation.model.ConditionType import com.nexflow.core.automation.model.Flow import com.nexflow.core.automation.model.TriggerType import com.nexflow.executor.NotificationActionExecutor +import com.nexflow.trigger.TimeTriggerScheduler import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject import javax.inject.Singleton @@ -54,6 +55,13 @@ enum class SpecialAccess { /** WRITE_SECURE_SETTINGS — grantable only via ADB, no system UI to send the user to. */ WRITE_SECURE_SETTINGS, + + /** + * SCHEDULE_EXACT_ALARM — declared in the manifest but, for a targetSdk 33+ app, denied by + * default on a fresh install (and after a backup-restore). Granted on the system's + * "Alarms & reminders" page. + */ + EXACT_ALARM, } /** @@ -79,6 +87,7 @@ data class MissingPermission( @Singleton class FlowPermissionChecker @Inject constructor( @ApplicationContext private val context: Context, + private val timeTriggerScheduler: TimeTriggerScheduler, ) { fun missingPermissions(flow: Flow): List { @@ -139,6 +148,16 @@ class FlowPermissionChecker @Inject constructor( if (!bluetoothGranted()) { add(R.string.perm_bluetooth, Manifest.permission.BLUETOOTH_CONNECT) } + // Without exact alarms the flow still runs, just late — the scheduler falls back + // to an inexact alarm the system batches into a Doze maintenance window, which + // in practice turns "09:00" into anything up to an hour later. That is the one + // failure mode a user cannot diagnose from the outside: the flow is enabled, the + // log shows it ran, and the only wrong thing is the time. So it is reported here + // like any other missing permission rather than left to be discovered. + TriggerType.TIME -> + if (!timeTriggerScheduler.canScheduleExact()) { + addSpecial(R.string.perm_exact_alarm, SpecialAccess.EXACT_ALARM) + } else -> Unit } } diff --git a/app/src/main/java/com/nexflow/permissions/PermissionIntents.kt b/app/src/main/java/com/nexflow/permissions/PermissionIntents.kt index 3a70c2d..0a3b29b 100644 --- a/app/src/main/java/com/nexflow/permissions/PermissionIntents.kt +++ b/app/src/main/java/com/nexflow/permissions/PermissionIntents.kt @@ -19,6 +19,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri +import android.os.Build import android.os.Bundle import android.provider.Settings import com.nexflow.service.NexFlowAccessibilityService @@ -59,6 +60,15 @@ object PermissionIntents { SpecialAccess.BACKGROUND_LOCATION -> Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, appUri(context)) SpecialAccess.WRITE_SECURE_SETTINGS -> null + // Official deep link to this app's "Alarms & reminders" toggle. The page (and the + // constant) only exist on API 31+; below that SCHEDULE_EXACT_ALARM is granted at + // install, so the checker never reports it and this branch is unreachable anyway. + SpecialAccess.EXACT_ALARM -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, appUri(context)) + } else { + null + } } /** diff --git a/app/src/main/java/com/nexflow/receiver/ExactAlarmPermissionReceiver.kt b/app/src/main/java/com/nexflow/receiver/ExactAlarmPermissionReceiver.kt new file mode 100644 index 0000000..17ab56c --- /dev/null +++ b/app/src/main/java/com/nexflow/receiver/ExactAlarmPermissionReceiver.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.receiver + +import android.app.AlarmManager +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import com.nexflow.core.automation.repository.FlowRepository +import com.nexflow.trigger.TimeTriggerScheduler +import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.launch +import javax.inject.Inject + +/** + * Upgrades already-scheduled TIME alarms the moment the user grants "Alarms & reminders". + * + * Alarms are scheduled once, with whatever precision was available at the time. Without this, + * a user who grants the permission after seeing the flow's warning would keep the inexact + * alarms they already have — still minutes late — until they happened to edit the flow or + * reboot. Re-running [TimeTriggerScheduler.sync] replaces each one with an exact alarm. + * + * The system does not broadcast on revocation (it cancels the exact alarms itself), so this + * only ever runs in the granting direction. + */ +@AndroidEntryPoint +class ExactAlarmPermissionReceiver : BroadcastReceiver() { + + @Inject lateinit var repository: FlowRepository + @Inject lateinit var timeTriggerScheduler: TimeTriggerScheduler + + override fun onReceive(context: Context, intent: Intent) { + if (intent.action != AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED) return + // Re-check rather than trust the broadcast: the docs require it, because the user can + // revoke again before this arrives. sync() would then just re-write inexact alarms. + if (!timeTriggerScheduler.canScheduleExact()) return + + val pending = goAsync() + CoroutineScope(SupervisorJob() + Dispatchers.Default).launch { + try { + timeTriggerScheduler.sync(repository.observeEnabled().first()) + } finally { + pending.finish() + } + } + } +} diff --git a/app/src/main/java/com/nexflow/service/FlowEngine.kt b/app/src/main/java/com/nexflow/service/FlowEngine.kt index 325119e..9951dfe 100644 --- a/app/src/main/java/com/nexflow/service/FlowEngine.kt +++ b/app/src/main/java/com/nexflow/service/FlowEngine.kt @@ -45,6 +45,9 @@ import kotlinx.coroutines.withContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.asFlow @@ -53,7 +56,6 @@ import kotlinx.coroutines.flow.flattenMerge import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import java.util.UUID -import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject import javax.inject.Singleton @@ -78,8 +80,16 @@ class FlowEngine @Inject constructor( private var engineJob: Job? = null - /** Flow ids currently executing, to drop overlapping runs of the same flow. */ - private val runningFlows = ConcurrentHashMap.newKeySet() + private val runningLock = Any() + private val _runningFlows = MutableStateFlow>(emptyList()) + + /** + * The flows executing right now, oldest first — the single source of truth behind every + * "running" indicator in the app (the list card, the service notification, the status + * popup). Doubles as the guard that drops overlapping runs of the same flow, so it is + * never merely a display copy that could drift from what the engine is really doing. + */ + val runningFlows: StateFlow> = _runningFlows.asStateFlow() fun start(scope: CoroutineScope) { engineJob = scope.launch { @@ -218,7 +228,7 @@ class FlowEngine @Inject constructor( ): ExecutionStatus? { // Skip if this flow is already executing — rapid repeated triggers must not stack // overlapping runs of the same flow. - if (!runningFlows.add(flow.id)) return null + if (!beginRun(flow)) return null try { val startMs = System.currentTimeMillis() val globals = globalVariableRepository.currentValues() @@ -302,10 +312,29 @@ class FlowEngine @Inject constructor( ) return status } finally { - runningFlows.remove(flow.id) + endRun(flow.id) } } + /** + * Claim the run slot for [flow]. Compare-and-set under a lock rather than a plain + * [MutableStateFlow.update]: the caller needs to know whether *it* was the one that + * claimed the slot, and two triggers firing in the same instant must not both decide + * they did. + * + * @return false when the flow is already running, in which case this run is dropped. + */ + private fun beginRun(flow: AutomationFlow): Boolean = synchronized(runningLock) { + if (_runningFlows.value.any { it.id == flow.id }) return false + _runningFlows.value = _runningFlows.value + + RunningFlow(flow.id, flow.name, System.currentTimeMillis()) + true + } + + private fun endRun(flowId: String) = synchronized(runningLock) { + _runningFlows.value = _runningFlows.value.filterNot { it.id == flowId } + } + /** * What the conditions are evaluated against: the same names the actions will see, so * `{{trigger.body}}` or `{{g:mode}}` mean the same thing in a constraint and in an action. @@ -344,3 +373,14 @@ class FlowEngine @Inject constructor( val triggerVariables: Map, ) } + +/** + * One flow the engine is executing right now. Carries the name so that surfaces without + * access to the repository — the foreground-service notification in particular — can say + * *which* flow is running rather than just that something is. + */ +data class RunningFlow( + val id: String, + val name: String, + val startedAt: Long, +) diff --git a/app/src/main/java/com/nexflow/service/FlowExecutionService.kt b/app/src/main/java/com/nexflow/service/FlowExecutionService.kt index 76511ee..f42f1cc 100644 --- a/app/src/main/java/com/nexflow/service/FlowExecutionService.kt +++ b/app/src/main/java/com/nexflow/service/FlowExecutionService.kt @@ -15,15 +15,20 @@ */ package com.nexflow.service +import android.Manifest import android.app.Notification import android.app.NotificationManager import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build import android.os.Bundle import android.os.IBinder import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat +import androidx.core.content.ContextCompat import com.nexflow.MainActivity import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -41,6 +46,8 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import javax.inject.Inject @@ -57,7 +64,48 @@ class FlowExecutionService : Service() { override fun onCreate() { super.onCreate() _running.value = true - startForeground(SERVICE_NOTIFICATION_ID, buildServiceNotification()) + startForeground(SERVICE_NOTIFICATION_ID, buildServiceNotification(emptyList())) + observeRunningFlows() + } + + /** + * Keep the ongoing notification naming the flows that are running. Background triggers were + * previously indistinguishable from nothing happening: the only clue a flow had fired was a + * Toast the user may well have missed. + * + * Started from [onCreate] rather than alongside the engine, because a manual run (widget, + * tile, shortcut) is served even while the master switch is off. + */ + private fun observeRunningFlows() { + serviceScope.launch { + flowEngine.runningFlows.collectLatest { running -> + // The platform drops notification updates posted more than about once a second, + // and a short flow can start and finish inside that window. collectLatest + + // a settling delay coalesces those bursts and always ends on the latest state; + // it also spares the shade a flicker for flows that finish in milliseconds. + delay(NOTIFICATION_SETTLE_MS) + postServiceNotification(running) + } + } + } + + /** + * Re-post the ongoing notification. [Service.startForeground] is only for entering the + * foreground state; updates to the notification it posted go through the notification + * manager under the same id. + */ + private fun postServiceNotification(running: List) { + // Without POST_NOTIFICATIONS (Android 13+) there is nothing in the shade to update — + // the service itself keeps running, so this is a skip, not a failure. + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != + PackageManager.PERMISSION_GRANTED + ) { + return + } + NotificationManagerCompat.from(this) + .notify(SERVICE_NOTIFICATION_ID, buildServiceNotification(running)) } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -120,7 +168,7 @@ class FlowExecutionService : Service() { override fun onBind(intent: Intent?): IBinder? = null - private fun buildServiceNotification(): Notification { + private fun buildServiceNotification(running: List): Notification { val openIntent = PendingIntent.getActivity( this, 0, Intent(this, MainActivity::class.java), @@ -131,18 +179,49 @@ class FlowExecutionService : Service() { Intent(this, FlowExecutionService::class.java).apply { action = ACTION_STOP }, PendingIntent.FLAG_IMMUTABLE, ) - return NotificationCompat.Builder(this, CHANNEL_SERVICE) + val builder = NotificationCompat.Builder(this, CHANNEL_SERVICE) .setSmallIcon(R.drawable.ic_notification) .setContentTitle("NexFlow") - .setContentText(getString(R.string.service_notification_text)) .setContentIntent(openIntent) .setOngoing(true) .setSilent(true) + // Every state change re-posts this same id; without this the shade would re-animate + // the notification on each one even though the channel is silent. + .setOnlyAlertOnce(true) .addAction(R.drawable.ic_notification, getString(R.string.action_stop), stopIntent) - .build() + + when (running.size) { + 0 -> builder.setContentText(getString(R.string.service_notification_text)) + 1 -> builder.setContentText( + getString(R.string.service_notification_running_one, running.first().name), + ) + // More than one at a time: the collapsed line counts them, and expanding lists which + // ones — a single truncated "A, B, C…" would hide exactly the flow being looked for. + else -> { + val summary = resources.getQuantityString( + R.plurals.service_notification_running_many, + running.size, + running.size, + ) + builder.setContentText(summary) + builder.setStyle( + NotificationCompat.InboxStyle().also { style -> + running.take(MAX_NOTIFICATION_LINES).forEach { style.addLine(it.name) } + style.setSummaryText(summary) + }, + ) + } + } + return builder.build() } companion object { + /** How long the running set must hold still before the notification is re-posted. */ + private const val NOTIFICATION_SETTLE_MS = 250L + + /** Cap on the expanded notification's flow lines; the shade truncates beyond this anyway. */ + private const val MAX_NOTIFICATION_LINES = 6 + const val CHANNEL_SERVICE = "nexflow_service" const val SERVICE_NOTIFICATION_ID = 1 const val ACTION_STOP = "com.nexflow.action.STOP_SERVICE" diff --git a/app/src/main/java/com/nexflow/trigger/NfcTagTriggerHandler.kt b/app/src/main/java/com/nexflow/trigger/NfcTagTriggerHandler.kt index 07a198c..aea3d80 100644 --- a/app/src/main/java/com/nexflow/trigger/NfcTagTriggerHandler.kt +++ b/app/src/main/java/com/nexflow/trigger/NfcTagTriggerHandler.kt @@ -29,8 +29,10 @@ import javax.inject.Singleton /** * Fires when an NFC tag is scanned by the user. - * Android only dispatches NFC to the foreground activity — this trigger works when - * the NexFlow app is open. The MainActivity handles NFC intents and feeds NfcEventSource. + * Android only routes NFC to the foreground activity — this trigger works when the NexFlow app + * is open. MainActivity owns reader mode and feeds NfcEventSource; it only claims the NFC + * controller while a flow like this one is enabled, because reader mode blocks every other app + * on the device from seeing a tag at all. * * Reports the scanned UID as `{{trigger.tag_id}}`, so one flow can branch on several tags. */ diff --git a/app/src/main/java/com/nexflow/ui/flows/FlowsScreen.kt b/app/src/main/java/com/nexflow/ui/flows/FlowsScreen.kt index 670f78d..319c3c2 100644 --- a/app/src/main/java/com/nexflow/ui/flows/FlowsScreen.kt +++ b/app/src/main/java/com/nexflow/ui/flows/FlowsScreen.kt @@ -25,12 +25,16 @@ import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.animation.scaleIn +import androidx.compose.animation.scaleOut import androidx.compose.animation.shrinkVertically import androidx.compose.animation.togetherWith import androidx.compose.foundation.background +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -40,6 +44,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.sizeIn import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize @@ -60,6 +65,7 @@ import androidx.compose.material.icons.outlined.FileOpen import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButtonMenu @@ -67,6 +73,7 @@ import androidx.compose.material3.FloatingActionButtonMenuItem import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.LargeTopAppBar +import androidx.compose.material3.LocalContentColor import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold @@ -92,8 +99,12 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.key +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -101,10 +112,12 @@ import androidx.compose.ui.draw.rotate import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.semantics.contentDescription @@ -114,7 +127,15 @@ import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.LineHeightStyle import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupPositionProvider +import androidx.compose.ui.window.PopupProperties import androidx.hilt.navigation.compose.hiltViewModel import com.nexflow.R import com.nexflow.core.automation.model.Flow @@ -126,6 +147,7 @@ import com.nexflow.ui.common.PermissionSetupDialogs import com.nexflow.ui.common.geminiGradientTint import com.nexflow.ui.flows.detail.config.info import com.nexflow.service.FlowExecutionService +import com.nexflow.service.RunningFlow import com.nexflow.ui.flowimport.ImportReviewDialog import com.nexflow.ui.flowimport.ImportViewModel import kotlinx.coroutines.delay @@ -142,6 +164,12 @@ fun FlowsScreen( ) { val flows by vm.flows.collectAsState() val flowsMissingPermissions by vm.flowsMissingPermissions.collectAsState() + val runningFlows by vm.runningFlows.collectAsState() + // What the indicators actually show: the live set, with each flow held on screen long + // enough to be read. Everything below reads this rather than `runningFlows` directly, so + // the card badge and the status popup never disagree. + val heldRunning = rememberHeldRunning(runningFlows) + val heldRunningIds = remember(heldRunning) { heldRunning.mapTo(mutableSetOf()) { it.id } } val importResult by importVm.result.collectAsState() var showCreateDialog by rememberSaveable { mutableStateOf(false) } var permissionReminder by remember { mutableStateOf(null) } @@ -270,6 +298,7 @@ fun FlowsScreen( ServiceCapsule( running = serviceRunning, notification = serviceNotification, + runningFlows = heldRunning, onClick = { // The capsule is the persistent master switch: remember the choice // so reopening the app / rebooting doesn't override it. @@ -407,6 +436,7 @@ fun FlowsScreen( FlowCard( flow = flow, permissionWarning = flow.id in flowsMissingPermissions, + running = flow.id in heldRunningIds, onClick = { onFlowClick(flow.id, null) }, onToggle = { vm.toggleEnabled(flow.id, it) }, onRun = { vm.runFlow(flow.id) }, @@ -513,10 +543,17 @@ fun FlowsScreen( } } +/** + * The master switch, and — on a long press — the app's answer to "what is running right now?". + * + * @param runningFlows what the popup lists; the capsule itself also shows the count as a badge + * so the answer is visible without the long press. + */ @Composable private fun ServiceCapsule( running: Boolean, notification: Boolean?, + runningFlows: List, onClick: () -> Unit, modifier: Modifier = Modifier, ) { @@ -529,44 +566,281 @@ private fun ServiceCapsule( else MaterialTheme.colorScheme.onSurfaceVariant + var showRunning by remember { mutableStateOf(false) } + val longPressLabel = stringResource(R.string.flows_running_status) + + // The popup anchors to this Box, not to the Surface: the Surface's own size animates as the + // service-state label appears, and an anchor that moves would drag the popup with it. + Box(modifier = modifier.padding(end = 8.dp)) { + Surface( + shape = CircleShape, + color = containerColor, + contentColor = contentColor, + modifier = Modifier + // Clip before the click so the ripple stays inside the pill. + .clip(CircleShape) + .combinedClickable( + onClick = onClick, + // combinedClickable performs the long-press haptic itself. + onLongClick = { showRunning = true }, + onLongClickLabel = longPressLabel, + ) + // Size change = spatial motion; the theme's expressive token keeps the bounce + // consistent with built-in component motion. + .animateContentSize(animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec()), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + ) { + Icon( + imageVector = if (running) Icons.Filled.Bolt else Icons.Outlined.Bolt, + contentDescription = if (running) stringResource(R.string.flows_stop_service) else stringResource(R.string.flows_start_service), + modifier = Modifier.size(20.dp), + ) + if (notification != null) { + Spacer(Modifier.width(6.dp)) + Text( + text = if (notification) stringResource(R.string.flows_service_started) else stringResource(R.string.flows_service_stopped), + // includeFontPadding's default top/bottom padding is asymmetric, so the + // glyphs sit visibly low within the line box even though the Row already + // centers the Text's own bounds against the Icon. + style = MaterialTheme.typography.labelMedium.copy( + lineHeightStyle = LineHeightStyle( + alignment = LineHeightStyle.Alignment.Center, + trim = LineHeightStyle.Trim.Both, + ), + platformStyle = PlatformTextStyle(includeFontPadding = false), + ), + ) + } else if (runningFlows.isNotEmpty()) { + // No service-state label competing for the room: show how many flows are + // going, so a background run is visible without opening anything. + Spacer(Modifier.width(6.dp)) + RunningCountBadge(count = runningFlows.size) + } + } + } + + RunningFlowsIsland( + running = runningFlows, + expanded = showRunning, + onDismiss = { showRunning = false }, + ) + } +} + +/** The live count riding on the master-switch capsule. */ +@Composable +private fun RunningCountBadge(count: Int, modifier: Modifier = Modifier) { Surface( - onClick = onClick, shape = CircleShape, - color = containerColor, - contentColor = contentColor, - modifier = modifier - .padding(end = 8.dp) - // Size change = spatial motion; the theme's expressive token keeps the bounce - // consistent with built-in component motion. + color = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + modifier = modifier, + ) { + // AnimatedContent, not a plain Text: the number changing under the user's eyes is the + // whole point, and a hard swap reads as a redraw rather than as something happening. + AnimatedContent( + targetState = count, + transitionSpec = { fadeIn() togetherWith fadeOut() }, + label = "running_count", + ) { value -> + Text( + text = value.toString(), + style = MaterialTheme.typography.labelSmall, + modifier = Modifier.padding(horizontal = 6.dp, vertical = 1.dp), + ) + } + } +} + +/** + * The running-flow list that drops out of the capsule on a long press — a status readout, not a + * menu, so it is a plain [Popup] rather than a dropdown: nothing in it is tappable and it never + * takes over the screen. + */ +@Composable +private fun RunningFlowsIsland( + running: List, + expanded: Boolean, + onDismiss: () -> Unit, +) { + // Driving AnimatedVisibility from a MutableTransitionState (rather than composing the popup + // on `expanded` alone) is what lets the exit animation play: the popup window has to stay + // composed until the transition reports it is idle again. + val transitionState = remember { MutableTransitionState(false) } + LaunchedEffect(expanded) { transitionState.targetState = expanded } + if (!transitionState.currentState && !transitionState.targetState && transitionState.isIdle) return + + val density = LocalDensity.current + val positionProvider = remember(density) { + with(density) { IslandPositionProvider(gapPx = 8.dp.roundToPx(), marginPx = 12.dp.roundToPx()) } + } + val spatial = MaterialTheme.motionScheme.defaultSpatialSpec() + val effects = MaterialTheme.motionScheme.defaultEffectsSpec() + + Popup( + popupPositionProvider = positionProvider, + onDismissRequest = onDismiss, + // focusable so the back gesture dismisses the popup instead of the screen behind it. + properties = PopupProperties(focusable = true), + ) { + AnimatedVisibility( + visibleState = transitionState, + // Grow out of the capsule's trailing edge, which is where the press happened. + enter = fadeIn(effects) + scaleIn(spatial, initialScale = 0.8f, transformOrigin = IslandOrigin), + exit = fadeOut(effects) + scaleOut(spatial, targetScale = 0.8f, transformOrigin = IslandOrigin), + label = "running_island", + ) { + RunningFlowsIslandContent(running) + } + } +} + +/** Top-trailing corner: the popup hangs from the capsule, so that is what it scales out of. */ +private val IslandOrigin = TransformOrigin(pivotFractionX = 1f, pivotFractionY = 0f) + +@Composable +private fun RunningFlowsIslandContent(running: List) { + Surface( + shape = MaterialTheme.shapes.extraLarge, + color = MaterialTheme.colorScheme.surfaceContainerHigh, + contentColor = MaterialTheme.colorScheme.onSurface, + shadowElevation = 6.dp, + // The list grows and shrinks as flows come and go while the popup is open; resize it + // rather than letting the window jump between sizes. + modifier = Modifier + .sizeIn(minWidth = 200.dp, maxWidth = 300.dp) .animateContentSize(animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec()), ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), + Column( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), ) { - Icon( - imageVector = if (running) Icons.Filled.Bolt else Icons.Outlined.Bolt, - contentDescription = if (running) stringResource(R.string.flows_stop_service) else stringResource(R.string.flows_start_service), - modifier = Modifier.size(20.dp), - ) - if (notification != null) { - Spacer(Modifier.width(6.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Icon( + Icons.Filled.Bolt, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(18.dp), + ) Text( - text = if (notification) stringResource(R.string.flows_service_started) else stringResource(R.string.flows_service_stopped), - // includeFontPadding's default top/bottom padding is asymmetric, so the - // glyphs sit visibly low within the line box even though the Row already - // centers the Text's own bounds against the Icon. - style = MaterialTheme.typography.labelMedium.copy( - lineHeightStyle = LineHeightStyle( - alignment = LineHeightStyle.Alignment.Center, - trim = LineHeightStyle.Trim.Both, - ), - platformStyle = PlatformTextStyle(includeFontPadding = false), - ), + stringResource(R.string.flows_running_title), + style = MaterialTheme.typography.titleSmall, + ) + } + if (running.isEmpty()) { + Text( + stringResource(R.string.flows_running_none), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant, ) + } else { + running.forEach { flow -> + key(flow.id) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp), + ) { + CircularProgressIndicator( + color = MaterialTheme.colorScheme.primary, + trackColor = Color.Transparent, + strokeWidth = 2.dp, + modifier = Modifier.size(14.dp), + ) + Text( + text = flow.name, + style = MaterialTheme.typography.bodyMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } + } + } + } + } +} + +/** + * Hangs the popup under the capsule and flush with its trailing edge, kept [marginPx] clear of + * the window edges so a long flow name can never push it off screen. + */ +private class IslandPositionProvider( + private val gapPx: Int, + private val marginPx: Int, +) : PopupPositionProvider { + override fun calculatePosition( + anchorBounds: IntRect, + windowSize: IntSize, + layoutDirection: LayoutDirection, + popupContentSize: IntSize, + ): IntOffset { + val preferredX = if (layoutDirection == LayoutDirection.Ltr) { + anchorBounds.right - popupContentSize.width + } else { + anchorBounds.left + } + val maxX = (windowSize.width - popupContentSize.width - marginPx).coerceAtLeast(marginPx) + return IntOffset( + x = preferredX.coerceIn(marginPx, maxX), + y = anchorBounds.bottom + gapPx, + ) + } +} + +/** + * [running] with each flow kept in the returned list for at least [minVisibleMs] after its run + * ends. A flow whose actions take 30ms is a real run the user asked for, but without this its + * indicator would appear and vanish inside a single frame — indistinguishable from nothing + * having happened, which is the complaint this whole indicator exists to answer. + */ +@Composable +private fun rememberHeldRunning( + running: List, + minVisibleMs: Long = 900L, +): List { + // id -> when its indicator first appeared. A snapshot map so reads recompose the callers. + val shownAt = remember { mutableStateMapOf() } + val shown = remember { mutableStateMapOf() } + // Ids whose run has already ended and that are only still listed to serve out the minimum. + val expiring = remember { mutableSetOf() } + val latest by rememberUpdatedState(running) + + // One long-lived collector rather than an effect keyed on `running`: the pending hold timers + // must survive *other* flows starting and stopping, and a keyed effect would cancel them. + LaunchedEffect(Unit) { + snapshotFlow { latest }.collect { flows -> + val now = System.currentTimeMillis() + flows.forEach { flow -> + // A flow that starts again while it is expiring restarts its minimum. + if (flow.id !in shownAt || expiring.remove(flow.id)) shownAt[flow.id] = now + shown[flow.id] = flow } + val liveIds = flows.mapTo(mutableSetOf()) { it.id } + shownAt.keys.toList() + .filterNot { it in liveIds || it in expiring } + .forEach { id -> + expiring += id + launch { + val elapsed = now - (shownAt[id] ?: now) + if (elapsed < minVisibleMs) delay(minVisibleMs - elapsed) + // Still expiring means it never restarted while we were holding it. + if (expiring.remove(id)) { + shownAt.remove(id) + shown.remove(id) + } + } + } } } + + // Oldest first, matching the engine's own ordering. + return shown.values.sortedBy { it.startedAt } } /** Warning banner shown while the automation service (master switch) is stopped. */ @@ -655,16 +929,15 @@ internal fun FlowCard( onRun: () -> Unit, onWarningClick: () -> Unit, modifier: Modifier = Modifier, + /** + * Whether this flow is executing right now — from the engine, so a run started by a + * trigger, a swipe or the widget lights the badge exactly like one started by the Run + * button. It used to be a three-second timer armed by that button alone, which meant the + * badge said "started" for runs that never began and stayed dark for every run the user + * had not tapped for. + */ + running: Boolean = false, ) { - var runActivated by remember { mutableStateOf(false) } - - LaunchedEffect(runActivated) { - if (runActivated) { - delay(3000L) - runActivated = false - } - } - Card( colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainerLowest), modifier = modifier.fillMaxWidth(), @@ -776,13 +1049,8 @@ internal fun FlowCard( } Spacer(Modifier.weight(1f)) RunCapsule( - activated = runActivated, - onClick = { - if (!runActivated) { - runActivated = true - onRun() - } - }, + running = running, + onClick = { if (!running) onRun() }, modifier = Modifier.padding(end = 8.dp), ) } @@ -790,26 +1058,30 @@ internal fun FlowCard( } } +/** The card's Run button, which doubles as its "this flow is executing" indicator. */ @Composable private fun RunCapsule( - activated: Boolean, + running: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier, ) { - val containerColor = if (activated) + val containerColor = if (running) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondaryContainer - val contentColor = if (activated) + val contentColor = if (running) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSecondaryContainer + val runningDesc = stringResource(R.string.flows_flow_running) Surface( onClick = onClick, shape = CircleShape, color = containerColor, contentColor = contentColor, + // Tapping a flow that is already running is a no-op, so stop offering it as a button. + enabled = !running, modifier = modifier.animateContentSize( animationSpec = MaterialTheme.motionScheme.defaultSpatialSpec(), ), @@ -818,14 +1090,25 @@ private fun RunCapsule( verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(horizontal = 10.dp, vertical = 6.dp), ) { - Icon( - imageVector = if (activated) Icons.Filled.Bolt else Icons.Filled.PlayArrow, - contentDescription = if (activated) stringResource(R.string.flows_flow_activated) else stringResource(R.string.fd_run_flow), - modifier = Modifier.size(16.dp), - ) - if (activated) { + if (running) { + // A spinner rather than a static "started" icon: the point is that the run is + // still going, and a frozen glyph cannot say that. + CircularProgressIndicator( + color = LocalContentColor.current, + trackColor = Color.Transparent, + strokeWidth = 2.dp, + modifier = Modifier + .size(16.dp) + .semantics { contentDescription = runningDesc }, + ) Spacer(Modifier.width(6.dp)) - Text(stringResource(R.string.flows_flow_started), style = MaterialTheme.typography.labelMedium) + Text(runningDesc, style = MaterialTheme.typography.labelMedium) + } else { + Icon( + imageVector = Icons.Filled.PlayArrow, + contentDescription = stringResource(R.string.fd_run_flow), + modifier = Modifier.size(16.dp), + ) } } } diff --git a/app/src/main/java/com/nexflow/ui/flows/FlowsViewModel.kt b/app/src/main/java/com/nexflow/ui/flows/FlowsViewModel.kt index 5ac2976..05be739 100644 --- a/app/src/main/java/com/nexflow/ui/flows/FlowsViewModel.kt +++ b/app/src/main/java/com/nexflow/ui/flows/FlowsViewModel.kt @@ -29,6 +29,7 @@ import com.nexflow.permissions.PermissionSetup import com.nexflow.permissions.PermissionSetupManager import com.nexflow.permissions.PermissionSetupResult import com.nexflow.service.FlowEngine +import com.nexflow.service.RunningFlow import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -53,6 +54,13 @@ class FlowsViewModel @Inject constructor( val flows: StateFlow> = repository.observeAll() .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), emptyList()) + /** + * The flows executing right now, straight from the engine — so a run started by a trigger, + * a swipe, the widget or another process lights the same indicator as one started by + * tapping Run. Oldest first, which is the order the status popup lists them in. + */ + val runningFlows: StateFlow> = flowEngine.runningFlows + private val _navigateToFlow = MutableSharedFlow(extraBufferCapacity = 1) val navigateToFlow: SharedFlow = _navigateToFlow.asSharedFlow() diff --git a/app/src/main/java/com/nexflow/ui/flows/detail/FlowDetailScreen.kt b/app/src/main/java/com/nexflow/ui/flows/detail/FlowDetailScreen.kt index 7776404..c14f5ea 100644 --- a/app/src/main/java/com/nexflow/ui/flows/detail/FlowDetailScreen.kt +++ b/app/src/main/java/com/nexflow/ui/flows/detail/FlowDetailScreen.kt @@ -17,7 +17,6 @@ package com.nexflow.ui.flows.detail import android.Manifest import android.annotation.SuppressLint -import android.app.Activity import android.content.Context import android.content.Intent import android.content.pm.PackageManager @@ -25,12 +24,12 @@ import androidx.core.content.FileProvider import java.io.File import android.location.LocationManager import android.net.wifi.WifiManager -import android.nfc.NfcAdapter import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import android.graphics.Bitmap import android.net.Uri +import android.nfc.NfcAdapter import android.view.WindowManager import com.canhub.cropper.CropImageContract import com.canhub.cropper.CropImageContractOptions @@ -211,6 +210,7 @@ import com.nexflow.ui.common.PermissionSetupDialogs import com.nexflow.ui.common.ShortcutPickerDialog import com.nexflow.core.automation.model.Variable import com.nexflow.core.automation.model.VariableType +import com.nexflow.event.NfcReaderMode import androidx.compose.ui.graphics.Color import com.nexflow.ui.flows.detail.config.ActionInfo import com.nexflow.ui.flows.detail.config.ConfigField @@ -2045,35 +2045,24 @@ internal fun ConfigDialog( } is ConfigField.NfcTagScan -> { + // Read-only: whether this device has NFC and whether it is on. + // Reader mode itself is owned by MainActivity, see below. val nfcAdapter = remember { NfcAdapter.getDefaultAdapter(context) } var scanning by remember { mutableStateOf(false) } - val activity = context as? Activity + // Ask MainActivity for reader mode rather than enabling it here: + // reader mode is device-wide and exclusive, so two owners meant + // this screen's disable also switched off the one the activity + // holds for live NFC triggers. DisposableEffect(scanning) { - var readerModeEnabled = false - if (scanning && nfcAdapter != null && activity != null) { - nfcAdapter.enableReaderMode( - activity, - { tag -> - val id = tag.id.joinToString("") { "%02X".format(it) } - values[field.key] = id - scanning = false - }, - NfcAdapter.FLAG_READER_NFC_A or NfcAdapter.FLAG_READER_NFC_B or - NfcAdapter.FLAG_READER_NFC_F or NfcAdapter.FLAG_READER_NFC_V or - NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, - null, - ) - readerModeEnabled = true - } - onDispose { - // Only disable reader mode if this effect actually enabled it. - // Unconditional disable would kill MainActivity's onResume reader mode. - if (readerModeEnabled) { - runCatching { - if (activity != null) nfcAdapter?.disableReaderMode(activity) - } - } + if (scanning) NfcReaderMode.beginScan() + onDispose { if (scanning) NfcReaderMode.endScan() } + } + LaunchedEffect(scanning) { + if (!scanning) return@LaunchedEffect + NfcReaderMode.scannedTags.collect { tagId -> + values[field.key] = tagId + scanning = false } } diff --git a/app/src/main/java/com/nexflow/ui/flows/detail/config/ActionConfig.kt b/app/src/main/java/com/nexflow/ui/flows/detail/config/ActionConfig.kt index 080fc02..e7aee56 100644 --- a/app/src/main/java/com/nexflow/ui/flows/detail/config/ActionConfig.kt +++ b/app/src/main/java/com/nexflow/ui/flows/detail/config/ActionConfig.kt @@ -525,7 +525,19 @@ fun ActionType.configSummary(context: Context, config: Map): Str else -> R.string.opt_media }, ) - context.getString(R.string.sum_stream_level, s, config["level"] ?: "?") + // Read the same normalized view the editor shows. The volume value moved from an + // absolute step under `level` to a percentage under `volume_percent`; this line still + // asked for `level`, so every volume action — new ones included — summarised as "?". + // Going through normalizeConfigForEditing also means a flow written before the change + // reads as the percentage it will actually run at, without having to be re-saved first. + val percent = normalizeConfigForEditing(ActionType.VOLUME_ADJUST, config)[ + VolumeActionExecutor.PERCENT_KEY, + ] + context.getString( + R.string.sum_stream_level, + s, + percent?.let { "$it%" } ?: context.getString(R.string.sum_not_set), + ) } ActionType.OPEN_APP -> config["package_name"]?.takeIf { it.isNotBlank() } ?: context.getString(R.string.sum_not_set) ActionType.LAUNCH_SHORTCUT -> config["label"]?.takeIf { it.isNotBlank() } ?: context.getString(R.string.sum_not_set) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index eda3b0b..9fef5d4 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -12,6 +12,10 @@ 自動化を実行中 + 実行中:%1$s + + %1$d 件のフローを実行中 + 停止 %1$s を実行 @@ -215,6 +219,7 @@ サイレント モードへのアクセス システム設定の変更 機内モード(ADB) + アラームとリマインダー バックグラウンドの位置情報を許可 @@ -339,8 +344,10 @@ 停止しました フローがありません + をタップして最初の自動化を作成 - フローを実行しました - フローを開始しました + 実行中 + 実行中のフローを表示 + 実行中 + 実行中のフローはありません 自動化サービスは停止中です — トリガーは実行されません 開始 diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index ddef1f9..5e51368 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -12,6 +12,10 @@ 自动化运行中 + 正在运行:%1$s + + 正在运行 %1$d 个流程 + 停止 运行 %1$s @@ -215,6 +219,7 @@ 勿扰模式访问权限 修改系统设置 飞行模式(ADB) + 闹钟和提醒 允许后台定位 @@ -339,8 +344,10 @@ 已关闭 尚无流程 点按 + 创建你的第一个自动化 - 流程已触发 - 流程已启动 + 运行中 + 显示运行中的流程 + 运行中 + 当前没有流程在运行 自动化服务已停止——触发器不会执行 启动 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 2977394..3aa9ef2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -12,6 +12,10 @@ 自動化執行中 + 正在執行:%1$s + + 正在執行 %1$d 個流程 + 停止 執行 %1$s @@ -215,6 +219,7 @@ 勿擾模式存取權 修改系統設定 飛航模式(ADB) + 鬧鐘和提醒 允許背景定位 @@ -339,8 +344,10 @@ 已關閉 尚無流程 點按 + 建立您的第一個自動化 - 流程已觸發 - 流程已啟動 + 執行中 + 顯示執行中的流程 + 執行中 + 目前沒有流程在執行 自動化服務已停止——觸發器不會執行 啟動 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fac67ec..7203942 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,11 @@ Automation is active + Running: %1$s + + Running %1$d flow + Running %1$d flows + Stop Run %1$s @@ -219,6 +224,7 @@ Do Not Disturb access Modify system settings Airplane mode (ADB) + Alarms & reminders Allow background location @@ -343,8 +349,10 @@ Stopped No flows yet Tap + to create your first automation - Flow activated - Flow started + Running + Show running flows + Running now + No flow is running Automation service is stopped — triggers won\'t run Start diff --git a/app/src/screenshotTest/kotlin/com/nexflow/ui/flows/FlowCardScreenshotTest.kt b/app/src/screenshotTest/kotlin/com/nexflow/ui/flows/FlowCardScreenshotTest.kt index 98564e5..1f3cedd 100644 --- a/app/src/screenshotTest/kotlin/com/nexflow/ui/flows/FlowCardScreenshotTest.kt +++ b/app/src/screenshotTest/kotlin/com/nexflow/ui/flows/FlowCardScreenshotTest.kt @@ -58,7 +58,11 @@ private fun sampleFlow( ) @Composable -private fun FlowCardPreview(flow: Flow, permissionWarning: Boolean = false) { +private fun FlowCardPreview( + flow: Flow, + permissionWarning: Boolean = false, + running: Boolean = false, +) { PreviewSurface { FlowCard( flow = flow, @@ -67,6 +71,7 @@ private fun FlowCardPreview(flow: Flow, permissionWarning: Boolean = false) { onToggle = {}, onRun = {}, onWarningClick = {}, + running = running, ) } } @@ -103,3 +108,24 @@ fun FlowCardDisabledWithWarning() { permissionWarning = true, ) } + +/** + * The running state: the Run button becomes a spinner plus a label, which is the row's widest + * badge and the one place a long translation of "Running" could collide with the trigger chips. + * + * layoutlib renders the indeterminate spinner at animation frame 0, so in the reference image it + * is a bare sliver rather than an arc. That is stable across runs (the images are byte-identical + * on a re-render) — it is the still frame of a real animation, not a broken indicator. + */ +@PreviewTest +@LocaleThemePreviews +@Composable +fun FlowCardRunning() { + FlowCardPreview( + flow = sampleFlow( + name = "Morning routine", + description = "Turn on Wi-Fi and read out today's weather", + ), + running = true, + ) +} diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 dark_e6b9ad11_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 dark_e6b9ad11_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..88d8e09caefded68acd23f154fa0de5d74162ee1 GIT binary patch literal 36694 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 literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 light_448008dd_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_en \302\267 light_448008dd_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..8c0d9baf3032f7b2845eab961e1897fb2f14694c GIT binary patch literal 36803 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 literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 dark_8f36ad31_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 dark_8f36ad31_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..bd944df1ffe9d272bf85380126c49bf0bc69a00f GIT binary patch literal 36704 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 Hf9rn$w1>XF literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 light_c92a17c0_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_ja \302\267 light_c92a17c0_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..a1d050075e4b1b6d0eac0fc457c71fea9820f43f GIT binary patch literal 36777 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 literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-CN \302\267 dark_a43c20f1_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-CN \302\267 dark_a43c20f1_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..a1d06b3982012a9425e45c15d3c2dfadec7bd537 GIT binary patch literal 36758 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 literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 dark_46e4ec12_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 dark_46e4ec12_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..9e0354c2c10c6eab39c1bbdf0b8b3486899bfff0 GIT binary patch literal 36943 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 TuO1520>(d|{wZ7k(w+YWH1+NP literal 0 HcmV?d00001 diff --git "a/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 light_c317a2a3_0.png" "b/app/src/screenshotTestGithubDebug/reference/com/nexflow/ui/flows/FlowCardScreenshotTestKt/FlowCardRunning_zh-TW \302\267 light_c317a2a3_0.png" new file mode 100644 index 0000000000000000000000000000000000000000..cac56c64eb6eb57a0a9f7532f0c51658c9476006 GIT binary patch literal 37080 zcmeFZXHZjZ+bD`%QN#lBNR=W;mm29xkq!a^(v>P*5{h&iA|SmJiUvlmL+u0)(_aRrR{q88!r_H18IZX_b#YjxTt#k$cZBppm??;M<(nOgVi^e zKS9oCt_L=C6;3YVO`Grg8T%NM=Jo=DZMqh0#)`|!SBAz$j9Yd*KkO%QzPg}%n)*-E zbsxHa%pfXC3FOd|64*;WNPMgvEZ;wZDOAd{p_LhbSccKS2l{ zI-fR68IqaEUl8JZvFKDK?U!P@raevvc7P<&&=h61_2G?*jS8%j8;loCi|q=sN2EOH zKKMde=$sUhoFc)sFZ-LQOY_r)YYZ`3StYI*W=(e~5OZ(H<|`X%*61TtKzf7o^}GIi zC9b~&^ynl(dZFmA;<`ImPf>2ZiUgIc+&T0uZe9-gySO^<

~}- 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 literal 0 HcmV?d00001 diff --git a/app/src/test/java/com/nexflow/event/NfcReaderModeTest.kt b/app/src/test/java/com/nexflow/event/NfcReaderModeTest.kt new file mode 100644 index 0000000..a848837 --- /dev/null +++ b/app/src/test/java/com/nexflow/event/NfcReaderModeTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.event + +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +/** + * Reader mode is exclusive and device-wide — while it is on, no other app sees a tag at all. + * So the count that decides whether it stays on has to be exact in both directions: leaking a + * request keeps every NFC tap on the phone hostage, and dropping one below zero would let a + * finished scan switch off reader mode that a live NFC trigger still needs. + */ +class NfcReaderModeTest { + + @AfterEach + fun drain() { + repeat(8) { NfcReaderMode.endScan() } + } + + @Test + fun `overlapping scans each hold their own request`() { + NfcReaderMode.beginScan() + NfcReaderMode.beginScan() + assertEquals(2, NfcReaderMode.scanRequests.value) + + // One config screen finishing must not release the other's hold. + NfcReaderMode.endScan() + assertEquals(1, NfcReaderMode.scanRequests.value) + + NfcReaderMode.endScan() + assertEquals(0, NfcReaderMode.scanRequests.value) + } + + @Test + fun `an unmatched release cannot drive the count negative`() { + // A composable disposed twice, or disposed after the process reused the singleton, + // would otherwise leave a debt that swallows the next real scan request. + NfcReaderMode.endScan() + assertEquals(0, NfcReaderMode.scanRequests.value) + + NfcReaderMode.beginScan() + assertEquals(1, NfcReaderMode.scanRequests.value) + } +} diff --git a/app/src/test/java/com/nexflow/permissions/ExactAlarmPermissionTest.kt b/app/src/test/java/com/nexflow/permissions/ExactAlarmPermissionTest.kt new file mode 100644 index 0000000..28fdf88 --- /dev/null +++ b/app/src/test/java/com/nexflow/permissions/ExactAlarmPermissionTest.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.permissions + +import android.content.Context +import android.provider.Settings +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.nexflow.core.automation.model.Flow +import com.nexflow.core.automation.model.Trigger +import com.nexflow.core.automation.model.TriggerLogic +import com.nexflow.core.automation.model.TriggerType +import com.nexflow.trigger.TimeTriggerScheduler +import io.mockk.every +import io.mockk.mockk +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +/** + * A TIME flow that cannot schedule exact alarms still runs — just late, because the scheduler + * falls back to an inexact alarm the system batches into a Doze maintenance window. That made it + * the one failure the user could not see: enabled flow, successful log, wrong time. These tests + * pin the reporting path that surfaces it, from the checker through to the Settings intent the + * wizard sends the user to. + * + * Robolectric because the permission label comes from resources. + */ +@RunWith(AndroidJUnit4::class) +class ExactAlarmPermissionTest { + + private val context = ApplicationProvider.getApplicationContext() + + private fun checker(canScheduleExact: Boolean) = FlowPermissionChecker( + context = context, + timeTriggerScheduler = mockk { + every { canScheduleExact() } returns canScheduleExact + }, + ) + + private fun timeFlow() = flowWith( + Trigger(id = "t1", type = TriggerType.TIME, config = mapOf("time" to "09:00")), + ) + + private fun flowWith(vararg triggers: Trigger) = Flow( + id = "f1", + schemaVersion = 1, + name = "morning", + description = "", + author = null, + tags = emptyList(), + enabled = true, + createdAt = 0L, + updatedAt = 0L, + triggers = triggers.toList(), + triggerLogic = TriggerLogic.ANY, + conditions = emptyList(), + actions = emptyList(), + variables = emptyList(), + ) + + @Test + fun `a TIME flow without exact-alarm permission is reported as missing it`() { + val missing = checker(canScheduleExact = false).missingPermissions(timeFlow()) + + val entry = missing.singleOrNull() + assertNotNull("a TIME trigger with no exact-alarm right must be reported", entry) + // Special access, not a runtime permission: there is no dialog for this one, the user + // has to be walked to the "Alarms & reminders" Settings page. + assertEquals(SpecialAccess.EXACT_ALARM, entry!!.special) + assertTrue(entry.runtimePermissions.isEmpty()) + } + + @Test + fun `a TIME flow with exact-alarm permission reports nothing`() { + assertTrue(checker(canScheduleExact = true).missingPermissions(timeFlow()).isEmpty()) + } + + @Test + fun `only TIME triggers ask for exact alarms`() { + // MANUAL is the default trigger on every newly created flow — if it picked this up, + // every flow in the list would show the warning badge. + val manual = flowWith(Trigger(id = "t1", type = TriggerType.MANUAL, config = emptyMap())) + assertTrue(checker(canScheduleExact = false).missingPermissions(manual).isEmpty()) + } + + @Test + fun `the wizard sends the user to the Alarms and reminders page for this app`() { + val intent = PermissionIntents.forSpecial(context, SpecialAccess.EXACT_ALARM) + + assertNotNull("EXACT_ALARM must have somewhere to send the user", intent) + assertEquals(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM, intent!!.action) + // Without the package uri the intent opens the all-apps list rather than this app's toggle. + assertEquals(context.packageName, intent.data?.schemeSpecificPart) + } +} diff --git a/app/src/test/java/com/nexflow/service/FlowEngineRunningStateTest.kt b/app/src/test/java/com/nexflow/service/FlowEngineRunningStateTest.kt new file mode 100644 index 0000000..33ec635 --- /dev/null +++ b/app/src/test/java/com/nexflow/service/FlowEngineRunningStateTest.kt @@ -0,0 +1,176 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.service + +import android.util.Log +import com.nexflow.core.automation.executor.ActionExecutor +import com.nexflow.core.automation.executor.ActionResult +import com.nexflow.core.automation.model.Action +import com.nexflow.core.automation.model.ActionType +import com.nexflow.core.automation.model.Flow +import com.nexflow.core.automation.model.TriggerLogic +import com.nexflow.core.automation.repository.FlowRepository +import com.nexflow.core.automation.repository.GlobalVariableRepository +import com.nexflow.trigger.TimeTriggerScheduler +import io.mockk.coEvery +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.unmockkStatic +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNull +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +/** + * [FlowEngine.runningFlows] is what every "running" indicator in the app reads — the list card's + * badge, the foreground-service notification and the status popup. Its value is only ever right + * if it is the same state the engine uses to drop overlapping runs, so these tests pin both + * halves: the list reflects a run in progress, and claiming a slot is what decides whether a + * second run of the same flow is allowed to start. + */ +@OptIn(ExperimentalCoroutinesApi::class) +class FlowEngineRunningStateTest { + + /** An executor that parks mid-run, so a run can be observed while it is still going. */ + private class BlockingExecutor : ActionExecutor { + override val supportedType = ActionType.TOAST + val started = CompletableDeferred() + val release = CompletableDeferred() + var runCount = 0 + + override suspend fun execute(action: Action, variables: MutableMap): ActionResult { + runCount++ + started.complete(Unit) + release.await() + return ActionResult.Success + } + } + + @BeforeEach + fun mockLog() { + mockkStatic(Log::class) + every { Log.d(any(), any()) } returns 0 + } + + @AfterEach + fun unmockLog() = unmockkStatic(Log::class) + + private fun engineFor(flow: Flow, repository: FlowRepository, executor: ActionExecutor): FlowEngine { + coEvery { repository.getById(flow.id) } returns flow + // Execution toast disabled so a run never touches android.widget.Toast on the JVM. + val prefs = mockk { + every { getBoolean(any(), any()) } returns false + } + val context = mockk { + every { getSharedPreferences(any(), any()) } returns prefs + } + return FlowEngine( + repository = repository, + globalVariableRepository = mockk(relaxed = true), + triggerHandlerSet = emptySet(), + actionExecutorSet = setOf(executor), + conditionEvaluatorSet = emptySet(), + timeTriggerScheduler = mockk(relaxed = true), + context = context, + ) + } + + @Test + fun `a flow is listed as running for as long as its actions are running`() = runTest { + val executor = BlockingExecutor() + val repository = mockk(relaxed = true) + val flow = testFlow() + val engine = engineFor(flow, repository, executor) + + assertTrue(engine.runningFlows.value.isEmpty(), "nothing runs before runNow is called") + + val run = launch { engine.runNow(flow.id) } + executor.started.await() + + val running = engine.runningFlows.value.single() + assertEquals(flow.id, running.id) + // The name travels with the entry: the service notification names the flow without ever + // touching the repository. + assertEquals("test", running.name) + + executor.release.complete(Unit) + run.join() + assertTrue(engine.runningFlows.value.isEmpty(), "the entry must be cleared when the run ends") + } + + @Test + fun `a second run of a flow already running is dropped and does not duplicate the entry`() = runTest { + val executor = BlockingExecutor() + val repository = mockk(relaxed = true) + val flow = testFlow() + val engine = engineFor(flow, repository, executor) + + val first = launch { engine.runNow(flow.id) } + executor.started.await() + + // Same flow again while the first is still going: the engine reports "never started". + assertNull(engine.runNow(flow.id)) + assertEquals(1, engine.runningFlows.value.size, "an overlapping run must not add an entry") + assertEquals(1, executor.runCount, "the dropped run must not have executed any action") + + executor.release.complete(Unit) + first.join() + } + + @Test + fun `a run that fails still clears its running entry`() = runTest { + val throwing = object : ActionExecutor { + override val supportedType = ActionType.TOAST + override suspend fun execute(action: Action, variables: MutableMap): ActionResult = + throw IllegalStateException("boom") + } + val repository = mockk(relaxed = true) + val flow = testFlow() + val engine = engineFor(flow, repository, throwing) + + engine.runNow(flow.id) + + // A stuck entry would leave the card spinning and the notification lying forever, with + // no way back short of restarting the service. + assertTrue(engine.runningFlows.value.isEmpty()) + } + + private fun testFlow() = Flow( + id = "f1", + schemaVersion = 1, + name = "test", + description = "", + author = null, + tags = emptyList(), + enabled = true, + createdAt = 0L, + updatedAt = 0L, + triggers = emptyList(), + triggerLogic = TriggerLogic.ANY, + conditions = emptyList(), + actions = listOf( + Action(id = "a0", type = ActionType.TOAST, config = mapOf("message" to "hi"), order = 0, enabled = true), + ), + variables = emptyList(), + ) +} diff --git a/app/src/test/java/com/nexflow/ui/flows/detail/config/VolumeSummaryTest.kt b/app/src/test/java/com/nexflow/ui/flows/detail/config/VolumeSummaryTest.kt new file mode 100644 index 0000000..25e5b30 --- /dev/null +++ b/app/src/test/java/com/nexflow/ui/flows/detail/config/VolumeSummaryTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2026 NexFlow Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.nexflow.ui.flows.detail.config + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.nexflow.core.automation.model.ActionType +import com.nexflow.executor.VolumeActionExecutor +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +/** + * The line under "Volume" on the flow detail screen. + * + * When the stored value moved from an absolute step (`level`) to a percentage + * (`volume_percent`), this summary kept asking for the old key and every volume action — + * including ones saved by the current editor — rendered as "Media: ?". + * + * Robolectric rather than [ActionConfigTest]'s mocked Context: that one answers every + * getString with a placeholder, so a summary built entirely from the wrong key still looks + * "not blank" to it. Only real resources can tell the value apart from the fallback. + */ +@RunWith(AndroidJUnit4::class) +class VolumeSummaryTest { + + private val context = ApplicationProvider.getApplicationContext() + + private fun summaryOf(config: Map): String = + ActionType.VOLUME_ADJUST.configSummary(context, config) + + private val notSet get() = context.getString(com.nexflow.R.string.sum_not_set) + + @Test + fun `a percentage is shown as a percentage`() { + val summary = summaryOf( + mapOf("stream" to "MEDIA", VolumeActionExecutor.PERCENT_KEY to "100"), + ) + + assertTrue("expected the percentage in \"$summary\"", summary.contains("100%")) + assertTrue("must not fall back to \"not set\": \"$summary\"", !summary.contains(notSet)) + } + + @Test + fun `a flow saved before the percentage change reads as the volume it will run at`() { + // 15 was the old slider's maximum, so a stored 15 meant "all the way up" — the same + // reading the editor uses. Without going through the migration the user would see the + // fallback on a flow that is perfectly valid and has simply not been re-saved. + val summary = summaryOf( + mapOf("stream" to "MEDIA", VolumeActionExecutor.LEGACY_LEVEL_KEY to "15"), + ) + + assertTrue("expected 100% for a legacy full-scale level, got \"$summary\"", summary.contains("100%")) + } + + @Test + fun `the stream is named alongside the level`() { + val ring = summaryOf(mapOf("stream" to "RING", VolumeActionExecutor.PERCENT_KEY to "40")) + + assertTrue(ring.contains(context.getString(com.nexflow.R.string.opt_ringtone))) + assertTrue(ring.contains("40%")) + } + + @Test + fun `a volume action with no level set says so instead of guessing`() { + assertTrue(summaryOf(mapOf("stream" to "MEDIA")).contains(notSet)) + } +}