Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ check(resolvedVersionCode > 0) { "ANDROID_VERSION_CODE must be a positive intege
val resolvedVersionName = versionNameInput ?: "1.2.9"

android {
// The modular implementation keeps its existing source namespace to avoid a
// risky package-only rewrite. The public product identity is com.nowen.video.
// Keep the source namespace stable during the UI migration. The installable
// product identity is independent from the upstream Nowen application.
namespace = "com.nowen.video.v2"
compileSdk = 35

defaultConfig {
applicationId = "com.nowen.video"
applicationId = "com.example.nowenplayer"
minSdk = 26
targetSdk = 35
versionCode = resolvedVersionCode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ class AppLaunchSmokeTest {
val composeRule = createAndroidComposeRule<MainActivity>()

@Test
fun freshInstallShowsServerSetupWithoutMigrationNotice() {
fun freshInstallShowsServerHubWithoutMigrationNotice() {
composeRule.waitUntil(timeoutMillis = 20_000) {
composeRule
.onAllNodesWithText("连接你的媒体空间")
.onAllNodesWithText("还没有服务器")
.fetchSemanticsNodes()
.isNotEmpty()
}

composeRule.onNodeWithText("连接你的媒体空间").assertIsDisplayed()
composeRule.onNodeWithText("扫描二维码").assertIsDisplayed()
composeRule.onNodeWithText("手动添加").assertIsDisplayed()
composeRule.onNodeWithText("服务器").assertIsDisplayed()
composeRule.onNodeWithText("还没有服务器").assertIsDisplayed()

check(
composeRule
Expand Down
6 changes: 3 additions & 3 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
android:name=".NowenApplication"
android:allowBackup="false"
android:icon="@drawable/ic_launcher"
android:label="Nowen Video"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Nowen"
android:theme="@style/Theme.MediaPlayer"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:exported="true"
android:supportsPictureInPicture="true"
android:theme="@style/Theme.Nowen">
android:theme="@style/Theme.MediaPlayer">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
90 changes: 88 additions & 2 deletions android/app/src/main/java/com/nowen/video/v2/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package com.nowen.video.v2

import android.app.PictureInPictureParams
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.util.Rational
import android.view.WindowInsets
import android.view.WindowInsetsController
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.core.view.WindowCompat
import com.nowen.video.v2.core.data.HighlightComputeAgent
import com.nowen.video.v2.feature.main.NowenApp
import com.nowen.video.v2.feature.main.PlaybackPictureInPictureHost
Expand All @@ -29,11 +34,17 @@ class MainActivity : ComponentActivity(), PlaybackPictureInPictureHost {
private val _pictureInPictureMode = MutableStateFlow(false)
override val pictureInPictureMode: StateFlow<Boolean> = _pictureInPictureMode
private var playbackPictureInPictureActive = false
private var playbackOriginalBrightness: Float? = null

override val playbackPictureInPictureSupported: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
private var highlightComputeScope: CoroutineScope? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
NowenApp()
}
Expand All @@ -55,16 +66,91 @@ class MainActivity : ComponentActivity(), PlaybackPictureInPictureHost {
}

override fun setPlaybackPictureInPictureActive(active: Boolean) {
playbackPictureInPictureActive = active
playbackPictureInPictureActive = active && playbackPictureInPictureSupported
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
setPictureInPictureParams(buildPictureInPictureParams(active))
setPictureInPictureParams(buildPictureInPictureParams(playbackPictureInPictureActive))
}

override fun enterPlaybackPictureInPicture() {
if (playbackPictureInPictureActive && playbackPictureInPictureSupported && !isInPictureInPictureMode) {
enterPictureInPictureMode(buildPictureInPictureParams(true))
}
}

override fun currentPlaybackScreenBrightness(): Float {
val current = window.attributes.screenBrightness
return if (current in 0f..1f) current else 0.5f
}

override fun setPlaybackScreenBrightness(brightness: Float) {
window.attributes = window.attributes.apply {
screenBrightness = brightness.coerceIn(0f, 1f)
}
}

override fun restorePlaybackScreenBrightness() {
val original = playbackOriginalBrightness ?: return
window.attributes = window.attributes.apply {
screenBrightness = original
}
playbackOriginalBrightness = null
}

override fun setPlaybackLandscape(active: Boolean) {
if (active && playbackOriginalBrightness == null) {
playbackOriginalBrightness = window.attributes.screenBrightness
}
if (!active) restorePlaybackScreenBrightness()
requestedOrientation = if (active) {
android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
} else {
android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
window.attributes = window.attributes.apply {
layoutInDisplayCutoutMode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
} else {
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
}
}
}
if (active) {
window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
WindowCompat.setDecorFitsSystemWindows(window, false)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
WindowCompat.setDecorFitsSystemWindows(window, true)
}
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = if (active) {
android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
android.view.View.SYSTEM_UI_FLAG_FULLSCREEN or
android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
} else {
0
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.let { controller ->
if (active) {
controller.hide(WindowInsets.Type.systemBars())
controller.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} else {
controller.show(WindowInsets.Type.systemBars())
}
}
}
}

override fun onUserLeaveHint() {
super.onUserLeaveHint()
if (
Build.VERSION.SDK_INT in Build.VERSION_CODES.O until Build.VERSION_CODES.S &&
playbackPictureInPictureActive &&
playbackPictureInPictureSupported &&
!isInPictureInPictureMode
) {
enterPictureInPictureMode(buildPictureInPictureParams(true))
Expand Down
12 changes: 6 additions & 6 deletions android/app/src/main/res/drawable/ic_launcher.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#6578FF"
android:pathData="M22,10h64a12,12 0,0 1,12 12v64a12,12 0,0 1,-12 12h-64a12,12 0,0 1,-12 -12v-64a12,12 0,0 1,12 -12z" />
android:fillColor="#5D6F9A"
android:pathData="M20,10h68a10,10 0,0 1,10 10v68a10,10 0,0 1,-10 10h-68a10,10 0,0 1,-10 -10v-68a10,10 0,0 1,10 -10z" />
<path
android:fillColor="#2ED3D0"
android:pathData="M18,28C18,18 26,10 36,10h44L22,92c-7,-4 -12,-11 -12,-20z" />
android:fillColor="#EAF0FF"
android:pathData="M43,33L76,54L43,75z" />
<path
android:fillColor="#FFFFFF"
android:pathData="M58,25L38,56h13l-4,27 23,-36h-14z" />
android:fillColor="#B8C7EA"
android:pathData="M29,33h6v42h-6z" />
</vector>
4 changes: 4 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">媒体播放器</string>
</resources>
2 changes: 1 addition & 1 deletion android/app/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Nowen" parent="android:style/Theme.Material.Light.NoActionBar">
<style name="Theme.MediaPlayer" parent="android:style/Theme.Material.NoActionBar">
<item name="android:fontFamily">sans</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:windowLightStatusBar">false</item>
Expand Down
Loading