Add update policy controls
This commit is contained in:
@@ -96,7 +96,7 @@ impl ElyShell {
|
|||||||
"ely://settings/plugins" => self.render_plugins_page(snapshot, cx),
|
"ely://settings/plugins" => self.render_plugins_page(snapshot, cx),
|
||||||
"ely://settings/profiles" => self.render_profiles_page(snapshot, cx),
|
"ely://settings/profiles" => self.render_profiles_page(snapshot, cx),
|
||||||
"ely://settings/sync" => self.render_sync_page(snapshot, cx),
|
"ely://settings/sync" => self.render_sync_page(snapshot, cx),
|
||||||
"ely://settings/updates" => self.render_updates_page(snapshot),
|
"ely://settings/updates" => self.render_updates_page(snapshot, cx),
|
||||||
"ely://sync/status" => self.render_sync_page(snapshot, cx),
|
"ely://sync/status" => self.render_sync_page(snapshot, cx),
|
||||||
url if super::web_surface::is_external_web_url(url) => {
|
url if super::web_surface::is_external_web_url(url) => {
|
||||||
self.render_external_web_canvas(tab, snapshot, cx)
|
self.render_external_web_canvas(tab, snapshot, cx)
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ use std::env;
|
|||||||
|
|
||||||
use ely_browser_core::BrowserSnapshot;
|
use ely_browser_core::BrowserSnapshot;
|
||||||
use ely_design_system::colors;
|
use ely_design_system::colors;
|
||||||
|
use ely_domain::UpdatePolicy;
|
||||||
use gpui::{AnyElement, IntoElement, ParentElement, Styled, div, px, rgb};
|
use gpui::{AnyElement, IntoElement, ParentElement, Styled, div, px, rgb};
|
||||||
use gpui_component::{IconName, StyledExt, scroll::ScrollableElement};
|
use gpui_component::{
|
||||||
|
IconName, Selectable, Sizable, StyledExt,
|
||||||
use crate::brand::SYNC_SERVICE_NAME;
|
button::{Button, ButtonVariants},
|
||||||
|
scroll::ScrollableElement,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{ElyShell, render_canvas_surface};
|
use super::{ElyShell, render_canvas_surface};
|
||||||
|
|
||||||
@@ -17,7 +20,11 @@ const RELEASE_MANIFEST_CACHE: &str = "release_manifest_cache";
|
|||||||
const RELEASE_INTEGRITY: &str = "SHA-256 + Ed25519";
|
const RELEASE_INTEGRITY: &str = "SHA-256 + Ed25519";
|
||||||
|
|
||||||
impl ElyShell {
|
impl ElyShell {
|
||||||
pub(super) fn render_updates_page(&mut self, snapshot: &BrowserSnapshot) -> AnyElement {
|
pub(super) fn render_updates_page(
|
||||||
|
&mut self,
|
||||||
|
snapshot: &BrowserSnapshot,
|
||||||
|
cx: &mut gpui::Context<Self>,
|
||||||
|
) -> AnyElement {
|
||||||
render_canvas_surface(
|
render_canvas_surface(
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
@@ -26,7 +33,8 @@ impl ElyShell {
|
|||||||
.flex_col()
|
.flex_col()
|
||||||
.gap_5()
|
.gap_5()
|
||||||
.child(render_updates_header(snapshot))
|
.child(render_updates_header(snapshot))
|
||||||
.child(render_updates_summary())
|
.child(render_updates_summary(snapshot.update_policy, cx))
|
||||||
|
.child(render_update_policy_rows(snapshot.update_policy, cx))
|
||||||
.child(render_update_contract_rows()),
|
.child(render_update_contract_rows()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -67,7 +75,10 @@ fn render_updates_header(snapshot: &BrowserSnapshot) -> AnyElement {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_updates_summary() -> AnyElement {
|
fn render_updates_summary(
|
||||||
|
update_policy: UpdatePolicy,
|
||||||
|
cx: &mut gpui::Context<ElyShell>,
|
||||||
|
) -> AnyElement {
|
||||||
div()
|
div()
|
||||||
.rounded_md()
|
.rounded_md()
|
||||||
.border_1()
|
.border_1()
|
||||||
@@ -99,15 +110,120 @@ fn render_updates_summary() -> AnyElement {
|
|||||||
.text_color(rgb(colors::INK))
|
.text_color(rgb(colors::INK))
|
||||||
.child("Release Manifest Contract"),
|
.child("Release Manifest Contract"),
|
||||||
)
|
)
|
||||||
.child(div().text_xs().truncate().text_color(rgb(colors::MUTED)).child(
|
.child(
|
||||||
format!(
|
div()
|
||||||
"{} target through {SYNC_SERVICE_NAME} release APIs",
|
.text_xs()
|
||||||
release_target()
|
.truncate()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(update_policy.detail()),
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(div().text_xs().font_semibold().text_color(rgb(colors::SUCCESS)).child(APP_VERSION))
|
.child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_2()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(rgb(colors::SUCCESS))
|
||||||
|
.child(update_policy.name()),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("reset-update-settings")
|
||||||
|
.ghost()
|
||||||
|
.xsmall()
|
||||||
|
.icon(IconName::Undo2)
|
||||||
|
.label("Reset")
|
||||||
|
.tooltip("Restore Update Defaults")
|
||||||
|
.on_click(cx.listener(|shell, _, _, cx| {
|
||||||
|
shell.reset_update_settings(cx);
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_update_policy_rows(
|
||||||
|
active_policy: UpdatePolicy,
|
||||||
|
cx: &mut gpui::Context<ElyShell>,
|
||||||
|
) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.border_t_1()
|
||||||
|
.border_color(rgb(colors::HAIRLINE))
|
||||||
|
.children(
|
||||||
|
UpdatePolicy::ALL
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, policy)| render_update_policy_row(index, policy, active_policy, cx)),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_update_policy_row(
|
||||||
|
index: usize,
|
||||||
|
policy: UpdatePolicy,
|
||||||
|
active_policy: UpdatePolicy,
|
||||||
|
cx: &mut gpui::Context<ElyShell>,
|
||||||
|
) -> AnyElement {
|
||||||
|
let selected = policy == active_policy;
|
||||||
|
|
||||||
|
div()
|
||||||
|
.py_3()
|
||||||
|
.border_b_1()
|
||||||
|
.border_color(rgb(colors::HAIRLINE))
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_between()
|
||||||
|
.gap_4()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_3()
|
||||||
|
.child(
|
||||||
|
div().text_color(rgb(policy_icon_color(selected))).child(policy_icon(selected)),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_1()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.font_semibold()
|
||||||
|
.truncate()
|
||||||
|
.text_color(rgb(colors::INK))
|
||||||
|
.child(policy.name()),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.truncate()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(policy.detail()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new(("update-policy", index))
|
||||||
|
.ghost()
|
||||||
|
.xsmall()
|
||||||
|
.selected(selected)
|
||||||
|
.label(policy_button_label(selected))
|
||||||
|
.tooltip(policy.name())
|
||||||
|
.on_click(cx.listener(move |shell, _, _, cx| {
|
||||||
|
shell.set_update_policy(policy, cx);
|
||||||
|
})),
|
||||||
|
)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +265,18 @@ fn render_update_contract_rows() -> AnyElement {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn policy_icon(selected: bool) -> IconName {
|
||||||
|
if selected { IconName::CircleCheck } else { IconName::LoaderCircle }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn policy_icon_color(selected: bool) -> u32 {
|
||||||
|
if selected { colors::PRIMARY } else { colors::MUTED_SOFT }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn policy_button_label(selected: bool) -> &'static str {
|
||||||
|
if selected { "Active" } else { "Select" }
|
||||||
|
}
|
||||||
|
|
||||||
fn update_row(
|
fn update_row(
|
||||||
icon: IconName,
|
icon: IconName,
|
||||||
label: &'static str,
|
label: &'static str,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use ely_domain::{
|
use ely_domain::{
|
||||||
ArchivePolicy, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy, NewTabDestination,
|
ArchivePolicy, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy, NewTabDestination,
|
||||||
ProfileId, ProfileSyncPolicy, SearchEngine, SyncObjectKind, SyncObjectPolicy,
|
ProfileId, ProfileSyncPolicy, SearchEngine, SyncObjectKind, SyncObjectPolicy, UpdatePolicy,
|
||||||
};
|
};
|
||||||
use gpui::Context;
|
use gpui::Context;
|
||||||
|
|
||||||
@@ -151,6 +151,24 @@ impl ElyShell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn set_update_policy(
|
||||||
|
&mut self,
|
||||||
|
update_policy: UpdatePolicy,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
if let ShellState::Ready(core) = &mut self.state {
|
||||||
|
core.set_update_policy(update_policy);
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn reset_update_settings(&mut self, cx: &mut Context<Self>) {
|
||||||
|
if let ShellState::Ready(core) = &mut self.state {
|
||||||
|
core.reset_update_settings();
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn archive_idle_tabs_now(&mut self, cx: &mut Context<Self>) {
|
pub(super) fn archive_idle_tabs_now(&mut self, cx: &mut Context<Self>) {
|
||||||
if let ShellState::Ready(core) = &mut self.state
|
if let ShellState::Ready(core) = &mut self.state
|
||||||
&& core.archive_idle_tabs(std::time::SystemTime::now()).is_ok()
|
&& core.archive_idle_tabs(std::time::SystemTime::now()).is_ok()
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use ely_domain::{
|
|||||||
DownloadEntry, DownloadPolicy, FavoriteLimit, HistoryEntry, HistoryRecordingPolicy,
|
DownloadEntry, DownloadPolicy, FavoriteLimit, HistoryEntry, HistoryRecordingPolicy,
|
||||||
NewTabDestination, NoteEntry, Profile, ProfileId, ProfileKind, ReadingListEntry, SearchEngine,
|
NewTabDestination, NoteEntry, Profile, ProfileId, ProfileKind, ReadingListEntry, SearchEngine,
|
||||||
SitePermissionAuditEvent, SitePermissionEntry, Space, SpaceId, SplitLayout, SyncStatus,
|
SitePermissionAuditEvent, SitePermissionEntry, Space, SpaceId, SplitLayout, SyncStatus,
|
||||||
TabGroup, TabId, UrlText,
|
TabGroup, TabId, UpdatePolicy, UrlText,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{CoreError, navigation::tab_title};
|
use crate::{CoreError, navigation::tab_title};
|
||||||
@@ -113,6 +113,7 @@ pub struct BrowserSnapshot {
|
|||||||
pub new_tab_destination: NewTabDestination,
|
pub new_tab_destination: NewTabDestination,
|
||||||
pub history_recording_policy: HistoryRecordingPolicy,
|
pub history_recording_policy: HistoryRecordingPolicy,
|
||||||
pub favorite_limit: FavoriteLimit,
|
pub favorite_limit: FavoriteLimit,
|
||||||
|
pub update_policy: UpdatePolicy,
|
||||||
pub command_query: String,
|
pub command_query: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +145,7 @@ pub struct BrowserCore {
|
|||||||
new_tab_destination: NewTabDestination,
|
new_tab_destination: NewTabDestination,
|
||||||
history_recording_policy: HistoryRecordingPolicy,
|
history_recording_policy: HistoryRecordingPolicy,
|
||||||
favorite_limit: FavoriteLimit,
|
favorite_limit: FavoriteLimit,
|
||||||
|
update_policy: UpdatePolicy,
|
||||||
sync_object_policies: SyncObjectPolicies,
|
sync_object_policies: SyncObjectPolicies,
|
||||||
command_query: String,
|
command_query: String,
|
||||||
}
|
}
|
||||||
@@ -189,6 +191,7 @@ impl BrowserCore {
|
|||||||
new_tab_destination,
|
new_tab_destination,
|
||||||
history_recording_policy: HistoryRecordingPolicy::default(),
|
history_recording_policy: HistoryRecordingPolicy::default(),
|
||||||
favorite_limit: FavoriteLimit::default(),
|
favorite_limit: FavoriteLimit::default(),
|
||||||
|
update_policy: UpdatePolicy::default(),
|
||||||
sync_object_policies: SyncObjectPolicies::default(),
|
sync_object_policies: SyncObjectPolicies::default(),
|
||||||
spaces: vec![space],
|
spaces: vec![space],
|
||||||
profiles: vec![profile],
|
profiles: vec![profile],
|
||||||
@@ -348,6 +351,19 @@ impl BrowserCore {
|
|||||||
self.favorite_limit
|
self.favorite_limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_update_policy(&mut self, update_policy: UpdatePolicy) {
|
||||||
|
self.update_policy = update_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_update_settings(&mut self) {
|
||||||
|
self.set_update_policy(UpdatePolicy::default());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn update_policy(&self) -> UpdatePolicy {
|
||||||
|
self.update_policy
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_command_query(&mut self, query: impl Into<String>) {
|
pub fn set_command_query(&mut self, query: impl Into<String>) {
|
||||||
self.command_query = query.into();
|
self.command_query = query.into();
|
||||||
}
|
}
|
||||||
@@ -393,6 +409,7 @@ impl BrowserCore {
|
|||||||
new_tab_destination: self.new_tab_destination,
|
new_tab_destination: self.new_tab_destination,
|
||||||
history_recording_policy: self.history_recording_policy,
|
history_recording_policy: self.history_recording_policy,
|
||||||
favorite_limit: self.favorite_limit,
|
favorite_limit: self.favorite_limit,
|
||||||
|
update_policy: self.update_policy,
|
||||||
command_query: self.command_query.clone(),
|
command_query: self.command_query.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use ely_browser_core::{BrowserCore, InitialBrowserConfig};
|
|||||||
use ely_domain::{
|
use ely_domain::{
|
||||||
ArchivePolicy, DEFAULT_SIDEBAR_WIDTH_PX, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy,
|
ArchivePolicy, DEFAULT_SIDEBAR_WIDTH_PX, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy,
|
||||||
NewTabDestination, ProfileKind, ProfileSyncPolicy, SearchEngine, SyncObjectKind,
|
NewTabDestination, ProfileKind, ProfileSyncPolicy, SearchEngine, SyncObjectKind,
|
||||||
SyncObjectPolicy,
|
SyncObjectPolicy, UpdatePolicy,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -47,6 +47,10 @@ fn section_resets_restore_settings_defaults() -> Result<(), Box<dyn Error>> {
|
|||||||
core.set_sync_object_policy(SyncObjectKind::Tabs, SyncObjectPolicy::Paused);
|
core.set_sync_object_policy(SyncObjectKind::Tabs, SyncObjectPolicy::Paused);
|
||||||
core.reset_sync_settings();
|
core.reset_sync_settings();
|
||||||
assert_eq!(core.sync_object_policy(SyncObjectKind::Tabs), SyncObjectPolicy::Enabled);
|
assert_eq!(core.sync_object_policy(SyncObjectKind::Tabs), SyncObjectPolicy::Enabled);
|
||||||
|
|
||||||
|
core.set_update_policy(UpdatePolicy::Manual);
|
||||||
|
core.reset_update_settings();
|
||||||
|
assert_eq!(core.snapshot()?.update_policy, UpdatePolicy::Automatic);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ mod split;
|
|||||||
mod sync;
|
mod sync;
|
||||||
mod tab;
|
mod tab;
|
||||||
mod tab_group;
|
mod tab_group;
|
||||||
|
mod update;
|
||||||
mod url_text;
|
mod url_text;
|
||||||
|
|
||||||
pub use archive::{ArchiveSource, ArchivedTab};
|
pub use archive::{ArchiveSource, ArchivedTab};
|
||||||
@@ -57,4 +58,5 @@ pub use sync::{
|
|||||||
};
|
};
|
||||||
pub use tab::{BrowserTab, TabFlags, TabState};
|
pub use tab::{BrowserTab, TabFlags, TabState};
|
||||||
pub use tab_group::TabGroup;
|
pub use tab_group::TabGroup;
|
||||||
|
pub use update::UpdatePolicy;
|
||||||
pub use url_text::UrlText;
|
pub use url_text::UrlText;
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||||
|
pub enum UpdatePolicy {
|
||||||
|
#[default]
|
||||||
|
Automatic,
|
||||||
|
Manual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UpdatePolicy {
|
||||||
|
pub const ALL: &[Self] = &[Self::Automatic, Self::Manual];
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn name(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Automatic => "Automatic",
|
||||||
|
Self::Manual => "Manual",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn detail(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Automatic => "Use release manifests as the automatic update source.",
|
||||||
|
Self::Manual => "Keep release manifest checks user-initiated.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user