Add profile sync policy controls
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
use ely_browser_core::BrowserSnapshot;
|
use ely_browser_core::BrowserSnapshot;
|
||||||
use ely_design_system::colors;
|
use ely_design_system::colors;
|
||||||
use ely_domain::{DownloadDestination, DownloadPolicy, Profile, ProfileId, ProfileKind};
|
use ely_domain::{
|
||||||
|
DownloadDestination, DownloadPolicy, Profile, ProfileId, ProfileKind, ProfileSyncPolicy,
|
||||||
|
};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, Context, InteractiveElement, IntoElement, ParentElement, SharedString, Styled, div,
|
AnyElement, Context, InteractiveElement, IntoElement, ParentElement, SharedString, Styled, div,
|
||||||
px, rgb,
|
px, rgb,
|
||||||
};
|
};
|
||||||
use gpui_component::{
|
use gpui_component::{
|
||||||
IconName, Sizable, StyledExt,
|
IconName, Selectable, Sizable, StyledExt,
|
||||||
button::{Button, ButtonVariants},
|
button::{Button, ButtonVariants},
|
||||||
scroll::ScrollableElement,
|
scroll::ScrollableElement,
|
||||||
};
|
};
|
||||||
@@ -81,6 +83,8 @@ fn render_profile_row(
|
|||||||
cx: &mut Context<ElyShell>,
|
cx: &mut Context<ElyShell>,
|
||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
let profile_id = profile.id().clone();
|
let profile_id = profile.id().clone();
|
||||||
|
let sync_profile_id = profile.id().clone();
|
||||||
|
let sync_policy = profile.sync_policy();
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id(SharedString::from(format!("profile-{}", profile.id().as_str())))
|
.id(SharedString::from(format!("profile-{}", profile.id().as_str())))
|
||||||
@@ -121,7 +125,14 @@ fn render_profile_row(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.child(render_profile_action(index, profile_id, active, cx))
|
.child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.gap_3()
|
||||||
|
.child(render_profile_sync_action(index, sync_profile_id, sync_policy, cx))
|
||||||
|
.child(render_profile_action(index, profile_id, active, cx)),
|
||||||
|
)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,11 +174,33 @@ fn render_profile_action(
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_profile_sync_action(
|
||||||
|
index: usize,
|
||||||
|
profile_id: ProfileId,
|
||||||
|
sync_policy: ProfileSyncPolicy,
|
||||||
|
cx: &mut Context<ElyShell>,
|
||||||
|
) -> AnyElement {
|
||||||
|
let next_policy = sync_policy.toggled();
|
||||||
|
let paused = sync_policy == ProfileSyncPolicy::Paused;
|
||||||
|
|
||||||
|
Button::new(("profile-sync-policy", index))
|
||||||
|
.ghost()
|
||||||
|
.xsmall()
|
||||||
|
.selected(paused)
|
||||||
|
.label(sync_policy.action_label())
|
||||||
|
.tooltip(sync_policy.label())
|
||||||
|
.on_click(cx.listener(move |shell, _, _, cx| {
|
||||||
|
shell.set_profile_sync_policy(&profile_id, next_policy, cx);
|
||||||
|
}))
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
fn profile_detail_label(profile: &Profile) -> String {
|
fn profile_detail_label(profile: &Profile) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{} - {}",
|
"{} - {} - {}",
|
||||||
profile_kind_label(profile.kind()),
|
profile_kind_label(profile.kind()),
|
||||||
download_policy_label(profile.download_policy())
|
download_policy_label(profile.download_policy()),
|
||||||
|
profile.sync_policy().label()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ mod splits;
|
|||||||
use ely_browser_core::{BrowserCore, InitialBrowserConfig};
|
use ely_browser_core::{BrowserCore, InitialBrowserConfig};
|
||||||
use ely_domain::{
|
use ely_domain::{
|
||||||
ArchivePolicy, CommandIntent, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy,
|
ArchivePolicy, CommandIntent, DownloadPolicy, FavoriteLimit, HistoryRecordingPolicy,
|
||||||
NewTabDestination, ProfileId, SearchEngine, SpaceId, SyncObjectKind, SyncObjectPolicy, TabId,
|
NewTabDestination, ProfileId, ProfileSyncPolicy, SearchEngine, SpaceId, SyncObjectKind,
|
||||||
UrlText,
|
SyncObjectPolicy, TabId, UrlText,
|
||||||
};
|
};
|
||||||
use gpui::{App, AppContext, Context, Entity, FocusHandle, Focusable, Subscription, Window};
|
use gpui::{App, AppContext, Context, Entity, FocusHandle, Focusable, Subscription, Window};
|
||||||
use gpui_component::input::{InputEvent, InputState, SelectAll};
|
use gpui_component::input::{InputEvent, InputState, SelectAll};
|
||||||
@@ -311,6 +311,19 @@ impl ElyShell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_profile_sync_policy(
|
||||||
|
&mut self,
|
||||||
|
profile_id: &ProfileId,
|
||||||
|
sync_policy: ProfileSyncPolicy,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
if let ShellState::Ready(core) = &mut self.state
|
||||||
|
&& core.set_profile_sync_policy(profile_id, sync_policy).is_ok()
|
||||||
|
{
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn set_favorite_limit(&mut self, favorite_limit: FavoriteLimit, cx: &mut Context<Self>) {
|
fn set_favorite_limit(&mut self, favorite_limit: FavoriteLimit, cx: &mut Context<Self>) {
|
||||||
if let ShellState::Ready(core) = &mut self.state {
|
if let ShellState::Ready(core) = &mut self.state {
|
||||||
core.set_favorite_limit(favorite_limit);
|
core.set_favorite_limit(favorite_limit);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use ely_domain::{DownloadPolicy, Profile, ProfileId, ProfileKind, TabId};
|
use ely_domain::{DownloadPolicy, Profile, ProfileId, ProfileKind, ProfileSyncPolicy, TabId};
|
||||||
|
|
||||||
use crate::CoreError;
|
use crate::CoreError;
|
||||||
|
|
||||||
@@ -89,4 +89,19 @@ impl BrowserCore {
|
|||||||
let profile_id = self.active_profile_id.clone();
|
let profile_id = self.active_profile_id.clone();
|
||||||
self.set_profile_download_policy(&profile_id, download_policy)
|
self.set_profile_download_policy(&profile_id, download_policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_profile_sync_policy(
|
||||||
|
&mut self,
|
||||||
|
profile_id: &ProfileId,
|
||||||
|
sync_policy: ProfileSyncPolicy,
|
||||||
|
) -> Result<(), CoreError> {
|
||||||
|
let profile = self
|
||||||
|
.profiles
|
||||||
|
.iter_mut()
|
||||||
|
.find(|profile| profile.id() == profile_id)
|
||||||
|
.ok_or_else(|| CoreError::ProfileNotFound { id: profile_id.clone() })?;
|
||||||
|
|
||||||
|
profile.set_sync_policy(sync_policy);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use ely_browser_core::{BrowserCore, InitialBrowserConfig};
|
use ely_browser_core::{BrowserCore, InitialBrowserConfig};
|
||||||
use ely_domain::{CommandIntent, ProfileKind, UrlText};
|
use ely_domain::{CommandIntent, ProfileKind, ProfileSyncPolicy, UrlText};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn new_private_profile_command_creates_private_profile() -> Result<(), Box<dyn Error>> {
|
fn new_private_profile_command_creates_private_profile() -> Result<(), Box<dyn Error>> {
|
||||||
@@ -45,3 +45,27 @@ fn private_profiles_do_not_record_history() -> Result<(), Box<dyn Error>> {
|
|||||||
assert!(private_snapshot.history_entries.is_empty());
|
assert!(private_snapshot.history_entries.is_empty());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn profile_sync_policy_can_pause_one_profile() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
let default_profile_id = core.snapshot()?.active_profile_id;
|
||||||
|
let research_profile_id = core.create_profile("Research", 0x9fc9a2, ProfileKind::Standard)?;
|
||||||
|
|
||||||
|
core.set_profile_sync_policy(&research_profile_id, ProfileSyncPolicy::Paused)?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
let Some(default_profile) =
|
||||||
|
snapshot.profiles.iter().find(|profile| profile.id() == &default_profile_id)
|
||||||
|
else {
|
||||||
|
return Err("missing default profile".into());
|
||||||
|
};
|
||||||
|
let Some(research_profile) =
|
||||||
|
snapshot.profiles.iter().find(|profile| profile.id() == &research_profile_id)
|
||||||
|
else {
|
||||||
|
return Err("missing research profile".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(default_profile.sync_policy(), ProfileSyncPolicy::Enabled);
|
||||||
|
assert_eq!(research_profile.sync_policy(), ProfileSyncPolicy::Paused);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ pub use plugin::{
|
|||||||
PluginSignature, PluginSignatureAlgorithm,
|
PluginSignature, PluginSignatureAlgorithm,
|
||||||
};
|
};
|
||||||
pub use privacy::HistoryRecordingPolicy;
|
pub use privacy::HistoryRecordingPolicy;
|
||||||
pub use profile::{Profile, ProfileKind};
|
pub use profile::{Profile, ProfileKind, ProfileSyncPolicy};
|
||||||
pub use reading_list::{ReadingListEntry, ReadingProgress};
|
pub use reading_list::{ReadingListEntry, ReadingProgress};
|
||||||
pub use search::SearchEngine;
|
pub use search::SearchEngine;
|
||||||
pub use site_permission::{
|
pub use site_permission::{
|
||||||
|
|||||||
@@ -6,6 +6,39 @@ pub enum ProfileKind {
|
|||||||
Private,
|
Private,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||||
|
pub enum ProfileSyncPolicy {
|
||||||
|
#[default]
|
||||||
|
Enabled,
|
||||||
|
Paused,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ProfileSyncPolicy {
|
||||||
|
#[must_use]
|
||||||
|
pub fn label(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Enabled => "Sync on",
|
||||||
|
Self::Paused => "Sync paused",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn action_label(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Enabled => "Pause Sync",
|
||||||
|
Self::Paused => "Resume Sync",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn toggled(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Self::Enabled => Self::Paused,
|
||||||
|
Self::Paused => Self::Enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct Profile {
|
pub struct Profile {
|
||||||
id: ProfileId,
|
id: ProfileId,
|
||||||
@@ -13,6 +46,7 @@ pub struct Profile {
|
|||||||
color_hex: u32,
|
color_hex: u32,
|
||||||
kind: ProfileKind,
|
kind: ProfileKind,
|
||||||
download_policy: DownloadPolicy,
|
download_policy: DownloadPolicy,
|
||||||
|
sync_policy: ProfileSyncPolicy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Profile {
|
impl Profile {
|
||||||
@@ -24,6 +58,7 @@ impl Profile {
|
|||||||
color_hex,
|
color_hex,
|
||||||
kind,
|
kind,
|
||||||
download_policy: DownloadPolicy::ask_every_time(),
|
download_policy: DownloadPolicy::ask_every_time(),
|
||||||
|
sync_policy: ProfileSyncPolicy::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +87,16 @@ impl Profile {
|
|||||||
&self.download_policy
|
&self.download_policy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn sync_policy(&self) -> ProfileSyncPolicy {
|
||||||
|
self.sync_policy
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_download_policy(&mut self, download_policy: DownloadPolicy) {
|
pub fn set_download_policy(&mut self, download_policy: DownloadPolicy) {
|
||||||
self.download_policy = download_policy;
|
self.download_policy = download_policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_sync_policy(&mut self, sync_policy: ProfileSyncPolicy) {
|
||||||
|
self.sync_policy = sync_policy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user