Merge remote-tracking branch 'origin/master' into feat/pricing-plan
Project CI / Backend tests (pull_request) Failing after 48s
Project CI / Native shell tests (pull_request) Failing after 3m50s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m21s
Project CI / Frontend tests (pull_request) Failing after 47s
Project CI / AI game creator shell web tests (pull_request) Failing after 39s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m6s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m23s
Project CI / Repository checks (pull_request) Successful in 6m31s
Project CI / Backend tests (pull_request) Failing after 48s
Project CI / Native shell tests (pull_request) Failing after 3m50s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 5m21s
Project CI / Frontend tests (pull_request) Failing after 47s
Project CI / AI game creator shell web tests (pull_request) Failing after 39s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 6m6s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 7m23s
Project CI / Repository checks (pull_request) Successful in 6m31s
# Conflicts: # docs/project-memory/shared-memory/decision-log.md
This commit is contained in:
@@ -16,8 +16,8 @@ use crate::{
|
||||
pub struct FrontendRuntimeConfigResponse {
|
||||
pub image_editor_agent_sidebar_enabled: bool,
|
||||
pub agc_template_library_enabled: bool,
|
||||
/// 游戏发布灰度:运营未配置 `game-distribution:publish` 时对已登录作者默认开放,
|
||||
/// 显式收紧后只有白名单/灰度命中的作者拿到 `true`;匿名一律 `false`(发布必须先登录)。
|
||||
/// 游戏发布灰度:未配置 `game-distribution:publish` 或 `enabled=false` 时不开放;
|
||||
/// 显式配置后按 enabled、白名单、标签和灰度比例判定,匿名一律 `false`(发布必须先登录)。
|
||||
pub game_distribution_publish_enabled: bool,
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+43
@@ -0,0 +1,43 @@
|
||||
(function () {
|
||||
function makeStorage() {
|
||||
var values = Object.create(null);
|
||||
return {
|
||||
get length() {
|
||||
return Object.keys(values).length;
|
||||
},
|
||||
key: function (index) {
|
||||
return Object.keys(values)[index] || null;
|
||||
},
|
||||
getItem: function (key) {
|
||||
key = String(key);
|
||||
return Object.prototype.hasOwnProperty.call(values, key)
|
||||
? values[key]
|
||||
: null;
|
||||
},
|
||||
setItem: function (key, value) {
|
||||
values[String(key)] = String(value);
|
||||
},
|
||||
removeItem: function (key) {
|
||||
delete values[String(key)];
|
||||
},
|
||||
clear: function () {
|
||||
values = Object.create(null);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function install(name) {
|
||||
try {
|
||||
Object.defineProperty(window, name, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
value: makeStorage(),
|
||||
});
|
||||
} catch (_) {
|
||||
// opaque-origin native storage may reject property replacement; keep the sandbox intact.
|
||||
}
|
||||
}
|
||||
|
||||
install('localStorage');
|
||||
install('sessionStorage');
|
||||
})();
|
||||
@@ -3,7 +3,7 @@ use std::sync::Mutex;
|
||||
#[cfg(test)]
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
collections::{BTreeMap, HashMap},
|
||||
error::Error,
|
||||
fmt,
|
||||
sync::{
|
||||
@@ -137,6 +137,12 @@ impl BackpressureState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct GameDistributionPreviewSession {
|
||||
pub(crate) version_id: String,
|
||||
pub(crate) expires_at: OffsetDateTime,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState(Arc<AppStateInner>);
|
||||
|
||||
@@ -307,6 +313,8 @@ pub struct AppStateInner {
|
||||
ai_task_service: AiTaskService,
|
||||
spacetime_client: SpacetimeClient,
|
||||
external_api_auth_state: ExternalApiAuthState,
|
||||
game_distribution_preview_sessions:
|
||||
Arc<AsyncMutex<HashMap<String, GameDistributionPreviewSession>>>,
|
||||
editor_project_state: EditorProjectState,
|
||||
#[cfg(any())]
|
||||
puzzle_gallery_cache: PuzzleGalleryCache,
|
||||
@@ -698,6 +706,7 @@ impl AppState {
|
||||
test_fail_editor_generation_enqueue: AtomicBool::new(false),
|
||||
#[cfg(test)]
|
||||
test_external_background_removal_enqueue: Arc::new(Mutex::new(None)),
|
||||
game_distribution_preview_sessions: Arc::new(AsyncMutex::new(HashMap::new())),
|
||||
oss_client,
|
||||
project_snapshot_oss_client,
|
||||
template_library_store,
|
||||
@@ -759,6 +768,35 @@ impl AppState {
|
||||
&self.refresh_cookie_config
|
||||
}
|
||||
|
||||
pub(crate) async fn create_game_distribution_preview_session(
|
||||
&self,
|
||||
version_id: String,
|
||||
expires_at: OffsetDateTime,
|
||||
) -> String {
|
||||
let token = uuid::Uuid::new_v4().to_string();
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let mut sessions = self.game_distribution_preview_sessions.lock().await;
|
||||
sessions.retain(|_, session| session.expires_at > now);
|
||||
sessions.insert(
|
||||
token.clone(),
|
||||
GameDistributionPreviewSession {
|
||||
version_id,
|
||||
expires_at,
|
||||
},
|
||||
);
|
||||
token
|
||||
}
|
||||
|
||||
pub(crate) async fn get_game_distribution_preview_session(
|
||||
&self,
|
||||
token: &str,
|
||||
) -> Option<GameDistributionPreviewSession> {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let mut sessions = self.game_distribution_preview_sessions.lock().await;
|
||||
sessions.retain(|_, session| session.expires_at > now);
|
||||
sessions.get(token).cloned()
|
||||
}
|
||||
|
||||
pub fn http_request_permit_pools(&self) -> HttpRequestPermitPools {
|
||||
self.http_request_permit_pools.clone()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user