Compare commits
33 Commits
collab-v0.
...
v0.78.1-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3b714a4ab | ||
|
|
03d5eebf08 | ||
|
|
8ea16a11b0 | ||
|
|
2042188f5a | ||
|
|
0bbb4b22c6 | ||
|
|
75901f1c33 | ||
|
|
a6ebc9bd26 | ||
|
|
9e3085b0c4 | ||
|
|
7af9dda869 | ||
|
|
2a5ac4f203 | ||
|
|
d8a3f16891 | ||
|
|
99257a8213 | ||
|
|
0f429243d7 | ||
|
|
cba41ef7c5 | ||
|
|
2ba38b2fca | ||
|
|
e7f78c4f74 | ||
|
|
8980df1f5d | ||
|
|
2db8ac4a6f | ||
|
|
818a514110 | ||
|
|
1b4f783b97 | ||
|
|
88599add56 | ||
|
|
05f6747132 | ||
|
|
1096720b41 | ||
|
|
5c7c4dd4dd | ||
|
|
da35202bbf | ||
|
|
f5c4a2a0dd | ||
|
|
77a63c6598 | ||
|
|
edd925f77b | ||
|
|
6d0f8290a4 | ||
|
|
6497ca8ccb | ||
|
|
e64fe6d660 | ||
|
|
7df2440757 | ||
|
|
6fd4e28813 |
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1188,7 +1188,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "collab"
|
||||
version = "0.7.2"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-tungstenite",
|
||||
@@ -8409,7 +8409,7 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.77.0"
|
||||
version = "0.78.1"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.2 6.00001C5.52563 6.00001 6.6 4.92545 6.6 3.60001C6.6 2.27457 5.52563 1.20001 4.2 1.20001C2.87438 1.20001 1.8 2.27457 1.8 3.60001C1.8 4.92545 2.87438 6.00001 4.2 6.00001ZM5.15063 6.90001H3.24938C1.45519 6.90001 0 8.35501 0 10.1494C0 10.5094 0.291 10.8 0.649875 10.8H7.7505C8.10938 10.8 8.4 10.5094 8.4 10.1494C8.4 8.35501 6.945 6.90001 5.15063 6.90001ZM11.55 4.95001H10.65V4.05001C10.65 3.80251 10.4494 3.60001 10.2 3.60001C9.95063 3.60001 9.75 3.80157 9.75 4.05001V4.95001H8.85C8.6025 4.95001 8.4 5.15251 8.4 5.40001C8.4 5.64751 8.60156 5.85001 8.85 5.85001H9.75V6.75001C9.75 6.99939 9.9525 7.20001 10.2 7.20001C10.4475 7.20001 10.65 6.99845 10.65 6.75001V5.85001H11.55C11.7994 5.85001 12 5.64939 12 5.40001C12 5.15064 11.7994 4.95001 11.55 4.95001Z" fill="white"/>
|
||||
<path d="M5.75062 7.09998H3.24938C1.45519 7.09998 0 8.55498 0 10.3493C0 10.7093 0.291 11 0.649875 11H8.3505C8.70938 11 9 10.7093 9 10.3493C9 8.55498 7.545 7.09998 5.75062 7.09998Z" fill="white"/>
|
||||
<path d="M7 3.5C7 4.82544 5.82562 6 4.5 6C3.17438 6 2 4.82544 2 3.5C2 2.17456 3.17438 1 4.5 1C5.82562 1 7 2.17456 7 3.5Z" fill="white"/>
|
||||
<path d="M9.5 3.75V5.5M9.5 7.25V5.5M9.5 5.5H11.25M9.5 5.5H7.75" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 564 B |
@@ -1,3 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.9 8.00002C7.44656 8.00002 8.7 6.74637 8.7 5.20002C8.7 3.65368 7.44656 2.40002 5.9 2.40002C4.35344 2.40002 3.1 3.65368 3.1 5.20002C3.1 6.74637 4.35344 8.00002 5.9 8.00002ZM7.00906 9.05002H4.79094C2.69772 9.05002 1 10.7475 1 12.841C1 13.261 1.3395 13.6 1.75819 13.6H10.0422C10.4609 13.6 10.8 13.261 10.8 12.841C10.8 10.7475 9.1025 9.05002 7.00906 9.05002ZM14.475 6.77502H13.425V5.72502C13.425 5.43627 13.1909 5.20002 12.9 5.20002C12.6091 5.20002 12.375 5.43518 12.375 5.72502V6.77502H11.325C11.0363 6.77502 10.8 7.01127 10.8 7.30002C10.8 7.58877 11.0352 7.82502 11.325 7.82502H12.375V8.87502C12.375 9.16596 12.6112 9.40002 12.9 9.40002C13.1887 9.40002 13.425 9.16487 13.425 8.87502V7.82502H14.475C14.7659 7.82502 15 7.59096 15 7.30002C15 7.00909 14.7659 6.77502 14.475 6.77502Z" fill="white"/>
|
||||
<path d="M7.00906 8.99999H4.79094C2.69772 8.99999 1 11.1475 1 13.2409C1 13.6609 1.3395 14 1.75819 14H10.0422C10.4609 14 10.8 13.6609 10.8 13.2409C10.8 11.1475 9.1025 8.99999 7.00906 8.99999Z" fill="white"/>
|
||||
<path d="M9 5C9 6.54634 7.44657 7.99998 5.90001 7.99998C4.35344 7.99998 3 6.54634 3 5C3 3.45366 4.45344 2 6 2C7.54656 2 9 3.45366 9 5Z" fill="white"/>
|
||||
<path d="M13.025 6H14.475C14.7659 6 15 6.20906 15 6.5C15 6.79094 14.7659 7 14.475 7H13V8.49995C13 8.7898 12.7638 9.02495 12.475 9.02495C12.1863 9.02495 11.95 8.79089 11.95 8.49995V7H10.525C10.2352 7 10 6.78875 10 6.5C10 6.21125 10.2362 6 10.525 6H11.975V4.525C11.975 4.23516 12.2091 4 12.5 4C12.7909 4 13.025 4.23625 13.025 4.525V6Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 907 B After Width: | Height: | Size: 810 B |
@@ -22,11 +22,6 @@
|
||||
"show_completions_on_input": true,
|
||||
// Whether the screen sharing icon is showed in the os status bar.
|
||||
"show_call_status_icon": true,
|
||||
// Whether new projects should start out 'online'. Online projects
|
||||
// appear in the contacts panel under your name, so that your contacts
|
||||
// can see which projects you are working on. Regardless of this
|
||||
// setting, projects keep their last online status when you reopen them.
|
||||
"projects_online_by_default": true,
|
||||
// Whether to use language servers to provide code intelligence.
|
||||
"enable_language_server": true,
|
||||
// When to automatically save edited buffers. This setting can
|
||||
@@ -202,12 +197,6 @@
|
||||
"Plain Text": {
|
||||
"soft_wrap": "preferred_line_length"
|
||||
},
|
||||
"C": {
|
||||
"tab_size": 2
|
||||
},
|
||||
"C++": {
|
||||
"tab_size": 2
|
||||
},
|
||||
"Elixir": {
|
||||
"tab_size": 2
|
||||
},
|
||||
@@ -218,9 +207,6 @@
|
||||
"Markdown": {
|
||||
"soft_wrap": "preferred_line_length"
|
||||
},
|
||||
"Rust": {
|
||||
"tab_size": 4
|
||||
},
|
||||
"JavaScript": {
|
||||
"tab_size": 2
|
||||
},
|
||||
|
||||
@@ -626,7 +626,7 @@ impl Room {
|
||||
|
||||
if let Some(live_kit) = this.live_kit.as_ref() {
|
||||
let tracks =
|
||||
live_kit.room.remote_video_tracks(&peer_id.to_string());
|
||||
live_kit.room.remote_video_tracks(&user.id.to_string());
|
||||
for track in tracks {
|
||||
this.remote_video_track_updated(
|
||||
RemoteVideoTrackUpdate::Subscribed(track),
|
||||
|
||||
@@ -66,12 +66,12 @@ pub const ZED_SECRET_CLIENT_TOKEN: &str = "618033988749894";
|
||||
pub const INITIAL_RECONNECTION_DELAY: Duration = Duration::from_millis(100);
|
||||
pub const CONNECTION_TIMEOUT: Duration = Duration::from_secs(5);
|
||||
|
||||
actions!(client, [Authenticate, SignOut]);
|
||||
actions!(client, [SignIn, SignOut]);
|
||||
|
||||
pub fn init(client: Arc<Client>, cx: &mut MutableAppContext) {
|
||||
cx.add_global_action({
|
||||
let client = client.clone();
|
||||
move |_: &Authenticate, cx| {
|
||||
move |_: &SignIn, cx| {
|
||||
let client = client.clone();
|
||||
cx.spawn(
|
||||
|cx| async move { client.authenticate_and_connect(true, &cx).log_err().await },
|
||||
|
||||
@@ -183,6 +183,11 @@ impl UserStore {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "test-support")]
|
||||
pub fn clear_cache(&mut self) {
|
||||
self.users.clear();
|
||||
}
|
||||
|
||||
async fn handle_update_invite_info(
|
||||
this: ModelHandle<Self>,
|
||||
message: TypedEnvelope<proto::UpdateInviteInfo>,
|
||||
|
||||
@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathan@zed.dev>"]
|
||||
default-run = "collab"
|
||||
edition = "2021"
|
||||
name = "collab"
|
||||
version = "0.7.2"
|
||||
version = "0.8.0"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
|
||||
@@ -78,6 +78,7 @@ pub async fn validate_api_token<B>(req: Request<B>, next: Next<B>) -> impl IntoR
|
||||
struct AuthenticatedUserParams {
|
||||
github_user_id: Option<i32>,
|
||||
github_login: String,
|
||||
github_email: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
@@ -92,7 +93,11 @@ async fn get_authenticated_user(
|
||||
) -> Result<Json<AuthenticatedUserResponse>> {
|
||||
let user = app
|
||||
.db
|
||||
.get_user_by_github_account(¶ms.github_login, params.github_user_id)
|
||||
.get_or_create_user_by_github_account(
|
||||
¶ms.github_login,
|
||||
params.github_user_id,
|
||||
params.github_email.as_deref(),
|
||||
)
|
||||
.await?
|
||||
.ok_or_else(|| Error::Http(StatusCode::NOT_FOUND, "user not found".into()))?;
|
||||
let metrics_id = app.db.get_user_metrics_id(user.id).await?;
|
||||
@@ -297,11 +302,7 @@ async fn create_access_token(
|
||||
let mut user_id = user.id;
|
||||
if let Some(impersonate) = params.impersonate {
|
||||
if user.admin {
|
||||
if let Some(impersonated_user) = app
|
||||
.db
|
||||
.get_user_by_github_account(&impersonate, None)
|
||||
.await?
|
||||
{
|
||||
if let Some(impersonated_user) = app.db.get_user_by_github_login(&impersonate).await? {
|
||||
user_id = impersonated_user.id;
|
||||
} else {
|
||||
return Err(Error::Http(
|
||||
|
||||
@@ -59,7 +59,7 @@ async fn main() {
|
||||
|
||||
for (github_user, admin) in zed_users {
|
||||
if db
|
||||
.get_user_by_github_account(&github_user.login, Some(github_user.id))
|
||||
.get_user_by_github_login(&github_user.login)
|
||||
.await
|
||||
.expect("failed to fetch user")
|
||||
.is_none()
|
||||
|
||||
@@ -295,10 +295,21 @@ impl Database {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_user_by_github_account(
|
||||
pub async fn get_user_by_github_login(&self, github_login: &str) -> Result<Option<User>> {
|
||||
self.transaction(|tx| async move {
|
||||
Ok(user::Entity::find()
|
||||
.filter(user::Column::GithubLogin.eq(github_login))
|
||||
.one(&*tx)
|
||||
.await?)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_or_create_user_by_github_account(
|
||||
&self,
|
||||
github_login: &str,
|
||||
github_user_id: Option<i32>,
|
||||
github_email: Option<&str>,
|
||||
) -> Result<Option<User>> {
|
||||
self.transaction(|tx| async move {
|
||||
let tx = &*tx;
|
||||
@@ -320,7 +331,19 @@ impl Database {
|
||||
user_by_github_login.github_user_id = ActiveValue::set(Some(github_user_id));
|
||||
Ok(Some(user_by_github_login.update(tx).await?))
|
||||
} else {
|
||||
Ok(None)
|
||||
let user = user::Entity::insert(user::ActiveModel {
|
||||
email_address: ActiveValue::set(github_email.map(|email| email.into())),
|
||||
github_login: ActiveValue::set(github_login.into()),
|
||||
github_user_id: ActiveValue::set(Some(github_user_id)),
|
||||
admin: ActiveValue::set(false),
|
||||
invite_count: ActiveValue::set(0),
|
||||
invite_code: ActiveValue::set(None),
|
||||
metrics_id: ActiveValue::set(Uuid::new_v4()),
|
||||
..Default::default()
|
||||
})
|
||||
.exec_with_returning(&*tx)
|
||||
.await?;
|
||||
Ok(Some(user))
|
||||
}
|
||||
} else {
|
||||
Ok(user::Entity::find()
|
||||
|
||||
@@ -92,8 +92,8 @@ test_both_dbs!(
|
||||
);
|
||||
|
||||
test_both_dbs!(
|
||||
test_get_user_by_github_account_postgres,
|
||||
test_get_user_by_github_account_sqlite,
|
||||
test_get_or_create_user_by_github_account_postgres,
|
||||
test_get_or_create_user_by_github_account_sqlite,
|
||||
db,
|
||||
{
|
||||
let user_id1 = db
|
||||
@@ -124,7 +124,7 @@ test_both_dbs!(
|
||||
.user_id;
|
||||
|
||||
let user = db
|
||||
.get_user_by_github_account("login1", None)
|
||||
.get_or_create_user_by_github_account("login1", None, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
@@ -133,19 +133,28 @@ test_both_dbs!(
|
||||
assert_eq!(user.github_user_id, Some(101));
|
||||
|
||||
assert!(db
|
||||
.get_user_by_github_account("non-existent-login", None)
|
||||
.get_or_create_user_by_github_account("non-existent-login", None, None)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_none());
|
||||
|
||||
let user = db
|
||||
.get_user_by_github_account("the-new-login2", Some(102))
|
||||
.get_or_create_user_by_github_account("the-new-login2", Some(102), None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(user.id, user_id2);
|
||||
assert_eq!(&user.github_login, "the-new-login2");
|
||||
assert_eq!(user.github_user_id, Some(102));
|
||||
|
||||
let user = db
|
||||
.get_or_create_user_by_github_account("login3", Some(103), Some("user3@example.com"))
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(&user.github_login, "login3");
|
||||
assert_eq!(user.github_user_id, Some(103));
|
||||
assert_eq!(user.email_address, Some("user3@example.com".into()));
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -1875,7 +1875,7 @@ async fn fuzzy_search_users(
|
||||
1 | 2 => session
|
||||
.db()
|
||||
.await
|
||||
.get_user_by_github_account(&query, None)
|
||||
.get_user_by_github_login(&query)
|
||||
.await?
|
||||
.into_iter()
|
||||
.collect(),
|
||||
|
||||
@@ -104,11 +104,7 @@ impl TestServer {
|
||||
});
|
||||
|
||||
let http = FakeHttpClient::with_404_response();
|
||||
let user_id = if let Ok(Some(user)) = self
|
||||
.app_state
|
||||
.db
|
||||
.get_user_by_github_account(name, None)
|
||||
.await
|
||||
let user_id = if let Ok(Some(user)) = self.app_state.db.get_user_by_github_login(name).await
|
||||
{
|
||||
user.id
|
||||
} else {
|
||||
|
||||
@@ -6292,6 +6292,99 @@ async fn test_basic_following(
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test(iterations = 10)]
|
||||
async fn test_join_call_after_screen_was_shared(
|
||||
deterministic: Arc<Deterministic>,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
deterministic.forbid_parking();
|
||||
let mut server = TestServer::start(&deterministic).await;
|
||||
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
server
|
||||
.make_contacts(&mut [(&client_a, cx_a), (&client_b, cx_b)])
|
||||
.await;
|
||||
|
||||
let active_call_a = cx_a.read(ActiveCall::global);
|
||||
let active_call_b = cx_b.read(ActiveCall::global);
|
||||
|
||||
// Call users B and C from client A.
|
||||
active_call_a
|
||||
.update(cx_a, |call, cx| {
|
||||
call.invite(client_b.user_id().unwrap(), None, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let room_a = active_call_a.read_with(cx_a, |call, _| call.room().unwrap().clone());
|
||||
deterministic.run_until_parked();
|
||||
assert_eq!(
|
||||
room_participants(&room_a, cx_a),
|
||||
RoomParticipants {
|
||||
remote: Default::default(),
|
||||
pending: vec!["user_b".to_string()]
|
||||
}
|
||||
);
|
||||
|
||||
// User B receives the call.
|
||||
let mut incoming_call_b = active_call_b.read_with(cx_b, |call, _| call.incoming());
|
||||
let call_b = incoming_call_b.next().await.unwrap().unwrap();
|
||||
assert_eq!(call_b.calling_user.github_login, "user_a");
|
||||
|
||||
// User A shares their screen
|
||||
let display = MacOSDisplay::new();
|
||||
active_call_a
|
||||
.update(cx_a, |call, cx| {
|
||||
call.room().unwrap().update(cx, |room, cx| {
|
||||
room.set_display_sources(vec![display.clone()]);
|
||||
room.share_screen(cx)
|
||||
})
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
client_b.user_store.update(cx_b, |user_store, _| {
|
||||
user_store.clear_cache();
|
||||
});
|
||||
|
||||
// User B joins the room
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.accept_incoming(cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let room_b = active_call_b.read_with(cx_b, |call, _| call.room().unwrap().clone());
|
||||
assert!(incoming_call_b.next().await.unwrap().is_none());
|
||||
|
||||
deterministic.run_until_parked();
|
||||
assert_eq!(
|
||||
room_participants(&room_a, cx_a),
|
||||
RoomParticipants {
|
||||
remote: vec!["user_b".to_string()],
|
||||
pending: vec![],
|
||||
}
|
||||
);
|
||||
assert_eq!(
|
||||
room_participants(&room_b, cx_b),
|
||||
RoomParticipants {
|
||||
remote: vec!["user_a".to_string()],
|
||||
pending: vec![],
|
||||
}
|
||||
);
|
||||
|
||||
// Ensure User B sees User A's screenshare.
|
||||
room_b.read_with(cx_b, |room, _| {
|
||||
assert_eq!(
|
||||
room.remote_participants()
|
||||
.get(&client_a.user_id().unwrap())
|
||||
.unwrap()
|
||||
.tracks
|
||||
.len(),
|
||||
1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_following_tab_order(
|
||||
deterministic: Arc<Deterministic>,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
ToggleScreenSharing,
|
||||
};
|
||||
use call::{ActiveCall, ParticipantLocation, Room};
|
||||
use client::{proto::PeerId, Authenticate, ContactEventKind, SignOut, User, UserStore};
|
||||
use client::{proto::PeerId, ContactEventKind, SignIn, SignOut, User, UserStore};
|
||||
use clock::ReplicaId;
|
||||
use contacts_popover::ContactsPopover;
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
@@ -119,12 +119,12 @@ impl View for CollabTitlebarItem {
|
||||
let status = &*status.borrow();
|
||||
if matches!(status, client::Status::Connected { .. }) {
|
||||
right_container.add_child(self.render_toggle_contacts_button(&theme, cx));
|
||||
right_container.add_child(self.render_user_menu_button(&theme, cx));
|
||||
} else {
|
||||
right_container.add_children(self.render_connection_status(status, cx));
|
||||
right_container.add_child(self.render_sign_in_button(&theme, cx));
|
||||
}
|
||||
|
||||
right_container.add_child(self.render_user_menu_button(&theme, cx));
|
||||
|
||||
Stack::new()
|
||||
.with_child(left_container.boxed())
|
||||
.with_child(right_container.aligned().right().boxed())
|
||||
@@ -313,7 +313,7 @@ impl CollabTitlebarItem {
|
||||
vec![
|
||||
ContextMenuItem::Item {
|
||||
label: "Sign in".into(),
|
||||
action: Box::new(Authenticate),
|
||||
action: Box::new(SignIn),
|
||||
},
|
||||
ContextMenuItem::Item {
|
||||
label: "Give Feedback".into(),
|
||||
@@ -379,7 +379,7 @@ impl CollabTitlebarItem {
|
||||
let style = titlebar
|
||||
.toggle_contacts_button
|
||||
.style_for(state, self.contacts_popover.is_some());
|
||||
Svg::new("icons/plus_8.svg")
|
||||
Svg::new("icons/user_plus_16.svg")
|
||||
.with_color(style.color)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
@@ -554,6 +554,22 @@ impl CollabTitlebarItem {
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_sign_in_button(&self, theme: &Theme, cx: &mut RenderContext<Self>) -> ElementBox {
|
||||
let titlebar = &theme.workspace.titlebar;
|
||||
MouseEventHandler::<SignIn>::new(0, cx, |state, _| {
|
||||
let style = titlebar.sign_in_prompt.style_for(state, false);
|
||||
Label::new("Sign In", style.text.clone())
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.boxed()
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, cx| {
|
||||
cx.dispatch_action(SignIn);
|
||||
})
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn render_contacts_popover_host<'a>(
|
||||
&'a self,
|
||||
theme: &'a theme::Titlebar,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::{contact_finder::ContactFinder, contact_list::ContactList, ToggleContactsMenu};
|
||||
use client::UserStore;
|
||||
use gpui::{
|
||||
actions, elements::*, ClipboardItem, CursorStyle, Entity, ModelHandle, MouseButton,
|
||||
MutableAppContext, RenderContext, View, ViewContext, ViewHandle,
|
||||
actions, elements::*, Entity, ModelHandle, MouseButton, MutableAppContext, RenderContext, View,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
use project::Project;
|
||||
use settings::Settings;
|
||||
@@ -98,61 +98,9 @@ impl View for ContactsPopover {
|
||||
Child::ContactFinder(child) => ChildView::new(child, cx),
|
||||
};
|
||||
|
||||
MouseEventHandler::<ContactsPopover>::new(0, cx, |_, cx| {
|
||||
MouseEventHandler::<ContactsPopover>::new(0, cx, |_, _| {
|
||||
Flex::column()
|
||||
.with_child(child.flex(1., true).boxed())
|
||||
.with_children(
|
||||
self.user_store
|
||||
.read(cx)
|
||||
.invite_info()
|
||||
.cloned()
|
||||
.and_then(|info| {
|
||||
enum InviteLink {}
|
||||
|
||||
if info.count > 0 {
|
||||
Some(
|
||||
MouseEventHandler::<InviteLink>::new(0, cx, |state, cx| {
|
||||
let style = theme
|
||||
.contacts_popover
|
||||
.invite_row
|
||||
.style_for(state, false)
|
||||
.clone();
|
||||
|
||||
let copied =
|
||||
cx.read_from_clipboard().map_or(false, |item| {
|
||||
item.text().as_str() == info.url.as_ref()
|
||||
});
|
||||
|
||||
Label::new(
|
||||
format!(
|
||||
"{} invite link ({} left)",
|
||||
if copied { "Copied" } else { "Copy" },
|
||||
info.count
|
||||
),
|
||||
style.label.clone(),
|
||||
)
|
||||
.aligned()
|
||||
.left()
|
||||
.constrained()
|
||||
.with_height(theme.contacts_popover.invite_row_height)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.boxed()
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, cx| {
|
||||
cx.write_to_clipboard(ClipboardItem::new(
|
||||
info.url.to_string(),
|
||||
));
|
||||
cx.notify();
|
||||
})
|
||||
.boxed(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}),
|
||||
)
|
||||
.contained()
|
||||
.with_style(theme.contacts_popover.container)
|
||||
.constrained()
|
||||
|
||||
@@ -2746,7 +2746,7 @@ impl Editor {
|
||||
.color,
|
||||
)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
.with_width(gutter_margin * style.icon_margin_scale)
|
||||
.aligned()
|
||||
.constrained()
|
||||
.with_height(line_height)
|
||||
|
||||
@@ -31,4 +31,4 @@ theme = { path = "../theme" }
|
||||
tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" }
|
||||
urlencoding = "2.1.2"
|
||||
util = { path = "../util" }
|
||||
workspace = { path = "../workspace" }
|
||||
workspace = { path = "../workspace" }
|
||||
|
||||
@@ -104,6 +104,15 @@ impl TestServer {
|
||||
room_name
|
||||
))
|
||||
} else {
|
||||
for track in &room.tracks {
|
||||
client_room
|
||||
.0
|
||||
.lock()
|
||||
.video_track_updates
|
||||
.0
|
||||
.try_broadcast(RemoteVideoTrackUpdate::Subscribed(track.clone()))
|
||||
.unwrap();
|
||||
}
|
||||
room.client_rooms.insert(identity, client_room);
|
||||
Ok(())
|
||||
}
|
||||
@@ -167,11 +176,13 @@ impl TestServer {
|
||||
.get_mut(&*room_name)
|
||||
.ok_or_else(|| anyhow!("room {} does not exist", room_name))?;
|
||||
|
||||
let update = RemoteVideoTrackUpdate::Subscribed(Arc::new(RemoteVideoTrack {
|
||||
let track = Arc::new(RemoteVideoTrack {
|
||||
sid: nanoid::nanoid!(17),
|
||||
publisher_id: identity.clone(),
|
||||
frames_rx: local_track.frames_rx.clone(),
|
||||
}));
|
||||
});
|
||||
|
||||
room.tracks.push(track.clone());
|
||||
|
||||
for (id, client_room) in &room.client_rooms {
|
||||
if *id != identity {
|
||||
@@ -180,18 +191,30 @@ impl TestServer {
|
||||
.lock()
|
||||
.video_track_updates
|
||||
.0
|
||||
.try_broadcast(update.clone())
|
||||
.try_broadcast(RemoteVideoTrackUpdate::Subscribed(track.clone()))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn video_tracks(&self, token: String) -> Result<Vec<Arc<RemoteVideoTrack>>> {
|
||||
let claims = live_kit_server::token::validate(&token, &self.secret_key)?;
|
||||
let room_name = claims.video.room.unwrap();
|
||||
|
||||
let mut server_rooms = self.rooms.lock();
|
||||
let room = server_rooms
|
||||
.get_mut(&*room_name)
|
||||
.ok_or_else(|| anyhow!("room {} does not exist", room_name))?;
|
||||
Ok(room.tracks.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestServerRoom {
|
||||
client_rooms: HashMap<Sid, Arc<Room>>,
|
||||
tracks: Vec<Arc<RemoteVideoTrack>>,
|
||||
}
|
||||
|
||||
impl TestServerRoom {}
|
||||
@@ -307,8 +330,17 @@ impl Room {
|
||||
|
||||
pub fn unpublish_track(&self, _: LocalTrackPublication) {}
|
||||
|
||||
pub fn remote_video_tracks(&self, _: &str) -> Vec<Arc<RemoteVideoTrack>> {
|
||||
Default::default()
|
||||
pub fn remote_video_tracks(&self, publisher_id: &str) -> Vec<Arc<RemoteVideoTrack>> {
|
||||
if !self.is_connected() {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
self.test_server()
|
||||
.video_tracks(self.token())
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.filter(|track| track.publisher_id() == publisher_id)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn remote_video_track_updates(&self) -> impl Stream<Item = RemoteVideoTrackUpdate> {
|
||||
@@ -332,6 +364,13 @@ impl Room {
|
||||
ConnectionState::Connected { token, .. } => token,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_connected(&self) -> bool {
|
||||
match *self.0.lock().connection.1.borrow() {
|
||||
ConnectionState::Disconnected => false,
|
||||
ConnectionState::Connected { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Room {
|
||||
|
||||
@@ -327,8 +327,6 @@ impl Column for DockAnchor {
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct SettingsFileContent {
|
||||
#[serde(default)]
|
||||
pub projects_online_by_default: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub buffer_font_family: Option<String>,
|
||||
#[serde(default)]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::{update_settings_file, watched_json::WatchedJsonFile, SettingsFileContent};
|
||||
use anyhow::Result;
|
||||
use assets::Assets;
|
||||
use fs::Fs;
|
||||
use gpui::MutableAppContext;
|
||||
use std::{path::Path, sync::Arc};
|
||||
use gpui::{AssetSource, MutableAppContext};
|
||||
use std::{io::ErrorKind, path::Path, sync::Arc};
|
||||
|
||||
// TODO: Switch SettingsFile to open a worktree and buffer for synchronization
|
||||
// And instant updates in the Zed editor
|
||||
@@ -26,6 +27,27 @@ impl SettingsFile {
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_settings(path: &Path, fs: &Arc<dyn Fs>) -> Result<String> {
|
||||
match fs.load(path).await {
|
||||
result @ Ok(_) => result,
|
||||
Err(err) => {
|
||||
if let Some(e) = err.downcast_ref::<std::io::Error>() {
|
||||
if e.kind() == ErrorKind::NotFound {
|
||||
return Ok(std::str::from_utf8(
|
||||
Assets
|
||||
.load("settings/initial_user_settings.json")
|
||||
.unwrap()
|
||||
.as_ref(),
|
||||
)
|
||||
.unwrap()
|
||||
.to_string());
|
||||
}
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
cx: &mut MutableAppContext,
|
||||
update: impl 'static + Send + FnOnce(&mut SettingsFileContent),
|
||||
@@ -39,7 +61,7 @@ impl SettingsFile {
|
||||
|
||||
cx.background()
|
||||
.spawn(async move {
|
||||
let old_text = fs.load(path).await?;
|
||||
let old_text = SettingsFile::load_settings(path, &fs).await?;
|
||||
|
||||
let new_text = update_settings_file(old_text, current_file_content, update);
|
||||
|
||||
|
||||
@@ -15,4 +15,4 @@ thread_local = "1.1.4"
|
||||
lazy_static = "1.4"
|
||||
parking_lot = "0.11.1"
|
||||
futures = "0.3"
|
||||
uuid = { version = "1.1.2", features = ["v4"] }
|
||||
uuid = { version = "1.1.2", features = ["v4"] }
|
||||
|
||||
@@ -15,4 +15,4 @@ quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
lazy_static = "1.4"
|
||||
sqlez = { path = "../sqlez" }
|
||||
sqlformat = "0.2"
|
||||
sqlformat = "0.2"
|
||||
|
||||
@@ -121,8 +121,6 @@ pub struct ContactsPopover {
|
||||
pub container: ContainerStyle,
|
||||
pub height: f32,
|
||||
pub width: f32,
|
||||
pub invite_row_height: f32,
|
||||
pub invite_row: Interactive<ContainedLabel>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default)]
|
||||
@@ -666,7 +664,7 @@ pub struct Folds {
|
||||
pub indicator: Interactive<InteractiveColor>,
|
||||
pub ellipses: FoldEllipses,
|
||||
pub fold_background: Color,
|
||||
pub icon_width: f32,
|
||||
pub icon_margin_scale: f32,
|
||||
pub folded_icon: String,
|
||||
pub foldable_icon: String,
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ theme = { path = "../theme" }
|
||||
theme_selector = { path = "../theme_selector" }
|
||||
util = { path = "../util" }
|
||||
picker = { path = "../picker" }
|
||||
workspace = { path = "../workspace" }
|
||||
workspace = { path = "../workspace" }
|
||||
|
||||
@@ -57,4 +57,4 @@ gpui = { path = "../gpui", features = ["test-support"] }
|
||||
project = { path = "../project", features = ["test-support"] }
|
||||
settings = { path = "../settings", features = ["test-support"] }
|
||||
fs = { path = "../fs", features = ["test-support"] }
|
||||
db = { path = "../db", features = ["test-support"] }
|
||||
db = { path = "../db", features = ["test-support"] }
|
||||
|
||||
@@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.77.0"
|
||||
version = "0.78.1"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
|
||||
@@ -1 +1 @@
|
||||
dev
|
||||
preview
|
||||
@@ -350,9 +350,7 @@ pub fn initialize_workspace(
|
||||
workspace.status_bar().update(cx, |status_bar, cx| {
|
||||
status_bar.add_left_item(diagnostic_summary, cx);
|
||||
status_bar.add_left_item(activity_indicator, cx);
|
||||
if **cx.default_global::<StaffMode>() {
|
||||
status_bar.add_right_item(toggle_terminal, cx);
|
||||
}
|
||||
status_bar.add_right_item(toggle_terminal, cx);
|
||||
status_bar.add_right_item(feedback_button, cx);
|
||||
status_bar.add_right_item(active_buffer_language, cx);
|
||||
status_bar.add_right_item(cursor_position, cx);
|
||||
|
||||
@@ -8,12 +8,12 @@ open_result=false
|
||||
|
||||
# If -o option is specified, the folder of the resulting dmg will be opened in finder
|
||||
# If -d is specified, Zed will be compiled in debug mode and the application's path printed
|
||||
# If -od or -do is specified Zed will be bundled in debug and the application will be run.
|
||||
# If -od or -do is specified Zed will be bundled in debug and the application will be run.
|
||||
while getopts 'od' flag
|
||||
do
|
||||
case "${flag}" in
|
||||
o) open_result=true;;
|
||||
d)
|
||||
d)
|
||||
build_flag="";
|
||||
target_dir="debug"
|
||||
;;
|
||||
@@ -119,12 +119,16 @@ hdiutil create -volname Zed -srcfolder "${dmg_source_directory}" -ov -format UDZ
|
||||
# This symlink causes CPU issues with Zed if the Zed codebase is the project being worked on, so we simply remove it for now.
|
||||
rm ${dmg_source_directory}/Applications
|
||||
|
||||
echo "Adding license agreement to DMG"
|
||||
npm install --global dmg-license minimist
|
||||
dmg-license script/terms/terms-of-use.json "${dmg_file_path}"
|
||||
|
||||
if [[ -n $MACOS_CERTIFICATE && -n $MACOS_CERTIFICATE_PASSWORD && -n $APPLE_NOTARIZATION_USERNAME && -n $APPLE_NOTARIZATION_PASSWORD ]]; then
|
||||
echo "Notarizing DMG with Apple"
|
||||
npm install -g notarize-cli
|
||||
npx notarize-cli --file ${dmg_file_path} --bundle-id dev.zed.Zed --username "$APPLE_NOTARIZATION_USERNAME" --password "$APPLE_NOTARIZATION_PASSWORD"
|
||||
npx notarize-cli --file "${dmg_file_path}" --bundle-id dev.zed.Zed --username "$APPLE_NOTARIZATION_USERNAME" --password "$APPLE_NOTARIZATION_PASSWORD"
|
||||
fi
|
||||
|
||||
if [ "$open_result" = true ]; then
|
||||
open $dmg_target_directory
|
||||
fi
|
||||
fi
|
||||
|
||||
9
script/terms/terms-of-use.json
Normal file
9
script/terms/terms-of-use.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"body": [
|
||||
{
|
||||
"lang": "en-US",
|
||||
"type": "rtf",
|
||||
"file": "terms-of-use.rtf"
|
||||
}
|
||||
]
|
||||
}
|
||||
1568
script/terms/terms-of-use.rtf
Normal file
1568
script/terms/terms-of-use.rtf
Normal file
File diff suppressed because it is too large
Load Diff
@@ -42,7 +42,7 @@ export default function contactsPanel(colorScheme: ColorScheme) {
|
||||
|
||||
return {
|
||||
background: background(layer),
|
||||
padding: { top: 12, bottom: 0 },
|
||||
padding: { top: 12 },
|
||||
userQueryEditor: {
|
||||
background: background(layer, "on"),
|
||||
cornerRadius: 6,
|
||||
|
||||
@@ -7,23 +7,11 @@ export default function contactsPopover(colorScheme: ColorScheme) {
|
||||
return {
|
||||
background: background(layer),
|
||||
cornerRadius: 6,
|
||||
padding: { top: 6 },
|
||||
padding: { top: 6, bottom: 6 },
|
||||
margin: { top: -6 },
|
||||
shadow: colorScheme.popoverShadow,
|
||||
border: border(layer),
|
||||
width: 300,
|
||||
height: 400,
|
||||
inviteRowHeight: 28,
|
||||
inviteRow: {
|
||||
padding: {
|
||||
left: sidePadding,
|
||||
right: sidePadding,
|
||||
},
|
||||
border: border(layer, { top: true }),
|
||||
text: text(layer, "sans", "variant", { size: "sm" }),
|
||||
hover: {
|
||||
text: text(layer, "sans", "hovered", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function editor(colorScheme: ColorScheme) {
|
||||
verticalScale: 0.55,
|
||||
},
|
||||
folds: {
|
||||
iconWidth: 8,
|
||||
iconMarginScale: 2.5,
|
||||
foldedIcon: "icons/chevron_right_8.svg",
|
||||
foldableIcon: "icons/chevron_down_8.svg",
|
||||
indicator: {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ColorScheme } from "../themes/common/colorScheme"
|
||||
import { withOpacity } from "../utils/color"
|
||||
import { background, border, text } from "./components"
|
||||
|
||||
export default function picker(colorScheme: ColorScheme) {
|
||||
@@ -53,14 +54,17 @@ export default function picker(colorScheme: ColorScheme) {
|
||||
text: text(layer, "sans", "variant"),
|
||||
highlightText: text(layer, "sans", "accent", { weight: "bold" }),
|
||||
active: {
|
||||
background: background(layer, "base", "active"),
|
||||
background: withOpacity(
|
||||
background(layer, "base", "active"),
|
||||
0.5
|
||||
),
|
||||
text: text(layer, "sans", "base", "active"),
|
||||
highlightText: text(layer, "sans", "accent", {
|
||||
weight: "bold",
|
||||
}),
|
||||
},
|
||||
hover: {
|
||||
background: background(layer, "hovered"),
|
||||
background: withOpacity(background(layer, "hovered"), 0.5),
|
||||
},
|
||||
},
|
||||
inputEditor,
|
||||
|
||||
@@ -3,80 +3,80 @@ import { withOpacity } from "../utils/color"
|
||||
import { background, border, foreground, text } from "./components"
|
||||
|
||||
export default function projectPanel(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.middle
|
||||
let layer = colorScheme.middle
|
||||
|
||||
let baseEntry = {
|
||||
height: 24,
|
||||
iconColor: foreground(layer, "variant"),
|
||||
iconSize: 8,
|
||||
iconSpacing: 8,
|
||||
}
|
||||
let baseEntry = {
|
||||
height: 24,
|
||||
iconColor: foreground(layer, "variant"),
|
||||
iconSize: 8,
|
||||
iconSpacing: 8,
|
||||
}
|
||||
|
||||
let entry = {
|
||||
...baseEntry,
|
||||
text: text(layer, "mono", "variant", { size: "sm" }),
|
||||
hover: {
|
||||
background: background(layer, "variant", "hovered"),
|
||||
},
|
||||
active: {
|
||||
background: background(layer, "active"),
|
||||
text: text(layer, "mono", "active", { size: "sm" }),
|
||||
},
|
||||
activeHover: {
|
||||
background: background(layer, "active"),
|
||||
text: text(layer, "mono", "active", { size: "sm" }),
|
||||
},
|
||||
}
|
||||
let entry = {
|
||||
...baseEntry,
|
||||
text: text(layer, "mono", "variant", { size: "sm" }),
|
||||
hover: {
|
||||
background: background(layer, "variant", "hovered"),
|
||||
},
|
||||
active: {
|
||||
background: colorScheme.isLight ? withOpacity(background(layer, "active"), 0.5) : background(layer, "active"),
|
||||
text: text(layer, "mono", "active", { size: "sm" }),
|
||||
},
|
||||
activeHover: {
|
||||
background: background(layer, "active"),
|
||||
text: text(layer, "mono", "active", { size: "sm" }),
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
openProjectButton: {
|
||||
background: background(layer),
|
||||
border: border(layer, "active"),
|
||||
cornerRadius: 4,
|
||||
margin: {
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
},
|
||||
padding: {
|
||||
top: 3,
|
||||
bottom: 3,
|
||||
left: 7,
|
||||
right: 7,
|
||||
},
|
||||
...text(layer, "sans", "default", { size: "sm" }),
|
||||
hover: {
|
||||
...text(layer, "sans", "default", { size: "sm" }),
|
||||
background: background(layer, "hovered"),
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
},
|
||||
background: background(layer),
|
||||
padding: { left: 12, right: 12, top: 6, bottom: 6 },
|
||||
indentWidth: 8,
|
||||
entry,
|
||||
draggedEntry: {
|
||||
...baseEntry,
|
||||
text: text(layer, "mono", "on", { size: "sm" }),
|
||||
background: withOpacity(background(layer, "on"), 0.9),
|
||||
border: border(layer),
|
||||
},
|
||||
ignoredEntry: {
|
||||
...entry,
|
||||
text: text(layer, "mono", "disabled"),
|
||||
},
|
||||
cutEntry: {
|
||||
...entry,
|
||||
text: text(layer, "mono", "disabled"),
|
||||
active: {
|
||||
background: background(layer, "active"),
|
||||
text: text(layer, "mono", "disabled", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
filenameEditor: {
|
||||
background: background(layer, "on"),
|
||||
text: text(layer, "mono", "on", { size: "sm" }),
|
||||
selection: colorScheme.players[0],
|
||||
},
|
||||
}
|
||||
return {
|
||||
openProjectButton: {
|
||||
background: background(layer),
|
||||
border: border(layer, "active"),
|
||||
cornerRadius: 4,
|
||||
margin: {
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
},
|
||||
padding: {
|
||||
top: 3,
|
||||
bottom: 3,
|
||||
left: 7,
|
||||
right: 7,
|
||||
},
|
||||
...text(layer, "sans", "default", { size: "sm" }),
|
||||
hover: {
|
||||
...text(layer, "sans", "default", { size: "sm" }),
|
||||
background: background(layer, "hovered"),
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
},
|
||||
background: background(layer),
|
||||
padding: { left: 12, right: 12, top: 6, bottom: 6 },
|
||||
indentWidth: 8,
|
||||
entry,
|
||||
draggedEntry: {
|
||||
...baseEntry,
|
||||
text: text(layer, "mono", "on", { size: "sm" }),
|
||||
background: withOpacity(background(layer, "on"), 0.9),
|
||||
border: border(layer),
|
||||
},
|
||||
ignoredEntry: {
|
||||
...entry,
|
||||
text: text(layer, "mono", "disabled"),
|
||||
},
|
||||
cutEntry: {
|
||||
...entry,
|
||||
text: text(layer, "mono", "disabled"),
|
||||
active: {
|
||||
background: background(layer, "active"),
|
||||
text: text(layer, "mono", "disabled", { size: "sm" }),
|
||||
},
|
||||
},
|
||||
filenameEditor: {
|
||||
background: background(layer, "on"),
|
||||
text: text(layer, "mono", "on", { size: "sm" }),
|
||||
selection: colorScheme.players[0],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ export default function statusBar(colorScheme: ColorScheme) {
|
||||
padding: { left: 6, right: 6 },
|
||||
...text(layer, "sans", "variant"),
|
||||
hover: {
|
||||
...text(layer, "sans", "on")
|
||||
}
|
||||
...text(layer, "sans", "on"),
|
||||
},
|
||||
},
|
||||
autoUpdateProgressMessage: text(layer, "sans", "variant"),
|
||||
autoUpdateDoneMessage: text(layer, "sans", "variant"),
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
|
||||
import { ColorScheme } from "../themes/common/colorScheme";
|
||||
import { withOpacity } from "../utils/color";
|
||||
import { border, background, foreground, text, TextProperties } from "./components";
|
||||
|
||||
import { ColorScheme } from "../themes/common/colorScheme"
|
||||
import { withOpacity } from "../utils/color"
|
||||
import {
|
||||
border,
|
||||
background,
|
||||
foreground,
|
||||
text,
|
||||
TextProperties,
|
||||
} from "./components"
|
||||
|
||||
export default function welcome(colorScheme: ColorScheme) {
|
||||
let layer = colorScheme.highest;
|
||||
let layer = colorScheme.highest
|
||||
|
||||
let checkboxBase = {
|
||||
cornerRadius: 4,
|
||||
@@ -20,9 +24,9 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
margin: {
|
||||
right: 8,
|
||||
top: 5,
|
||||
bottom: 5
|
||||
bottom: 5,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let interactive_text_size: TextProperties = { size: "sm" }
|
||||
|
||||
@@ -34,7 +38,7 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
dimensions: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
}
|
||||
},
|
||||
},
|
||||
logoSubheading: {
|
||||
...text(layer, "sans", "variant", { size: "md" }),
|
||||
@@ -46,13 +50,13 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
buttonGroup: {
|
||||
margin: {
|
||||
top: 8,
|
||||
bottom: 16
|
||||
bottom: 16,
|
||||
},
|
||||
},
|
||||
headingGroup: {
|
||||
margin: {
|
||||
top: 8,
|
||||
bottom: 12
|
||||
bottom: 12,
|
||||
},
|
||||
},
|
||||
checkboxGroup: {
|
||||
@@ -62,7 +66,7 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
padding: {
|
||||
left: 12,
|
||||
top: 2,
|
||||
bottom: 2
|
||||
bottom: 2,
|
||||
},
|
||||
},
|
||||
button: {
|
||||
@@ -71,7 +75,7 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
cornerRadius: 4,
|
||||
margin: {
|
||||
top: 4,
|
||||
bottom: 4
|
||||
bottom: 4,
|
||||
},
|
||||
padding: {
|
||||
top: 3,
|
||||
@@ -90,8 +94,7 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
...text(layer, "sans", "variant", { size: "2xs" }),
|
||||
padding: {
|
||||
top: -4,
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
checkboxContainer: {
|
||||
margin: {
|
||||
@@ -99,7 +102,7 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
},
|
||||
padding: {
|
||||
bottom: 8,
|
||||
}
|
||||
},
|
||||
},
|
||||
checkbox: {
|
||||
label: {
|
||||
@@ -112,28 +115,28 @@ export default function welcome(colorScheme: ColorScheme) {
|
||||
dimensions: {
|
||||
width: 12,
|
||||
height: 12,
|
||||
}
|
||||
},
|
||||
},
|
||||
default: {
|
||||
...checkboxBase,
|
||||
background: background(layer, "default"),
|
||||
border: border(layer, "active")
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
checked: {
|
||||
...checkboxBase,
|
||||
background: background(layer, "hovered"),
|
||||
border: border(layer, "active")
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
hovered: {
|
||||
...checkboxBase,
|
||||
background: background(layer, "hovered"),
|
||||
border: border(layer, "active")
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
hoveredAndChecked: {
|
||||
...checkboxBase,
|
||||
background: background(layer, "hovered"),
|
||||
border: border(layer, "active")
|
||||
}
|
||||
}
|
||||
border: border(layer, "active"),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,12 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||
},
|
||||
},
|
||||
logoShadow: {
|
||||
color: withOpacity(colorScheme.isLight ? "#FFFFFF" : colorScheme.lowest.base.default.background, colorScheme.isLight ? 1 : 0.6),
|
||||
color: withOpacity(
|
||||
colorScheme.isLight
|
||||
? "#FFFFFF"
|
||||
: colorScheme.lowest.base.default.background,
|
||||
colorScheme.isLight ? 1 : 0.6
|
||||
),
|
||||
icon: "icons/logo_96.svg",
|
||||
dimensions: {
|
||||
width: 256,
|
||||
@@ -74,12 +79,12 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||
top: 3,
|
||||
left: 8,
|
||||
right: 8,
|
||||
bottom: 3
|
||||
bottom: 3,
|
||||
},
|
||||
cornerRadius: 8,
|
||||
hover: {
|
||||
...text(layer, "sans", "active", { size: "sm" }),
|
||||
}
|
||||
},
|
||||
},
|
||||
keyboardHintWidth: 320,
|
||||
},
|
||||
@@ -121,9 +126,9 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||
titlebar: {
|
||||
itemSpacing,
|
||||
facePileSpacing: 2,
|
||||
height: 33, // 32px + 1px for overlaid border
|
||||
height: 33, // 32px + 1px border. It's important the content area of the titlebar is evenly sized to vertically center avatar images.
|
||||
background: background(layer),
|
||||
border: border(layer, { bottom: true, overlay: true }),
|
||||
border: border(layer, { bottom: true }),
|
||||
padding: {
|
||||
left: 80,
|
||||
right: itemSpacing,
|
||||
@@ -155,8 +160,8 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||
padding: {
|
||||
left: 2,
|
||||
right: 2,
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
top: 2,
|
||||
bottom: 2,
|
||||
},
|
||||
cornerRadius: 6,
|
||||
},
|
||||
@@ -212,7 +217,7 @@ export default function workspace(colorScheme: ColorScheme) {
|
||||
margin: { left: itemSpacing },
|
||||
cornerRadius: 6,
|
||||
color: foreground(layer, "variant"),
|
||||
iconWidth: 8,
|
||||
iconWidth: 14,
|
||||
buttonWidth: 20,
|
||||
active: {
|
||||
background: background(layer, "variant", "active"),
|
||||
|
||||
Reference in New Issue
Block a user