gpui: Add SharedUrl
type (#3975)
This PR adds a `SharedUrl` type to GPUI. It's just like a `SharedString`, but for denoting that the contained value is a URL. Mainlined from @nathansobo's GPUI blog post: https://github.com/zed-industries/zed/pull/3968/files#diff-7ee75937e2daf7dd53f71b17698d8bd6d46993d06928d411781b9bd739b5f231R9-R12 Release Notes: - N/A
This commit is contained in:
parent
fa53353c57
commit
f0ef63bfa0
7 changed files with 48 additions and 21 deletions
|
@ -3,7 +3,7 @@ use anyhow::{anyhow, Context, Result};
|
||||||
use collections::{hash_map::Entry, HashMap, HashSet};
|
use collections::{hash_map::Entry, HashMap, HashSet};
|
||||||
use feature_flags::FeatureFlagAppExt;
|
use feature_flags::FeatureFlagAppExt;
|
||||||
use futures::{channel::mpsc, Future, StreamExt};
|
use futures::{channel::mpsc, Future, StreamExt};
|
||||||
use gpui::{AsyncAppContext, EventEmitter, Model, ModelContext, SharedString, Task};
|
use gpui::{AsyncAppContext, EventEmitter, Model, ModelContext, SharedUrl, Task};
|
||||||
use postage::{sink::Sink, watch};
|
use postage::{sink::Sink, watch};
|
||||||
use rpc::proto::{RequestMessage, UsersResponse};
|
use rpc::proto::{RequestMessage, UsersResponse};
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
@ -19,7 +19,7 @@ pub struct ParticipantIndex(pub u32);
|
||||||
pub struct User {
|
pub struct User {
|
||||||
pub id: UserId,
|
pub id: UserId,
|
||||||
pub github_login: String,
|
pub github_login: String,
|
||||||
pub avatar_uri: SharedString,
|
pub avatar_uri: SharedUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use gpui::{img, prelude::*, AnyElement};
|
use gpui::{img, prelude::*, AnyElement, SharedUrl};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct CollabNotification {
|
pub struct CollabNotification {
|
||||||
avatar_uri: SharedString,
|
avatar_uri: SharedUrl,
|
||||||
accept_button: Button,
|
accept_button: Button,
|
||||||
dismiss_button: Button,
|
dismiss_button: Button,
|
||||||
children: SmallVec<[AnyElement; 2]>,
|
children: SmallVec<[AnyElement; 2]>,
|
||||||
|
@ -12,7 +12,7 @@ pub struct CollabNotification {
|
||||||
|
|
||||||
impl CollabNotification {
|
impl CollabNotification {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
avatar_uri: impl Into<SharedString>,
|
avatar_uri: impl Into<SharedUrl>,
|
||||||
accept_button: Button,
|
accept_button: Button,
|
||||||
dismiss_button: Button,
|
dismiss_button: Button,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
point, size, BorrowWindow, Bounds, DevicePixels, Element, ImageData, InteractiveElement,
|
point, size, BorrowWindow, Bounds, DevicePixels, Element, ImageData, InteractiveElement,
|
||||||
InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedString, Size,
|
InteractiveElementState, Interactivity, IntoElement, LayoutId, Pixels, SharedUrl, Size,
|
||||||
StyleRefinement, Styled, WindowContext,
|
StyleRefinement, Styled, WindowContext,
|
||||||
};
|
};
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
|
@ -12,13 +12,13 @@ use util::ResultExt;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ImageSource {
|
pub enum ImageSource {
|
||||||
/// Image content will be loaded from provided URI at render time.
|
/// Image content will be loaded from provided URI at render time.
|
||||||
Uri(SharedString),
|
Uri(SharedUrl),
|
||||||
Data(Arc<ImageData>),
|
Data(Arc<ImageData>),
|
||||||
Surface(CVImageBuffer),
|
Surface(CVImageBuffer),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SharedString> for ImageSource {
|
impl From<SharedUrl> for ImageSource {
|
||||||
fn from(value: SharedString) -> Self {
|
fn from(value: SharedUrl) -> Self {
|
||||||
Self::Uri(value)
|
Self::Uri(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod platform;
|
||||||
pub mod prelude;
|
pub mod prelude;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod shared_string;
|
mod shared_string;
|
||||||
|
mod shared_url;
|
||||||
mod style;
|
mod style;
|
||||||
mod styled;
|
mod styled;
|
||||||
mod subscription;
|
mod subscription;
|
||||||
|
@ -67,6 +68,7 @@ pub use refineable::*;
|
||||||
pub use scene::*;
|
pub use scene::*;
|
||||||
use seal::Sealed;
|
use seal::Sealed;
|
||||||
pub use shared_string::*;
|
pub use shared_string::*;
|
||||||
|
pub use shared_url::*;
|
||||||
pub use smol::Timer;
|
pub use smol::Timer;
|
||||||
pub use style::*;
|
pub use style::*;
|
||||||
pub use styled::*;
|
pub use styled::*;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{ImageData, ImageId, SharedString};
|
use crate::{ImageData, ImageId, SharedUrl};
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use futures::{
|
use futures::{
|
||||||
future::{BoxFuture, Shared},
|
future::{BoxFuture, Shared},
|
||||||
|
@ -44,7 +44,7 @@ impl From<ImageError> for Error {
|
||||||
|
|
||||||
pub struct ImageCache {
|
pub struct ImageCache {
|
||||||
client: Arc<dyn HttpClient>,
|
client: Arc<dyn HttpClient>,
|
||||||
images: Arc<Mutex<HashMap<SharedString, FetchImageFuture>>>,
|
images: Arc<Mutex<HashMap<SharedUrl, FetchImageFuture>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type FetchImageFuture = Shared<BoxFuture<'static, Result<Arc<ImageData>, Error>>>;
|
type FetchImageFuture = Shared<BoxFuture<'static, Result<Arc<ImageData>, Error>>>;
|
||||||
|
@ -59,7 +59,7 @@ impl ImageCache {
|
||||||
|
|
||||||
pub fn get(
|
pub fn get(
|
||||||
&self,
|
&self,
|
||||||
uri: impl Into<SharedString>,
|
uri: impl Into<SharedUrl>,
|
||||||
) -> Shared<BoxFuture<'static, Result<Arc<ImageData>, Error>>> {
|
) -> Shared<BoxFuture<'static, Result<Arc<ImageData>, Error>>> {
|
||||||
let uri = uri.into();
|
let uri = uri.into();
|
||||||
let mut images = self.images.lock();
|
let mut images = self.images.lock();
|
||||||
|
|
25
crates/gpui/src/shared_url.rs
Normal file
25
crates/gpui/src/shared_url.rs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
use derive_more::{Deref, DerefMut};
|
||||||
|
|
||||||
|
use crate::SharedString;
|
||||||
|
|
||||||
|
/// A [`SharedString`] containing a URL.
|
||||||
|
#[derive(Deref, DerefMut, Default, PartialEq, Eq, Hash, Clone)]
|
||||||
|
pub struct SharedUrl(SharedString);
|
||||||
|
|
||||||
|
impl std::fmt::Debug for SharedUrl {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for SharedUrl {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0.as_ref())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Into<SharedString>> From<T> for SharedUrl {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self(value.into())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::Render;
|
use gpui::{Render, SharedUrl};
|
||||||
use story::Story;
|
use story::Story;
|
||||||
|
|
||||||
use crate::{prelude::*, Avatar};
|
use crate::{prelude::*, Avatar};
|
||||||
|
@ -43,7 +43,7 @@ impl Render for ListItemStory {
|
||||||
.child(
|
.child(
|
||||||
ListItem::new("with_start slot avatar")
|
ListItem::new("with_start slot avatar")
|
||||||
.child("Hello, world!")
|
.child("Hello, world!")
|
||||||
.start_slot(Avatar::new(SharedString::from(
|
.start_slot(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
|
@ -51,7 +51,7 @@ impl Render for ListItemStory {
|
||||||
.child(
|
.child(
|
||||||
ListItem::new("with_left_avatar")
|
ListItem::new("with_left_avatar")
|
||||||
.child("Hello, world!")
|
.child("Hello, world!")
|
||||||
.end_slot(Avatar::new(SharedString::from(
|
.end_slot(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
|
@ -62,23 +62,23 @@ impl Render for ListItemStory {
|
||||||
.end_slot(
|
.end_slot(
|
||||||
h_stack()
|
h_stack()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
.child(Avatar::new(SharedString::from(
|
.child(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||||
)))
|
)))
|
||||||
.child(Avatar::new(SharedString::from(
|
.child(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||||
)))
|
)))
|
||||||
.child(Avatar::new(SharedString::from(
|
.child(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||||
)))
|
)))
|
||||||
.child(Avatar::new(SharedString::from(
|
.child(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||||
)))
|
)))
|
||||||
.child(Avatar::new(SharedString::from(
|
.child(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1789?v=4",
|
"https://avatars.githubusercontent.com/u/1789?v=4",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
.end_hover_slot(Avatar::new(SharedString::from(
|
.end_hover_slot(Avatar::new(SharedUrl::from(
|
||||||
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
"https://avatars.githubusercontent.com/u/1714999?v=4",
|
||||||
))),
|
))),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue