Skip to content

Commit c5ff360

Browse files
committed
feat: Optimize NAS login and improve server connection probing
1 parent 6bf6a56 commit c5ff360

File tree

8 files changed

+134
-73
lines changed

8 files changed

+134
-73
lines changed

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/data/store/AccountDataCache.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ object AccountDataCache {
2222

2323
var displayHost: String = ""
2424

25+
var displayPort: Int = 0
26+
2527
var port: Int = 0
2628

2729
var isLoggedIn: Boolean = false

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/manager/LoginStateManager.kt

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -72,40 +72,58 @@ object LoginStateManager {
7272
isHttps: Boolean,
7373
toastManager: ToastManager,
7474
loginViewModel: LoginViewModel,
75-
rememberPassword: Boolean
75+
rememberPassword: Boolean,
76+
onProbeRequired: ((String) -> Unit)? = null,
77+
isProbeFinished: Boolean = false
7678
) {
7779
// val loginState by loginViewModel.uiState.collectAsState()
7880
if (host.isBlank() || username.isBlank() || password.isBlank()) {
7981
toastManager.showToast("请填写完整的登录信息", ToastType.Failed)
8082
return
8183
}
82-
if (isHttps) {
83-
AccountDataCache.isHttps = true
84-
} else {
85-
AccountDataCache.isHttps = false
86-
}
84+
85+
if (!isProbeFinished) {
86+
if (isHttps) {
87+
AccountDataCache.isHttps = true
88+
} else {
89+
AccountDataCache.isHttps = false
90+
}
8791
// val isValidDomainOrIP = DomainIpValidator.isValidDomainOrIP(host)
8892
// if (!isValidDomainOrIP) {
8993
// toastManager.showToast("请填写正确的ip地址或域名", ToastType.Failed)
9094
// return
9195
// }
92-
AccountDataCache.displayHost = host
93-
if (port != 0) {
94-
AccountDataCache.port = port
95-
} else {
96-
AccountDataCache.port = 0
97-
}
96+
AccountDataCache.displayHost = host
97+
AccountDataCache.displayPort = port
98+
if (port != 0) {
99+
AccountDataCache.port = port
100+
} else {
101+
AccountDataCache.port = 0
102+
}
98103

99-
// 如果使用 FN ID 或 FN 域名
100-
val normalizedHost = if (host.contains('.')) host else "$host.5ddd.com"
101-
if (normalizedHost.contains("5ddd.com")) {
102-
AccountDataCache.isHttps = true
103-
AccountDataCache.insertCookie("mode" to "relay")
104-
AccountDataCache.port = 0
104+
// 如果使用 FN ID 或 FN 域名
105+
val normalizedHost = if (host.contains('.')) host else "$host.5ddd.com"
106+
if (normalizedHost.contains("5ddd.com")) {
107+
if (onProbeRequired != null) {
108+
onProbeRequired("https://$normalizedHost")
109+
return
110+
}
111+
AccountDataCache.isHttps = true
112+
AccountDataCache.insertCookie("mode" to "relay")
113+
AccountDataCache.port = 0
114+
} else {
115+
AccountDataCache.removeCookie("mode")
116+
}
117+
AccountDataCache.host = normalizedHost
105118
} else {
106-
AccountDataCache.removeCookie("mode")
119+
if (AccountDataCache.host.contains("ddd.com")) {
120+
AccountDataCache.isHttps = true
121+
AccountDataCache.insertCookie("mode" to "relay")
122+
AccountDataCache.port = 0
123+
} else {
124+
AccountDataCache.removeCookie("mode")
125+
}
107126
}
108-
AccountDataCache.host = normalizedHost
109127

110128

111129
AccountDataCache.userName = username

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/manager/PreferencesManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class PreferencesManager private constructor() {
6565
AccountDataCache.isNasLogin = settings.getBoolean("isNasLogin", false)
6666
AccountDataCache.fnId = settings.getString("fnId", "")
6767
AccountDataCache.displayHost = settings.getString("displayHost", "")
68+
AccountDataCache.displayPort = settings.getInt("displayPort", 0)
6869
}
6970

7071
fun saveAllLoginInfo() {
@@ -81,6 +82,7 @@ class PreferencesManager private constructor() {
8182
settings.putBoolean("isNasLogin", AccountDataCache.isNasLogin)
8283
settings.putString("fnId", AccountDataCache.fnId)
8384
settings.putString("displayHost", AccountDataCache.displayHost)
85+
settings.putInt("displayPort", AccountDataCache.displayPort)
8486
}
8587

8688
fun saveToken(token: String) {

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/ui/component/login/NasLoginComponents.kt

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Row
88
import androidx.compose.foundation.layout.fillMaxSize
99
import androidx.compose.foundation.layout.fillMaxWidth
1010
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.padding
1112
import androidx.compose.foundation.shape.RoundedCornerShape
1213
import androidx.compose.foundation.text.BasicTextField
1314
import androidx.compose.foundation.text.KeyboardOptions
@@ -66,6 +67,7 @@ fun NasLoginAddressBar(
6667
value = addressBarValue,
6768
onValueChange = onAddressBarValueChange,
6869
modifier = Modifier
70+
.padding(end = 12.dp)
6971
.height(30.dp)
7072
.weight(1f),
7173
singleLine = true,
@@ -128,6 +130,14 @@ fun FnConnectWebViewContainer(
128130
.background(Color.White)
129131
) {
130132
when {
133+
webViewInitError != null -> {
134+
Text(
135+
text = "WebView 初始化失败:${webViewInitError.message ?: "未知错误"}",
136+
color = Color.Black,
137+
modifier = Modifier.align(Alignment.Center)
138+
)
139+
}
140+
131141
webViewInitialized -> {
132142
WebView(
133143
state = webViewState,
@@ -145,14 +155,6 @@ fun FnConnectWebViewContainer(
145155
)
146156
}
147157

148-
webViewInitError != null -> {
149-
Text(
150-
text = "WebView 初始化失败:${webViewInitError.message ?: "未知错误"}",
151-
color = Color.Black,
152-
modifier = Modifier.align(Alignment.Center)
153-
)
154-
}
155-
156158
else -> {
157159
Text(
158160
text = "WebView 初始化中,请稍候…",

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/ui/screen/LoginScreen.kt

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ data class FnConnectWindowRequest(
122122
val fnId: String,
123123
val autoLoginUsername: String? = null,
124124
val autoLoginPassword: String? = null,
125-
val allowAutoLogin: Boolean = false
125+
val allowAutoLogin: Boolean = false,
126+
val onBaseUrlDetected: ((String) -> Unit)? = null
126127
)
127128

128129
@OptIn(ExperimentalHazeMaterialsApi::class, ExperimentalComposeUiApi::class)
@@ -152,6 +153,7 @@ fun LoginScreen(
152153
var isAutoLogin by remember { mutableStateOf(false) }
153154
var fnAutoUsername by remember { mutableStateOf("") }
154155
var fnAutoPassword by remember { mutableStateOf("") }
156+
var isProbeMode by remember { mutableStateOf(false) }
155157
// 登录历史记录列表
156158
var loginHistoryList by remember { mutableStateOf<List<LoginHistory>>(emptyList()) }
157159

@@ -160,7 +162,7 @@ fun LoginScreen(
160162
// 初始化时加载保存的账号信息
161163
remember {
162164
host = AccountDataCache.displayHost
163-
port = AccountDataCache.port
165+
port = AccountDataCache.displayPort
164166
username = AccountDataCache.userName
165167
password = AccountDataCache.password
166168
isHttps = AccountDataCache.isHttps
@@ -242,21 +244,26 @@ fun LoginScreen(
242244
}
243245

244246
if (showFnConnectWebView) {
245-
FnConnectWebViewScreen(
247+
NasLoginWebViewScreen(
246248
initialUrl = fnConnectUrl,
247249
fnId = fnId,
248-
onBack = { showFnConnectWebView = false },
250+
onBack = {
251+
showFnConnectWebView = false
252+
isProbeMode = false
253+
},
249254
onLoginSuccess = { history ->
250255
// 更新历史记录列表
251256
loginHistoryList = upsertLoginHistory(loginHistoryList, history)
252257
// 保存到偏好设置
253258
val preferencesManager = PreferencesManager.getInstance()
254259
preferencesManager.saveLoginHistory(loginHistoryList)
255260
showFnConnectWebView = false
261+
isProbeMode = false
256262
},
257263
autoLoginUsername = fnAutoUsername,
258264
autoLoginPassword = fnAutoPassword,
259265
allowAutoLogin = isAutoLogin,
266+
onBaseUrlDetected = null
260267
)
261268
} else {
262269
Box(
@@ -551,7 +558,38 @@ fun LoginScreen(
551558
isHttps = isHttps,
552559
toastManager = toastManager,
553560
loginViewModel = loginViewModel,
554-
rememberPassword = rememberPassword
561+
rememberPassword = rememberPassword,
562+
onProbeRequired = { url ->
563+
val openWindow = onOpenFnConnectWindow
564+
if (openWindow != null) {
565+
openWindow(
566+
FnConnectWindowRequest(
567+
initialUrl = url,
568+
fnId = "",
569+
autoLoginUsername = null,
570+
autoLoginPassword = null,
571+
allowAutoLogin = false,
572+
onBaseUrlDetected = {
573+
handleLogin(
574+
host = host,
575+
port = port,
576+
username = username,
577+
password = password,
578+
isHttps = isHttps,
579+
toastManager = toastManager,
580+
loginViewModel = loginViewModel,
581+
rememberPassword = rememberPassword,
582+
isProbeFinished = true
583+
)
584+
}
585+
)
586+
)
587+
} else {
588+
showFnConnectWebView = true
589+
fnConnectUrl = url
590+
isProbeMode = true
591+
}
592+
}
555593
)
556594
}
557595
},

composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/ui/screen/FnConnectWebViewScreen.kt renamed to composeApp/src/commonMain/kotlin/com/jankinwu/fntv/client/ui/screen/NasLoginWebViewScreen.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import androidx.compose.runtime.LaunchedEffect
1616
import androidx.compose.runtime.getValue
1717
import androidx.compose.runtime.mutableStateOf
1818
import androidx.compose.runtime.remember
19-
import androidx.compose.runtime.rememberCoroutineScope
2019
import androidx.compose.runtime.setValue
2120
import androidx.compose.ui.Alignment
2221
import androidx.compose.ui.Modifier
@@ -58,7 +57,7 @@ private val logger = Logger.withTag("FnConnectWebViewScreen")
5857

5958
@OptIn(ExperimentalHazeMaterialsApi::class, ExperimentalMaterial3Api::class)
6059
@Composable
61-
fun FnConnectWebViewScreen(
60+
fun NasLoginWebViewScreen(
6261
modifier: Modifier = Modifier,
6362
initialUrl: String,
6463
fnId: String,
@@ -67,6 +66,7 @@ fun FnConnectWebViewScreen(
6766
autoLoginUsername: String? = null,
6867
autoLoginPassword: String? = null,
6968
allowAutoLogin: Boolean = false,
69+
onBaseUrlDetected: ((String) -> Unit)? = null
7070
) {
7171
val toastManager = rememberToastManager()
7272
val hazeState = rememberHazeState()
@@ -133,6 +133,10 @@ fun FnConnectWebViewScreen(
133133
baseUrl = url.substringBefore("/login")
134134
AccountDataCache.updateFnOfficialBaseUrlFromUrl(baseUrl)
135135
logger.i("Base url: $baseUrl")
136+
if (onBaseUrlDetected != null) {
137+
onBaseUrlDetected(baseUrl)
138+
return@LaunchedEffect
139+
}
136140
}
137141
}
138142
}
@@ -194,7 +198,7 @@ fun FnConnectWebViewScreen(
194198
Column(
195199
modifier = Modifier
196200
.fillMaxSize()
197-
.padding(top = 12.dp, end = 12.dp)
201+
.padding(top = 12.dp)
198202
) {
199203
NasLoginAddressBar(
200204
addressBarValue = addressBarValue,

composeApp/src/jvmMain/kotlin/com/jankinwu/fntv/client/main.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import com.jankinwu.fntv.client.ui.providable.LocalWebViewInitialized
3636
import com.jankinwu.fntv.client.ui.providable.LocalWebViewRestartRequired
3737
import com.jankinwu.fntv.client.ui.providable.LocalWindowHandle
3838
import com.jankinwu.fntv.client.ui.providable.LocalWindowState
39-
import com.jankinwu.fntv.client.ui.screen.FnConnectWebViewScreen
39+
import com.jankinwu.fntv.client.ui.screen.NasLoginWebViewScreen
4040
import com.jankinwu.fntv.client.ui.screen.FnConnectWindowRequest
4141
import com.jankinwu.fntv.client.ui.screen.LoginScreen
4242
import com.jankinwu.fntv.client.ui.screen.PlayerManager
@@ -159,7 +159,7 @@ fun main() {
159159
LocalFrameWindowScope provides this@Window,
160160
LocalWindowState provides state,
161161
LocalWindowHandle provides window.windowHandle,
162-
LocalWebViewInitialized provides (webViewInitialized && !webViewRestartRequired && webViewInitError == null),
162+
LocalWebViewInitialized provides (webViewInitialized && webViewInitError == null),
163163
LocalWebViewRestartRequired provides webViewRestartRequired,
164164
LocalWebViewInitError provides webViewInitError
165165
) {
@@ -268,15 +268,15 @@ fun main() {
268268
LocalFrameWindowScope provides this@Window,
269269
LocalWindowState provides fnConnectWindowState,
270270
LocalWindowHandle provides window.windowHandle,
271-
LocalWebViewInitialized provides (webViewInitialized && !webViewRestartRequired && webViewInitError == null),
271+
LocalWebViewInitialized provides (webViewInitialized && webViewInitError == null),
272272
LocalWebViewRestartRequired provides webViewRestartRequired,
273273
LocalWebViewInitError provides webViewInitError
274274
) {
275275
AppTheme(
276276
displayMicaLayer = true,
277277
state = fnConnectWindowState
278278
) {
279-
FnConnectWebViewScreen(
279+
NasLoginWebViewScreen(
280280
initialUrl = request.initialUrl,
281281
fnId = request.fnId,
282282
onBack = { fnConnectWindowRequest = null },
@@ -290,6 +290,10 @@ fun main() {
290290
autoLoginUsername = request.autoLoginUsername,
291291
autoLoginPassword = request.autoLoginPassword,
292292
allowAutoLogin = request.allowAutoLogin,
293+
onBaseUrlDetected = {
294+
request.onBaseUrlDetected?.invoke(it)
295+
fnConnectWindowRequest = null
296+
}
293297
)
294298
}
295299
}

0 commit comments

Comments
 (0)