Skip to content

Commit affc756

Browse files
authored
Merge pull request #221 from SWangHash/wc/bugfix
Enhance OHOS toolbar and restore market access functionality
2 parents 625267d + cad2ff9 commit affc756

25 files changed

Lines changed: 1529 additions & 141 deletions

File tree

‎scripts/core-boundaries/rules/feature-rules.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export const optionalDependencyFeatureOwnerRules = [
161161
{ depName: 'anyhow', ownerFeatures: ['browser-control', 'debug-log', 'feedback', 'mcp', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete'] },
162162
{
163163
depName: 'async-trait',
164-
ownerFeatures: ['feedback','git', 'mcp', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'review-platform', 'script-tool-runtime', 'speech', 'workspace-search'],
164+
ownerFeatures: ['feedback', 'git', 'mcp', 'miniapp-market', 'remote-connect', 'remote-ssh', 'remote-ssh-concrete', 'review-platform', 'script-tool-runtime', 'speech', 'workspace-search'],
165165
},
166166
{
167167
depName: 'base64',

‎src/apps/desktop/src/api/miniapp_market_api.rs‎

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ use bitfun_services_integrations::miniapp_market::{
2323
use serde::{Deserialize, Serialize};
2424
use std::collections::HashMap;
2525
use std::path::{Path, PathBuf};
26+
#[cfg(target_env = "ohos")]
27+
use std::sync::Arc;
2628
use std::sync::OnceLock;
2729
use std::time::{SystemTime, UNIX_EPOCH};
2830
use tauri::{AppHandle, Emitter, Manager, State, WebviewWindow};
@@ -32,6 +34,20 @@ use tokio::sync::Mutex;
3234
const MARKET_UPLOAD_PROGRESS_EVENT: &str = "miniapp-market-upload-progress";
3335
const MARKET_ACCOUNT_CHANGED_EVENT: &str = "miniapp-market-account-changed";
3436

37+
async fn market_client() -> Result<MarketClient, String> {
38+
#[cfg(target_env = "ohos")]
39+
{
40+
let store =
41+
Arc::new(crate::api::ohos::market_credentials::OhosMarketCredentialStore::new());
42+
return MarketClient::from_environment_with_credential_store(store)
43+
.await
44+
.map_err(market_error);
45+
}
46+
47+
#[cfg(not(target_env = "ohos"))]
48+
MarketClient::from_environment().await.map_err(market_error)
49+
}
50+
3551
#[derive(Debug, Clone)]
3652
struct PendingDesktopAuth {
3753
request: DesktopAuthPollRequest,
@@ -170,27 +186,21 @@ pub struct MarketPackageInspection {
170186
pub async fn miniapp_market_browse(
171187
request: MarketBrowseRequest,
172188
) -> Result<CursorPage<MarketListingSummary>, String> {
173-
let client = MarketClient::from_environment()
174-
.await
175-
.map_err(market_error)?;
189+
let client = market_client().await?;
176190
client.browse(&request).await.map_err(market_error)
177191
}
178192

179193
#[tauri::command]
180194
pub async fn miniapp_market_get_listing(
181195
request: MarketSlugRequest,
182196
) -> Result<MarketListingDetail, String> {
183-
let mut client = MarketClient::from_environment()
184-
.await
185-
.map_err(market_error)?;
197+
let mut client = market_client().await?;
186198
client.listing(&request.slug).await.map_err(market_error)
187199
}
188200

189201
#[tauri::command]
190202
pub async fn miniapp_market_auth_start() -> Result<DesktopAuthStartView, String> {
191-
let client = MarketClient::from_environment()
192-
.await
193-
.map_err(market_error)?;
203+
let client = market_client().await?;
194204
let started = client.start_desktop_auth().await.map_err(market_error)?;
195205
let mut pending = pending_desktop_auth().lock().await;
196206
let now = unix_now();
@@ -231,9 +241,7 @@ pub async fn miniapp_market_auth_poll(
231241
}
232242
pending
233243
};
234-
let mut client = MarketClient::from_environment()
235-
.await
236-
.map_err(market_error)?;
244+
let mut client = market_client().await?;
237245
let response: DesktopAuthPollResponse = client
238246
.poll_desktop_auth(&pending.request)
239247
.await
@@ -254,17 +262,13 @@ pub async fn miniapp_market_auth_poll(
254262

255263
#[tauri::command]
256264
pub async fn miniapp_market_me() -> Result<Option<MarketMe>, String> {
257-
let mut client = MarketClient::from_environment()
258-
.await
259-
.map_err(market_error)?;
265+
let mut client = market_client().await?;
260266
client.me().await.map_err(market_error)
261267
}
262268

263269
#[tauri::command]
264270
pub async fn miniapp_market_logout(app: AppHandle) -> Result<(), String> {
265-
let mut client = MarketClient::from_environment()
266-
.await
267-
.map_err(market_error)?;
271+
let mut client = market_client().await?;
268272
client.logout().await.map_err(market_error)?;
269273
emit_market_account_changed(&app, "signed-out");
270274
Ok(())
@@ -277,9 +281,7 @@ pub async fn miniapp_market_set_rating(
277281
if request.value.is_some_and(|value| !(1..=5).contains(&value)) {
278282
return Err("Rating must be between 1 and 5.".to_string());
279283
}
280-
let mut client = MarketClient::from_environment()
281-
.await
282-
.map_err(market_error)?;
284+
let mut client = market_client().await?;
283285
client
284286
.set_rating(&request.slug, request.value)
285287
.await
@@ -290,9 +292,7 @@ pub async fn miniapp_market_set_rating(
290292
pub async fn miniapp_market_set_favorite(
291293
request: MarketSetFavoriteRequest,
292294
) -> Result<FavoriteAggregate, String> {
293-
let mut client = MarketClient::from_environment()
294-
.await
295-
.map_err(market_error)?;
295+
let mut client = market_client().await?;
296296
client
297297
.set_favorite(&request.slug, request.enabled)
298298
.await
@@ -301,19 +301,15 @@ pub async fn miniapp_market_set_favorite(
301301

302302
#[tauri::command]
303303
pub async fn miniapp_market_list_submissions() -> Result<Vec<MarketSubmission>, String> {
304-
let mut client = MarketClient::from_environment()
305-
.await
306-
.map_err(market_error)?;
304+
let mut client = market_client().await?;
307305
client.list_submissions().await.map_err(market_error)
308306
}
309307

310308
#[tauri::command]
311309
pub async fn miniapp_market_withdraw_submission(
312310
request: MarketSubmissionIdRequest,
313311
) -> Result<MarketSubmission, String> {
314-
let mut client = MarketClient::from_environment()
315-
.await
316-
.map_err(market_error)?;
312+
let mut client = market_client().await?;
317313
client
318314
.withdraw_submission(&request.submission_id)
319315
.await
@@ -397,9 +393,7 @@ pub async fn miniapp_market_install(
397393
state: State<'_, AppState>,
398394
request: MarketInstallRequest,
399395
) -> Result<MarketInstallResult, String> {
400-
let mut client = MarketClient::from_environment()
401-
.await
402-
.map_err(market_error)?;
396+
let mut client = market_client().await?;
403397
let detail = client.listing(&request.slug).await.map_err(market_error)?;
404398
let release = find_release(&detail, request.release_number)?;
405399
validate_minimum_bitfun_version(&release.min_bitfun_version)?;
@@ -588,7 +582,9 @@ pub async fn miniapp_market_capture_window(
588582
.outer_size()
589583
.map_err(|error| format!("Could not read the BitFun window size: {error}"))?;
590584
if size.width < 320 || size.height < 240 {
591-
return Err("The BitFun window is too small to capture a review screenshot.".to_string());
585+
return Err(
586+
"The BitFun window is too small to capture a review screenshot.".to_string(),
587+
);
592588
}
593589

594590
let capture_dir = app
@@ -649,7 +645,6 @@ pub async fn miniapp_market_capture_window(
649645
{
650646
Err("Unable to support the ohos".to_string())
651647
}
652-
653648
}
654649

655650
#[tauri::command]
@@ -663,9 +658,7 @@ pub async fn miniapp_market_submit_installed(
663658
.get(&request.app_id)
664659
.await
665660
.map_err(|error| error.to_string())?;
666-
let mut client = MarketClient::from_environment()
667-
.await
668-
.map_err(market_error)?;
661+
let mut client = market_client().await?;
669662
let mut progress = |submission_id: Option<&str>, phase: &'static str, completed, total| {
670663
emit_upload_progress(&app, submission_id, phase, completed, total);
671664
};
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#![cfg(target_env = "ohos")]
2+
3+
use async_trait::async_trait;
4+
use bitfun_services_integrations::miniapp_market::{
5+
MarketCredentialStore, StoredMarketCredentials,
6+
};
7+
use serde::{Deserialize, Serialize};
8+
9+
const ARKTS_FUNCTION: &str = "market_secure_credentials";
10+
11+
#[derive(Debug, Serialize)]
12+
#[serde(rename_all = "snake_case")]
13+
enum CredentialAction {
14+
Load,
15+
Store,
16+
Clear,
17+
}
18+
19+
#[derive(Debug, Serialize)]
20+
struct CredentialRequest<'a> {
21+
action: CredentialAction,
22+
#[serde(skip_serializing_if = "Option::is_none")]
23+
value: Option<&'a str>,
24+
}
25+
26+
#[derive(Debug, Deserialize)]
27+
struct CredentialResponse {
28+
status: String,
29+
value: Option<String>,
30+
code: Option<String>,
31+
}
32+
33+
#[derive(Debug)]
34+
pub struct OhosMarketCredentialStore;
35+
36+
impl OhosMarketCredentialStore {
37+
pub fn new() -> Self {
38+
Self
39+
}
40+
41+
async fn call(&self, request: CredentialRequest<'_>) -> Result<CredentialResponse, String> {
42+
let input = serde_json::to_string(&request)
43+
.map_err(|error| format!("encode market credential request: {error}"))?;
44+
let output = bitfun_core::util::call_arkts_string_function(ARKTS_FUNCTION, input)
45+
.await
46+
.map_err(|error| format!("call OpenHarmony market credential store: {error}"))?;
47+
serde_json::from_str(&output)
48+
.map_err(|error| format!("decode market credential response: {error}"))
49+
}
50+
}
51+
52+
#[async_trait]
53+
impl MarketCredentialStore for OhosMarketCredentialStore {
54+
async fn load(&self) -> Result<Option<StoredMarketCredentials>, String> {
55+
let response = self
56+
.call(CredentialRequest {
57+
action: CredentialAction::Load,
58+
value: None,
59+
})
60+
.await?;
61+
match response.status.as_str() {
62+
"ok" => response
63+
.value
64+
.ok_or_else(|| "market credential response omitted its value".to_string())
65+
.and_then(|value| {
66+
serde_json::from_str(&value)
67+
.map_err(|error| format!("parse market credentials: {error}"))
68+
})
69+
.map(Some),
70+
"not_found" => Ok(None),
71+
_ => Err(format!(
72+
"OpenHarmony market credential load failed: code={}",
73+
response.code.as_deref().unwrap_or("UNKNOWN")
74+
)),
75+
}
76+
}
77+
78+
async fn save(&self, credentials: &StoredMarketCredentials) -> Result<(), String> {
79+
let value = serde_json::to_string(credentials)
80+
.map_err(|error| format!("serialize market credentials: {error}"))?;
81+
let response = self
82+
.call(CredentialRequest {
83+
action: CredentialAction::Store,
84+
value: Some(&value),
85+
})
86+
.await?;
87+
if response.status == "ok" {
88+
Ok(())
89+
} else {
90+
Err(format!(
91+
"OpenHarmony market credential store failed: code={}",
92+
response.code.as_deref().unwrap_or("UNKNOWN")
93+
))
94+
}
95+
}
96+
97+
async fn clear(&self) -> Result<(), String> {
98+
let response = self
99+
.call(CredentialRequest {
100+
action: CredentialAction::Clear,
101+
value: None,
102+
})
103+
.await?;
104+
if matches!(response.status.as_str(), "ok" | "not_found") {
105+
Ok(())
106+
} else {
107+
Err(format!(
108+
"OpenHarmony market credential delete failed: code={}",
109+
response.code.as_deref().unwrap_or("UNKNOWN")
110+
))
111+
}
112+
}
113+
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
pub mod ohos_file_system;
2-
pub mod window;
31
pub mod browser;
42
#[cfg(target_env = "ohos")]
53
pub mod feedback_credentials;
4+
#[cfg(target_env = "ohos")]
5+
pub mod market_credentials;
6+
pub mod ohos_file_system;
67
pub mod update;
8+
pub mod window;

0 commit comments

Comments
 (0)