fix: pull active media session on start, icon centering, tap highlight, media card
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
/* Hearth 桌面样式:侧边栏 + 5 页框架 + 柔光玻璃容器 */
|
||||
/* Hearth launcher styles: sidebar + 5-page frame + soft-glass containers */
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
/* 移除 WebView 默认蓝色点击高亮,改用下方 :active 的 Miuix 风格反馈 */
|
||||
/* Remove the default blue tap highlight; use the Miuix-style :active feedback below */
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
html, body { height: 100%; }
|
||||
|
||||
@@ -72,12 +79,28 @@ body {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.rail-item .ico { width: 24px; height: 24px; }
|
||||
.rail-item .ico {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.rail-item .ico svg { width: 100%; height: 100%; display: block; }
|
||||
.rail-item .lbl { font-size: 11px; }
|
||||
|
||||
.rail-item.active { background: var(--accent); color: #fff; }
|
||||
|
||||
/* Miuix 风格点击反馈:轻按压时整体轻微变淡,替代默认蓝色高亮 */
|
||||
/* Miuix-style press feedback: a subtle fade on press instead of the blue highlight */
|
||||
.rail-item:active,
|
||||
.cell:active,
|
||||
.wcell:active,
|
||||
.st-item:active {
|
||||
opacity: 0.6;
|
||||
transition: opacity .12s ease;
|
||||
}
|
||||
|
||||
.content { flex: 1; overflow: hidden; }
|
||||
|
||||
.page { display: none; height: 100%; }
|
||||
|
||||
@@ -22,36 +22,21 @@ class MediaSessionSource(context: Context) {
|
||||
private var callback: ((MediaInfo?) -> Unit)? = null
|
||||
private var registered = false
|
||||
|
||||
// 具名监听器字段:回调通过 callback 字段转发,便于 start/stop 幂等管理
|
||||
// Named listener field: forwards via callback, enabling idempotent start/stop
|
||||
// 具名监听器字段:会话列表变化时回调
|
||||
// Named listener field: fires when the active-session list changes
|
||||
private val activeSessionsListener =
|
||||
MediaSessionManager.OnActiveSessionsChangedListener { controllers ->
|
||||
val cb = callback ?: return@OnActiveSessionsChangedListener
|
||||
val c = controllers?.firstOrNull()
|
||||
if (c == null) {
|
||||
Log.d(TAG, "no active media session")
|
||||
cb(null)
|
||||
return@OnActiveSessionsChangedListener
|
||||
}
|
||||
val meta = c.metadata
|
||||
val state = c.playbackState
|
||||
cb(
|
||||
MediaInfo(
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_TITLE) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ARTIST) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ALBUM) ?: "",
|
||||
state?.state == PlaybackState.STATE_PLAYING,
|
||||
state?.position ?: 0L,
|
||||
meta?.getLong(MediaMetadata.METADATA_KEY_DURATION) ?: 0L,
|
||||
c.packageName,
|
||||
)
|
||||
)
|
||||
Log.d(TAG, "media: ${c.packageName}")
|
||||
notifyMedia(controllers?.firstOrNull(), cb)
|
||||
}
|
||||
|
||||
// 注册监听:幂等——先移除旧监听再注册,避免重复 start 累积监听器
|
||||
// Register the listener: idempotent — remove the old listener first, avoiding
|
||||
// listener accumulation from repeated start() calls
|
||||
// 注册监听:幂等——先移除旧监听再注册,避免重复 start 累积监听器。
|
||||
// 注册后主动拉取一次当前活跃会话:注册前已开始的播放不会触发变化回调,
|
||||
// 主动拉取保证启动时媒体卡即可显示。
|
||||
// Register the listener: idempotent — remove the old one first to avoid accumulation.
|
||||
// After registering, actively pull the current sessions once: playback that started
|
||||
// before registration never fires the change callback, so the active pull makes the
|
||||
// media card show immediately on startup.
|
||||
fun start(cb: (MediaInfo?) -> Unit) {
|
||||
stop()
|
||||
callback = cb
|
||||
@@ -59,6 +44,8 @@ class MediaSessionSource(context: Context) {
|
||||
msm.addOnActiveSessionsChangedListener(activeSessionsListener, listenerComponent)
|
||||
registered = true
|
||||
Log.d(TAG, "start: media session listener registered")
|
||||
val current = msm.getActiveSessions(listenerComponent).firstOrNull()
|
||||
notifyMedia(current, cb)
|
||||
} catch (e: SecurityException) {
|
||||
// 未授权「通知使用权」时系统抛 SecurityException:媒体监听降级为不可用,不崩溃。
|
||||
// 用户在系统设置开启通知使用权后,重启 Hearth 才会恢复媒体卡。
|
||||
@@ -81,6 +68,30 @@ class MediaSessionSource(context: Context) {
|
||||
callback = null
|
||||
}
|
||||
|
||||
// 从 controller 提取 metadata + playbackState 构造 MediaInfo 并回调
|
||||
// Build MediaInfo from the controller's metadata + playbackState and invoke the callback
|
||||
private fun notifyMedia(controller: MediaController?, cb: (MediaInfo?) -> Unit) {
|
||||
if (controller == null) {
|
||||
Log.d(TAG, "no active media session")
|
||||
cb(null)
|
||||
return
|
||||
}
|
||||
val meta = controller.metadata
|
||||
val state = controller.playbackState
|
||||
cb(
|
||||
MediaInfo(
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_TITLE) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ARTIST) ?: "",
|
||||
meta?.getString(MediaMetadata.METADATA_KEY_ALBUM) ?: "",
|
||||
state?.state == PlaybackState.STATE_PLAYING,
|
||||
state?.position ?: 0L,
|
||||
meta?.getLong(MediaMetadata.METADATA_KEY_DURATION) ?: 0L,
|
||||
controller.packageName,
|
||||
)
|
||||
)
|
||||
Log.d(TAG, "media: ${controller.packageName}")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "HearthMedia"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user