mirror of
https://github.com/thegeneralist01/archivr
synced 2026-07-22 11:15:41 +02:00
feat: Extensions settings tab + capture dialog redesign with Advanced options
Settings/Extensions tab (admin-only): - New 'Extensions' tab between Cookies and Storage - ExtensionsTab component: shows uBlock Origin Lite card with pill toggle - Reads ublock_enabled from instance settings; patch via existing PATCH endpoint - Shows ublock_ext_available status from server (whether ARCHIVR_UBLOCK_EXT is set) Instance settings: - Add ublock_enabled BOOLEAN (default true) to instance_settings auth DB table - Idempotent ALTER TABLE migration in initialize_auth_schema() - get/update_instance_settings include ublock_enabled - GET /api/admin/instance-settings now also returns ublock_ext_available (computed from ARCHIVR_UBLOCK_EXT env var at request time) - PATCH /api/admin/instance-settings accepts ublock_enabled Per-capture override: - CaptureBody gains ublock_enabled: Option<bool> - CaptureConfig gains ublock_enabled: Option<bool> - singlefile::save() gains ublock_enabled_override: Option<bool> param - Capture handler resolves: body override > global instance setting > env var - submitCapture(aid, loc, qual, extensions) in api.js passes ublock_enabled Capture dialog redesign: - Archive button: full-width, 13px padding, min-width 220px, primary CTA - Cancel: full-width but text-style, below Archive - ‹Advanced options› chevron toggle (rotates on open) - Expanded panel shows uBlock toggle for this capture session - Loads global ublock_enabled default from instance settings on mount Styles: - .ext-toggle pill switch (44×24 and 36×20 small variant) - .ext-card for Settings Extensions tab - .capture-advanced + .capture-advanced-panel + .capture-chevron - .capture-ext-row / .capture-ext-label / .capture-ext-name / .capture-ext-desc - .form-hint utility class
This commit is contained in:
parent
8a90259a76
commit
1b3543ead8
13 changed files with 400 additions and 87 deletions
|
|
@ -653,6 +653,8 @@ struct CaptureBody {
|
|||
/// Optional quality cap for yt-dlp sources: `"best"` or any `"NNNp"` string
|
||||
/// (e.g. `"1080p"`, `"720p"`, `"2160p"`). Absent or `"best"` → highest available.
|
||||
quality: Option<String>,
|
||||
/// Per-capture uBlock override. Absent → use global instance setting.
|
||||
ublock_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
|
|
@ -733,14 +735,26 @@ async fn capture_handler(
|
|||
let job_uid = database::create_capture_job(&conn, &archive_id)?;
|
||||
drop(conn);
|
||||
|
||||
// Load cookie rules from the auth DB to pass into the capture background task.
|
||||
let cookie_rules = {
|
||||
// Load cookie rules and global uBlock setting from the auth DB.
|
||||
let (cookie_rules, global_ublock) = {
|
||||
match database::open_auth_db(&state.auth_db_path) {
|
||||
Ok(conn) => database::list_cookie_rules(&conn).unwrap_or_default(),
|
||||
Err(_) => vec![],
|
||||
Ok(conn) => {
|
||||
let rules = database::list_cookie_rules(&conn).unwrap_or_default();
|
||||
let ublock = database::get_instance_settings(&conn)
|
||||
.map(|s| s.ublock_enabled)
|
||||
.unwrap_or(true);
|
||||
(rules, ublock)
|
||||
}
|
||||
Err(_) => (vec![], true),
|
||||
}
|
||||
};
|
||||
let capture_config = capture::CaptureConfig { cookie_rules };
|
||||
// Per-capture body overrides global; if body doesn't specify, use the global setting.
|
||||
// The resolved bool is then passed as Some(_) to singlefile, overriding the env var.
|
||||
let effective_ublock = body.ublock_enabled.unwrap_or(global_ublock);
|
||||
let capture_config = capture::CaptureConfig {
|
||||
cookie_rules,
|
||||
ublock_enabled: Some(effective_ublock),
|
||||
};
|
||||
|
||||
// Spawn background capture.
|
||||
let locator = body.locator.trim().to_string();
|
||||
|
|
@ -1020,10 +1034,20 @@ async fn patch_me(
|
|||
async fn get_instance_settings_handler(
|
||||
State(state): State<AppState>,
|
||||
auth_user: AuthUser,
|
||||
) -> Result<Json<database::InstanceSettings>, ApiError> {
|
||||
) -> Result<Json<serde_json::Value>, ApiError> {
|
||||
auth_user.require_role(ROLE_ADMIN)?;
|
||||
let conn = database::open_auth_db(&state.auth_db_path)?;
|
||||
Ok(Json(database::get_instance_settings(&conn)?))
|
||||
let settings = database::get_instance_settings(&conn)?;
|
||||
let ublock_ext_available = std::env::var("ARCHIVR_UBLOCK_EXT")
|
||||
.ok()
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|p| std::path::Path::new(&p).is_dir())
|
||||
.unwrap_or(false);
|
||||
let mut val = serde_json::to_value(&settings).unwrap_or_default();
|
||||
if let Some(obj) = val.as_object_mut() {
|
||||
obj.insert("ublock_ext_available".into(), serde_json::Value::Bool(ublock_ext_available));
|
||||
}
|
||||
Ok(Json(val))
|
||||
}
|
||||
|
||||
async fn update_instance_settings_handler(
|
||||
|
|
@ -1038,6 +1062,7 @@ async fn update_instance_settings_handler(
|
|||
if let Some(v) = body.public_entry_content_enabled { settings.public_entry_content_enabled = v; }
|
||||
if let Some(v) = body.open_registration_enabled { settings.open_registration_enabled = v; }
|
||||
if let Some(v) = body.default_entry_visibility { settings.default_entry_visibility = v; }
|
||||
if let Some(v) = body.ublock_enabled { settings.ublock_enabled = v; }
|
||||
database::update_instance_settings(&conn, &settings)?;
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
|
@ -1367,6 +1392,7 @@ struct UpdateInstanceSettingsBody {
|
|||
public_entry_content_enabled: Option<bool>,
|
||||
open_registration_enabled: Option<bool>,
|
||||
default_entry_visibility: Option<u32>,
|
||||
ublock_enabled: Option<bool>,
|
||||
}
|
||||
|
||||
async fn admin_list_users(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue