diff --git a/data/resources/icons/scalable/actions/idp-apple-dark.svg b/data/resources/icons/scalable/actions/idp-apple-dark.svg deleted file mode 100644 index a1c99081..00000000 --- a/data/resources/icons/scalable/actions/idp-apple-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-apple.svg b/data/resources/icons/scalable/actions/idp-apple.svg deleted file mode 100644 index 39d8356c..00000000 --- a/data/resources/icons/scalable/actions/idp-apple.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-facebook.svg b/data/resources/icons/scalable/actions/idp-facebook.svg deleted file mode 100644 index 9aabcdc5..00000000 --- a/data/resources/icons/scalable/actions/idp-facebook.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-github-dark.svg b/data/resources/icons/scalable/actions/idp-github-dark.svg deleted file mode 100644 index fee0a9fc..00000000 --- a/data/resources/icons/scalable/actions/idp-github-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-github.svg b/data/resources/icons/scalable/actions/idp-github.svg deleted file mode 100644 index cb628a47..00000000 --- a/data/resources/icons/scalable/actions/idp-github.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-gitlab.svg b/data/resources/icons/scalable/actions/idp-gitlab.svg deleted file mode 100644 index 47087deb..00000000 --- a/data/resources/icons/scalable/actions/idp-gitlab.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-google-dark.svg b/data/resources/icons/scalable/actions/idp-google-dark.svg deleted file mode 100644 index 11614169..00000000 --- a/data/resources/icons/scalable/actions/idp-google-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-google.svg b/data/resources/icons/scalable/actions/idp-google.svg deleted file mode 100644 index 11614169..00000000 --- a/data/resources/icons/scalable/actions/idp-google.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-x-dark.svg b/data/resources/icons/scalable/actions/idp-x-dark.svg deleted file mode 100644 index 5ba1a1eb..00000000 --- a/data/resources/icons/scalable/actions/idp-x-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/icons/scalable/actions/idp-x-light.svg b/data/resources/icons/scalable/actions/idp-x-light.svg deleted file mode 100644 index 0a74df05..00000000 --- a/data/resources/icons/scalable/actions/idp-x-light.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/data/resources/resources.gresource.xml b/data/resources/resources.gresource.xml index ce2b0019..43acd04d 100644 --- a/data/resources/resources.gresource.xml +++ b/data/resources/resources.gresource.xml @@ -19,16 +19,6 @@ icons/scalable/actions/go-next-symbolic.svg icons/scalable/actions/go-previous-symbolic.svg icons/scalable/actions/hide-symbolic.svg - icons/scalable/actions/idp-apple-dark.svg - icons/scalable/actions/idp-apple.svg - icons/scalable/actions/idp-facebook.svg - icons/scalable/actions/idp-github-dark.svg - icons/scalable/actions/idp-github.svg - icons/scalable/actions/idp-gitlab.svg - icons/scalable/actions/idp-google-dark.svg - icons/scalable/actions/idp-google.svg - icons/scalable/actions/idp-x-dark.svg - icons/scalable/actions/idp-x-light.svg icons/scalable/actions/map-marker-symbolic.svg icons/scalable/actions/media-playback-pause-symbolic.svg icons/scalable/actions/media-playback-start-symbolic.svg diff --git a/po/POTFILES.in b/po/POTFILES.in index 44cde3a7..31ec53a5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -99,7 +99,6 @@ src/login/method_page.rs src/login/mod.blp src/login/mod.rs src/login/session_setup_view.blp -src/login/sso_idp_button.rs src/secret/linux.rs src/session/mod.rs src/session/notifications/mod.rs diff --git a/src/login/method_page.blp b/src/login/method_page.blp index 35223cd0..e06657db 100644 --- a/src/login/method_page.blp +++ b/src/login/method_page.blp @@ -113,28 +113,16 @@ template $LoginMethodPage: Adw.NavigationPage { } } - Gtk.Box sso_idp_box { - visible: false; - spacing: 12; - homogeneous: true; - hexpand: true; - vexpand: true; - - accessibility { - label: _("Single Sign-On Providers"); - } - } - - Gtk.Button more_sso_btn { + Gtk.Button sso_button { styles [ "standalone-button", "pill", ] + label: _("Login via SSO"); can-shrink: true; halign: center; action-name: "login.sso"; - action-target: "@ms nothing"; } $LoadingButton next_button { diff --git a/src/login/method_page.rs b/src/login/method_page.rs index f69cb2ea..8722a984 100644 --- a/src/login/method_page.rs +++ b/src/login/method_page.rs @@ -1,16 +1,14 @@ use adw::{prelude::*, subclass::prelude::*}; use gettextrs::gettext; use gtk::glib; -use ruma::{OwnedServerName, api::client::session::get_login_types::v3::LoginType}; +use ruma::OwnedServerName; use tracing::warn; use url::Url; -use super::{Login, sso_idp_button::SsoIdpButton}; +use super::Login; use crate::{components::LoadingButton, gettext_f, prelude::*, spawn_tokio, toast}; mod imp { - use std::cell::RefCell; - use glib::subclass::InitializingObject; use super::*; @@ -28,10 +26,7 @@ mod imp { #[template_child] password_entry: TemplateChild, #[template_child] - sso_idp_box: TemplateChild, - sso_idp_box_children: RefCell>, - #[template_child] - more_sso_btn: TemplateChild, + sso_button: TemplateChild, #[template_child] next_button: TemplateChild, /// The parent `Login` object. @@ -108,45 +103,8 @@ mod imp { } /// Update the SSO group. - pub(super) fn update_sso(&self, login_types: Vec) { - let Some(sso_login) = login_types.into_iter().find_map(|t| match t { - LoginType::Sso(sso) => Some(sso), - _ => None, - }) else { - self.sso_idp_box.set_visible(false); - self.more_sso_btn.set_visible(false); - return; - }; - - self.clean_idp_box(); - - let mut has_unknown_methods = false; - let mut has_known_methods = false; - - if !sso_login.identity_providers.is_empty() { - let mut sso_idp_box_children = self.sso_idp_box_children.borrow_mut(); - sso_idp_box_children.reserve(sso_login.identity_providers.len()); - - for identity_provider in sso_login.identity_providers { - if let Some(btn) = SsoIdpButton::new(identity_provider) { - self.sso_idp_box.append(&btn); - sso_idp_box_children.push(btn); - - has_known_methods = true; - } else { - has_unknown_methods = true; - } - } - } - self.sso_idp_box.set_visible(has_known_methods); - - if has_known_methods { - self.more_sso_btn.set_label(&gettext("More SSO Providers")); - self.more_sso_btn.set_visible(has_unknown_methods); - } else { - self.more_sso_btn.set_label(&gettext("Login via SSO")); - self.more_sso_btn.set_visible(true); - } + pub(super) fn update_sso(&self, supports_sso: bool) { + self.sso_button.set_visible(supports_sso); } /// Whether the current state allows to login with a password. @@ -210,14 +168,6 @@ mod imp { self.password_entry.set_text(""); self.next_button.set_is_loading(false); self.update_next_state(); - self.clean_idp_box(); - } - - /// Empty the identity providers box. - fn clean_idp_box(&self) { - for child in self.sso_idp_box_children.borrow_mut().drain(..) { - self.sso_idp_box.remove(&child); - } } } } @@ -239,11 +189,11 @@ impl LoginMethodPage { &self, homeserver_url: &Url, domain_name: Option<&OwnedServerName>, - login_types: Vec, + supports_sso: bool, ) { let imp = self.imp(); imp.update_title(homeserver_url, domain_name); - imp.update_sso(login_types); + imp.update_sso(supports_sso); imp.update_next_state(); } diff --git a/src/login/mod.rs b/src/login/mod.rs index 9c9da4bf..a0869a6d 100644 --- a/src/login/mod.rs +++ b/src/login/mod.rs @@ -23,7 +23,6 @@ mod in_browser_page; mod local_server; mod method_page; mod session_setup_view; -mod sso_idp_button; use self::{ advanced_dialog::LoginAdvancedDialog, @@ -105,14 +104,9 @@ mod imp { klass.set_css_name("login"); klass.set_accessible_role(gtk::AccessibleRole::Group); - klass.install_action_async( - "login.sso", - Some(&Option::::static_variant_type()), - |obj, _, variant| async move { - let idp = variant.and_then(|v| v.get::>()).flatten(); - obj.imp().init_matrix_sso_login(idp).await; - }, - ); + klass.install_action_async("login.sso", None, |obj, _, _| async move { + obj.imp().init_matrix_sso_login().await; + }); klass.install_action_async("login.open-advanced", None, |obj, _, _| async move { obj.imp().open_advanced_dialog().await; @@ -328,6 +322,9 @@ mod imp { let supports_password = login_types .iter() .any(|login_type| matches!(login_type, LoginType::Password(_))); + let supports_sso = login_types + .iter() + .any(|login_type| matches!(login_type, LoginType::Sso(_))); if supports_password { let server_name = self @@ -336,14 +333,14 @@ mod imp { .then(|| self.homeserver_page.homeserver()) .and_then(|s| sanitize_server_name(&s).ok()); - self.show_method_page(&client.homeserver(), server_name.as_ref(), login_types); + self.show_method_page(&client.homeserver(), server_name.as_ref(), supports_sso); } else { - self.init_matrix_sso_login(None).await; + self.init_matrix_sso_login().await; } } /// Prepare to log in via the Matrix SSO API. - pub(super) async fn init_matrix_sso_login(&self, idp: Option) { + pub(super) async fn init_matrix_sso_login(&self) { let Some(client) = self.client.borrow().clone() else { return; }; @@ -355,7 +352,7 @@ mod imp { let matrix_auth = client.matrix_auth(); let handle = spawn_tokio!(async move { matrix_auth - .get_sso_login_url(redirect_uri.as_str(), idp.as_deref()) + .get_sso_login_url(redirect_uri.as_str(), None) .await }); @@ -376,10 +373,10 @@ mod imp { &self, homeserver: &Url, server_name: Option<&OwnedServerName>, - login_types: Vec, + supports_sso: bool, ) { self.method_page - .update(homeserver, server_name, login_types); + .update(homeserver, server_name, supports_sso); self.navigation.push_by_tag(LoginPage::Method.as_ref()); } diff --git a/src/login/sso_idp_button.blp b/src/login/sso_idp_button.blp deleted file mode 100644 index 3f85812f..00000000 --- a/src/login/sso_idp_button.blp +++ /dev/null @@ -1,10 +0,0 @@ -using Gtk 4.0; - -template $SsoIdpButton: Gtk.Button { - action-name: "login.sso"; - - styles [ - "card", - "sso-button", - ] -} diff --git a/src/login/sso_idp_button.rs b/src/login/sso_idp_button.rs deleted file mode 100644 index d5e2dce8..00000000 --- a/src/login/sso_idp_button.rs +++ /dev/null @@ -1,183 +0,0 @@ -use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*}; -use matrix_sdk::ruma::api::client::session::get_login_types::v3::{ - IdentityProvider, IdentityProviderBrand, -}; - -use crate::gettext_f; - -mod imp { - use std::{cell::OnceCell, marker::PhantomData}; - - use glib::subclass::InitializingObject; - - use super::*; - - #[derive(Debug, Default, gtk::CompositeTemplate, glib::Properties)] - #[template(resource = "/org/gnome/Fractal/ui/login/sso_idp_button.ui")] - #[properties(wrapper_type = super::SsoIdpButton)] - pub struct SsoIdpButton { - /// The identity provider of this button. - identity_provider: OnceCell, - /// The ID of the identity provider. - #[property(get = Self::id)] - id: PhantomData, - /// The name of the identity provider. - #[property(get = Self::name)] - name: PhantomData, - /// The brand of the identity provider, as a string. - #[property(get = Self::brand_string)] - brand_string: PhantomData, - } - - #[glib::object_subclass] - impl ObjectSubclass for SsoIdpButton { - const NAME: &'static str = "SsoIdpButton"; - type Type = super::SsoIdpButton; - type ParentType = gtk::Button; - - fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); - - klass.set_accessible_role(gtk::AccessibleRole::Button); - } - - fn instance_init(obj: &InitializingObject) { - obj.init_template(); - } - } - - #[glib::derived_properties] - impl ObjectImpl for SsoIdpButton {} - - impl WidgetImpl for SsoIdpButton {} - impl ButtonImpl for SsoIdpButton {} - - impl SsoIdpButton { - /// Set the identity provider of this button. - pub(super) fn set_identity_provider(&self, identity_provider: IdentityProvider) { - let identity_provider = self.identity_provider.get_or_init(|| identity_provider); - - adw::StyleManager::default().connect_dark_notify(clone!( - #[weak(rename_to = imp)] - self, - move |_| imp.update_icon() - )); - self.update_icon(); - - self.obj() - .set_action_target_value(Some(&Some(&identity_provider.id).to_variant())); - self.obj().set_tooltip_text(Some(&gettext_f( - // Translators: Do NOT translate the content between '{' and '}', this is a - // variable name. - // This is the tooltip text on buttons to log in via Single Sign-On. - // The brand is something like Facebook, Apple, GitHub… - "Log in with {brand}", - &[("brand", &identity_provider.name)], - ))); - } - - /// The identity provider of this button. - fn identity_provider(&self) -> &IdentityProvider { - self.identity_provider - .get() - .expect("identity provider is initialized") - } - - /// The ID of the identity provider. - fn id(&self) -> String { - self.identity_provider().id.clone() - } - - /// The name of the identity provider. - fn name(&self) -> String { - self.identity_provider().name.clone() - } - - /// The brand of the identity provider. - fn brand(&self) -> &IdentityProviderBrand { - self.identity_provider() - .brand - .as_ref() - .expect("identity provider has a brand") - } - - /// The brand of the identity provider, as a string. - fn brand_string(&self) -> String { - self.brand().to_string() - } - - /// The icon name of the brand, according to the current theme. - fn brand_icon(&self) -> &str { - let is_dark = adw::StyleManager::default().is_dark(); - - match self.brand() { - IdentityProviderBrand::Apple => { - if is_dark { - "idp-apple-dark" - } else { - "idp-apple" - } - } - IdentityProviderBrand::Facebook => "idp-facebook", - IdentityProviderBrand::GitHub => { - if is_dark { - "idp-github-dark" - } else { - "idp-github" - } - } - IdentityProviderBrand::GitLab => "idp-gitlab", - IdentityProviderBrand::Google => "idp-google", - IdentityProviderBrand::Twitter => { - if is_dark { - "idp-x-dark" - } else { - "idp-x-light" - } - } - // We do not construct this for other brands. - _ => unreachable!(), - } - } - - /// Update the icon of this button for the current state. - fn update_icon(&self) { - self.obj().set_icon_name(self.brand_icon()); - } - } -} - -glib::wrapper! { - /// A button to represent an SSO identity provider. - pub struct SsoIdpButton(ObjectSubclass) - @extends gtk::Widget, gtk::Button, - @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Actionable; -} - -impl SsoIdpButton { - /// The supported SSO identity provider brands of `SsoIdpButton`. - const SUPPORTED_IDP_BRANDS: &[IdentityProviderBrand] = &[ - IdentityProviderBrand::Apple, - IdentityProviderBrand::Facebook, - IdentityProviderBrand::GitHub, - IdentityProviderBrand::GitLab, - IdentityProviderBrand::Google, - IdentityProviderBrand::Twitter, - ]; - - /// Create a new `SsoIdpButton` with the given identity provider. - /// - /// Returns `None` if the identity provider's brand is not supported. - pub fn new(identity_provider: IdentityProvider) -> Option { - // If this is not a supported brand, return `None`. - let brand = identity_provider.brand.as_ref()?; - if !Self::SUPPORTED_IDP_BRANDS.contains(brand) { - return None; - } - - let obj = glib::Object::new::(); - obj.imp().set_identity_provider(identity_provider); - - Some(obj) - } -} diff --git a/src/ui-blueprint-resources.in b/src/ui-blueprint-resources.in index 0370d141..40e7c00f 100644 --- a/src/ui-blueprint-resources.in +++ b/src/ui-blueprint-resources.in @@ -74,7 +74,6 @@ login/in_browser_page.blp login/method_page.blp login/mod.blp login/session_setup_view.blp -login/sso_idp_button.blp session_view/content.blp session_view/create_direct_chat_dialog/mod.blp session_view/create_room_dialog.blp