mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Merge branch 'main' into copilot-ui
This commit is contained in:
commit
dcb9c0b9d8
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -1441,7 +1441,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "collab"
|
||||
version = "0.33.0"
|
||||
version = "0.34.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1926,11 +1926,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.1.20"
|
||||
source = "git+https://github.com/zed-industries/rust-ctor?rev=7f824cf6a7943885a649b579f33f9ac53f0d1db6#7f824cf6a7943885a649b579f33f9ac53f0d1db6"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3065,7 +3066,6 @@ dependencies = [
|
||||
"slotmap",
|
||||
"smallvec",
|
||||
"smol",
|
||||
"sqlez",
|
||||
"sum_tree",
|
||||
"taffy",
|
||||
"thiserror",
|
||||
@ -6846,7 +6846,6 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_json_lenient",
|
||||
"smallvec",
|
||||
"sqlez",
|
||||
"toml 0.5.11",
|
||||
"tree-sitter",
|
||||
"tree-sitter-json 0.19.0",
|
||||
@ -7838,6 +7837,7 @@ dependencies = [
|
||||
"convert_case 0.6.0",
|
||||
"gpui",
|
||||
"indexmap 1.9.3",
|
||||
"indoc",
|
||||
"json_comments",
|
||||
"log",
|
||||
"palette",
|
||||
@ -8489,7 +8489,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "tree-sitter-nu"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/nushell/tree-sitter-nu?rev=a0b80b2e21e5e39571252dc799e19eb89f1fc912#a0b80b2e21e5e39571252dc799e19eb89f1fc912"
|
||||
source = "git+https://github.com/nushell/tree-sitter-nu?rev=26bbaecda0039df4067861ab38ea8ea169f7f5aa#26bbaecda0039df4067861ab38ea8ea169f7f5aa"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter",
|
||||
@ -9439,6 +9439,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"settings",
|
||||
"smallvec",
|
||||
"sqlez",
|
||||
"terminal",
|
||||
"theme",
|
||||
"ui",
|
||||
|
@ -92,10 +92,7 @@ resolver = "2"
|
||||
anyhow = { version = "1.0.57" }
|
||||
async-trait = { version = "0.1" }
|
||||
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
|
||||
# TODO: Switch back to the published version of `ctor` once:
|
||||
# 1. A new version of `ctor` is published with this change: https://github.com/mmastrac/rust-ctor/pull/295
|
||||
# 2. We've confirmed it's fine to update to the latest version of `ctor` (we're currently on v0.1.20).
|
||||
ctor = { git = "https://github.com/zed-industries/rust-ctor", rev = "7f824cf6a7943885a649b579f33f9ac53f0d1db6" }
|
||||
ctor = "0.2.6"
|
||||
derive_more = { version = "0.99.17" }
|
||||
env_logger = { version = "0.9" }
|
||||
futures = { version = "0.3" }
|
||||
@ -158,7 +155,7 @@ tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-rack
|
||||
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "f545a41f57502e1b5ddf2a6668896c1b0620f930"}
|
||||
tree-sitter-lua = "0.0.14"
|
||||
tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" }
|
||||
tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "a0b80b2e21e5e39571252dc799e19eb89f1fc912"}
|
||||
tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "26bbaecda0039df4067861ab38ea8ea169f7f5aa"}
|
||||
tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "6608d9d60c386f19d80af7d8132322fa11199c42"}
|
||||
tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"}
|
||||
|
||||
|
@ -1286,8 +1286,8 @@ impl Panel for AssistantPanel {
|
||||
}
|
||||
}
|
||||
|
||||
fn icon(&self, _cx: &WindowContext) -> Option<Icon> {
|
||||
Some(Icon::Ai)
|
||||
fn icon(&self, cx: &WindowContext) -> Option<Icon> {
|
||||
Some(Icon::Ai).filter(|_| AssistantSettings::get_global(cx).button)
|
||||
}
|
||||
|
||||
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
|
||||
@ -2827,8 +2827,8 @@ impl InlineAssistant {
|
||||
|
||||
fn handle_codegen_changed(&mut self, _: Model<Codegen>, cx: &mut ViewContext<Self>) {
|
||||
let is_read_only = !self.codegen.read(cx).idle();
|
||||
self.prompt_editor.update(cx, |editor, _cx| {
|
||||
let was_read_only = editor.read_only();
|
||||
self.prompt_editor.update(cx, |editor, cx| {
|
||||
let was_read_only = editor.read_only(cx);
|
||||
if was_read_only != is_read_only {
|
||||
if is_read_only {
|
||||
editor.set_read_only(true);
|
||||
@ -3063,7 +3063,7 @@ impl InlineAssistant {
|
||||
fn render_prompt_editor(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: if self.prompt_editor.read(cx).read_only() {
|
||||
color: if self.prompt_editor.read(cx).read_only(cx) {
|
||||
cx.theme().colors().text_disabled
|
||||
} else {
|
||||
cx.theme().colors().text
|
||||
|
@ -36,12 +36,14 @@ impl ParticipantLocation {
|
||||
pub struct LocalParticipant {
|
||||
pub projects: Vec<proto::ParticipantProject>,
|
||||
pub active_project: Option<WeakModel<Project>>,
|
||||
pub role: proto::ChannelRole,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RemoteParticipant {
|
||||
pub user: Arc<User>,
|
||||
pub peer_id: proto::PeerId,
|
||||
pub role: proto::ChannelRole,
|
||||
pub projects: Vec<proto::ParticipantProject>,
|
||||
pub location: ParticipantLocation,
|
||||
pub participant_index: ParticipantIndex,
|
||||
|
@ -247,14 +247,18 @@ impl Room {
|
||||
let response = client.request(proto::CreateRoom {}).await?;
|
||||
let room_proto = response.room.ok_or_else(|| anyhow!("invalid room"))?;
|
||||
let room = cx.new_model(|cx| {
|
||||
Self::new(
|
||||
let mut room = Self::new(
|
||||
room_proto.id,
|
||||
None,
|
||||
response.live_kit_connection_info,
|
||||
client,
|
||||
user_store,
|
||||
cx,
|
||||
)
|
||||
);
|
||||
if let Some(participant) = room_proto.participants.first() {
|
||||
room.local_participant.role = participant.role()
|
||||
}
|
||||
room
|
||||
})?;
|
||||
|
||||
let initial_project_id = if let Some(initial_project) = initial_project {
|
||||
@ -606,6 +610,16 @@ impl Room {
|
||||
.find(|p| p.peer_id == peer_id)
|
||||
}
|
||||
|
||||
pub fn role_for_user(&self, user_id: u64) -> Option<proto::ChannelRole> {
|
||||
self.remote_participants
|
||||
.get(&user_id)
|
||||
.map(|participant| participant.role)
|
||||
}
|
||||
|
||||
pub fn local_participant_is_admin(&self) -> bool {
|
||||
self.local_participant.role == proto::ChannelRole::Admin
|
||||
}
|
||||
|
||||
pub fn pending_participants(&self) -> &[Arc<User>] {
|
||||
&self.pending_participants
|
||||
}
|
||||
@ -710,7 +724,20 @@ impl Room {
|
||||
this.participant_user_ids.clear();
|
||||
|
||||
if let Some(participant) = local_participant {
|
||||
let role = participant.role();
|
||||
this.local_participant.projects = participant.projects;
|
||||
if this.local_participant.role != role {
|
||||
this.local_participant.role = role;
|
||||
|
||||
this.joined_projects.retain(|project| {
|
||||
if let Some(project) = project.upgrade() {
|
||||
project.update(cx, |project, _| project.set_role(role));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.local_participant.projects.clear();
|
||||
}
|
||||
@ -766,6 +793,7 @@ impl Room {
|
||||
});
|
||||
}
|
||||
|
||||
let role = participant.role();
|
||||
let location = ParticipantLocation::from_proto(participant.location)
|
||||
.unwrap_or(ParticipantLocation::External);
|
||||
if let Some(remote_participant) =
|
||||
@ -774,8 +802,11 @@ impl Room {
|
||||
remote_participant.peer_id = peer_id;
|
||||
remote_participant.projects = participant.projects;
|
||||
remote_participant.participant_index = participant_index;
|
||||
if location != remote_participant.location {
|
||||
if location != remote_participant.location
|
||||
|| role != remote_participant.role
|
||||
{
|
||||
remote_participant.location = location;
|
||||
remote_participant.role = role;
|
||||
cx.emit(Event::ParticipantLocationChanged {
|
||||
participant_id: peer_id,
|
||||
});
|
||||
@ -789,6 +820,7 @@ impl Room {
|
||||
peer_id,
|
||||
projects: participant.projects,
|
||||
location,
|
||||
role,
|
||||
muted: true,
|
||||
speaking: false,
|
||||
video_tracks: Default::default(),
|
||||
@ -1091,15 +1123,24 @@ impl Room {
|
||||
) -> Task<Result<Model<Project>>> {
|
||||
let client = self.client.clone();
|
||||
let user_store = self.user_store.clone();
|
||||
let role = self.local_participant.role;
|
||||
cx.emit(Event::RemoteProjectJoined { project_id: id });
|
||||
cx.spawn(move |this, mut cx| async move {
|
||||
let project =
|
||||
Project::remote(id, client, user_store, language_registry, fs, cx.clone()).await?;
|
||||
let project = Project::remote(
|
||||
id,
|
||||
client,
|
||||
user_store,
|
||||
language_registry,
|
||||
fs,
|
||||
role,
|
||||
cx.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.joined_projects.retain(|project| {
|
||||
if let Some(project) = project.upgrade() {
|
||||
!project.read(cx).is_read_only()
|
||||
!project.read(cx).is_disconnected()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -1224,6 +1265,11 @@ impl Room {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn read_only(&self) -> bool {
|
||||
!(self.local_participant().role == proto::ChannelRole::Member
|
||||
|| self.local_participant().role == proto::ChannelRole::Admin)
|
||||
}
|
||||
|
||||
pub fn is_speaking(&self) -> bool {
|
||||
self.live_kit
|
||||
.as_ref()
|
||||
|
@ -62,7 +62,12 @@ impl ChannelBuffer {
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let buffer = cx.new_model(|_| {
|
||||
language::Buffer::remote(response.buffer_id, response.replica_id as u16, base_text)
|
||||
language::Buffer::remote(
|
||||
response.buffer_id,
|
||||
response.replica_id as u16,
|
||||
channel.channel_buffer_capability(),
|
||||
base_text,
|
||||
)
|
||||
})?;
|
||||
buffer.update(&mut cx, |buffer, cx| buffer.apply_ops(operations, cx))??;
|
||||
|
||||
|
@ -11,6 +11,7 @@ use gpui::{
|
||||
AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, SharedString, Task,
|
||||
WeakModel,
|
||||
};
|
||||
use language::Capability;
|
||||
use rpc::{
|
||||
proto::{self, ChannelVisibility},
|
||||
TypedEnvelope,
|
||||
@ -74,8 +75,12 @@ impl Channel {
|
||||
slug.trim_matches(|c| c == '-').to_string()
|
||||
}
|
||||
|
||||
pub fn can_edit_notes(&self) -> bool {
|
||||
self.role == proto::ChannelRole::Member || self.role == proto::ChannelRole::Admin
|
||||
pub fn channel_buffer_capability(&self) -> Capability {
|
||||
if self.role == proto::ChannelRole::Member || self.role == proto::ChannelRole::Admin {
|
||||
Capability::ReadWrite
|
||||
} else {
|
||||
Capability::ReadOnly
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathan@zed.dev>"]
|
||||
default-run = "collab"
|
||||
edition = "2021"
|
||||
name = "collab"
|
||||
version = "0.33.0"
|
||||
version = "0.34.0"
|
||||
publish = false
|
||||
|
||||
[[bin]]
|
||||
|
@ -13,6 +13,7 @@ metadata:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
|
||||
service.beta.kubernetes.io/do-loadbalancer-certificate-id: ${ZED_DO_CERTIFICATE_ID}
|
||||
service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector:
|
||||
|
@ -7,6 +7,7 @@ metadata:
|
||||
annotations:
|
||||
service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443"
|
||||
service.beta.kubernetes.io/do-loadbalancer-certificate-id: ${ZED_DO_CERTIFICATE_ID}
|
||||
service.beta.kubernetes.io/do-loadbalancer-disable-lets-encrypt-dns-records: "true"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
selector:
|
||||
|
@ -161,7 +161,8 @@ CREATE TABLE "room_participants" (
|
||||
"calling_user_id" INTEGER NOT NULL REFERENCES users (id),
|
||||
"calling_connection_id" INTEGER NOT NULL,
|
||||
"calling_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE SET NULL,
|
||||
"participant_index" INTEGER
|
||||
"participant_index" INTEGER,
|
||||
"role" TEXT
|
||||
);
|
||||
CREATE UNIQUE INDEX "index_room_participants_on_user_id" ON "room_participants" ("user_id");
|
||||
CREATE INDEX "index_room_participants_on_room_id" ON "room_participants" ("room_id");
|
||||
|
@ -0,0 +1 @@
|
||||
ALTER TABLE room_participants ADD COLUMN role TEXT;
|
@ -132,6 +132,14 @@ impl ChannelRole {
|
||||
Admin | Member | Banned => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn can_share_projects(&self) -> bool {
|
||||
use ChannelRole::*;
|
||||
match self {
|
||||
Admin | Member => true,
|
||||
Guest | Banned => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<proto::ChannelRole> for ChannelRole {
|
||||
|
@ -129,51 +129,52 @@ impl Database {
|
||||
.await?,
|
||||
);
|
||||
|
||||
debug_assert!(
|
||||
self.channel_role_for_user(&channel, user_id, &*tx).await? == role
|
||||
);
|
||||
} else if channel.visibility == ChannelVisibility::Public {
|
||||
role = Some(ChannelRole::Guest);
|
||||
let channel_to_join = self
|
||||
.public_ancestors_including_self(&channel, &*tx)
|
||||
.await?
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or(channel.clone());
|
||||
|
||||
channel_member::Entity::insert(channel_member::ActiveModel {
|
||||
id: ActiveValue::NotSet,
|
||||
channel_id: ActiveValue::Set(channel_to_join.id),
|
||||
user_id: ActiveValue::Set(user_id),
|
||||
accepted: ActiveValue::Set(true),
|
||||
role: ActiveValue::Set(ChannelRole::Guest),
|
||||
})
|
||||
.exec(&*tx)
|
||||
.await?;
|
||||
|
||||
accept_invite_result = Some(
|
||||
self.calculate_membership_updated(&channel_to_join, user_id, &*tx)
|
||||
.await?,
|
||||
);
|
||||
|
||||
debug_assert!(
|
||||
self.channel_role_for_user(&channel, user_id, &*tx).await? == role
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if channel.visibility == ChannelVisibility::Public {
|
||||
role = Some(ChannelRole::Guest);
|
||||
let channel_to_join = self
|
||||
.public_ancestors_including_self(&channel, &*tx)
|
||||
.await?
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or(channel.clone());
|
||||
|
||||
channel_member::Entity::insert(channel_member::ActiveModel {
|
||||
id: ActiveValue::NotSet,
|
||||
channel_id: ActiveValue::Set(channel_to_join.id),
|
||||
user_id: ActiveValue::Set(user_id),
|
||||
accepted: ActiveValue::Set(true),
|
||||
role: ActiveValue::Set(ChannelRole::Guest),
|
||||
})
|
||||
.exec(&*tx)
|
||||
.await?;
|
||||
|
||||
accept_invite_result = Some(
|
||||
self.calculate_membership_updated(&channel_to_join, user_id, &*tx)
|
||||
.await?,
|
||||
);
|
||||
|
||||
debug_assert!(self.channel_role_for_user(&channel, user_id, &*tx).await? == role);
|
||||
}
|
||||
|
||||
if role.is_none() || role == Some(ChannelRole::Banned) {
|
||||
Err(anyhow!("not allowed"))?
|
||||
}
|
||||
let role = role.unwrap();
|
||||
|
||||
let live_kit_room = format!("channel-{}", nanoid::nanoid!(30));
|
||||
let room_id = self
|
||||
.get_or_create_channel_room(channel_id, &live_kit_room, environment, &*tx)
|
||||
.await?;
|
||||
|
||||
self.join_channel_room_internal(room_id, user_id, connection, &*tx)
|
||||
self.join_channel_room_internal(room_id, user_id, connection, role, &*tx)
|
||||
.await
|
||||
.map(|jr| (jr, accept_invite_result, role.unwrap()))
|
||||
.map(|jr| (jr, accept_invite_result, role))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -46,6 +46,13 @@ impl Database {
|
||||
if participant.room_id != room_id {
|
||||
return Err(anyhow!("shared project on unexpected room"))?;
|
||||
}
|
||||
if !participant
|
||||
.role
|
||||
.unwrap_or(ChannelRole::Member)
|
||||
.can_share_projects()
|
||||
{
|
||||
return Err(anyhow!("guests cannot share projects"))?;
|
||||
}
|
||||
|
||||
let project = project::ActiveModel {
|
||||
room_id: ActiveValue::set(participant.room_id),
|
||||
|
@ -131,7 +131,12 @@ impl Database {
|
||||
connection.owner_id as i32,
|
||||
))),
|
||||
participant_index: ActiveValue::set(Some(0)),
|
||||
..Default::default()
|
||||
role: ActiveValue::set(Some(ChannelRole::Admin)),
|
||||
|
||||
id: ActiveValue::NotSet,
|
||||
location_kind: ActiveValue::NotSet,
|
||||
location_project_id: ActiveValue::NotSet,
|
||||
initial_project_id: ActiveValue::NotSet,
|
||||
}
|
||||
.insert(&*tx)
|
||||
.await?;
|
||||
@ -151,6 +156,22 @@ impl Database {
|
||||
initial_project_id: Option<ProjectId>,
|
||||
) -> Result<RoomGuard<(proto::Room, proto::IncomingCall)>> {
|
||||
self.room_transaction(room_id, |tx| async move {
|
||||
let caller = room_participant::Entity::find()
|
||||
.filter(
|
||||
room_participant::Column::UserId
|
||||
.eq(calling_user_id)
|
||||
.and(room_participant::Column::RoomId.eq(room_id)),
|
||||
)
|
||||
.one(&*tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("user is not in the room"))?;
|
||||
|
||||
let called_user_role = match caller.role.unwrap_or(ChannelRole::Member) {
|
||||
ChannelRole::Admin | ChannelRole::Member => ChannelRole::Member,
|
||||
ChannelRole::Guest => ChannelRole::Guest,
|
||||
ChannelRole::Banned => return Err(anyhow!("banned users cannot invite").into()),
|
||||
};
|
||||
|
||||
room_participant::ActiveModel {
|
||||
room_id: ActiveValue::set(room_id),
|
||||
user_id: ActiveValue::set(called_user_id),
|
||||
@ -162,7 +183,13 @@ impl Database {
|
||||
calling_connection.owner_id as i32,
|
||||
))),
|
||||
initial_project_id: ActiveValue::set(initial_project_id),
|
||||
..Default::default()
|
||||
role: ActiveValue::set(Some(called_user_role)),
|
||||
|
||||
id: ActiveValue::NotSet,
|
||||
answering_connection_id: ActiveValue::NotSet,
|
||||
answering_connection_server_id: ActiveValue::NotSet,
|
||||
location_kind: ActiveValue::NotSet,
|
||||
location_project_id: ActiveValue::NotSet,
|
||||
}
|
||||
.insert(&*tx)
|
||||
.await?;
|
||||
@ -384,6 +411,7 @@ impl Database {
|
||||
room_id: RoomId,
|
||||
user_id: UserId,
|
||||
connection: ConnectionId,
|
||||
role: ChannelRole,
|
||||
tx: &DatabaseTransaction,
|
||||
) -> Result<JoinRoom> {
|
||||
let participant_index = self
|
||||
@ -404,7 +432,11 @@ impl Database {
|
||||
connection.owner_id as i32,
|
||||
))),
|
||||
participant_index: ActiveValue::Set(Some(participant_index)),
|
||||
..Default::default()
|
||||
role: ActiveValue::set(Some(role)),
|
||||
id: ActiveValue::NotSet,
|
||||
location_kind: ActiveValue::NotSet,
|
||||
location_project_id: ActiveValue::NotSet,
|
||||
initial_project_id: ActiveValue::NotSet,
|
||||
}])
|
||||
.on_conflict(
|
||||
OnConflict::columns([room_participant::Column::UserId])
|
||||
@ -413,6 +445,7 @@ impl Database {
|
||||
room_participant::Column::AnsweringConnectionServerId,
|
||||
room_participant::Column::AnsweringConnectionLost,
|
||||
room_participant::Column::ParticipantIndex,
|
||||
room_participant::Column::Role,
|
||||
])
|
||||
.to_owned(),
|
||||
)
|
||||
@ -1126,6 +1159,7 @@ impl Database {
|
||||
projects: Default::default(),
|
||||
location: Some(proto::ParticipantLocation { variant: location }),
|
||||
participant_index: participant_index as u32,
|
||||
role: db_participant.role.unwrap_or(ChannelRole::Member).into(),
|
||||
},
|
||||
);
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::db::{ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
|
||||
use crate::db::{ChannelRole, ProjectId, RoomId, RoomParticipantId, ServerId, UserId};
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
@ -19,6 +19,7 @@ pub struct Model {
|
||||
pub calling_connection_id: i32,
|
||||
pub calling_connection_server_id: Option<ServerId>,
|
||||
pub participant_index: Option<i32>,
|
||||
pub role: Option<ChannelRole>,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
|
@ -2,6 +2,7 @@ use call::Room;
|
||||
use gpui::{Model, TestAppContext};
|
||||
|
||||
mod channel_buffer_tests;
|
||||
mod channel_guest_tests;
|
||||
mod channel_message_tests;
|
||||
mod channel_tests;
|
||||
mod editor_tests;
|
||||
|
86
crates/collab/src/tests/channel_guest_tests.rs
Normal file
86
crates/collab/src/tests/channel_guest_tests.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use crate::tests::TestServer;
|
||||
use call::ActiveCall;
|
||||
use gpui::{BackgroundExecutor, TestAppContext, VisualTestContext};
|
||||
use rpc::proto;
|
||||
use workspace::Workspace;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_channel_guests(
|
||||
executor: BackgroundExecutor,
|
||||
cx_a: &mut TestAppContext,
|
||||
cx_b: &mut TestAppContext,
|
||||
) {
|
||||
let mut server = TestServer::start(executor.clone()).await;
|
||||
let client_a = server.create_client(cx_a, "user_a").await;
|
||||
let client_b = server.create_client(cx_b, "user_b").await;
|
||||
|
||||
let channel_id = server
|
||||
.make_channel("the-channel", None, (&client_a, cx_a), &mut [])
|
||||
.await;
|
||||
|
||||
client_a
|
||||
.channel_store()
|
||||
.update(cx_a, |channel_store, cx| {
|
||||
channel_store.set_channel_visibility(channel_id, proto::ChannelVisibility::Public, cx)
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
client_a
|
||||
.fs()
|
||||
.insert_tree(
|
||||
"/a",
|
||||
serde_json::json!({
|
||||
"a.txt": "a-contents",
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let active_call_a = cx_a.read(ActiveCall::global);
|
||||
|
||||
// Client A shares a project in the channel
|
||||
active_call_a
|
||||
.update(cx_a, |call, cx| call.join_channel(channel_id, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
||||
let project_id = active_call_a
|
||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
cx_a.executor().run_until_parked();
|
||||
|
||||
// Client B joins channel A as a guest
|
||||
cx_b.update(|cx| workspace::join_channel(channel_id, client_b.app_state.clone(), None, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// b should be following a in the shared project.
|
||||
// B is a guest,
|
||||
cx_a.executor().run_until_parked();
|
||||
|
||||
// todo!() the test window does not call activation handlers
|
||||
// correctly yet, so this API does not work.
|
||||
// let project_b = active_call_b.read_with(cx_b, |call, _| {
|
||||
// call.location()
|
||||
// .unwrap()
|
||||
// .upgrade()
|
||||
// .expect("should not be weak")
|
||||
// });
|
||||
|
||||
let window_b = cx_b.update(|cx| cx.active_window().unwrap());
|
||||
let cx_b = &mut VisualTestContext::from_window(window_b, cx_b);
|
||||
|
||||
let workspace_b = window_b
|
||||
.downcast::<Workspace>()
|
||||
.unwrap()
|
||||
.root_view(cx_b)
|
||||
.unwrap();
|
||||
let project_b = workspace_b.update(cx_b, |workspace, _| workspace.project().clone());
|
||||
|
||||
assert_eq!(
|
||||
project_b.read_with(cx_b, |project, _| project.remote_id()),
|
||||
Some(project_id),
|
||||
);
|
||||
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()))
|
||||
}
|
@ -19,6 +19,7 @@ use project::{
|
||||
search::SearchQuery, DiagnosticSummary, FormatTrigger, HoverBlockKind, Project, ProjectPath,
|
||||
};
|
||||
use rand::prelude::*;
|
||||
use rpc::proto::ChannelRole;
|
||||
use serde_json::json;
|
||||
use settings::SettingsStore;
|
||||
use std::{
|
||||
@ -1380,7 +1381,7 @@ async fn test_unshare_project(
|
||||
.unwrap();
|
||||
executor.run_until_parked();
|
||||
|
||||
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
|
||||
assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
|
||||
|
||||
// Client C opens the project.
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
@ -1393,7 +1394,7 @@ async fn test_unshare_project(
|
||||
|
||||
assert!(worktree_a.read_with(cx_a, |tree, _| !tree.as_local().unwrap().is_shared()));
|
||||
|
||||
assert!(project_c.read_with(cx_c, |project, _| project.is_read_only()));
|
||||
assert!(project_c.read_with(cx_c, |project, _| project.is_disconnected()));
|
||||
|
||||
// Client C can open the project again after client A re-shares.
|
||||
let project_id = active_call_a
|
||||
@ -1419,7 +1420,7 @@ async fn test_unshare_project(
|
||||
project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
|
||||
|
||||
project_c2.read_with(cx_c, |project, _| {
|
||||
assert!(project.is_read_only());
|
||||
assert!(project.is_disconnected());
|
||||
assert!(project.collaborators().is_empty());
|
||||
});
|
||||
}
|
||||
@ -1551,7 +1552,7 @@ async fn test_project_reconnect(
|
||||
});
|
||||
|
||||
project_b1.read_with(cx_b, |project, _| {
|
||||
assert!(!project.is_read_only());
|
||||
assert!(!project.is_disconnected());
|
||||
assert_eq!(project.collaborators().len(), 1);
|
||||
});
|
||||
|
||||
@ -1653,7 +1654,7 @@ async fn test_project_reconnect(
|
||||
});
|
||||
|
||||
project_b1.read_with(cx_b, |project, cx| {
|
||||
assert!(!project.is_read_only());
|
||||
assert!(!project.is_disconnected());
|
||||
assert_eq!(
|
||||
project
|
||||
.worktree_for_id(worktree1_id, cx)
|
||||
@ -1687,9 +1688,9 @@ async fn test_project_reconnect(
|
||||
);
|
||||
});
|
||||
|
||||
project_b2.read_with(cx_b, |project, _| assert!(project.is_read_only()));
|
||||
project_b2.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
|
||||
|
||||
project_b3.read_with(cx_b, |project, _| assert!(!project.is_read_only()));
|
||||
project_b3.read_with(cx_b, |project, _| assert!(!project.is_disconnected()));
|
||||
|
||||
buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WaZ"));
|
||||
|
||||
@ -1746,7 +1747,7 @@ async fn test_project_reconnect(
|
||||
executor.run_until_parked();
|
||||
|
||||
project_b1.read_with(cx_b, |project, cx| {
|
||||
assert!(!project.is_read_only());
|
||||
assert!(!project.is_disconnected());
|
||||
assert_eq!(
|
||||
project
|
||||
.worktree_for_id(worktree1_id, cx)
|
||||
@ -1780,7 +1781,7 @@ async fn test_project_reconnect(
|
||||
);
|
||||
});
|
||||
|
||||
project_b3.read_with(cx_b, |project, _| assert!(project.is_read_only()));
|
||||
project_b3.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
|
||||
|
||||
buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WXaYZ"));
|
||||
|
||||
@ -3535,7 +3536,7 @@ async fn test_leaving_project(
|
||||
});
|
||||
|
||||
project_b2.read_with(cx_b, |project, _| {
|
||||
assert!(project.is_read_only());
|
||||
assert!(project.is_disconnected());
|
||||
});
|
||||
|
||||
project_c.read_with(cx_c, |project, _| {
|
||||
@ -3550,6 +3551,7 @@ async fn test_leaving_project(
|
||||
client_b.user_store().clone(),
|
||||
client_b.language_registry().clone(),
|
||||
FakeFs::new(cx.background_executor().clone()),
|
||||
ChannelRole::Member,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
@ -3568,11 +3570,11 @@ async fn test_leaving_project(
|
||||
});
|
||||
|
||||
project_b2.read_with(cx_b, |project, _| {
|
||||
assert!(project.is_read_only());
|
||||
assert!(project.is_disconnected());
|
||||
});
|
||||
|
||||
project_c.read_with(cx_c, |project, _| {
|
||||
assert!(project.is_read_only());
|
||||
assert!(project.is_disconnected());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1149,7 +1149,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
Some((project, cx))
|
||||
});
|
||||
|
||||
if !guest_project.is_read_only() {
|
||||
if !guest_project.is_disconnected() {
|
||||
if let Some((host_project, host_cx)) = host_project {
|
||||
let host_worktree_snapshots =
|
||||
host_project.read_with(host_cx, |host_project, cx| {
|
||||
@ -1236,7 +1236,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
||||
let buffers = client.buffers().clone();
|
||||
for (guest_project, guest_buffers) in &buffers {
|
||||
let project_id = if guest_project.read_with(client_cx, |project, _| {
|
||||
project.is_local() || project.is_read_only()
|
||||
project.is_local() || project.is_disconnected()
|
||||
}) {
|
||||
continue;
|
||||
} else {
|
||||
|
@ -518,7 +518,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
||||
for project in client.remote_projects().iter() {
|
||||
project.read_with(&client_cx, |project, _| {
|
||||
assert!(
|
||||
project.is_read_only(),
|
||||
project.is_disconnected(),
|
||||
"project {:?} should be read only",
|
||||
project.remote_id()
|
||||
)
|
||||
|
@ -138,12 +138,6 @@ impl ChannelView {
|
||||
editor.set_collaboration_hub(Box::new(ChannelBufferCollaborationHub(
|
||||
channel_buffer.clone(),
|
||||
)));
|
||||
editor.set_read_only(
|
||||
!channel_buffer
|
||||
.read(cx)
|
||||
.channel(cx)
|
||||
.is_some_and(|c| c.can_edit_notes()),
|
||||
);
|
||||
editor
|
||||
});
|
||||
let _editor_event_subscription =
|
||||
@ -178,8 +172,7 @@ impl ChannelView {
|
||||
cx.notify();
|
||||
}),
|
||||
ChannelBufferEvent::ChannelChanged => {
|
||||
self.editor.update(cx, |editor, cx| {
|
||||
editor.set_read_only(!self.channel(cx).is_some_and(|c| c.can_edit_notes()));
|
||||
self.editor.update(cx, |_, cx| {
|
||||
cx.emit(editor::EditorEvent::TitleChanged);
|
||||
cx.notify()
|
||||
});
|
||||
@ -254,11 +247,11 @@ impl Item for ChannelView {
|
||||
fn tab_content(&self, _: Option<usize>, selected: bool, cx: &WindowContext) -> AnyElement {
|
||||
let label = if let Some(channel) = self.channel(cx) {
|
||||
match (
|
||||
channel.can_edit_notes(),
|
||||
self.channel_buffer.read(cx).buffer().read(cx).read_only(),
|
||||
self.channel_buffer.read(cx).is_connected(),
|
||||
) {
|
||||
(true, true) => format!("#{}", channel.name),
|
||||
(false, true) => format!("#{} (read-only)", channel.name),
|
||||
(false, true) => format!("#{}", channel.name),
|
||||
(true, true) => format!("#{} (read-only)", channel.name),
|
||||
(_, false) => format!("#{} (disconnected)", channel.name),
|
||||
}
|
||||
} else {
|
||||
|
@ -607,8 +607,12 @@ impl Panel for ChatPanel {
|
||||
"ChatPanel"
|
||||
}
|
||||
|
||||
fn icon(&self, _cx: &WindowContext) -> Option<ui::Icon> {
|
||||
Some(ui::Icon::MessageBubbles)
|
||||
fn icon(&self, cx: &WindowContext) -> Option<ui::Icon> {
|
||||
if !is_channels_feature_enabled(cx) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(ui::Icon::MessageBubbles).filter(|_| ChatPanelSettings::get_global(cx).button)
|
||||
}
|
||||
|
||||
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
|
||||
|
@ -151,6 +151,10 @@ enum ListEntry {
|
||||
peer_id: Option<PeerId>,
|
||||
is_last: bool,
|
||||
},
|
||||
GuestCount {
|
||||
count: usize,
|
||||
has_visible_participants: bool,
|
||||
},
|
||||
IncomingRequest(Arc<User>),
|
||||
OutgoingRequest(Arc<User>),
|
||||
ChannelInvite(Arc<Channel>),
|
||||
@ -380,10 +384,14 @@ impl CollabPanel {
|
||||
|
||||
if !self.collapsed_sections.contains(&Section::ActiveCall) {
|
||||
let room = room.read(cx);
|
||||
let mut guest_count_ix = 0;
|
||||
let mut guest_count = if room.read_only() { 1 } else { 0 };
|
||||
let mut non_guest_count = if room.read_only() { 0 } else { 1 };
|
||||
|
||||
if let Some(channel_id) = room.channel_id() {
|
||||
self.entries.push(ListEntry::ChannelNotes { channel_id });
|
||||
self.entries.push(ListEntry::ChannelChat { channel_id })
|
||||
self.entries.push(ListEntry::ChannelChat { channel_id });
|
||||
guest_count_ix = self.entries.len();
|
||||
}
|
||||
|
||||
// Populate the active user.
|
||||
@ -402,7 +410,7 @@ impl CollabPanel {
|
||||
&Default::default(),
|
||||
executor.clone(),
|
||||
));
|
||||
if !matches.is_empty() {
|
||||
if !matches.is_empty() && !room.read_only() {
|
||||
let user_id = user.id;
|
||||
self.entries.push(ListEntry::CallParticipant {
|
||||
user,
|
||||
@ -430,13 +438,23 @@ impl CollabPanel {
|
||||
// Populate remote participants.
|
||||
self.match_candidates.clear();
|
||||
self.match_candidates
|
||||
.extend(room.remote_participants().iter().map(|(_, participant)| {
|
||||
StringMatchCandidate {
|
||||
id: participant.user.id as usize,
|
||||
string: participant.user.github_login.clone(),
|
||||
char_bag: participant.user.github_login.chars().collect(),
|
||||
}
|
||||
}));
|
||||
.extend(
|
||||
room.remote_participants()
|
||||
.iter()
|
||||
.filter_map(|(_, participant)| {
|
||||
if participant.role == proto::ChannelRole::Guest {
|
||||
guest_count += 1;
|
||||
return None;
|
||||
} else {
|
||||
non_guest_count += 1;
|
||||
}
|
||||
Some(StringMatchCandidate {
|
||||
id: participant.user.id as usize,
|
||||
string: participant.user.github_login.clone(),
|
||||
char_bag: participant.user.github_login.chars().collect(),
|
||||
})
|
||||
}),
|
||||
);
|
||||
let matches = executor.block(match_strings(
|
||||
&self.match_candidates,
|
||||
&query,
|
||||
@ -470,6 +488,15 @@ impl CollabPanel {
|
||||
});
|
||||
}
|
||||
}
|
||||
if guest_count > 0 {
|
||||
self.entries.insert(
|
||||
guest_count_ix,
|
||||
ListEntry::GuestCount {
|
||||
count: guest_count,
|
||||
has_visible_participants: non_guest_count > 0,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Populate pending participants.
|
||||
self.match_candidates.clear();
|
||||
@ -959,6 +986,41 @@ impl CollabPanel {
|
||||
.tooltip(move |cx| Tooltip::text("Open Chat", cx))
|
||||
}
|
||||
|
||||
fn render_guest_count(
|
||||
&self,
|
||||
count: usize,
|
||||
has_visible_participants: bool,
|
||||
is_selected: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> impl IntoElement {
|
||||
let manageable_channel_id = ActiveCall::global(cx).read(cx).room().and_then(|room| {
|
||||
let room = room.read(cx);
|
||||
if room.local_participant_is_admin() {
|
||||
room.channel_id()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
ListItem::new("guest_count")
|
||||
.selected(is_selected)
|
||||
.start_slot(
|
||||
h_stack()
|
||||
.gap_1()
|
||||
.child(render_tree_branch(!has_visible_participants, cx))
|
||||
.child(""),
|
||||
)
|
||||
.child(Label::new(if count == 1 {
|
||||
format!("{} guest", count)
|
||||
} else {
|
||||
format!("{} guests", count)
|
||||
}))
|
||||
.when_some(manageable_channel_id, |el, channel_id| {
|
||||
el.tooltip(move |cx| Tooltip::text("Manage Members", cx))
|
||||
.on_click(cx.listener(move |this, _, cx| this.manage_members(channel_id, cx)))
|
||||
})
|
||||
}
|
||||
|
||||
fn has_subchannels(&self, ix: usize) -> bool {
|
||||
self.entries.get(ix).map_or(false, |entry| {
|
||||
if let ListEntry::Channel { has_children, .. } = entry {
|
||||
@ -1180,6 +1242,18 @@ impl CollabPanel {
|
||||
});
|
||||
}
|
||||
}
|
||||
ListEntry::GuestCount { .. } => {
|
||||
let Some(room) = ActiveCall::global(cx).read(cx).room() else {
|
||||
return;
|
||||
};
|
||||
let room = room.read(cx);
|
||||
let Some(channel_id) = room.channel_id() else {
|
||||
return;
|
||||
};
|
||||
if room.local_participant_is_admin() {
|
||||
self.manage_members(channel_id, cx)
|
||||
}
|
||||
}
|
||||
ListEntry::Channel { channel, .. } => {
|
||||
let is_active = maybe!({
|
||||
let call_channel = ActiveCall::global(cx)
|
||||
@ -1735,6 +1809,12 @@ impl CollabPanel {
|
||||
ListEntry::ParticipantScreen { peer_id, is_last } => self
|
||||
.render_participant_screen(*peer_id, *is_last, is_selected, cx)
|
||||
.into_any_element(),
|
||||
ListEntry::GuestCount {
|
||||
count,
|
||||
has_visible_participants,
|
||||
} => self
|
||||
.render_guest_count(*count, *has_visible_participants, is_selected, cx)
|
||||
.into_any_element(),
|
||||
ListEntry::ChannelNotes { channel_id } => self
|
||||
.render_channel_notes(*channel_id, is_selected, cx)
|
||||
.into_any_element(),
|
||||
@ -1766,7 +1846,7 @@ impl CollabPanel {
|
||||
) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: if editor.read(cx).read_only() {
|
||||
color: if editor.read(cx).read_only(cx) {
|
||||
cx.theme().colors().text_disabled
|
||||
} else {
|
||||
cx.theme().colors().text
|
||||
@ -2538,6 +2618,11 @@ impl PartialEq for ListEntry {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ListEntry::GuestCount { .. } => {
|
||||
if let ListEntry::GuestCount { .. } = other {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -10,11 +10,12 @@ use gpui::{
|
||||
};
|
||||
use project::{Project, RepositoryEntry};
|
||||
use recent_projects::RecentProjects;
|
||||
use rpc::proto;
|
||||
use std::sync::Arc;
|
||||
use theme::{ActiveTheme, PlayerColors};
|
||||
use ui::{
|
||||
h_stack, popover_menu, prelude::*, Avatar, Button, ButtonLike, ButtonStyle, ContextMenu, Icon,
|
||||
IconButton, IconElement, Tooltip,
|
||||
IconButton, IconElement, TintColor, Tooltip,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use vcs_menu::{build_branch_list, BranchList, OpenRecent as ToggleVcsMenu};
|
||||
@ -175,14 +176,17 @@ impl Render for CollabTitlebarItem {
|
||||
let is_muted = room.is_muted(cx);
|
||||
let is_deafened = room.is_deafened().unwrap_or(false);
|
||||
let is_screen_sharing = room.is_screen_sharing();
|
||||
let read_only = room.read_only();
|
||||
|
||||
this.when(is_local, |this| {
|
||||
this.when(is_local && !read_only, |this| {
|
||||
this.child(
|
||||
Button::new(
|
||||
"toggle_sharing",
|
||||
if is_shared { "Unshare" } else { "Share" },
|
||||
)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.selected(is_shared)
|
||||
.label_size(LabelSize::Small)
|
||||
.on_click(cx.listener(
|
||||
move |this, _, cx| {
|
||||
@ -205,20 +209,23 @@ impl Render for CollabTitlebarItem {
|
||||
.detach_and_log_err(cx);
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
IconButton::new(
|
||||
"mute-microphone",
|
||||
if is_muted {
|
||||
ui::Icon::MicMute
|
||||
} else {
|
||||
ui::Icon::Mic
|
||||
},
|
||||
.when(!read_only, |this| {
|
||||
this.child(
|
||||
IconButton::new(
|
||||
"mute-microphone",
|
||||
if is_muted {
|
||||
ui::Icon::MicMute
|
||||
} else {
|
||||
ui::Icon::Mic
|
||||
},
|
||||
)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon_size(IconSize::Small)
|
||||
.selected(is_muted)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Negative))
|
||||
.on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
|
||||
)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon_size(IconSize::Small)
|
||||
.selected(is_muted)
|
||||
.on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
IconButton::new(
|
||||
"mute-sound",
|
||||
@ -229,22 +236,35 @@ impl Render for CollabTitlebarItem {
|
||||
},
|
||||
)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Negative))
|
||||
.icon_size(IconSize::Small)
|
||||
.selected(is_deafened)
|
||||
.tooltip(move |cx| {
|
||||
Tooltip::with_meta("Deafen Audio", None, "Mic will be muted", cx)
|
||||
if !read_only {
|
||||
Tooltip::with_meta(
|
||||
"Deafen Audio",
|
||||
None,
|
||||
"Mic will be muted",
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::text("Deafen Audio", cx)
|
||||
}
|
||||
})
|
||||
.on_click(move |_, cx| crate::toggle_mute(&Default::default(), cx)),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("screen-share", ui::Icon::Screen)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon_size(IconSize::Small)
|
||||
.selected(is_screen_sharing)
|
||||
.on_click(move |_, cx| {
|
||||
crate::toggle_screen_sharing(&Default::default(), cx)
|
||||
}),
|
||||
.on_click(move |_, cx| crate::toggle_deafen(&Default::default(), cx)),
|
||||
)
|
||||
.when(!read_only, |this| {
|
||||
this.child(
|
||||
IconButton::new("screen-share", ui::Icon::Screen)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon_size(IconSize::Small)
|
||||
.selected(is_screen_sharing)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.on_click(move |_, cx| {
|
||||
crate::toggle_screen_sharing(&Default::default(), cx)
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
.map(|el| {
|
||||
let status = self.client.status();
|
||||
@ -409,6 +429,10 @@ impl CollabTitlebarItem {
|
||||
current_user: &Arc<User>,
|
||||
cx: &ViewContext<Self>,
|
||||
) -> Option<FacePile> {
|
||||
if room.role_for_user(user.id) == Some(proto::ChannelRole::Guest) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let followers = project_id.map_or(&[] as &[_], |id| room.followers_for(peer_id, id));
|
||||
|
||||
let pile = FacePile::default()
|
||||
@ -504,8 +528,7 @@ impl CollabTitlebarItem {
|
||||
| client::Status::ReconnectionError { .. } => Some(
|
||||
div()
|
||||
.id("disconnected")
|
||||
.bg(gpui::red()) // todo!() @nate
|
||||
.child(IconElement::new(Icon::Disconnected))
|
||||
.child(IconElement::new(Icon::Disconnected).size(IconSize::Small))
|
||||
.tooltip(|cx| Tooltip::text("Disconnected", cx))
|
||||
.into_any_element(),
|
||||
),
|
||||
@ -522,9 +545,9 @@ impl CollabTitlebarItem {
|
||||
};
|
||||
|
||||
Some(
|
||||
div()
|
||||
.bg(gpui::red()) // todo!() @nate
|
||||
.child(Button::new("connection-status", label).on_click(|_, cx| {
|
||||
Button::new("connection-status", label)
|
||||
.label_size(LabelSize::Small)
|
||||
.on_click(|_, cx| {
|
||||
if let Some(auto_updater) = auto_update::AutoUpdater::get(cx) {
|
||||
if auto_updater.read(cx).status() == AutoUpdateStatus::Updated {
|
||||
workspace::restart(&Default::default(), cx);
|
||||
@ -532,7 +555,7 @@ impl CollabTitlebarItem {
|
||||
}
|
||||
}
|
||||
auto_update::check(&Default::default(), cx);
|
||||
}))
|
||||
})
|
||||
.into_any_element(),
|
||||
)
|
||||
}
|
||||
@ -542,16 +565,18 @@ impl CollabTitlebarItem {
|
||||
|
||||
pub fn render_sign_in_button(&mut self, _: &mut ViewContext<Self>) -> Button {
|
||||
let client = self.client.clone();
|
||||
Button::new("sign_in", "Sign in").on_click(move |_, cx| {
|
||||
let client = client.clone();
|
||||
cx.spawn(move |mut cx| async move {
|
||||
client
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.await
|
||||
.notify_async_err(&mut cx);
|
||||
Button::new("sign_in", "Sign in")
|
||||
.label_size(LabelSize::Small)
|
||||
.on_click(move |_, cx| {
|
||||
let client = client.clone();
|
||||
cx.spawn(move |mut cx| async move {
|
||||
client
|
||||
.authenticate_and_connect(true, &cx)
|
||||
.await
|
||||
.notify_async_err(&mut cx);
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
.detach();
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render_user_menu_button(&mut self, cx: &mut ViewContext<Self>) -> impl Element {
|
||||
|
@ -151,7 +151,12 @@ impl ProjectDiagnosticsEditor {
|
||||
let focus_in_subscription =
|
||||
cx.on_focus_in(&focus_handle, |diagnostics, cx| diagnostics.focus_in(cx));
|
||||
|
||||
let excerpts = cx.new_model(|cx| MultiBuffer::new(project_handle.read(cx).replica_id()));
|
||||
let excerpts = cx.new_model(|cx| {
|
||||
MultiBuffer::new(
|
||||
project_handle.read(cx).replica_id(),
|
||||
project_handle.read(cx).capability(),
|
||||
)
|
||||
});
|
||||
let editor = cx.new_view(|cx| {
|
||||
let mut editor =
|
||||
Editor::for_multibuffer(excerpts.clone(), Some(project_handle.clone()), cx);
|
||||
@ -1572,6 +1577,7 @@ mod tests {
|
||||
workspace::init_settings(cx);
|
||||
Project::init_settings(cx);
|
||||
crate::init(cx);
|
||||
editor::init(cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -54,10 +54,10 @@ use itertools::Itertools;
|
||||
pub use language::{char_kind, CharKind};
|
||||
use language::{
|
||||
language_settings::{self, all_language_settings, InlayHintSettings},
|
||||
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel,
|
||||
Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language,
|
||||
LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection, SelectionGoal,
|
||||
TransactionId,
|
||||
markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CodeAction,
|
||||
CodeLabel, Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize,
|
||||
Language, LanguageRegistry, LanguageServerName, OffsetRangeExt, Point, Selection,
|
||||
SelectionGoal, TransactionId,
|
||||
};
|
||||
|
||||
use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
|
||||
@ -2049,8 +2049,8 @@ impl Editor {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_only(&self) -> bool {
|
||||
self.read_only
|
||||
pub fn read_only(&self, cx: &AppContext) -> bool {
|
||||
self.read_only || self.buffer.read(cx).read_only()
|
||||
}
|
||||
|
||||
pub fn set_read_only(&mut self, read_only: bool) {
|
||||
@ -2199,7 +2199,7 @@ impl Editor {
|
||||
S: ToOffset,
|
||||
T: Into<Arc<str>>,
|
||||
{
|
||||
if self.read_only {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2213,7 +2213,7 @@ impl Editor {
|
||||
S: ToOffset,
|
||||
T: Into<Arc<str>>,
|
||||
{
|
||||
if self.read_only {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2232,7 +2232,7 @@ impl Editor {
|
||||
S: ToOffset,
|
||||
T: Into<Arc<str>>,
|
||||
{
|
||||
if self.read_only {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2596,7 +2596,7 @@ impl Editor {
|
||||
pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
|
||||
let text: Arc<str> = text.into();
|
||||
|
||||
if self.read_only {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3049,7 +3049,7 @@ impl Editor {
|
||||
autoindent_mode: Option<AutoindentMode>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
if self.read_only {
|
||||
if self.read_only(cx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3786,7 +3786,8 @@ impl Editor {
|
||||
|
||||
let mut ranges_to_highlight = Vec::new();
|
||||
let excerpt_buffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
|
||||
let mut multibuffer =
|
||||
MultiBuffer::new(replica_id, Capability::ReadWrite).with_title(title);
|
||||
for (buffer_handle, transaction) in &entries {
|
||||
let buffer = buffer_handle.read(cx);
|
||||
ranges_to_highlight.extend(
|
||||
@ -7491,9 +7492,10 @@ impl Editor {
|
||||
locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
|
||||
let mut locations = locations.into_iter().peekable();
|
||||
let mut ranges_to_highlight = Vec::new();
|
||||
let capability = workspace.project().read(cx).capability();
|
||||
|
||||
let excerpt_buffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(replica_id);
|
||||
let mut multibuffer = MultiBuffer::new(replica_id, capability);
|
||||
while let Some(location) = locations.next() {
|
||||
let buffer = location.buffer.read(cx);
|
||||
let mut ranges_for_buffer = Vec::new();
|
||||
@ -8608,7 +8610,8 @@ impl Editor {
|
||||
}
|
||||
|
||||
pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
|
||||
self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
|
||||
(self.read_only(cx) || self.blink_manager.read(cx).visible())
|
||||
&& self.focus_handle.is_focused(cx)
|
||||
}
|
||||
|
||||
fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
|
||||
|
@ -17,8 +17,9 @@ use gpui::{
|
||||
use indoc::indoc;
|
||||
use language::{
|
||||
language_settings::{AllLanguageSettings, AllLanguageSettingsContent, LanguageSettingsContent},
|
||||
BracketPairConfig, FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry,
|
||||
Override, Point,
|
||||
BracketPairConfig,
|
||||
Capability::ReadWrite,
|
||||
FakeLspAdapter, LanguageConfig, LanguageConfigOverride, LanguageRegistry, Override, Point,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use project::project_settings::{LspSettings, ProjectSettings};
|
||||
@ -2355,7 +2356,7 @@ fn test_indent_outdent_with_excerpts(cx: &mut TestAppContext) {
|
||||
.with_language(rust_language, cx)
|
||||
});
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
toml_buffer.clone(),
|
||||
[ExcerptRange {
|
||||
@ -6019,7 +6020,7 @@ fn test_editing_disjoint_excerpts(cx: &mut TestAppContext) {
|
||||
|
||||
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer.clone(),
|
||||
[
|
||||
@ -6103,7 +6104,7 @@ fn test_editing_overlapping_excerpts(cx: &mut TestAppContext) {
|
||||
});
|
||||
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), initial_text));
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(buffer, excerpt_ranges, cx);
|
||||
multibuffer
|
||||
});
|
||||
@ -6162,7 +6163,7 @@ fn test_refresh_selections(cx: &mut TestAppContext) {
|
||||
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
|
||||
let mut excerpt1_id = None;
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
excerpt1_id = multibuffer
|
||||
.push_excerpts(
|
||||
buffer.clone(),
|
||||
@ -6247,7 +6248,7 @@ fn test_refresh_selections_while_selecting_with_mouse(cx: &mut TestAppContext) {
|
||||
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(3, 4, 'a')));
|
||||
let mut excerpt1_id = None;
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
excerpt1_id = multibuffer
|
||||
.push_excerpts(
|
||||
buffer.clone(),
|
||||
@ -6636,7 +6637,7 @@ async fn test_following_with_multiple_excerpts(cx: &mut gpui::TestAppContext) {
|
||||
let cx = &mut VisualTestContext::from_window(*workspace.deref(), cx);
|
||||
|
||||
let leader = pane.update(cx, |_, cx| {
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, ReadWrite));
|
||||
cx.new_view(|cx| build_editor(multibuffer.clone(), cx))
|
||||
});
|
||||
|
||||
@ -7425,7 +7426,7 @@ async fn test_copilot_multibuffer(executor: BackgroundExecutor, cx: &mut gpui::T
|
||||
let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "a = 1\nb = 2\n"));
|
||||
let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "c = 3\nd = 4\n"));
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer_1.clone(),
|
||||
[ExcerptRange {
|
||||
@ -7552,7 +7553,7 @@ async fn test_copilot_disabled_globs(executor: BackgroundExecutor, cx: &mut gpui
|
||||
.unwrap();
|
||||
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
private_buffer.clone(),
|
||||
[ExcerptRange {
|
||||
|
@ -1910,7 +1910,13 @@ impl EditorElement {
|
||||
layouts.push(layout);
|
||||
}
|
||||
|
||||
selections.push((style.local_player, layouts));
|
||||
let player = if editor.read_only(cx) {
|
||||
cx.theme().players().read_only()
|
||||
} else {
|
||||
style.local_player
|
||||
};
|
||||
|
||||
selections.push((player, layouts));
|
||||
}
|
||||
|
||||
if let Some(collaboration_hub) = &editor.collaboration_hub {
|
||||
|
@ -93,6 +93,7 @@ mod tests {
|
||||
use crate::editor_tests::init_test;
|
||||
use crate::Point;
|
||||
use gpui::{Context, TestAppContext};
|
||||
use language::Capability::ReadWrite;
|
||||
use multi_buffer::{ExcerptRange, MultiBuffer};
|
||||
use project::{FakeFs, Project};
|
||||
use unindent::Unindent;
|
||||
@ -183,7 +184,7 @@ mod tests {
|
||||
cx.background_executor.run_until_parked();
|
||||
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer_1.clone(),
|
||||
[
|
||||
|
@ -515,34 +515,28 @@ impl DiagnosticPopover {
|
||||
};
|
||||
|
||||
struct DiagnosticColors {
|
||||
pub text: Hsla,
|
||||
pub background: Hsla,
|
||||
pub border: Hsla,
|
||||
}
|
||||
|
||||
let diagnostic_colors = match self.local_diagnostic.diagnostic.severity {
|
||||
DiagnosticSeverity::ERROR => DiagnosticColors {
|
||||
text: style.status.error,
|
||||
background: style.status.error_background,
|
||||
border: style.status.error_border,
|
||||
},
|
||||
DiagnosticSeverity::WARNING => DiagnosticColors {
|
||||
text: style.status.warning,
|
||||
background: style.status.warning_background,
|
||||
border: style.status.warning_border,
|
||||
},
|
||||
DiagnosticSeverity::INFORMATION => DiagnosticColors {
|
||||
text: style.status.info,
|
||||
background: style.status.info_background,
|
||||
border: style.status.info_border,
|
||||
},
|
||||
DiagnosticSeverity::HINT => DiagnosticColors {
|
||||
text: style.status.hint,
|
||||
background: style.status.hint_background,
|
||||
border: style.status.hint_border,
|
||||
},
|
||||
_ => DiagnosticColors {
|
||||
text: style.status.ignored,
|
||||
background: style.status.ignored_background,
|
||||
border: style.status.ignored_border,
|
||||
},
|
||||
@ -554,7 +548,7 @@ impl DiagnosticPopover {
|
||||
.px_2()
|
||||
.py_1()
|
||||
.bg(diagnostic_colors.background)
|
||||
.text_color(diagnostic_colors.text)
|
||||
.text_color(style.text.color)
|
||||
.border_1()
|
||||
.border_color(diagnostic_colors.border)
|
||||
.rounded_md()
|
||||
|
@ -1206,7 +1206,8 @@ pub mod tests {
|
||||
use gpui::{Context, TestAppContext, WindowHandle};
|
||||
use itertools::Itertools;
|
||||
use language::{
|
||||
language_settings::AllLanguageSettingsContent, FakeLspAdapter, Language, LanguageConfig,
|
||||
language_settings::AllLanguageSettingsContent, Capability, FakeLspAdapter, Language,
|
||||
LanguageConfig,
|
||||
};
|
||||
use lsp::FakeLanguageServer;
|
||||
use parking_lot::Mutex;
|
||||
@ -2459,7 +2460,7 @@ pub mod tests {
|
||||
.await
|
||||
.unwrap();
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer_1.clone(),
|
||||
[
|
||||
@ -2798,7 +2799,7 @@ pub mod tests {
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let (buffer_1_excerpts, buffer_2_excerpts) = multibuffer.update(cx, |multibuffer, cx| {
|
||||
let buffer_1_excerpts = multibuffer.push_excerpts(
|
||||
buffer_1.clone(),
|
||||
|
@ -103,7 +103,8 @@ impl FollowableItem for Editor {
|
||||
if state.singleton && buffers.len() == 1 {
|
||||
multibuffer = MultiBuffer::singleton(buffers.pop().unwrap(), cx)
|
||||
} else {
|
||||
multibuffer = MultiBuffer::new(replica_id);
|
||||
multibuffer =
|
||||
MultiBuffer::new(replica_id, project.read(cx).capability());
|
||||
let mut excerpts = state.excerpts.into_iter().peekable();
|
||||
while let Some(excerpt) = excerpts.peek() {
|
||||
let buffer_id = excerpt.buffer_id;
|
||||
|
@ -930,10 +930,7 @@ mod tests {
|
||||
fn do_work() { «test»(); }
|
||||
"});
|
||||
|
||||
// Deactivating the window dismisses the highlight
|
||||
cx.update_workspace(|workspace, cx| {
|
||||
workspace.on_window_activation_changed(cx);
|
||||
});
|
||||
cx.cx.cx.deactivate_window();
|
||||
cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
|
||||
fn test() { do_work(); }
|
||||
fn do_work() { test(); }
|
||||
|
@ -461,6 +461,7 @@ mod tests {
|
||||
Buffer, DisplayMap, ExcerptRange, InlayId, MultiBuffer,
|
||||
};
|
||||
use gpui::{font, Context as _};
|
||||
use language::Capability;
|
||||
use project::Project;
|
||||
use settings::SettingsStore;
|
||||
use util::post_inc;
|
||||
@ -766,7 +767,7 @@ mod tests {
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abc\ndefg\nhijkl\nmn"));
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer.clone(),
|
||||
[
|
||||
|
@ -17,7 +17,7 @@ use regex::Regex;
|
||||
use serde_derive::Serialize;
|
||||
use ui::{prelude::*, Button, ButtonStyle, IconPosition, Tooltip};
|
||||
use util::ResultExt;
|
||||
use workspace::{ModalView, Workspace};
|
||||
use workspace::{ModalView, Toast, Workspace};
|
||||
|
||||
use crate::{system_specs::SystemSpecs, GiveFeedback, OpenZedCommunityRepo};
|
||||
|
||||
@ -125,6 +125,20 @@ impl FeedbackModal {
|
||||
.language_for_name("Markdown");
|
||||
|
||||
let project = workspace.project().clone();
|
||||
let is_local_project = project.read(cx).is_local();
|
||||
|
||||
if !is_local_project {
|
||||
const TOAST_ID: usize = 0xdeadbeef;
|
||||
|
||||
workspace.show_toast(
|
||||
Toast::new(
|
||||
TOAST_ID,
|
||||
"You can only submit feedback in your own project.",
|
||||
),
|
||||
cx,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
cx.spawn(|workspace, mut cx| async move {
|
||||
let markdown = markdown.await.log_err();
|
||||
|
@ -18,7 +18,6 @@ collections = { path = "../collections" }
|
||||
gpui_macros = { path = "../gpui_macros" }
|
||||
util = { path = "../util" }
|
||||
sum_tree = { path = "../sum_tree" }
|
||||
sqlez = { path = "../sqlez" }
|
||||
async-task = "4.7"
|
||||
backtrace = { version = "0.3", optional = true }
|
||||
ctor.workspace = true
|
||||
|
@ -1,14 +1,13 @@
|
||||
use crate::{
|
||||
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
||||
BackgroundExecutor, Bounds, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
|
||||
InputEvent, IntoElement, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
|
||||
PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
|
||||
TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext,
|
||||
WindowHandle, WindowOptions,
|
||||
BackgroundExecutor, ClipboardItem, Context, Entity, EventEmitter, ForegroundExecutor,
|
||||
IntoElement, Keystroke, Model, ModelContext, Pixels, Platform, Render, Result, Size, Task,
|
||||
TestDispatcher, TestPlatform, TestWindow, TextSystem, View, ViewContext, VisualContext,
|
||||
WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
use futures::{Stream, StreamExt};
|
||||
use std::{future::Future, mem, ops::Deref, rc::Rc, sync::Arc, time::Duration};
|
||||
use std::{future::Future, ops::Deref, rc::Rc, sync::Arc, time::Duration};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TestAppContext {
|
||||
@ -185,42 +184,7 @@ impl TestAppContext {
|
||||
}
|
||||
|
||||
pub fn simulate_window_resize(&self, window_handle: AnyWindowHandle, size: Size<Pixels>) {
|
||||
let (mut handlers, scale_factor) = self
|
||||
.app
|
||||
.borrow_mut()
|
||||
.update_window(window_handle, |_, cx| {
|
||||
let platform_window = cx.window.platform_window.as_test().unwrap();
|
||||
let scale_factor = platform_window.scale_factor();
|
||||
match &mut platform_window.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => {
|
||||
platform_window.bounds = WindowBounds::Fixed(Bounds {
|
||||
origin: Point::default(),
|
||||
size: size.map(|pixels| f64::from(pixels).into()),
|
||||
});
|
||||
}
|
||||
WindowBounds::Fixed(bounds) => {
|
||||
bounds.size = size.map(|pixels| f64::from(pixels).into());
|
||||
}
|
||||
}
|
||||
|
||||
(
|
||||
mem::take(&mut platform_window.handlers.lock().resize),
|
||||
scale_factor,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
for handler in &mut handlers {
|
||||
handler(size, scale_factor);
|
||||
}
|
||||
|
||||
self.app
|
||||
.borrow_mut()
|
||||
.update_window(window_handle, |_, cx| {
|
||||
let platform_window = cx.window.platform_window.as_test().unwrap();
|
||||
platform_window.handlers.lock().resize = handlers;
|
||||
})
|
||||
.unwrap();
|
||||
self.test_window(window_handle).simulate_resize(size);
|
||||
}
|
||||
|
||||
pub fn spawn<Fut, R>(&self, f: impl FnOnce(AsyncAppContext) -> Fut) -> Task<R>
|
||||
@ -313,41 +277,22 @@ impl TestAppContext {
|
||||
keystroke: Keystroke,
|
||||
is_held: bool,
|
||||
) {
|
||||
let keystroke2 = keystroke.clone();
|
||||
let handled = window
|
||||
.update(self, |_, cx| {
|
||||
cx.dispatch_event(InputEvent::KeyDown(KeyDownEvent { keystroke, is_held }))
|
||||
})
|
||||
.is_ok_and(|handled| handled);
|
||||
if handled {
|
||||
return;
|
||||
}
|
||||
|
||||
let input_handler = self.update_test_window(window, |window| window.input_handler.clone());
|
||||
let Some(input_handler) = input_handler else {
|
||||
panic!(
|
||||
"dispatch_keystroke {:?} failed to dispatch action or input",
|
||||
&keystroke2
|
||||
);
|
||||
};
|
||||
let text = keystroke2.ime_key.unwrap_or(keystroke2.key);
|
||||
input_handler.lock().replace_text_in_range(None, &text);
|
||||
self.test_window(window)
|
||||
.simulate_keystroke(keystroke, is_held)
|
||||
}
|
||||
|
||||
pub fn update_test_window<R>(
|
||||
&mut self,
|
||||
window: AnyWindowHandle,
|
||||
f: impl FnOnce(&mut TestWindow) -> R,
|
||||
) -> R {
|
||||
window
|
||||
.update(self, |_, cx| {
|
||||
f(cx.window
|
||||
.platform_window
|
||||
.as_any_mut()
|
||||
.downcast_mut::<TestWindow>()
|
||||
.unwrap())
|
||||
})
|
||||
pub fn test_window(&self, window: AnyWindowHandle) -> TestWindow {
|
||||
self.app
|
||||
.borrow_mut()
|
||||
.windows
|
||||
.get_mut(window.id)
|
||||
.unwrap()
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.platform_window
|
||||
.as_test()
|
||||
.unwrap()
|
||||
.clone()
|
||||
}
|
||||
|
||||
pub fn notifications<T: 'static>(&mut self, entity: &impl Entity<T>) -> impl Stream<Item = ()> {
|
||||
@ -563,11 +508,7 @@ impl<'a> VisualTestContext<'a> {
|
||||
}
|
||||
|
||||
pub fn window_title(&mut self) -> Option<String> {
|
||||
self.cx
|
||||
.update_window(self.window, |_, cx| {
|
||||
cx.window.platform_window.as_test().unwrap().title.clone()
|
||||
})
|
||||
.unwrap()
|
||||
self.cx.test_window(self.window).0.lock().title.clone()
|
||||
}
|
||||
|
||||
pub fn simulate_keystrokes(&mut self, keystrokes: &str) {
|
||||
@ -578,37 +519,11 @@ impl<'a> VisualTestContext<'a> {
|
||||
self.cx.simulate_input(self.window, input)
|
||||
}
|
||||
|
||||
pub fn simulate_activation(&mut self) {
|
||||
self.simulate_window_events(&mut |handlers| {
|
||||
handlers
|
||||
.active_status_change
|
||||
.iter_mut()
|
||||
.for_each(|f| f(true));
|
||||
})
|
||||
}
|
||||
|
||||
pub fn simulate_deactivation(&mut self) {
|
||||
self.simulate_window_events(&mut |handlers| {
|
||||
handlers
|
||||
.active_status_change
|
||||
.iter_mut()
|
||||
.for_each(|f| f(false));
|
||||
})
|
||||
}
|
||||
|
||||
fn simulate_window_events(&mut self, f: &mut dyn FnMut(&mut TestWindowHandlers)) {
|
||||
let handlers = self
|
||||
.cx
|
||||
.update_window(self.window, |_, cx| {
|
||||
cx.window
|
||||
.platform_window
|
||||
.as_test()
|
||||
.unwrap()
|
||||
.handlers
|
||||
.clone()
|
||||
})
|
||||
.unwrap();
|
||||
f(&mut *handlers.lock());
|
||||
pub fn deactivate_window(&mut self) {
|
||||
if Some(self.window) == self.test_platform.active_window() {
|
||||
self.test_platform.set_active_window(None)
|
||||
}
|
||||
self.background_executor.run_until_parked();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -339,6 +339,15 @@ impl Hsla {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn grayscale(&self) -> Self {
|
||||
Hsla {
|
||||
h: self.h,
|
||||
s: 0.,
|
||||
l: self.l,
|
||||
a: self.a,
|
||||
}
|
||||
}
|
||||
|
||||
/// Fade out the color by a given factor. This factor should be between 0.0 and 1.0.
|
||||
/// Where 0.0 will leave the color unchanged, and 1.0 will completely fade out the color.
|
||||
pub fn fade_out(&mut self, factor: f32) {
|
||||
|
@ -44,8 +44,9 @@ pub trait IntoElement: Sized {
|
||||
}
|
||||
|
||||
/// Convert into an element, then draw in the current window at the given origin.
|
||||
/// The provided available space is provided to the layout engine to determine the size of the root element.
|
||||
/// Once the element is drawn, its associated element staet is yielded to the given callback.
|
||||
/// The available space argument is provided to the layout engine to determine the size of the
|
||||
// root element. Once the element is drawn, its associated element state is yielded to the
|
||||
// given callback.
|
||||
fn draw_and_update_state<T, R>(
|
||||
self,
|
||||
origin: Point<Pixels>,
|
||||
|
@ -31,39 +31,6 @@ pub trait Along {
|
||||
fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self;
|
||||
}
|
||||
|
||||
impl sqlez::bindable::StaticColumnCount for Axis {}
|
||||
impl sqlez::bindable::Bind for Axis {
|
||||
fn bind(
|
||||
&self,
|
||||
statement: &sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<i32> {
|
||||
match self {
|
||||
Axis::Horizontal => "Horizontal",
|
||||
Axis::Vertical => "Vertical",
|
||||
}
|
||||
.bind(statement, start_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlez::bindable::Column for Axis {
|
||||
fn column(
|
||||
statement: &mut sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<(Self, i32)> {
|
||||
String::column(statement, start_index).and_then(|(axis_text, next_index)| {
|
||||
Ok((
|
||||
match axis_text.as_str() {
|
||||
"Horizontal" => Axis::Horizontal,
|
||||
"Vertical" => Axis::Vertical,
|
||||
_ => anyhow::bail!("Stored serialized item kind is incorrect"),
|
||||
},
|
||||
next_index,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes a location in a 2D cartesian coordinate space.
|
||||
///
|
||||
/// It holds two public fields, `x` and `y`, which represent the coordinates in the space.
|
||||
@ -2296,18 +2263,6 @@ impl From<f64> for GlobalPixels {
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlez::bindable::StaticColumnCount for GlobalPixels {}
|
||||
|
||||
impl sqlez::bindable::Bind for GlobalPixels {
|
||||
fn bind(
|
||||
&self,
|
||||
statement: &sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<i32> {
|
||||
self.0.bind(statement, start_index)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with [WindowContext::set_rem_size].
|
||||
///
|
||||
/// Rems are used for defining lengths that are scalable and consistent across different UI elements.
|
||||
|
@ -6,19 +6,17 @@ mod mac;
|
||||
mod test;
|
||||
|
||||
use crate::{
|
||||
point, size, Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId,
|
||||
FontMetrics, FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap,
|
||||
LineLayout, Pixels, Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result,
|
||||
Scene, SharedString, Size, TaskLabel,
|
||||
Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, FontMetrics,
|
||||
FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap, LineLayout, Pixels,
|
||||
Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, Scene, SharedString,
|
||||
Size, TaskLabel,
|
||||
};
|
||||
use anyhow::{anyhow, bail};
|
||||
use anyhow::anyhow;
|
||||
use async_task::Runnable;
|
||||
use futures::channel::oneshot;
|
||||
use parking::Unparker;
|
||||
use seahash::SeaHasher;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlez::bindable::{Bind, Column, StaticColumnCount};
|
||||
use sqlez::statement::Statement;
|
||||
use std::borrow::Cow;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::time::Duration;
|
||||
@ -396,67 +394,6 @@ pub enum WindowBounds {
|
||||
Fixed(Bounds<GlobalPixels>),
|
||||
}
|
||||
|
||||
impl StaticColumnCount for WindowBounds {
|
||||
fn column_count() -> usize {
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
impl Bind for WindowBounds {
|
||||
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||
let (region, next_index) = match self {
|
||||
WindowBounds::Fullscreen => {
|
||||
let next_index = statement.bind(&"Fullscreen", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Maximized => {
|
||||
let next_index = statement.bind(&"Maximized", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Fixed(region) => {
|
||||
let next_index = statement.bind(&"Fixed", start_index)?;
|
||||
(Some(*region), next_index)
|
||||
}
|
||||
};
|
||||
|
||||
statement.bind(
|
||||
®ion.map(|region| {
|
||||
(
|
||||
region.origin.x,
|
||||
region.origin.y,
|
||||
region.size.width,
|
||||
region.size.height,
|
||||
)
|
||||
}),
|
||||
next_index,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Column for WindowBounds {
|
||||
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
|
||||
let (window_state, next_index) = String::column(statement, start_index)?;
|
||||
let bounds = match window_state.as_str() {
|
||||
"Fullscreen" => WindowBounds::Fullscreen,
|
||||
"Maximized" => WindowBounds::Maximized,
|
||||
"Fixed" => {
|
||||
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
|
||||
let x: f64 = x;
|
||||
let y: f64 = y;
|
||||
let width: f64 = width;
|
||||
let height: f64 = height;
|
||||
WindowBounds::Fixed(Bounds {
|
||||
origin: point(x.into(), y.into()),
|
||||
size: size(width.into(), height.into()),
|
||||
})
|
||||
}
|
||||
_ => bail!("Window State did not have a valid string"),
|
||||
};
|
||||
|
||||
Ok((bounds, next_index + 4))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum WindowAppearance {
|
||||
Light,
|
||||
|
@ -19,7 +19,7 @@ pub struct TestPlatform {
|
||||
background_executor: BackgroundExecutor,
|
||||
foreground_executor: ForegroundExecutor,
|
||||
|
||||
active_window: Arc<Mutex<Option<AnyWindowHandle>>>,
|
||||
pub(crate) active_window: RefCell<Option<TestWindow>>,
|
||||
active_display: Rc<dyn PlatformDisplay>,
|
||||
active_cursor: Mutex<CursorStyle>,
|
||||
current_clipboard_item: Mutex<Option<ClipboardItem>>,
|
||||
@ -79,6 +79,28 @@ impl TestPlatform {
|
||||
self.prompts.borrow_mut().multiple_choice.push_back(tx);
|
||||
rx
|
||||
}
|
||||
|
||||
pub(crate) fn set_active_window(&self, window: Option<TestWindow>) {
|
||||
let executor = self.foreground_executor().clone();
|
||||
let previous_window = self.active_window.borrow_mut().take();
|
||||
*self.active_window.borrow_mut() = window.clone();
|
||||
|
||||
executor
|
||||
.spawn(async move {
|
||||
if let Some(previous_window) = previous_window {
|
||||
if let Some(window) = window.as_ref() {
|
||||
if Arc::ptr_eq(&previous_window.0, &window.0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
previous_window.simulate_active_status_change(false);
|
||||
}
|
||||
if let Some(window) = window {
|
||||
window.simulate_active_status_change(true);
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
// todo!("implement out what our tests needed in GPUI 1")
|
||||
@ -106,7 +128,7 @@ impl Platform for TestPlatform {
|
||||
}
|
||||
|
||||
fn activate(&self, _ignoring_other_apps: bool) {
|
||||
unimplemented!()
|
||||
//
|
||||
}
|
||||
|
||||
fn hide(&self) {
|
||||
@ -130,7 +152,10 @@ impl Platform for TestPlatform {
|
||||
}
|
||||
|
||||
fn active_window(&self) -> Option<crate::AnyWindowHandle> {
|
||||
self.active_window.lock().clone()
|
||||
self.active_window
|
||||
.borrow()
|
||||
.as_ref()
|
||||
.map(|window| window.0.lock().handle)
|
||||
}
|
||||
|
||||
fn open_window(
|
||||
@ -139,12 +164,13 @@ impl Platform for TestPlatform {
|
||||
options: WindowOptions,
|
||||
_draw: Box<dyn FnMut() -> Result<Scene>>,
|
||||
) -> Box<dyn crate::PlatformWindow> {
|
||||
*self.active_window.lock() = Some(handle);
|
||||
Box::new(TestWindow::new(
|
||||
let window = TestWindow::new(
|
||||
options,
|
||||
handle,
|
||||
self.weak.clone(),
|
||||
self.active_display.clone(),
|
||||
))
|
||||
);
|
||||
Box::new(window)
|
||||
}
|
||||
|
||||
fn set_display_link_output_callback(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
px, AtlasKey, AtlasTextureId, AtlasTile, Pixels, PlatformAtlas, PlatformDisplay,
|
||||
PlatformInputHandler, PlatformWindow, Point, Size, TestPlatform, TileId, WindowAppearance,
|
||||
WindowBounds, WindowOptions,
|
||||
px, AnyWindowHandle, AtlasKey, AtlasTextureId, AtlasTile, Bounds, InputEvent, KeyDownEvent,
|
||||
Keystroke, Pixels, PlatformAtlas, PlatformDisplay, PlatformInputHandler, PlatformWindow, Point,
|
||||
Size, TestPlatform, TileId, WindowAppearance, WindowBounds, WindowOptions,
|
||||
};
|
||||
use collections::HashMap;
|
||||
use parking_lot::Mutex;
|
||||
@ -10,51 +10,122 @@ use std::{
|
||||
sync::{self, Arc},
|
||||
};
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct TestWindowHandlers {
|
||||
pub(crate) active_status_change: Vec<Box<dyn FnMut(bool)>>,
|
||||
pub(crate) input: Vec<Box<dyn FnMut(crate::InputEvent) -> bool>>,
|
||||
pub(crate) moved: Vec<Box<dyn FnMut()>>,
|
||||
pub(crate) resize: Vec<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||
}
|
||||
|
||||
pub struct TestWindow {
|
||||
pub struct TestWindowState {
|
||||
pub(crate) bounds: WindowBounds,
|
||||
pub(crate) handle: AnyWindowHandle,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
pub(crate) title: Option<String>,
|
||||
pub(crate) edited: bool,
|
||||
pub(crate) input_handler: Option<Arc<Mutex<Box<dyn PlatformInputHandler>>>>,
|
||||
pub(crate) handlers: Arc<Mutex<TestWindowHandlers>>,
|
||||
platform: Weak<TestPlatform>,
|
||||
sprite_atlas: Arc<dyn PlatformAtlas>,
|
||||
|
||||
input_callback: Option<Box<dyn FnMut(InputEvent) -> bool>>,
|
||||
active_status_change_callback: Option<Box<dyn FnMut(bool)>>,
|
||||
resize_callback: Option<Box<dyn FnMut(Size<Pixels>, f32)>>,
|
||||
moved_callback: Option<Box<dyn FnMut()>>,
|
||||
input_handler: Option<Box<dyn PlatformInputHandler>>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TestWindow(pub(crate) Arc<Mutex<TestWindowState>>);
|
||||
|
||||
impl TestWindow {
|
||||
pub fn new(
|
||||
options: WindowOptions,
|
||||
handle: AnyWindowHandle,
|
||||
platform: Weak<TestPlatform>,
|
||||
display: Rc<dyn PlatformDisplay>,
|
||||
) -> Self {
|
||||
Self {
|
||||
Self(Arc::new(Mutex::new(TestWindowState {
|
||||
bounds: options.bounds,
|
||||
display,
|
||||
platform,
|
||||
input_handler: None,
|
||||
handle,
|
||||
sprite_atlas: Arc::new(TestAtlas::new()),
|
||||
handlers: Default::default(),
|
||||
title: Default::default(),
|
||||
edited: false,
|
||||
|
||||
input_callback: None,
|
||||
active_status_change_callback: None,
|
||||
resize_callback: None,
|
||||
moved_callback: None,
|
||||
input_handler: None,
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn simulate_resize(&mut self, size: Size<Pixels>) {
|
||||
let scale_factor = self.scale_factor();
|
||||
let mut lock = self.0.lock();
|
||||
let Some(mut callback) = lock.resize_callback.take() else {
|
||||
return;
|
||||
};
|
||||
match &mut lock.bounds {
|
||||
WindowBounds::Fullscreen | WindowBounds::Maximized => {
|
||||
lock.bounds = WindowBounds::Fixed(Bounds {
|
||||
origin: Point::default(),
|
||||
size: size.map(|pixels| f64::from(pixels).into()),
|
||||
});
|
||||
}
|
||||
WindowBounds::Fixed(bounds) => {
|
||||
bounds.size = size.map(|pixels| f64::from(pixels).into());
|
||||
}
|
||||
}
|
||||
drop(lock);
|
||||
callback(size, scale_factor);
|
||||
self.0.lock().resize_callback = Some(callback);
|
||||
}
|
||||
|
||||
pub(crate) fn simulate_active_status_change(&self, active: bool) {
|
||||
let mut lock = self.0.lock();
|
||||
let Some(mut callback) = lock.active_status_change_callback.take() else {
|
||||
return;
|
||||
};
|
||||
drop(lock);
|
||||
callback(active);
|
||||
self.0.lock().active_status_change_callback = Some(callback);
|
||||
}
|
||||
|
||||
pub fn simulate_input(&mut self, event: InputEvent) -> bool {
|
||||
let mut lock = self.0.lock();
|
||||
let Some(mut callback) = lock.input_callback.take() else {
|
||||
return false;
|
||||
};
|
||||
drop(lock);
|
||||
let result = callback(event);
|
||||
self.0.lock().input_callback = Some(callback);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn simulate_keystroke(&mut self, keystroke: Keystroke, is_held: bool) {
|
||||
if self.simulate_input(InputEvent::KeyDown(KeyDownEvent {
|
||||
keystroke: keystroke.clone(),
|
||||
is_held,
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut lock = self.0.lock();
|
||||
let Some(mut input_handler) = lock.input_handler.take() else {
|
||||
panic!(
|
||||
"simulate_keystroke {:?} input event was not handled and there was no active input",
|
||||
&keystroke
|
||||
);
|
||||
};
|
||||
drop(lock);
|
||||
let text = keystroke.ime_key.unwrap_or(keystroke.key);
|
||||
input_handler.replace_text_in_range(None, &text);
|
||||
|
||||
self.0.lock().input_handler = Some(input_handler);
|
||||
}
|
||||
}
|
||||
|
||||
impl PlatformWindow for TestWindow {
|
||||
fn bounds(&self) -> WindowBounds {
|
||||
self.bounds
|
||||
self.0.lock().bounds
|
||||
}
|
||||
|
||||
fn content_size(&self) -> Size<Pixels> {
|
||||
let bounds = match self.bounds {
|
||||
let bounds = match self.bounds() {
|
||||
WindowBounds::Fixed(bounds) => bounds,
|
||||
WindowBounds::Maximized | WindowBounds::Fullscreen => self.display().bounds(),
|
||||
};
|
||||
@ -74,7 +145,7 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn display(&self) -> std::rc::Rc<dyn crate::PlatformDisplay> {
|
||||
self.display.clone()
|
||||
self.0.lock().display.clone()
|
||||
}
|
||||
|
||||
fn mouse_position(&self) -> Point<Pixels> {
|
||||
@ -90,11 +161,11 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn set_input_handler(&mut self, input_handler: Box<dyn crate::PlatformInputHandler>) {
|
||||
self.input_handler = Some(Arc::new(Mutex::new(input_handler)));
|
||||
self.0.lock().input_handler = Some(input_handler);
|
||||
}
|
||||
|
||||
fn clear_input_handler(&mut self) {
|
||||
self.input_handler = None;
|
||||
self.0.lock().input_handler = None;
|
||||
}
|
||||
|
||||
fn prompt(
|
||||
@ -103,19 +174,29 @@ impl PlatformWindow for TestWindow {
|
||||
_msg: &str,
|
||||
_answers: &[&str],
|
||||
) -> futures::channel::oneshot::Receiver<usize> {
|
||||
self.platform.upgrade().expect("platform dropped").prompt()
|
||||
self.0
|
||||
.lock()
|
||||
.platform
|
||||
.upgrade()
|
||||
.expect("platform dropped")
|
||||
.prompt()
|
||||
}
|
||||
|
||||
fn activate(&self) {
|
||||
unimplemented!()
|
||||
self.0
|
||||
.lock()
|
||||
.platform
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.set_active_window(Some(self.clone()))
|
||||
}
|
||||
|
||||
fn set_title(&mut self, title: &str) {
|
||||
self.title = Some(title.to_owned());
|
||||
self.0.lock().title = Some(title.to_owned());
|
||||
}
|
||||
|
||||
fn set_edited(&mut self, edited: bool) {
|
||||
self.edited = edited;
|
||||
self.0.lock().edited = edited;
|
||||
}
|
||||
|
||||
fn show_character_palette(&self) {
|
||||
@ -135,15 +216,15 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn on_input(&self, callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
|
||||
self.handlers.lock().input.push(callback)
|
||||
self.0.lock().input_callback = Some(callback)
|
||||
}
|
||||
|
||||
fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
|
||||
self.handlers.lock().active_status_change.push(callback)
|
||||
self.0.lock().active_status_change_callback = Some(callback)
|
||||
}
|
||||
|
||||
fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
|
||||
self.handlers.lock().resize.push(callback)
|
||||
self.0.lock().resize_callback = Some(callback)
|
||||
}
|
||||
|
||||
fn on_fullscreen(&self, _callback: Box<dyn FnMut(bool)>) {
|
||||
@ -151,7 +232,7 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn on_moved(&self, callback: Box<dyn FnMut()>) {
|
||||
self.handlers.lock().moved.push(callback)
|
||||
self.0.lock().moved_callback = Some(callback)
|
||||
}
|
||||
|
||||
fn on_should_close(&self, _callback: Box<dyn FnMut() -> bool>) {
|
||||
@ -175,7 +256,7 @@ impl PlatformWindow for TestWindow {
|
||||
}
|
||||
|
||||
fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
|
||||
self.sprite_atlas.clone()
|
||||
self.0.lock().sprite_atlas.clone()
|
||||
}
|
||||
|
||||
fn as_test(&mut self) -> Option<&mut TestWindow> {
|
||||
|
@ -57,6 +57,12 @@ lazy_static! {
|
||||
pub static ref BUFFER_DIFF_TASK: TaskLabel = TaskLabel::new();
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
pub enum Capability {
|
||||
ReadWrite,
|
||||
ReadOnly,
|
||||
}
|
||||
|
||||
pub struct Buffer {
|
||||
text: TextBuffer,
|
||||
diff_base: Option<String>,
|
||||
@ -90,6 +96,7 @@ pub struct Buffer {
|
||||
completion_triggers: Vec<String>,
|
||||
completion_triggers_timestamp: clock::Lamport,
|
||||
deferred_ops: OperationQueue<Operation>,
|
||||
capability: Capability,
|
||||
}
|
||||
|
||||
pub struct BufferSnapshot {
|
||||
@ -405,19 +412,27 @@ impl Buffer {
|
||||
TextBuffer::new(replica_id, id, base_text.into()),
|
||||
None,
|
||||
None,
|
||||
Capability::ReadWrite,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn remote(remote_id: u64, replica_id: ReplicaId, base_text: String) -> Self {
|
||||
pub fn remote(
|
||||
remote_id: u64,
|
||||
replica_id: ReplicaId,
|
||||
capability: Capability,
|
||||
base_text: String,
|
||||
) -> Self {
|
||||
Self::build(
|
||||
TextBuffer::new(replica_id, remote_id, base_text),
|
||||
None,
|
||||
None,
|
||||
capability,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn from_proto(
|
||||
replica_id: ReplicaId,
|
||||
capability: Capability,
|
||||
message: proto::BufferState,
|
||||
file: Option<Arc<dyn File>>,
|
||||
) -> Result<Self> {
|
||||
@ -426,6 +441,7 @@ impl Buffer {
|
||||
buffer,
|
||||
message.diff_base.map(|text| text.into_boxed_str().into()),
|
||||
file,
|
||||
capability,
|
||||
);
|
||||
this.text.set_line_ending(proto::deserialize_line_ending(
|
||||
rpc::proto::LineEnding::from_i32(message.line_ending)
|
||||
@ -504,10 +520,19 @@ impl Buffer {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn capability(&self) -> Capability {
|
||||
self.capability
|
||||
}
|
||||
|
||||
pub fn read_only(&self) -> bool {
|
||||
self.capability == Capability::ReadOnly
|
||||
}
|
||||
|
||||
pub fn build(
|
||||
buffer: TextBuffer,
|
||||
diff_base: Option<String>,
|
||||
file: Option<Arc<dyn File>>,
|
||||
capability: Capability,
|
||||
) -> Self {
|
||||
let saved_mtime = if let Some(file) = file.as_ref() {
|
||||
file.mtime()
|
||||
@ -526,6 +551,7 @@ impl Buffer {
|
||||
diff_base,
|
||||
git_diff: git::diff::BufferDiff::new(),
|
||||
file,
|
||||
capability,
|
||||
syntax_map: Mutex::new(SyntaxMap::new()),
|
||||
parsing_in_background: false,
|
||||
parse_count: 0,
|
||||
|
@ -1926,7 +1926,7 @@ fn test_serialization(cx: &mut gpui::AppContext) {
|
||||
.background_executor()
|
||||
.block(buffer1.read(cx).serialize_ops(None, cx));
|
||||
let buffer2 = cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::from_proto(1, state, None).unwrap();
|
||||
let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
|
||||
buffer
|
||||
.apply_ops(
|
||||
ops.into_iter()
|
||||
@ -1967,7 +1967,8 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
|
||||
let ops = cx
|
||||
.background_executor()
|
||||
.block(base_buffer.read(cx).serialize_ops(None, cx));
|
||||
let mut buffer = Buffer::from_proto(i as ReplicaId, state, None).unwrap();
|
||||
let mut buffer =
|
||||
Buffer::from_proto(i as ReplicaId, Capability::ReadWrite, state, None).unwrap();
|
||||
buffer
|
||||
.apply_ops(
|
||||
ops.into_iter()
|
||||
@ -2083,8 +2084,13 @@ fn test_random_collaboration(cx: &mut AppContext, mut rng: StdRng) {
|
||||
replica_id
|
||||
);
|
||||
new_buffer = Some(cx.new_model(|cx| {
|
||||
let mut new_buffer =
|
||||
Buffer::from_proto(new_replica_id, old_buffer_state, None).unwrap();
|
||||
let mut new_buffer = Buffer::from_proto(
|
||||
new_replica_id,
|
||||
Capability::ReadWrite,
|
||||
old_buffer_state,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
new_buffer
|
||||
.apply_ops(
|
||||
old_buffer_ops
|
||||
|
@ -772,9 +772,10 @@ impl Render for LspLogToolbarItemView {
|
||||
}),
|
||||
);
|
||||
if server_selected && row.logs_selected {
|
||||
let selected_ix = menu.select_last();
|
||||
debug_assert_eq!(
|
||||
Some(ix * 3 + 1),
|
||||
menu.select_last(),
|
||||
selected_ix,
|
||||
"Could not scroll to a just added LSP menu item"
|
||||
);
|
||||
}
|
||||
@ -822,9 +823,10 @@ impl Render for LspLogToolbarItemView {
|
||||
}),
|
||||
);
|
||||
if server_selected && row.rpc_trace_selected {
|
||||
let selected_ix = menu.select_last();
|
||||
debug_assert_eq!(
|
||||
Some(ix * 3 + 2),
|
||||
menu.select_last(),
|
||||
selected_ix,
|
||||
"Could not scroll to a just added LSP menu item"
|
||||
);
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ impl<'a> VideoGrant<'a> {
|
||||
Self {
|
||||
room: Some(Cow::Borrowed(room)),
|
||||
room_join: Some(true),
|
||||
can_publish: Some(false),
|
||||
can_subscribe: Some(true),
|
||||
..Default::default()
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ pub use language::Completion;
|
||||
use language::{
|
||||
char_kind,
|
||||
language_settings::{language_settings, LanguageSettings},
|
||||
AutoindentMode, Buffer, BufferChunks, BufferSnapshot, CharKind, Chunk, CursorShape,
|
||||
AutoindentMode, Buffer, BufferChunks, BufferSnapshot, Capability, CharKind, Chunk, CursorShape,
|
||||
DiagnosticEntry, File, IndentSize, Language, LanguageScope, OffsetRangeExt, OffsetUtf16,
|
||||
Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _,
|
||||
ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
|
||||
@ -55,6 +55,7 @@ pub struct MultiBuffer {
|
||||
replica_id: ReplicaId,
|
||||
history: History,
|
||||
title: Option<String>,
|
||||
capability: Capability,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@ -225,13 +226,14 @@ struct ExcerptBytes<'a> {
|
||||
}
|
||||
|
||||
impl MultiBuffer {
|
||||
pub fn new(replica_id: ReplicaId) -> Self {
|
||||
pub fn new(replica_id: ReplicaId, capability: Capability) -> Self {
|
||||
Self {
|
||||
snapshot: Default::default(),
|
||||
buffers: Default::default(),
|
||||
next_excerpt_id: 1,
|
||||
subscriptions: Default::default(),
|
||||
singleton: false,
|
||||
capability,
|
||||
replica_id,
|
||||
history: History {
|
||||
next_transaction_id: Default::default(),
|
||||
@ -271,6 +273,7 @@ impl MultiBuffer {
|
||||
next_excerpt_id: 1,
|
||||
subscriptions: Default::default(),
|
||||
singleton: self.singleton,
|
||||
capability: self.capability,
|
||||
replica_id: self.replica_id,
|
||||
history: self.history.clone(),
|
||||
title: self.title.clone(),
|
||||
@ -282,8 +285,12 @@ impl MultiBuffer {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn read_only(&self) -> bool {
|
||||
self.capability == Capability::ReadOnly
|
||||
}
|
||||
|
||||
pub fn singleton(buffer: Model<Buffer>, cx: &mut ModelContext<Self>) -> Self {
|
||||
let mut this = Self::new(buffer.read(cx).replica_id());
|
||||
let mut this = Self::new(buffer.read(cx).replica_id(), buffer.read(cx).capability());
|
||||
this.singleton = true;
|
||||
this.push_excerpts(
|
||||
buffer,
|
||||
@ -1657,7 +1664,7 @@ impl MultiBuffer {
|
||||
excerpts: [(&str, Vec<Range<Point>>); COUNT],
|
||||
cx: &mut gpui::AppContext,
|
||||
) -> Model<Self> {
|
||||
let multi = cx.new_model(|_| Self::new(0));
|
||||
let multi = cx.new_model(|_| Self::new(0, Capability::ReadWrite));
|
||||
for (text, ranges) in excerpts {
|
||||
let buffer = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), text));
|
||||
let excerpt_ranges = ranges.into_iter().map(|range| ExcerptRange {
|
||||
@ -1678,7 +1685,7 @@ impl MultiBuffer {
|
||||
|
||||
pub fn build_random(rng: &mut impl rand::Rng, cx: &mut gpui::AppContext) -> Model<Self> {
|
||||
cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
|
||||
let mutation_count = rng.gen_range(1..=5);
|
||||
multibuffer.randomly_edit_excerpts(rng, mutation_count, cx);
|
||||
multibuffer
|
||||
@ -4176,7 +4183,7 @@ mod tests {
|
||||
let ops = cx
|
||||
.background_executor()
|
||||
.block(host_buffer.read(cx).serialize_ops(None, cx));
|
||||
let mut buffer = Buffer::from_proto(1, state, None).unwrap();
|
||||
let mut buffer = Buffer::from_proto(1, Capability::ReadWrite, state, None).unwrap();
|
||||
buffer
|
||||
.apply_ops(
|
||||
ops.into_iter()
|
||||
@ -4205,7 +4212,7 @@ mod tests {
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'a')));
|
||||
let buffer_2 =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(6, 6, 'g')));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
|
||||
let events = Arc::new(RwLock::new(Vec::<Event>::new()));
|
||||
multibuffer.update(cx, |_, cx| {
|
||||
@ -4442,8 +4449,8 @@ mod tests {
|
||||
let buffer_2 =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(10, 3, 'm')));
|
||||
|
||||
let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let leader_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let follower_multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let follower_edit_event_count = Arc::new(RwLock::new(0));
|
||||
|
||||
follower_multibuffer.update(cx, |_, cx| {
|
||||
@ -4547,7 +4554,7 @@ mod tests {
|
||||
fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
|
||||
multibuffer.push_excerpts_with_context_lines(
|
||||
buffer.clone(),
|
||||
@ -4584,7 +4591,7 @@ mod tests {
|
||||
async fn test_stream_excerpts_with_context_lines(cx: &mut TestAppContext) {
|
||||
let buffer =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), sample_text(20, 3, 'a')));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let anchor_ranges = multibuffer.update(cx, |multibuffer, cx| {
|
||||
let snapshot = buffer.read(cx);
|
||||
let ranges = vec![
|
||||
@ -4619,7 +4626,7 @@ mod tests {
|
||||
|
||||
#[gpui::test]
|
||||
fn test_empty_multibuffer(cx: &mut AppContext) {
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
|
||||
let snapshot = multibuffer.read(cx).snapshot(cx);
|
||||
assert_eq!(snapshot.text(), "");
|
||||
@ -4652,7 +4659,7 @@ mod tests {
|
||||
let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
|
||||
let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "efghi"));
|
||||
let multibuffer = cx.new_model(|cx| {
|
||||
let mut multibuffer = MultiBuffer::new(0);
|
||||
let mut multibuffer = MultiBuffer::new(0, Capability::ReadWrite);
|
||||
multibuffer.push_excerpts(
|
||||
buffer_1.clone(),
|
||||
[ExcerptRange {
|
||||
@ -4710,7 +4717,7 @@ mod tests {
|
||||
let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "abcd"));
|
||||
let buffer_2 =
|
||||
cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "ABCDEFGHIJKLMNOP"));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
|
||||
// Create an insertion id in buffer 1 that doesn't exist in buffer 2.
|
||||
// Add an excerpt from buffer 1 that spans this new insertion.
|
||||
@ -4844,7 +4851,7 @@ mod tests {
|
||||
.unwrap_or(10);
|
||||
|
||||
let mut buffers: Vec<Model<Buffer>> = Vec::new();
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let mut excerpt_ids = Vec::<ExcerptId>::new();
|
||||
let mut expected_excerpts = Vec::<(Model<Buffer>, Range<text::Anchor>)>::new();
|
||||
let mut anchors = Vec::new();
|
||||
@ -5266,7 +5273,7 @@ mod tests {
|
||||
|
||||
let buffer_1 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "1234"));
|
||||
let buffer_2 = cx.new_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), "5678"));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0));
|
||||
let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
|
||||
let group_interval = multibuffer.read(cx).history.group_interval;
|
||||
multibuffer.update(cx, |multibuffer, cx| {
|
||||
multibuffer.push_excerpts(
|
||||
|
@ -39,11 +39,11 @@ use language::{
|
||||
deserialize_anchor, deserialize_fingerprint, deserialize_line_ending, deserialize_version,
|
||||
serialize_anchor, serialize_version, split_operations,
|
||||
},
|
||||
range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, CodeAction,
|
||||
CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff, Event as BufferEvent,
|
||||
File as _, Language, LanguageRegistry, LanguageServerName, LocalFile, LspAdapterDelegate,
|
||||
OffsetRangeExt, Operation, Patch, PendingLanguageServer, PointUtf16, TextBufferSnapshot,
|
||||
ToOffset, ToPointUtf16, Transaction, Unclipped,
|
||||
range_from_lsp, range_to_lsp, Bias, Buffer, BufferSnapshot, CachedLspAdapter, Capability,
|
||||
CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticEntry, DiagnosticSet, Diff,
|
||||
Event as BufferEvent, File as _, Language, LanguageRegistry, LanguageServerName, LocalFile,
|
||||
LspAdapterDelegate, OffsetRangeExt, Operation, Patch, PendingLanguageServer, PointUtf16,
|
||||
TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction, Unclipped,
|
||||
};
|
||||
use log::error;
|
||||
use lsp::{
|
||||
@ -262,6 +262,7 @@ enum ProjectClientState {
|
||||
},
|
||||
Remote {
|
||||
sharing_has_stopped: bool,
|
||||
capability: Capability,
|
||||
remote_id: u64,
|
||||
replica_id: ReplicaId,
|
||||
},
|
||||
@ -702,6 +703,7 @@ impl Project {
|
||||
user_store: Model<UserStore>,
|
||||
languages: Arc<LanguageRegistry>,
|
||||
fs: Arc<dyn Fs>,
|
||||
role: proto::ChannelRole,
|
||||
mut cx: AsyncAppContext,
|
||||
) -> Result<Model<Self>> {
|
||||
client.authenticate_and_connect(true, &cx).await?;
|
||||
@ -756,6 +758,7 @@ impl Project {
|
||||
client: client.clone(),
|
||||
client_state: Some(ProjectClientState::Remote {
|
||||
sharing_has_stopped: false,
|
||||
capability: Capability::ReadWrite,
|
||||
remote_id,
|
||||
replica_id,
|
||||
}),
|
||||
@ -796,6 +799,7 @@ impl Project {
|
||||
prettiers_per_worktree: HashMap::default(),
|
||||
prettier_instances: HashMap::default(),
|
||||
};
|
||||
this.set_role(role);
|
||||
for worktree in worktrees {
|
||||
let _ = this.add_worktree(&worktree, cx);
|
||||
}
|
||||
@ -1618,6 +1622,17 @@ impl Project {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn set_role(&mut self, role: proto::ChannelRole) {
|
||||
if let Some(ProjectClientState::Remote { capability, .. }) = &mut self.client_state {
|
||||
*capability = if role == proto::ChannelRole::Member || role == proto::ChannelRole::Admin
|
||||
{
|
||||
Capability::ReadWrite
|
||||
} else {
|
||||
Capability::ReadOnly
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn disconnected_from_host_internal(&mut self, cx: &mut AppContext) {
|
||||
if let Some(ProjectClientState::Remote {
|
||||
sharing_has_stopped,
|
||||
@ -1659,7 +1674,7 @@ impl Project {
|
||||
cx.emit(Event::Closed);
|
||||
}
|
||||
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
pub fn is_disconnected(&self) -> bool {
|
||||
match &self.client_state {
|
||||
Some(ProjectClientState::Remote {
|
||||
sharing_has_stopped,
|
||||
@ -1669,6 +1684,17 @@ impl Project {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capability(&self) -> Capability {
|
||||
match &self.client_state {
|
||||
Some(ProjectClientState::Remote { capability, .. }) => *capability,
|
||||
Some(ProjectClientState::Local { .. }) | None => Capability::ReadWrite,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
self.is_disconnected() || self.capability() == Capability::ReadOnly
|
||||
}
|
||||
|
||||
pub fn is_local(&self) -> bool {
|
||||
match &self.client_state {
|
||||
Some(ProjectClientState::Remote { .. }) => false,
|
||||
@ -6013,7 +6039,7 @@ impl Project {
|
||||
this.upgrade().context("project dropped")?;
|
||||
let response = rpc.request(message).await?;
|
||||
let this = this.upgrade().context("project dropped")?;
|
||||
if this.update(&mut cx, |this, _| this.is_read_only())? {
|
||||
if this.update(&mut cx, |this, _| this.is_disconnected())? {
|
||||
Err(anyhow!("disconnected before completing request"))
|
||||
} else {
|
||||
request
|
||||
@ -7192,7 +7218,8 @@ impl Project {
|
||||
|
||||
let buffer_id = state.id;
|
||||
let buffer = cx.new_model(|_| {
|
||||
Buffer::from_proto(this.replica_id(), state, buffer_file).unwrap()
|
||||
Buffer::from_proto(this.replica_id(), this.capability(), state, buffer_file)
|
||||
.unwrap()
|
||||
});
|
||||
this.incomplete_remote_buffers
|
||||
.insert(buffer_id, Some(buffer));
|
||||
@ -7940,7 +7967,7 @@ impl Project {
|
||||
|
||||
if let Some(buffer) = buffer {
|
||||
break buffer;
|
||||
} else if this.update(&mut cx, |this, _| this.is_read_only())? {
|
||||
} else if this.update(&mut cx, |this, _| this.is_disconnected())? {
|
||||
return Err(anyhow!("disconnected before buffer {} could be opened", id));
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,8 @@ use language::{
|
||||
deserialize_fingerprint, deserialize_version, serialize_fingerprint, serialize_line_ending,
|
||||
serialize_version,
|
||||
},
|
||||
Buffer, DiagnosticEntry, File as _, LineEnding, PointUtf16, Rope, RopeFingerprint, Unclipped,
|
||||
Buffer, Capability, DiagnosticEntry, File as _, LineEnding, PointUtf16, Rope, RopeFingerprint,
|
||||
Unclipped,
|
||||
};
|
||||
use lsp::LanguageServerId;
|
||||
use parking_lot::Mutex;
|
||||
@ -682,7 +683,14 @@ impl LocalWorktree {
|
||||
.background_executor()
|
||||
.spawn(async move { text::Buffer::new(0, id, contents) })
|
||||
.await;
|
||||
cx.new_model(|_| Buffer::build(text_buffer, diff_base, Some(Arc::new(file))))
|
||||
cx.new_model(|_| {
|
||||
Buffer::build(
|
||||
text_buffer,
|
||||
diff_base,
|
||||
Some(Arc::new(file)),
|
||||
Capability::ReadWrite,
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -388,8 +388,18 @@ impl ProjectPanel {
|
||||
let is_dir = entry.is_dir();
|
||||
let worktree_id = worktree.id();
|
||||
let is_local = project.is_local();
|
||||
let is_read_only = project.is_read_only();
|
||||
|
||||
let context_menu = ContextMenu::build(cx, |mut menu, cx| {
|
||||
if is_read_only {
|
||||
menu = menu.action("Copy Relative Path", Box::new(CopyRelativePath));
|
||||
if is_dir {
|
||||
menu = menu.action("Search Inside", Box::new(NewSearchInDirectory))
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
if is_local {
|
||||
menu = menu.action(
|
||||
"Add Folder to Project",
|
||||
@ -1473,6 +1483,7 @@ impl ProjectPanel {
|
||||
impl Render for ProjectPanel {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
let has_worktree = self.visible_entries.len() != 0;
|
||||
let project = self.project.read(cx);
|
||||
|
||||
if has_worktree {
|
||||
div()
|
||||
@ -1485,21 +1496,25 @@ impl Render for ProjectPanel {
|
||||
.on_action(cx.listener(Self::expand_selected_entry))
|
||||
.on_action(cx.listener(Self::collapse_selected_entry))
|
||||
.on_action(cx.listener(Self::collapse_all_entries))
|
||||
.on_action(cx.listener(Self::new_file))
|
||||
.on_action(cx.listener(Self::new_directory))
|
||||
.on_action(cx.listener(Self::rename))
|
||||
.on_action(cx.listener(Self::delete))
|
||||
.on_action(cx.listener(Self::confirm))
|
||||
.on_action(cx.listener(Self::open_file))
|
||||
.on_action(cx.listener(Self::confirm))
|
||||
.on_action(cx.listener(Self::cancel))
|
||||
.on_action(cx.listener(Self::cut))
|
||||
.on_action(cx.listener(Self::copy))
|
||||
.on_action(cx.listener(Self::copy_path))
|
||||
.on_action(cx.listener(Self::copy_relative_path))
|
||||
.on_action(cx.listener(Self::paste))
|
||||
.on_action(cx.listener(Self::reveal_in_finder))
|
||||
.on_action(cx.listener(Self::open_in_terminal))
|
||||
.on_action(cx.listener(Self::new_search_in_directory))
|
||||
.when(!project.is_read_only(), |el| {
|
||||
el.on_action(cx.listener(Self::new_file))
|
||||
.on_action(cx.listener(Self::new_directory))
|
||||
.on_action(cx.listener(Self::rename))
|
||||
.on_action(cx.listener(Self::delete))
|
||||
.on_action(cx.listener(Self::cut))
|
||||
.on_action(cx.listener(Self::copy))
|
||||
.on_action(cx.listener(Self::paste))
|
||||
})
|
||||
.when(project.is_local(), |el| {
|
||||
el.on_action(cx.listener(Self::reveal_in_finder))
|
||||
.on_action(cx.listener(Self::open_in_terminal))
|
||||
})
|
||||
.track_focus(&self.focus_handle)
|
||||
.child(
|
||||
uniform_list(
|
||||
|
@ -395,6 +395,7 @@ mod tests {
|
||||
language::init(cx);
|
||||
Project::init_settings(cx);
|
||||
workspace::init_settings(cx);
|
||||
editor::init(cx);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -269,6 +269,7 @@ message Participant {
|
||||
repeated ParticipantProject projects = 3;
|
||||
ParticipantLocation location = 4;
|
||||
uint32 participant_index = 5;
|
||||
ChannelRole role = 6;
|
||||
}
|
||||
|
||||
message PendingParticipant {
|
||||
|
@ -70,7 +70,7 @@ impl BufferSearchBar {
|
||||
fn render_text_input(&self, editor: &View<Editor>, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: if editor.read(cx).read_only() {
|
||||
color: if editor.read(cx).read_only(cx) {
|
||||
cx.theme().colors().text_disabled
|
||||
} else {
|
||||
cx.theme().colors().text
|
||||
@ -223,6 +223,7 @@ impl Render for BufferSearchBar {
|
||||
.gap_2()
|
||||
.border_1()
|
||||
.border_color(editor_border)
|
||||
.min_w(rems(384. / 16.))
|
||||
.rounded_lg()
|
||||
.child(IconElement::new(Icon::MagnifyingGlass))
|
||||
.child(self.render_text_input(&self.query_editor, cx))
|
||||
|
@ -38,8 +38,8 @@ use std::{
|
||||
use theme::ThemeSettings;
|
||||
|
||||
use ui::{
|
||||
h_stack, prelude::*, v_stack, Button, Icon, IconButton, IconElement, Label, LabelCommon,
|
||||
LabelSize, Selectable, Tooltip,
|
||||
h_stack, prelude::*, v_stack, Icon, IconButton, IconElement, Label, LabelCommon, LabelSize,
|
||||
Selectable, ToggleButton, Tooltip,
|
||||
};
|
||||
use util::{paths::PathMatcher, ResultExt as _};
|
||||
use workspace::{
|
||||
@ -132,9 +132,11 @@ pub struct ProjectSearchBar {
|
||||
impl ProjectSearch {
|
||||
fn new(project: Model<Project>, cx: &mut ModelContext<Self>) -> Self {
|
||||
let replica_id = project.read(cx).replica_id();
|
||||
let capability = project.read(cx).capability();
|
||||
|
||||
Self {
|
||||
project,
|
||||
excerpts: cx.new_model(|_| MultiBuffer::new(replica_id)),
|
||||
excerpts: cx.new_model(|_| MultiBuffer::new(replica_id, capability)),
|
||||
pending_search: Default::default(),
|
||||
match_ranges: Default::default(),
|
||||
active_query: None,
|
||||
@ -286,7 +288,6 @@ impl Render for ProjectSearchView {
|
||||
.size_full()
|
||||
.track_focus(&self.focus_handle)
|
||||
.child(self.results_editor.clone())
|
||||
.into_any()
|
||||
} else {
|
||||
let model = self.model.read(cx);
|
||||
let has_no_results = model.no_results.unwrap_or(false);
|
||||
@ -363,6 +364,7 @@ impl Render for ProjectSearchView {
|
||||
.flex_1()
|
||||
.size_full()
|
||||
.justify_center()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.track_focus(&self.focus_handle)
|
||||
.child(
|
||||
h_stack()
|
||||
@ -372,7 +374,6 @@ impl Render for ProjectSearchView {
|
||||
.child(v_stack().child(major_text).children(minor_text))
|
||||
.child(h_stack().flex_1()),
|
||||
)
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1557,7 +1558,7 @@ impl ProjectSearchBar {
|
||||
fn render_text_input(&self, editor: &View<Editor>, cx: &ViewContext<Self>) -> impl IntoElement {
|
||||
let settings = ThemeSettings::get_global(cx);
|
||||
let text_style = TextStyle {
|
||||
color: if editor.read(cx).read_only() {
|
||||
color: if editor.read(cx).read_only(cx) {
|
||||
cx.theme().colors().text_disabled
|
||||
} else {
|
||||
cx.theme().colors().text
|
||||
@ -1677,20 +1678,26 @@ impl Render for ProjectSearchBar {
|
||||
|
||||
let mode_column = v_stack().items_start().justify_start().child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
h_stack()
|
||||
.child(
|
||||
Button::new("project-search-text-button", "Text")
|
||||
ToggleButton::new("project-search-text-button", "Text")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(search.current_mode == SearchMode::Text)
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.activate_search_mode(SearchMode::Text, cx)
|
||||
}))
|
||||
.tooltip(|cx| {
|
||||
Tooltip::for_action("Toggle text search", &ActivateTextMode, cx)
|
||||
}),
|
||||
})
|
||||
.first(),
|
||||
)
|
||||
.child(
|
||||
Button::new("project-search-regex-button", "Regex")
|
||||
ToggleButton::new("project-search-regex-button", "Regex")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(search.current_mode == SearchMode::Regex)
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.activate_search_mode(SearchMode::Regex, cx)
|
||||
@ -1701,11 +1708,20 @@ impl Render for ProjectSearchBar {
|
||||
&ActivateRegexMode,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.map(|this| {
|
||||
if semantic_is_available {
|
||||
this.middle()
|
||||
} else {
|
||||
this.last()
|
||||
}
|
||||
}),
|
||||
)
|
||||
.when(semantic_is_available, |this| {
|
||||
this.child(
|
||||
Button::new("project-search-semantic-button", "Semantic")
|
||||
ToggleButton::new("project-search-semantic-button", "Semantic")
|
||||
.style(ButtonStyle::Filled)
|
||||
.size(ButtonSize::Large)
|
||||
.selected(search.current_mode == SearchMode::Semantic)
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.activate_search_mode(SearchMode::Semantic, cx)
|
||||
@ -1716,7 +1732,8 @@ impl Render for ProjectSearchBar {
|
||||
&ActivateSemanticMode,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
})
|
||||
.last(),
|
||||
)
|
||||
}),
|
||||
)
|
||||
@ -1867,6 +1884,7 @@ impl Render for ProjectSearchBar {
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_between()
|
||||
.gap_2()
|
||||
.child(query_column)
|
||||
.child(mode_column)
|
||||
.child(replace_column)
|
||||
|
@ -14,7 +14,6 @@ test-support = ["gpui/test-support", "fs/test-support"]
|
||||
[dependencies]
|
||||
collections = { path = "../collections" }
|
||||
gpui = { path = "../gpui" }
|
||||
sqlez = { path = "../sqlez" }
|
||||
fs = { path = "../fs" }
|
||||
feature_flags = { path = "../feature_flags" }
|
||||
util = { path = "../util" }
|
||||
|
@ -131,6 +131,15 @@ impl PlayerColors {
|
||||
*self.0.last().unwrap()
|
||||
}
|
||||
|
||||
pub fn read_only(&self) -> PlayerColor {
|
||||
let local = self.local();
|
||||
PlayerColor {
|
||||
cursor: local.cursor.grayscale(),
|
||||
background: local.background.grayscale(),
|
||||
selection: local.selection.grayscale(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn color_for_participant(&self, participant_index: u32) -> PlayerColor {
|
||||
let len = self.0.len() - 1;
|
||||
self.0[(participant_index as usize % len) + 1]
|
||||
|
1013
crates/theme/src/themes/LICENSES
Normal file
1013
crates/theme/src/themes/LICENSES
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,457 +15,6 @@ pub fn one() -> UserThemeFamily {
|
||||
name: "One".into(),
|
||||
author: "Zed Industries".into(),
|
||||
themes: vec![
|
||||
UserTheme {
|
||||
name: "One Light".into(),
|
||||
appearance: Appearance::Light,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0xc9c9caff).into()),
|
||||
border_variant: Some(rgba(0xdfdfe0ff).into()),
|
||||
border_focused: Some(rgba(0xcbcdf6ff).into()),
|
||||
border_selected: Some(rgba(0xcbcdf6ff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0xd3d3d4ff).into()),
|
||||
elevated_surface_background: Some(rgba(0xebebecff).into()),
|
||||
surface_background: Some(rgba(0xebebecff).into()),
|
||||
background: Some(rgba(0xdcdcddff).into()),
|
||||
panel_background: Some(rgba(0xebebecff).into()),
|
||||
element_background: Some(rgba(0xebebecff).into()),
|
||||
element_hover: Some(rgba(0xdfdfe0ff).into()),
|
||||
element_active: Some(rgba(0xcacacaff).into()),
|
||||
element_selected: Some(rgba(0xcacacaff).into()),
|
||||
element_disabled: Some(rgba(0xebebecff).into()),
|
||||
drop_target_background: Some(rgba(0x7f818880).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0xdfdfe0ff).into()),
|
||||
ghost_element_active: Some(rgba(0xcacacaff).into()),
|
||||
ghost_element_selected: Some(rgba(0xcacacaff).into()),
|
||||
ghost_element_disabled: Some(rgba(0xebebecff).into()),
|
||||
text: Some(rgba(0x383a41ff).into()),
|
||||
text_muted: Some(rgba(0x7f8188ff).into()),
|
||||
text_placeholder: Some(rgba(0xa1a1a3ff).into()),
|
||||
text_disabled: Some(rgba(0xa1a1a3ff).into()),
|
||||
text_accent: Some(rgba(0x5c79e2ff).into()),
|
||||
icon: Some(rgba(0x383a41ff).into()),
|
||||
icon_muted: Some(rgba(0x7f8188ff).into()),
|
||||
icon_disabled: Some(rgba(0xa1a1a3ff).into()),
|
||||
icon_placeholder: Some(rgba(0x7f8188ff).into()),
|
||||
icon_accent: Some(rgba(0x5c79e2ff).into()),
|
||||
status_bar_background: Some(rgba(0xdcdcddff).into()),
|
||||
title_bar_background: Some(rgba(0xdcdcddff).into()),
|
||||
toolbar_background: Some(rgba(0xfafafaff).into()),
|
||||
tab_bar_background: Some(rgba(0xebebecff).into()),
|
||||
tab_inactive_background: Some(rgba(0xebebecff).into()),
|
||||
tab_active_background: Some(rgba(0xfafafaff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0x383a414c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0xdfdfe0ff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0xdfdfe0ff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0xeeeeeeff).into()),
|
||||
editor_foreground: Some(rgba(0x383a41ff).into()),
|
||||
editor_background: Some(rgba(0xfafafaff).into()),
|
||||
editor_gutter_background: Some(rgba(0xfafafaff).into()),
|
||||
editor_subheader_background: Some(rgba(0xebebecff).into()),
|
||||
editor_active_line_background: Some(rgba(0xebebecbf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0xebebecff).into()),
|
||||
editor_line_number: Some(rgba(0x383a4159).into()),
|
||||
editor_active_line_number: Some(rgba(0x383a41ff).into()),
|
||||
editor_invisible: Some(rgba(0x7f8188ff).into()),
|
||||
editor_wrap_guide: Some(rgba(0x383a410d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0x383a411a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x5c79e21a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0xa3a3a466).into()),
|
||||
terminal_background: Some(rgba(0xfafafaff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0xaaaaaaff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0xf0b0a4ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0xb2cfa9ff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0xf1dfc1ff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0xb5baf2ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0xcea6d3ff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0xa4bfdbff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0x383a41ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0xfafafaff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xd36151ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x669f59ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xdec184ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x5c79e2ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0x994fa6ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x3b82b7ff).into()),
|
||||
terminal_ansi_white: Some(rgba(0x383a41ff).into()),
|
||||
link_text_hover: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xdec184ff).into()),
|
||||
conflict_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
conflict_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
created: Some(rgba(0x669f59ff).into()),
|
||||
created_background: Some(rgba(0xe0ebdcff).into()),
|
||||
created_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
deleted: Some(rgba(0xd36151ff).into()),
|
||||
deleted_background: Some(rgba(0xfbdfd9ff).into()),
|
||||
deleted_border: Some(rgba(0xf6c6bdff).into()),
|
||||
error: Some(rgba(0xd36151ff).into()),
|
||||
error_background: Some(rgba(0xfbdfd9ff).into()),
|
||||
error_border: Some(rgba(0xf6c6bdff).into()),
|
||||
hidden: Some(rgba(0xa1a1a3ff).into()),
|
||||
hidden_background: Some(rgba(0xdcdcddff).into()),
|
||||
hidden_border: Some(rgba(0xd3d3d4ff).into()),
|
||||
hint: Some(rgba(0x9295beff).into()),
|
||||
hint_background: Some(rgba(0xe2e2faff).into()),
|
||||
hint_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
ignored: Some(rgba(0x7f8188ff).into()),
|
||||
ignored_background: Some(rgba(0xdcdcddff).into()),
|
||||
ignored_border: Some(rgba(0xc9c9caff).into()),
|
||||
info: Some(rgba(0x5c79e2ff).into()),
|
||||
info_background: Some(rgba(0xe2e2faff).into()),
|
||||
info_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
modified: Some(rgba(0xdec184ff).into()),
|
||||
modified_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
modified_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
predictive: Some(rgba(0x9c9fc7ff).into()),
|
||||
predictive_background: Some(rgba(0xe0ebdcff).into()),
|
||||
predictive_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
renamed: Some(rgba(0x5c79e2ff).into()),
|
||||
renamed_background: Some(rgba(0xe2e2faff).into()),
|
||||
renamed_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
success: Some(rgba(0x669f59ff).into()),
|
||||
success_background: Some(rgba(0xe0ebdcff).into()),
|
||||
success_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
unreachable: Some(rgba(0x7f8188ff).into()),
|
||||
unreachable_background: Some(rgba(0xdcdcddff).into()),
|
||||
unreachable_border: Some(rgba(0xc9c9caff).into()),
|
||||
warning: Some(rgba(0xdec184ff).into()),
|
||||
warning_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
warning_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x5c79e2ff).into(),
|
||||
background: rgba(0x5c79e2ff).into(),
|
||||
selection: rgba(0x5c79e23d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x994fa6ff).into(),
|
||||
background: rgba(0x994fa6ff).into(),
|
||||
selection: rgba(0x994fa63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xad6f27ff).into(),
|
||||
background: rgba(0xad6f27ff).into(),
|
||||
selection: rgba(0xad6f273d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xa44aabff).into(),
|
||||
background: rgba(0xa44aabff).into(),
|
||||
selection: rgba(0xa44aab3d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x3b82b7ff).into(),
|
||||
background: rgba(0x3b82b7ff).into(),
|
||||
selection: rgba(0x3b82b73d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xd36151ff).into(),
|
||||
background: rgba(0xd36151ff).into(),
|
||||
selection: rgba(0xd361513d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xdec184ff).into(),
|
||||
background: rgba(0xdec184ff).into(),
|
||||
selection: rgba(0xdec1843d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x669f59ff).into(),
|
||||
background: rgba(0x669f59ff).into(),
|
||||
selection: rgba(0x669f593d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xa2a3a7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x7c7e86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x669f59ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9295beff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xa449abff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9c9fc7ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x4d4f52ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x4d4f52ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xb92c46ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x659f58ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x7c7e86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x659f58ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
font_weight: Some(UserFontWeight(400.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "One Dark".into(),
|
||||
appearance: Appearance::Dark,
|
||||
@ -917,6 +466,457 @@ pub fn one() -> UserThemeFamily {
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "One Light".into(),
|
||||
appearance: Appearance::Light,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0xc9c9caff).into()),
|
||||
border_variant: Some(rgba(0xdfdfe0ff).into()),
|
||||
border_focused: Some(rgba(0xcbcdf6ff).into()),
|
||||
border_selected: Some(rgba(0xcbcdf6ff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0xd3d3d4ff).into()),
|
||||
elevated_surface_background: Some(rgba(0xebebecff).into()),
|
||||
surface_background: Some(rgba(0xebebecff).into()),
|
||||
background: Some(rgba(0xdcdcddff).into()),
|
||||
panel_background: Some(rgba(0xebebecff).into()),
|
||||
element_background: Some(rgba(0xebebecff).into()),
|
||||
element_hover: Some(rgba(0xdfdfe0ff).into()),
|
||||
element_active: Some(rgba(0xcacacaff).into()),
|
||||
element_selected: Some(rgba(0xcacacaff).into()),
|
||||
element_disabled: Some(rgba(0xebebecff).into()),
|
||||
drop_target_background: Some(rgba(0x7f818880).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0xdfdfe0ff).into()),
|
||||
ghost_element_active: Some(rgba(0xcacacaff).into()),
|
||||
ghost_element_selected: Some(rgba(0xcacacaff).into()),
|
||||
ghost_element_disabled: Some(rgba(0xebebecff).into()),
|
||||
text: Some(rgba(0x383a41ff).into()),
|
||||
text_muted: Some(rgba(0x7f8188ff).into()),
|
||||
text_placeholder: Some(rgba(0xa1a1a3ff).into()),
|
||||
text_disabled: Some(rgba(0xa1a1a3ff).into()),
|
||||
text_accent: Some(rgba(0x5c79e2ff).into()),
|
||||
icon: Some(rgba(0x383a41ff).into()),
|
||||
icon_muted: Some(rgba(0x7f8188ff).into()),
|
||||
icon_disabled: Some(rgba(0xa1a1a3ff).into()),
|
||||
icon_placeholder: Some(rgba(0x7f8188ff).into()),
|
||||
icon_accent: Some(rgba(0x5c79e2ff).into()),
|
||||
status_bar_background: Some(rgba(0xdcdcddff).into()),
|
||||
title_bar_background: Some(rgba(0xdcdcddff).into()),
|
||||
toolbar_background: Some(rgba(0xfafafaff).into()),
|
||||
tab_bar_background: Some(rgba(0xebebecff).into()),
|
||||
tab_inactive_background: Some(rgba(0xebebecff).into()),
|
||||
tab_active_background: Some(rgba(0xfafafaff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0x383a414c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0xdfdfe0ff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0xdfdfe0ff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0xeeeeeeff).into()),
|
||||
editor_foreground: Some(rgba(0x383a41ff).into()),
|
||||
editor_background: Some(rgba(0xfafafaff).into()),
|
||||
editor_gutter_background: Some(rgba(0xfafafaff).into()),
|
||||
editor_subheader_background: Some(rgba(0xebebecff).into()),
|
||||
editor_active_line_background: Some(rgba(0xebebecbf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0xebebecff).into()),
|
||||
editor_line_number: Some(rgba(0x383a4159).into()),
|
||||
editor_active_line_number: Some(rgba(0x383a41ff).into()),
|
||||
editor_invisible: Some(rgba(0x7f8188ff).into()),
|
||||
editor_wrap_guide: Some(rgba(0x383a410d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0x383a411a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x5c79e21a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0xa3a3a466).into()),
|
||||
terminal_background: Some(rgba(0xfafafaff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0xaaaaaaff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0xf0b0a4ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0xb2cfa9ff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0xf1dfc1ff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0xb5baf2ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0xcea6d3ff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0xa4bfdbff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0x383a41ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0xfafafaff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xd36151ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x669f59ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xdec184ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x5c79e2ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0x994fa6ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x3b82b7ff).into()),
|
||||
terminal_ansi_white: Some(rgba(0x383a41ff).into()),
|
||||
link_text_hover: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xdec184ff).into()),
|
||||
conflict_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
conflict_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
created: Some(rgba(0x669f59ff).into()),
|
||||
created_background: Some(rgba(0xe0ebdcff).into()),
|
||||
created_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
deleted: Some(rgba(0xd36151ff).into()),
|
||||
deleted_background: Some(rgba(0xfbdfd9ff).into()),
|
||||
deleted_border: Some(rgba(0xf6c6bdff).into()),
|
||||
error: Some(rgba(0xd36151ff).into()),
|
||||
error_background: Some(rgba(0xfbdfd9ff).into()),
|
||||
error_border: Some(rgba(0xf6c6bdff).into()),
|
||||
hidden: Some(rgba(0xa1a1a3ff).into()),
|
||||
hidden_background: Some(rgba(0xdcdcddff).into()),
|
||||
hidden_border: Some(rgba(0xd3d3d4ff).into()),
|
||||
hint: Some(rgba(0x9295beff).into()),
|
||||
hint_background: Some(rgba(0xe2e2faff).into()),
|
||||
hint_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
ignored: Some(rgba(0x7f8188ff).into()),
|
||||
ignored_background: Some(rgba(0xdcdcddff).into()),
|
||||
ignored_border: Some(rgba(0xc9c9caff).into()),
|
||||
info: Some(rgba(0x5c79e2ff).into()),
|
||||
info_background: Some(rgba(0xe2e2faff).into()),
|
||||
info_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
modified: Some(rgba(0xdec184ff).into()),
|
||||
modified_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
modified_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
predictive: Some(rgba(0x9c9fc7ff).into()),
|
||||
predictive_background: Some(rgba(0xe0ebdcff).into()),
|
||||
predictive_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
renamed: Some(rgba(0x5c79e2ff).into()),
|
||||
renamed_background: Some(rgba(0xe2e2faff).into()),
|
||||
renamed_border: Some(rgba(0xcbcdf6ff).into()),
|
||||
success: Some(rgba(0x669f59ff).into()),
|
||||
success_background: Some(rgba(0xe0ebdcff).into()),
|
||||
success_border: Some(rgba(0xc8dcc1ff).into()),
|
||||
unreachable: Some(rgba(0x7f8188ff).into()),
|
||||
unreachable_background: Some(rgba(0xdcdcddff).into()),
|
||||
unreachable_border: Some(rgba(0xc9c9caff).into()),
|
||||
warning: Some(rgba(0xdec184ff).into()),
|
||||
warning_background: Some(rgba(0xfaf2e6ff).into()),
|
||||
warning_border: Some(rgba(0xf5e8d2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x5c79e2ff).into(),
|
||||
background: rgba(0x5c79e2ff).into(),
|
||||
selection: rgba(0x5c79e23d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x994fa6ff).into(),
|
||||
background: rgba(0x994fa6ff).into(),
|
||||
selection: rgba(0x994fa63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xad6f27ff).into(),
|
||||
background: rgba(0xad6f27ff).into(),
|
||||
selection: rgba(0xad6f273d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xa44aabff).into(),
|
||||
background: rgba(0xa44aabff).into(),
|
||||
selection: rgba(0xa44aab3d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x3b82b7ff).into(),
|
||||
background: rgba(0x3b82b7ff).into(),
|
||||
selection: rgba(0x3b82b73d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xd36151ff).into(),
|
||||
background: rgba(0xd36151ff).into(),
|
||||
selection: rgba(0xd361513d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xdec184ff).into(),
|
||||
background: rgba(0xdec184ff).into(),
|
||||
selection: rgba(0xdec1843d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x669f59ff).into(),
|
||||
background: rgba(0x669f59ff).into(),
|
||||
selection: rgba(0x669f593d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xa2a3a7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x7c7e86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x669f59ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9295beff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xa449abff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9c9fc7ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x4d4f52ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x4d4f52ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xb92c46ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x659f58ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x7c7e86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f27ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5c79e2ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x659f58ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xd36050ff).into()),
|
||||
font_weight: Some(UserFontWeight(400.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x3982b7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x383a41ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xad6f26ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5b79e3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,464 @@ pub fn rose_pine() -> UserThemeFamily {
|
||||
name: "Rosé Pine".into(),
|
||||
author: "Zed Industries".into(),
|
||||
themes: vec![
|
||||
UserTheme {
|
||||
name: "Rosé Pine".into(),
|
||||
appearance: Appearance::Dark,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0x423f55ff).into()),
|
||||
border_variant: Some(rgba(0x232132ff).into()),
|
||||
border_focused: Some(rgba(0x435255ff).into()),
|
||||
border_selected: Some(rgba(0x435255ff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0x353347ff).into()),
|
||||
elevated_surface_background: Some(rgba(0x1d1b2aff).into()),
|
||||
surface_background: Some(rgba(0x1d1b2aff).into()),
|
||||
background: Some(rgba(0x292739ff).into()),
|
||||
panel_background: Some(rgba(0x1d1b2aff).into()),
|
||||
element_background: Some(rgba(0x1d1b2aff).into()),
|
||||
element_hover: Some(rgba(0x232132ff).into()),
|
||||
element_active: Some(rgba(0x403e53ff).into()),
|
||||
element_selected: Some(rgba(0x403e53ff).into()),
|
||||
element_disabled: Some(rgba(0x1d1b2aff).into()),
|
||||
drop_target_background: Some(rgba(0x75718e80).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0x232132ff).into()),
|
||||
ghost_element_active: Some(rgba(0x403e53ff).into()),
|
||||
ghost_element_selected: Some(rgba(0x403e53ff).into()),
|
||||
ghost_element_disabled: Some(rgba(0x1d1b2aff).into()),
|
||||
text: Some(rgba(0xe0def4ff).into()),
|
||||
text_muted: Some(rgba(0x75718eff).into()),
|
||||
text_placeholder: Some(rgba(0x2f2b43ff).into()),
|
||||
text_disabled: Some(rgba(0x2f2b43ff).into()),
|
||||
text_accent: Some(rgba(0x9cced7ff).into()),
|
||||
icon: Some(rgba(0xe0def4ff).into()),
|
||||
icon_muted: Some(rgba(0x75718eff).into()),
|
||||
icon_disabled: Some(rgba(0x2f2b43ff).into()),
|
||||
icon_placeholder: Some(rgba(0x75718eff).into()),
|
||||
icon_accent: Some(rgba(0x9cced7ff).into()),
|
||||
status_bar_background: Some(rgba(0x292739ff).into()),
|
||||
title_bar_background: Some(rgba(0x292739ff).into()),
|
||||
toolbar_background: Some(rgba(0x191724ff).into()),
|
||||
tab_bar_background: Some(rgba(0x1d1b2aff).into()),
|
||||
tab_inactive_background: Some(rgba(0x1d1b2aff).into()),
|
||||
tab_active_background: Some(rgba(0x191724ff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0xe0def44c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0x232132ff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0x232132ff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0x1c1a29ff).into()),
|
||||
editor_foreground: Some(rgba(0xe0def4ff).into()),
|
||||
editor_background: Some(rgba(0x191724ff).into()),
|
||||
editor_gutter_background: Some(rgba(0x191724ff).into()),
|
||||
editor_subheader_background: Some(rgba(0x1d1b2aff).into()),
|
||||
editor_active_line_background: Some(rgba(0x1d1b2abf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0x1d1b2aff).into()),
|
||||
editor_line_number: Some(rgba(0xe0def459).into()),
|
||||
editor_active_line_number: Some(rgba(0xe0def4ff).into()),
|
||||
editor_invisible: Some(rgba(0x75718eff).into()),
|
||||
editor_wrap_guide: Some(rgba(0xe0def40d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0xe0def41a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x9cced71a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0x28253c66).into()),
|
||||
terminal_background: Some(rgba(0x191724ff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0x403d55ff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0x31614fff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0x4c3b47ff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0x203a46ff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0x191724ff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xea6f92ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x9cced7ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0x9d7691ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x32748fff).into()),
|
||||
terminal_ansi_white: Some(rgba(0xe0def4ff).into()),
|
||||
link_text_hover: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xf5c177ff).into()),
|
||||
conflict_background: Some(rgba(0x50341aff).into()),
|
||||
conflict_border: Some(rgba(0x6d4d2bff).into()),
|
||||
created: Some(rgba(0x5dc2a3ff).into()),
|
||||
created_background: Some(rgba(0x182e23ff).into()),
|
||||
created_border: Some(rgba(0x254839ff).into()),
|
||||
deleted: Some(rgba(0xea6f92ff).into()),
|
||||
deleted_background: Some(rgba(0x431820ff).into()),
|
||||
deleted_border: Some(rgba(0x612834ff).into()),
|
||||
error: Some(rgba(0xea6f92ff).into()),
|
||||
error_background: Some(rgba(0x431820ff).into()),
|
||||
error_border: Some(rgba(0x612834ff).into()),
|
||||
hidden: Some(rgba(0x2f2b43ff).into()),
|
||||
hidden_background: Some(rgba(0x292739ff).into()),
|
||||
hidden_border: Some(rgba(0x353347ff).into()),
|
||||
hint: Some(rgba(0x5e768cff).into()),
|
||||
hint_background: Some(rgba(0x2f3739ff).into()),
|
||||
hint_border: Some(rgba(0x435255ff).into()),
|
||||
ignored: Some(rgba(0x75718eff).into()),
|
||||
ignored_background: Some(rgba(0x292739ff).into()),
|
||||
ignored_border: Some(rgba(0x423f55ff).into()),
|
||||
info: Some(rgba(0x9cced7ff).into()),
|
||||
info_background: Some(rgba(0x2f3739ff).into()),
|
||||
info_border: Some(rgba(0x435255ff).into()),
|
||||
modified: Some(rgba(0xf5c177ff).into()),
|
||||
modified_background: Some(rgba(0x50341aff).into()),
|
||||
modified_border: Some(rgba(0x6d4d2bff).into()),
|
||||
predictive: Some(rgba(0x556b81ff).into()),
|
||||
predictive_background: Some(rgba(0x182e23ff).into()),
|
||||
predictive_border: Some(rgba(0x254839ff).into()),
|
||||
renamed: Some(rgba(0x9cced7ff).into()),
|
||||
renamed_background: Some(rgba(0x2f3739ff).into()),
|
||||
renamed_border: Some(rgba(0x435255ff).into()),
|
||||
success: Some(rgba(0x5dc2a3ff).into()),
|
||||
success_background: Some(rgba(0x182e23ff).into()),
|
||||
success_border: Some(rgba(0x254839ff).into()),
|
||||
unreachable: Some(rgba(0x75718eff).into()),
|
||||
unreachable_background: Some(rgba(0x292739ff).into()),
|
||||
unreachable_border: Some(rgba(0x423f55ff).into()),
|
||||
warning: Some(rgba(0xf5c177ff).into()),
|
||||
warning_background: Some(rgba(0x50341aff).into()),
|
||||
warning_border: Some(rgba(0x6d4d2bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x9cced7ff).into(),
|
||||
background: rgba(0x9cced7ff).into(),
|
||||
selection: rgba(0x9cced73d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x9d7691ff).into(),
|
||||
background: rgba(0x9d7691ff).into(),
|
||||
selection: rgba(0x9d76913d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xc4a7e6ff).into(),
|
||||
background: rgba(0xc4a7e6ff).into(),
|
||||
selection: rgba(0xc4a7e63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xc4a7e6ff).into(),
|
||||
background: rgba(0xc4a7e6ff).into(),
|
||||
selection: rgba(0xc4a7e63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x32748fff).into(),
|
||||
background: rgba(0x32748fff).into(),
|
||||
selection: rgba(0x32748f3d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xea6f92ff).into(),
|
||||
background: rgba(0xea6f92ff).into(),
|
||||
selection: rgba(0xea6f923d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xf5c177ff).into(),
|
||||
background: rgba(0xf5c177ff).into(),
|
||||
selection: rgba(0xf5c1773d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x5dc2a3ff).into(),
|
||||
background: rgba(0x5dc2a3ff).into(),
|
||||
selection: rgba(0x5dc2a33d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x6e6a86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x777390ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5dc2a3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function.method".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5e768cff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x31748fff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
font_style: Some(UserFontStyle::Normal),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5dc2a3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x31748fff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x556b81ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x908caaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xf6c177ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x777390ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xf6c177ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type.builtin".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "Rosé Pine Dawn".into(),
|
||||
appearance: Appearance::Light,
|
||||
@ -931,464 +1389,6 @@ pub fn rose_pine() -> UserThemeFamily {
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "Rosé Pine".into(),
|
||||
appearance: Appearance::Dark,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0x423f55ff).into()),
|
||||
border_variant: Some(rgba(0x232132ff).into()),
|
||||
border_focused: Some(rgba(0x435255ff).into()),
|
||||
border_selected: Some(rgba(0x435255ff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0x353347ff).into()),
|
||||
elevated_surface_background: Some(rgba(0x1d1b2aff).into()),
|
||||
surface_background: Some(rgba(0x1d1b2aff).into()),
|
||||
background: Some(rgba(0x292739ff).into()),
|
||||
panel_background: Some(rgba(0x1d1b2aff).into()),
|
||||
element_background: Some(rgba(0x1d1b2aff).into()),
|
||||
element_hover: Some(rgba(0x232132ff).into()),
|
||||
element_active: Some(rgba(0x403e53ff).into()),
|
||||
element_selected: Some(rgba(0x403e53ff).into()),
|
||||
element_disabled: Some(rgba(0x1d1b2aff).into()),
|
||||
drop_target_background: Some(rgba(0x75718e80).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0x232132ff).into()),
|
||||
ghost_element_active: Some(rgba(0x403e53ff).into()),
|
||||
ghost_element_selected: Some(rgba(0x403e53ff).into()),
|
||||
ghost_element_disabled: Some(rgba(0x1d1b2aff).into()),
|
||||
text: Some(rgba(0xe0def4ff).into()),
|
||||
text_muted: Some(rgba(0x75718eff).into()),
|
||||
text_placeholder: Some(rgba(0x2f2b43ff).into()),
|
||||
text_disabled: Some(rgba(0x2f2b43ff).into()),
|
||||
text_accent: Some(rgba(0x9cced7ff).into()),
|
||||
icon: Some(rgba(0xe0def4ff).into()),
|
||||
icon_muted: Some(rgba(0x75718eff).into()),
|
||||
icon_disabled: Some(rgba(0x2f2b43ff).into()),
|
||||
icon_placeholder: Some(rgba(0x75718eff).into()),
|
||||
icon_accent: Some(rgba(0x9cced7ff).into()),
|
||||
status_bar_background: Some(rgba(0x292739ff).into()),
|
||||
title_bar_background: Some(rgba(0x292739ff).into()),
|
||||
toolbar_background: Some(rgba(0x191724ff).into()),
|
||||
tab_bar_background: Some(rgba(0x1d1b2aff).into()),
|
||||
tab_inactive_background: Some(rgba(0x1d1b2aff).into()),
|
||||
tab_active_background: Some(rgba(0x191724ff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0xe0def44c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0x232132ff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0x232132ff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0x1c1a29ff).into()),
|
||||
editor_foreground: Some(rgba(0xe0def4ff).into()),
|
||||
editor_background: Some(rgba(0x191724ff).into()),
|
||||
editor_gutter_background: Some(rgba(0x191724ff).into()),
|
||||
editor_subheader_background: Some(rgba(0x1d1b2aff).into()),
|
||||
editor_active_line_background: Some(rgba(0x1d1b2abf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0x1d1b2aff).into()),
|
||||
editor_line_number: Some(rgba(0xe0def459).into()),
|
||||
editor_active_line_number: Some(rgba(0xe0def4ff).into()),
|
||||
editor_invisible: Some(rgba(0x75718eff).into()),
|
||||
editor_wrap_guide: Some(rgba(0xe0def40d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0xe0def41a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x9cced71a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0x28253c66).into()),
|
||||
terminal_background: Some(rgba(0x191724ff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0x403d55ff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0x7e3647ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0x31614fff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0x8a653bff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0x566c70ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0x4c3b47ff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0x203a46ff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0xe0def4ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0x191724ff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xea6f92ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x5dc2a3ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xf5c177ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x9cced7ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0x9d7691ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x32748fff).into()),
|
||||
terminal_ansi_white: Some(rgba(0xe0def4ff).into()),
|
||||
link_text_hover: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xf5c177ff).into()),
|
||||
conflict_background: Some(rgba(0x50341aff).into()),
|
||||
conflict_border: Some(rgba(0x6d4d2bff).into()),
|
||||
created: Some(rgba(0x5dc2a3ff).into()),
|
||||
created_background: Some(rgba(0x182e23ff).into()),
|
||||
created_border: Some(rgba(0x254839ff).into()),
|
||||
deleted: Some(rgba(0xea6f92ff).into()),
|
||||
deleted_background: Some(rgba(0x431820ff).into()),
|
||||
deleted_border: Some(rgba(0x612834ff).into()),
|
||||
error: Some(rgba(0xea6f92ff).into()),
|
||||
error_background: Some(rgba(0x431820ff).into()),
|
||||
error_border: Some(rgba(0x612834ff).into()),
|
||||
hidden: Some(rgba(0x2f2b43ff).into()),
|
||||
hidden_background: Some(rgba(0x292739ff).into()),
|
||||
hidden_border: Some(rgba(0x353347ff).into()),
|
||||
hint: Some(rgba(0x5e768cff).into()),
|
||||
hint_background: Some(rgba(0x2f3739ff).into()),
|
||||
hint_border: Some(rgba(0x435255ff).into()),
|
||||
ignored: Some(rgba(0x75718eff).into()),
|
||||
ignored_background: Some(rgba(0x292739ff).into()),
|
||||
ignored_border: Some(rgba(0x423f55ff).into()),
|
||||
info: Some(rgba(0x9cced7ff).into()),
|
||||
info_background: Some(rgba(0x2f3739ff).into()),
|
||||
info_border: Some(rgba(0x435255ff).into()),
|
||||
modified: Some(rgba(0xf5c177ff).into()),
|
||||
modified_background: Some(rgba(0x50341aff).into()),
|
||||
modified_border: Some(rgba(0x6d4d2bff).into()),
|
||||
predictive: Some(rgba(0x556b81ff).into()),
|
||||
predictive_background: Some(rgba(0x182e23ff).into()),
|
||||
predictive_border: Some(rgba(0x254839ff).into()),
|
||||
renamed: Some(rgba(0x9cced7ff).into()),
|
||||
renamed_background: Some(rgba(0x2f3739ff).into()),
|
||||
renamed_border: Some(rgba(0x435255ff).into()),
|
||||
success: Some(rgba(0x5dc2a3ff).into()),
|
||||
success_background: Some(rgba(0x182e23ff).into()),
|
||||
success_border: Some(rgba(0x254839ff).into()),
|
||||
unreachable: Some(rgba(0x75718eff).into()),
|
||||
unreachable_background: Some(rgba(0x292739ff).into()),
|
||||
unreachable_border: Some(rgba(0x423f55ff).into()),
|
||||
warning: Some(rgba(0xf5c177ff).into()),
|
||||
warning_background: Some(rgba(0x50341aff).into()),
|
||||
warning_border: Some(rgba(0x6d4d2bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x9cced7ff).into(),
|
||||
background: rgba(0x9cced7ff).into(),
|
||||
selection: rgba(0x9cced73d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x9d7691ff).into(),
|
||||
background: rgba(0x9d7691ff).into(),
|
||||
selection: rgba(0x9d76913d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xc4a7e6ff).into(),
|
||||
background: rgba(0xc4a7e6ff).into(),
|
||||
selection: rgba(0xc4a7e63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xc4a7e6ff).into(),
|
||||
background: rgba(0xc4a7e6ff).into(),
|
||||
selection: rgba(0xc4a7e63d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x32748fff).into(),
|
||||
background: rgba(0x32748fff).into(),
|
||||
selection: rgba(0x32748f3d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xea6f92ff).into(),
|
||||
background: rgba(0xea6f92ff).into(),
|
||||
selection: rgba(0xea6f923d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xf5c177ff).into(),
|
||||
background: rgba(0xf5c177ff).into(),
|
||||
selection: rgba(0xf5c1773d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x5dc2a3ff).into(),
|
||||
background: rgba(0x5dc2a3ff).into(),
|
||||
selection: rgba(0x5dc2a33d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x6e6a86ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x777390ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5dc2a3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function.method".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5e768cff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x31748fff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
font_style: Some(UserFontStyle::Normal),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xebbcbaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5dc2a3ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x31748fff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x556b81ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x908caaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9d99b6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xf6c177ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x777390ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xc4a7e6ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xf6c177ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type.builtin".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9ccfd8ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xe0def4ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x9cced7ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -15,450 +15,6 @@ pub fn solarized() -> UserThemeFamily {
|
||||
name: "Solarized".into(),
|
||||
author: "Zed Industries".into(),
|
||||
themes: vec![
|
||||
UserTheme {
|
||||
name: "Solarized Light".into(),
|
||||
appearance: Appearance::Light,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0x9faaa8ff).into()),
|
||||
border_variant: Some(rgba(0xdcdacbff).into()),
|
||||
border_focused: Some(rgba(0xbfd3efff).into()),
|
||||
border_selected: Some(rgba(0xbfd3efff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0xb7bdb6ff).into()),
|
||||
elevated_surface_background: Some(rgba(0xf3eddaff).into()),
|
||||
surface_background: Some(rgba(0xf3eddaff).into()),
|
||||
background: Some(rgba(0xcfd0c4ff).into()),
|
||||
panel_background: Some(rgba(0xf3eddaff).into()),
|
||||
element_background: Some(rgba(0xf3eddaff).into()),
|
||||
element_hover: Some(rgba(0xdcdacbff).into()),
|
||||
element_active: Some(rgba(0xa2aca9ff).into()),
|
||||
element_selected: Some(rgba(0xa2aca9ff).into()),
|
||||
element_disabled: Some(rgba(0xf3eddaff).into()),
|
||||
drop_target_background: Some(rgba(0x34555e80).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0xdcdacbff).into()),
|
||||
ghost_element_active: Some(rgba(0xa2aca9ff).into()),
|
||||
ghost_element_selected: Some(rgba(0xa2aca9ff).into()),
|
||||
ghost_element_disabled: Some(rgba(0xf3eddaff).into()),
|
||||
text: Some(rgba(0x002b36ff).into()),
|
||||
text_muted: Some(rgba(0x34555eff).into()),
|
||||
text_placeholder: Some(rgba(0x6a7f86ff).into()),
|
||||
text_disabled: Some(rgba(0x6a7f86ff).into()),
|
||||
text_accent: Some(rgba(0x298bd1ff).into()),
|
||||
icon: Some(rgba(0x002b36ff).into()),
|
||||
icon_muted: Some(rgba(0x34555eff).into()),
|
||||
icon_disabled: Some(rgba(0x6a7f86ff).into()),
|
||||
icon_placeholder: Some(rgba(0x34555eff).into()),
|
||||
icon_accent: Some(rgba(0x298bd1ff).into()),
|
||||
status_bar_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
title_bar_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
toolbar_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
tab_bar_background: Some(rgba(0xf3eddaff).into()),
|
||||
tab_inactive_background: Some(rgba(0xf3eddaff).into()),
|
||||
tab_active_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0x002b364c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0xdcdacbff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0xdcdacbff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0xf5eedbff).into()),
|
||||
editor_foreground: Some(rgba(0x002b36ff).into()),
|
||||
editor_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
editor_gutter_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
editor_subheader_background: Some(rgba(0xf3eddaff).into()),
|
||||
editor_active_line_background: Some(rgba(0xf3eddabf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0xf3eddaff).into()),
|
||||
editor_line_number: Some(rgba(0x002b3659).into()),
|
||||
editor_active_line_number: Some(rgba(0x002b36ff).into()),
|
||||
editor_invisible: Some(rgba(0x34555eff).into()),
|
||||
editor_wrap_guide: Some(rgba(0x002b360d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0x002b361a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x298bd11a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0x6d828866).into()),
|
||||
terminal_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0x7b8e91ff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0xfaa091ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0xc6cb8bff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0xe1c28aff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0xa5c3e9ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0xf0a2bfff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0x9fd0cbff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0x002b36ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0xfdf6e3ff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xdc3330ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x859904ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xb58904ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x298bd1ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0xd33882ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()),
|
||||
terminal_ansi_white: Some(rgba(0x002b36ff).into()),
|
||||
link_text_hover: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xb58904ff).into()),
|
||||
conflict_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
conflict_border: Some(rgba(0xebd3aaff).into()),
|
||||
created: Some(rgba(0x859904ff).into()),
|
||||
created_background: Some(rgba(0xe9ead0ff).into()),
|
||||
created_border: Some(rgba(0xd6d9abff).into()),
|
||||
deleted: Some(rgba(0xdc3330ff).into()),
|
||||
deleted_background: Some(rgba(0xffd9d2ff).into()),
|
||||
deleted_border: Some(rgba(0xffbbafff).into()),
|
||||
error: Some(rgba(0xdc3330ff).into()),
|
||||
error_background: Some(rgba(0xffd9d2ff).into()),
|
||||
error_border: Some(rgba(0xffbbafff).into()),
|
||||
hidden: Some(rgba(0x6a7f86ff).into()),
|
||||
hidden_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
hidden_border: Some(rgba(0xb7bdb6ff).into()),
|
||||
hint: Some(rgba(0x5889a3ff).into()),
|
||||
hint_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
hint_border: Some(rgba(0xbfd3efff).into()),
|
||||
ignored: Some(rgba(0x34555eff).into()),
|
||||
ignored_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
ignored_border: Some(rgba(0x9faaa8ff).into()),
|
||||
info: Some(rgba(0x298bd1ff).into()),
|
||||
info_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
info_border: Some(rgba(0xbfd3efff).into()),
|
||||
modified: Some(rgba(0xb58904ff).into()),
|
||||
modified_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
modified_border: Some(rgba(0xebd3aaff).into()),
|
||||
predictive: Some(rgba(0x679aafff).into()),
|
||||
predictive_background: Some(rgba(0xe9ead0ff).into()),
|
||||
predictive_border: Some(rgba(0xd6d9abff).into()),
|
||||
renamed: Some(rgba(0x298bd1ff).into()),
|
||||
renamed_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
renamed_border: Some(rgba(0xbfd3efff).into()),
|
||||
success: Some(rgba(0x859904ff).into()),
|
||||
success_background: Some(rgba(0xe9ead0ff).into()),
|
||||
success_border: Some(rgba(0xd6d9abff).into()),
|
||||
unreachable: Some(rgba(0x34555eff).into()),
|
||||
unreachable_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
unreachable_border: Some(rgba(0x9faaa8ff).into()),
|
||||
warning: Some(rgba(0xb58904ff).into()),
|
||||
warning_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
warning_border: Some(rgba(0xebd3aaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x298bd1ff).into(),
|
||||
background: rgba(0x298bd1ff).into(),
|
||||
selection: rgba(0x298bd13d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xd33882ff).into(),
|
||||
background: rgba(0xd33882ff).into(),
|
||||
selection: rgba(0xd338823d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xcb4c18ff).into(),
|
||||
background: rgba(0xcb4c18ff).into(),
|
||||
selection: rgba(0xcb4c183d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x6d71c4ff).into(),
|
||||
background: rgba(0x6d71c4ff).into(),
|
||||
selection: rgba(0x6d71c43d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x2ca198ff).into(),
|
||||
background: rgba(0x2ca198ff).into(),
|
||||
selection: rgba(0x2ca1983d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xdc3330ff).into(),
|
||||
background: rgba(0xdc3330ff).into(),
|
||||
selection: rgba(0xdc33303d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xb58904ff).into(),
|
||||
background: rgba(0xb58904ff).into(),
|
||||
selection: rgba(0xb589043d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x859904ff).into(),
|
||||
background: rgba(0x859904ff).into(),
|
||||
selection: rgba(0x8599043d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xb58904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5889a3ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x679aafff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x2ca198ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "Solarized Dark".into(),
|
||||
appearance: Appearance::Dark,
|
||||
@ -903,6 +459,450 @@ pub fn solarized() -> UserThemeFamily {
|
||||
}),
|
||||
},
|
||||
},
|
||||
UserTheme {
|
||||
name: "Solarized Light".into(),
|
||||
appearance: Appearance::Light,
|
||||
styles: UserThemeStylesRefinement {
|
||||
colors: ThemeColorsRefinement {
|
||||
border: Some(rgba(0x9faaa8ff).into()),
|
||||
border_variant: Some(rgba(0xdcdacbff).into()),
|
||||
border_focused: Some(rgba(0xbfd3efff).into()),
|
||||
border_selected: Some(rgba(0xbfd3efff).into()),
|
||||
border_transparent: Some(rgba(0x00000000).into()),
|
||||
border_disabled: Some(rgba(0xb7bdb6ff).into()),
|
||||
elevated_surface_background: Some(rgba(0xf3eddaff).into()),
|
||||
surface_background: Some(rgba(0xf3eddaff).into()),
|
||||
background: Some(rgba(0xcfd0c4ff).into()),
|
||||
panel_background: Some(rgba(0xf3eddaff).into()),
|
||||
element_background: Some(rgba(0xf3eddaff).into()),
|
||||
element_hover: Some(rgba(0xdcdacbff).into()),
|
||||
element_active: Some(rgba(0xa2aca9ff).into()),
|
||||
element_selected: Some(rgba(0xa2aca9ff).into()),
|
||||
element_disabled: Some(rgba(0xf3eddaff).into()),
|
||||
drop_target_background: Some(rgba(0x34555e80).into()),
|
||||
ghost_element_background: Some(rgba(0x00000000).into()),
|
||||
ghost_element_hover: Some(rgba(0xdcdacbff).into()),
|
||||
ghost_element_active: Some(rgba(0xa2aca9ff).into()),
|
||||
ghost_element_selected: Some(rgba(0xa2aca9ff).into()),
|
||||
ghost_element_disabled: Some(rgba(0xf3eddaff).into()),
|
||||
text: Some(rgba(0x002b36ff).into()),
|
||||
text_muted: Some(rgba(0x34555eff).into()),
|
||||
text_placeholder: Some(rgba(0x6a7f86ff).into()),
|
||||
text_disabled: Some(rgba(0x6a7f86ff).into()),
|
||||
text_accent: Some(rgba(0x298bd1ff).into()),
|
||||
icon: Some(rgba(0x002b36ff).into()),
|
||||
icon_muted: Some(rgba(0x34555eff).into()),
|
||||
icon_disabled: Some(rgba(0x6a7f86ff).into()),
|
||||
icon_placeholder: Some(rgba(0x34555eff).into()),
|
||||
icon_accent: Some(rgba(0x298bd1ff).into()),
|
||||
status_bar_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
title_bar_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
toolbar_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
tab_bar_background: Some(rgba(0xf3eddaff).into()),
|
||||
tab_inactive_background: Some(rgba(0xf3eddaff).into()),
|
||||
tab_active_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
scrollbar_thumb_background: Some(rgba(0x002b364c).into()),
|
||||
scrollbar_thumb_hover_background: Some(rgba(0xdcdacbff).into()),
|
||||
scrollbar_thumb_border: Some(rgba(0xdcdacbff).into()),
|
||||
scrollbar_track_background: Some(rgba(0x00000000).into()),
|
||||
scrollbar_track_border: Some(rgba(0xf5eedbff).into()),
|
||||
editor_foreground: Some(rgba(0x002b36ff).into()),
|
||||
editor_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
editor_gutter_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
editor_subheader_background: Some(rgba(0xf3eddaff).into()),
|
||||
editor_active_line_background: Some(rgba(0xf3eddabf).into()),
|
||||
editor_highlighted_line_background: Some(rgba(0xf3eddaff).into()),
|
||||
editor_line_number: Some(rgba(0x002b3659).into()),
|
||||
editor_active_line_number: Some(rgba(0x002b36ff).into()),
|
||||
editor_invisible: Some(rgba(0x34555eff).into()),
|
||||
editor_wrap_guide: Some(rgba(0x002b360d).into()),
|
||||
editor_active_wrap_guide: Some(rgba(0x002b361a).into()),
|
||||
editor_document_highlight_read_background: Some(rgba(0x298bd11a).into()),
|
||||
editor_document_highlight_write_background: Some(rgba(0x6d828866).into()),
|
||||
terminal_background: Some(rgba(0xfdf6e3ff).into()),
|
||||
terminal_ansi_bright_black: Some(rgba(0x7b8e91ff).into()),
|
||||
terminal_ansi_bright_red: Some(rgba(0xfaa091ff).into()),
|
||||
terminal_ansi_bright_green: Some(rgba(0xc6cb8bff).into()),
|
||||
terminal_ansi_bright_yellow: Some(rgba(0xe1c28aff).into()),
|
||||
terminal_ansi_bright_blue: Some(rgba(0xa5c3e9ff).into()),
|
||||
terminal_ansi_bright_magenta: Some(rgba(0xf0a2bfff).into()),
|
||||
terminal_ansi_bright_cyan: Some(rgba(0x9fd0cbff).into()),
|
||||
terminal_ansi_bright_white: Some(rgba(0x002b36ff).into()),
|
||||
terminal_ansi_black: Some(rgba(0xfdf6e3ff).into()),
|
||||
terminal_ansi_red: Some(rgba(0xdc3330ff).into()),
|
||||
terminal_ansi_green: Some(rgba(0x859904ff).into()),
|
||||
terminal_ansi_yellow: Some(rgba(0xb58904ff).into()),
|
||||
terminal_ansi_blue: Some(rgba(0x298bd1ff).into()),
|
||||
terminal_ansi_magenta: Some(rgba(0xd33882ff).into()),
|
||||
terminal_ansi_cyan: Some(rgba(0x2ca198ff).into()),
|
||||
terminal_ansi_white: Some(rgba(0x002b36ff).into()),
|
||||
link_text_hover: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
status: StatusColorsRefinement {
|
||||
conflict: Some(rgba(0xb58904ff).into()),
|
||||
conflict_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
conflict_border: Some(rgba(0xebd3aaff).into()),
|
||||
created: Some(rgba(0x859904ff).into()),
|
||||
created_background: Some(rgba(0xe9ead0ff).into()),
|
||||
created_border: Some(rgba(0xd6d9abff).into()),
|
||||
deleted: Some(rgba(0xdc3330ff).into()),
|
||||
deleted_background: Some(rgba(0xffd9d2ff).into()),
|
||||
deleted_border: Some(rgba(0xffbbafff).into()),
|
||||
error: Some(rgba(0xdc3330ff).into()),
|
||||
error_background: Some(rgba(0xffd9d2ff).into()),
|
||||
error_border: Some(rgba(0xffbbafff).into()),
|
||||
hidden: Some(rgba(0x6a7f86ff).into()),
|
||||
hidden_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
hidden_border: Some(rgba(0xb7bdb6ff).into()),
|
||||
hint: Some(rgba(0x5889a3ff).into()),
|
||||
hint_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
hint_border: Some(rgba(0xbfd3efff).into()),
|
||||
ignored: Some(rgba(0x34555eff).into()),
|
||||
ignored_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
ignored_border: Some(rgba(0x9faaa8ff).into()),
|
||||
info: Some(rgba(0x298bd1ff).into()),
|
||||
info_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
info_border: Some(rgba(0xbfd3efff).into()),
|
||||
modified: Some(rgba(0xb58904ff).into()),
|
||||
modified_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
modified_border: Some(rgba(0xebd3aaff).into()),
|
||||
predictive: Some(rgba(0x679aafff).into()),
|
||||
predictive_background: Some(rgba(0xe9ead0ff).into()),
|
||||
predictive_border: Some(rgba(0xd6d9abff).into()),
|
||||
renamed: Some(rgba(0x298bd1ff).into()),
|
||||
renamed_background: Some(rgba(0xdbe6f6ff).into()),
|
||||
renamed_border: Some(rgba(0xbfd3efff).into()),
|
||||
success: Some(rgba(0x859904ff).into()),
|
||||
success_background: Some(rgba(0xe9ead0ff).into()),
|
||||
success_border: Some(rgba(0xd6d9abff).into()),
|
||||
unreachable: Some(rgba(0x34555eff).into()),
|
||||
unreachable_background: Some(rgba(0xcfd0c4ff).into()),
|
||||
unreachable_border: Some(rgba(0x9faaa8ff).into()),
|
||||
warning: Some(rgba(0xb58904ff).into()),
|
||||
warning_background: Some(rgba(0xf5e6d0ff).into()),
|
||||
warning_border: Some(rgba(0xebd3aaff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
player: Some(PlayerColors(vec![
|
||||
PlayerColor {
|
||||
cursor: rgba(0x298bd1ff).into(),
|
||||
background: rgba(0x298bd1ff).into(),
|
||||
selection: rgba(0x298bd13d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xd33882ff).into(),
|
||||
background: rgba(0xd33882ff).into(),
|
||||
selection: rgba(0xd338823d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xcb4c18ff).into(),
|
||||
background: rgba(0xcb4c18ff).into(),
|
||||
selection: rgba(0xcb4c183d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x6d71c4ff).into(),
|
||||
background: rgba(0x6d71c4ff).into(),
|
||||
selection: rgba(0x6d71c43d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x2ca198ff).into(),
|
||||
background: rgba(0x2ca198ff).into(),
|
||||
selection: rgba(0x2ca1983d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xdc3330ff).into(),
|
||||
background: rgba(0xdc3330ff).into(),
|
||||
selection: rgba(0xdc33303d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0xb58904ff).into(),
|
||||
background: rgba(0xb58904ff).into(),
|
||||
selection: rgba(0xb589043d).into(),
|
||||
},
|
||||
PlayerColor {
|
||||
cursor: rgba(0x859904ff).into(),
|
||||
background: rgba(0x859904ff).into(),
|
||||
selection: rgba(0x8599043d).into(),
|
||||
},
|
||||
])),
|
||||
syntax: Some(UserSyntaxTheme {
|
||||
highlights: vec![
|
||||
(
|
||||
"attribute".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"boolean".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"comment.doc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"constructor".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"embedded".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"emphasis.strong".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"enum".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"function".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xb58904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"hint".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x5889a3ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"keyword".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"label".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_text".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"link_uri".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"number".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x859904ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"operator".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"predictive".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x679aafff).into()),
|
||||
font_style: Some(UserFontStyle::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"preproc".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"primary".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"property".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.bracket".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.delimiter".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.list_marker".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"punctuation.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x05333eff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.escape".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x30525bff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.regex".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"string.special.symbol".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"tag".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"text.literal".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0xcb4c18ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"title".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
font_weight: Some(UserFontWeight(700.0)),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"type".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x2ca198ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variable".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x002b36ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"variant".into(),
|
||||
UserHighlightStyle {
|
||||
color: Some(rgba(0x298bd1ff).into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
],
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ clap = { version = "4.4", features = ["derive"] }
|
||||
convert_case = "0.6.0"
|
||||
gpui = { path = "../gpui" }
|
||||
indexmap = { version = "1.6.2", features = ["serde"] }
|
||||
indoc.workspace = true
|
||||
json_comments = "0.2.2"
|
||||
log.workspace = true
|
||||
palette = { version = "0.7.3", default-features = false, features = ["std"] }
|
||||
|
@ -18,6 +18,7 @@ use clap::Parser;
|
||||
use convert_case::{Case, Casing};
|
||||
use gpui::serde_json;
|
||||
use indexmap::IndexMap;
|
||||
use indoc::formatdoc;
|
||||
use json_comments::StripComments;
|
||||
use log::LevelFilter;
|
||||
use serde::Deserialize;
|
||||
@ -28,7 +29,7 @@ use crate::theme_printer::UserThemeFamilyPrinter;
|
||||
use crate::vscode::VsCodeTheme;
|
||||
use crate::vscode::VsCodeThemeConverter;
|
||||
use crate::zed1::theme::Theme as Zed1Theme;
|
||||
use crate::zed1::Zed1ThemeConverter;
|
||||
use crate::zed1::{zed1_theme_licenses, Zed1ThemeConverter};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct FamilyMetadata {
|
||||
@ -200,7 +201,13 @@ fn main() -> Result<()> {
|
||||
"Summercamp",
|
||||
];
|
||||
|
||||
let mut zed1_themes_by_family: HashMap<String, Vec<UserTheme>> = HashMap::from_iter(
|
||||
let zed1_licenses_by_theme: HashMap<String, zed1::Zed1ThemeLicense> = HashMap::from_iter(
|
||||
zed1_theme_licenses()
|
||||
.into_iter()
|
||||
.map(|theme_license| (theme_license.theme.clone(), theme_license)),
|
||||
);
|
||||
|
||||
let mut zed1_themes_by_family: IndexMap<String, Vec<UserTheme>> = IndexMap::from_iter(
|
||||
zed1_theme_familes
|
||||
.into_iter()
|
||||
.map(|family| (family.to_string(), Vec::new())),
|
||||
@ -254,13 +261,44 @@ fn main() -> Result<()> {
|
||||
themes_for_family.push(theme);
|
||||
}
|
||||
|
||||
zed1_themes_by_family.sort_keys();
|
||||
|
||||
let mut licenses = Vec::new();
|
||||
|
||||
for (family, themes) in zed1_themes_by_family {
|
||||
let theme_family = UserThemeFamily {
|
||||
let mut theme_family = UserThemeFamily {
|
||||
name: family,
|
||||
author: "Zed Industries".to_string(),
|
||||
themes,
|
||||
};
|
||||
|
||||
theme_family
|
||||
.themes
|
||||
.sort_unstable_by_key(|theme| theme.name.clone());
|
||||
|
||||
for theme in &theme_family.themes {
|
||||
let license = zed1_licenses_by_theme
|
||||
.get(&theme.name)
|
||||
.ok_or_else(|| anyhow!("missing license for theme: '{}'", theme.name))?;
|
||||
|
||||
let license_header = match license.license_url.as_ref() {
|
||||
Some(license_url) => {
|
||||
format!("[{theme_name}]({license_url})", theme_name = theme.name)
|
||||
}
|
||||
None => theme.name.clone(),
|
||||
};
|
||||
|
||||
licenses.push(formatdoc!(
|
||||
"
|
||||
## {license_header}
|
||||
|
||||
{license_text}
|
||||
********************************************************************************
|
||||
",
|
||||
license_text = license.license_text
|
||||
));
|
||||
}
|
||||
|
||||
theme_families.push(theme_family);
|
||||
}
|
||||
|
||||
@ -357,6 +395,12 @@ fn main() -> Result<()> {
|
||||
|
||||
mod_rs_file.write_all(mod_rs_contents.as_bytes())?;
|
||||
|
||||
log::info!("Writing LICENSES file...");
|
||||
|
||||
let mut licenses_file = File::create(themes_output_path.join(format!("LICENSES")))?;
|
||||
|
||||
licenses_file.write_all(licenses.join("\n").as_bytes())?;
|
||||
|
||||
log::info!("Formatting themes...");
|
||||
|
||||
let format_result = format_themes_crate()
|
||||
|
@ -1,4 +1,6 @@
|
||||
mod converter;
|
||||
mod licenses;
|
||||
pub mod theme;
|
||||
|
||||
pub use converter::*;
|
||||
pub use licenses::*;
|
||||
|
1192
crates/theme_importer/src/zed1/licenses.rs
Normal file
1192
crates/theme_importer/src/zed1/licenses.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -92,6 +92,13 @@ impl Selectable for Button {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableButton for Button {
|
||||
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||
self.base = self.base.selected_style(style);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Disableable for Button {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.base = self.base.disabled(disabled);
|
||||
|
@ -12,6 +12,7 @@ pub(super) struct ButtonIcon {
|
||||
disabled: bool,
|
||||
selected: bool,
|
||||
selected_icon: Option<Icon>,
|
||||
selected_style: Option<ButtonStyle>,
|
||||
}
|
||||
|
||||
impl ButtonIcon {
|
||||
@ -23,6 +24,7 @@ impl ButtonIcon {
|
||||
disabled: false,
|
||||
selected: false,
|
||||
selected_icon: None,
|
||||
selected_style: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,6 +64,13 @@ impl Selectable for ButtonIcon {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableButton for ButtonIcon {
|
||||
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||
self.selected_style = Some(style);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ButtonIcon {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
let icon = self
|
||||
@ -71,6 +80,8 @@ impl RenderOnce for ButtonIcon {
|
||||
|
||||
let icon_color = if self.disabled {
|
||||
Color::Disabled
|
||||
} else if self.selected_style.is_some() && self.selected {
|
||||
self.selected_style.unwrap().into()
|
||||
} else if self.selected {
|
||||
Color::Selected
|
||||
} else {
|
||||
|
@ -4,6 +4,10 @@ use smallvec::SmallVec;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait SelectableButton: Selectable {
|
||||
fn selected_style(self, style: ButtonStyle) -> Self;
|
||||
}
|
||||
|
||||
pub trait ButtonCommon: Clickable + Disableable {
|
||||
/// A unique element ID to identify the button.
|
||||
fn id(&self) -> &ElementId;
|
||||
@ -36,17 +40,68 @@ pub enum IconPosition {
|
||||
End,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub enum TintColor {
|
||||
#[default]
|
||||
Accent,
|
||||
Negative,
|
||||
Warning,
|
||||
}
|
||||
|
||||
impl TintColor {
|
||||
fn button_like_style(self, cx: &mut WindowContext) -> ButtonLikeStyles {
|
||||
match self {
|
||||
TintColor::Accent => ButtonLikeStyles {
|
||||
background: cx.theme().status().info_background,
|
||||
border_color: cx.theme().status().info_border,
|
||||
label_color: cx.theme().colors().text,
|
||||
icon_color: cx.theme().colors().text,
|
||||
},
|
||||
TintColor::Negative => ButtonLikeStyles {
|
||||
background: cx.theme().status().error_background,
|
||||
border_color: cx.theme().status().error_border,
|
||||
label_color: cx.theme().colors().text,
|
||||
icon_color: cx.theme().colors().text,
|
||||
},
|
||||
TintColor::Warning => ButtonLikeStyles {
|
||||
background: cx.theme().status().warning_background,
|
||||
border_color: cx.theme().status().warning_border,
|
||||
label_color: cx.theme().colors().text,
|
||||
icon_color: cx.theme().colors().text,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TintColor> for Color {
|
||||
fn from(tint: TintColor) -> Self {
|
||||
match tint {
|
||||
TintColor::Accent => Color::Accent,
|
||||
TintColor::Negative => Color::Error,
|
||||
TintColor::Warning => Color::Warning,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Used to go from ButtonStyle -> Color through tint colors.
|
||||
impl From<ButtonStyle> for Color {
|
||||
fn from(style: ButtonStyle) -> Self {
|
||||
match style {
|
||||
ButtonStyle::Tinted(tint) => tint.into(),
|
||||
_ => Color::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)]
|
||||
pub enum ButtonStyle {
|
||||
/// A filled button with a solid background color. Provides emphasis versus
|
||||
/// the more common subtle button.
|
||||
Filled,
|
||||
|
||||
/// 🚧 Under construction 🚧
|
||||
///
|
||||
/// Used to emphasize a button in some way, like a selected state, or a semantic
|
||||
/// coloring like an error or success button.
|
||||
Tinted,
|
||||
Tinted(TintColor),
|
||||
|
||||
/// The default button style, used for most buttons. Has a transparent background,
|
||||
/// but has a background color to indicate states like hover and active.
|
||||
@ -86,12 +141,7 @@ impl ButtonStyle {
|
||||
label_color: Color::Default.color(cx),
|
||||
icon_color: Color::Default.color(cx),
|
||||
},
|
||||
ButtonStyle::Tinted => ButtonLikeStyles {
|
||||
background: gpui::red(),
|
||||
border_color: gpui::red(),
|
||||
label_color: gpui::red(),
|
||||
icon_color: gpui::red(),
|
||||
},
|
||||
ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
|
||||
ButtonStyle::Subtle => ButtonLikeStyles {
|
||||
background: cx.theme().colors().ghost_element_background,
|
||||
border_color: transparent_black(),
|
||||
@ -115,12 +165,7 @@ impl ButtonStyle {
|
||||
label_color: Color::Default.color(cx),
|
||||
icon_color: Color::Default.color(cx),
|
||||
},
|
||||
ButtonStyle::Tinted => ButtonLikeStyles {
|
||||
background: gpui::red(),
|
||||
border_color: gpui::red(),
|
||||
label_color: gpui::red(),
|
||||
icon_color: gpui::red(),
|
||||
},
|
||||
ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
|
||||
ButtonStyle::Subtle => ButtonLikeStyles {
|
||||
background: cx.theme().colors().ghost_element_hover,
|
||||
border_color: transparent_black(),
|
||||
@ -146,12 +191,7 @@ impl ButtonStyle {
|
||||
label_color: Color::Default.color(cx),
|
||||
icon_color: Color::Default.color(cx),
|
||||
},
|
||||
ButtonStyle::Tinted => ButtonLikeStyles {
|
||||
background: gpui::red(),
|
||||
border_color: gpui::red(),
|
||||
label_color: gpui::red(),
|
||||
icon_color: gpui::red(),
|
||||
},
|
||||
ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
|
||||
ButtonStyle::Subtle => ButtonLikeStyles {
|
||||
background: cx.theme().colors().ghost_element_active,
|
||||
border_color: transparent_black(),
|
||||
@ -178,12 +218,7 @@ impl ButtonStyle {
|
||||
label_color: Color::Default.color(cx),
|
||||
icon_color: Color::Default.color(cx),
|
||||
},
|
||||
ButtonStyle::Tinted => ButtonLikeStyles {
|
||||
background: gpui::red(),
|
||||
border_color: gpui::red(),
|
||||
label_color: gpui::red(),
|
||||
icon_color: gpui::red(),
|
||||
},
|
||||
ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
|
||||
ButtonStyle::Subtle => ButtonLikeStyles {
|
||||
background: cx.theme().colors().ghost_element_background,
|
||||
border_color: cx.theme().colors().border_focused,
|
||||
@ -208,12 +243,7 @@ impl ButtonStyle {
|
||||
label_color: Color::Disabled.color(cx),
|
||||
icon_color: Color::Disabled.color(cx),
|
||||
},
|
||||
ButtonStyle::Tinted => ButtonLikeStyles {
|
||||
background: gpui::red(),
|
||||
border_color: gpui::red(),
|
||||
label_color: gpui::red(),
|
||||
icon_color: gpui::red(),
|
||||
},
|
||||
ButtonStyle::Tinted(tint) => tint.button_like_style(cx),
|
||||
ButtonStyle::Subtle => ButtonLikeStyles {
|
||||
background: cx.theme().colors().ghost_element_disabled,
|
||||
border_color: cx.theme().colors().border_disabled,
|
||||
@ -264,6 +294,7 @@ pub struct ButtonLike {
|
||||
pub(super) style: ButtonStyle,
|
||||
pub(super) disabled: bool,
|
||||
pub(super) selected: bool,
|
||||
pub(super) selected_style: Option<ButtonStyle>,
|
||||
pub(super) width: Option<DefiniteLength>,
|
||||
size: ButtonSize,
|
||||
rounding: Option<ButtonLikeRounding>,
|
||||
@ -280,6 +311,7 @@ impl ButtonLike {
|
||||
style: ButtonStyle::default(),
|
||||
disabled: false,
|
||||
selected: false,
|
||||
selected_style: None,
|
||||
width: None,
|
||||
size: ButtonSize::Default,
|
||||
rounding: Some(ButtonLikeRounding::All),
|
||||
@ -309,6 +341,13 @@ impl Selectable for ButtonLike {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableButton for ButtonLike {
|
||||
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||
self.selected_style = Some(style);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Clickable for ButtonLike {
|
||||
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||
self.on_click = Some(Box::new(handler));
|
||||
@ -364,6 +403,11 @@ impl ParentElement for ButtonLike {
|
||||
|
||||
impl RenderOnce for ButtonLike {
|
||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||
let style = self
|
||||
.selected_style
|
||||
.filter(|_| self.selected)
|
||||
.unwrap_or(self.style);
|
||||
|
||||
self.base
|
||||
.h_flex()
|
||||
.id(self.id.clone())
|
||||
@ -382,12 +426,12 @@ impl RenderOnce for ButtonLike {
|
||||
ButtonSize::Default | ButtonSize::Compact => this.px_1(),
|
||||
ButtonSize::None => this,
|
||||
})
|
||||
.bg(self.style.enabled(cx).background)
|
||||
.bg(style.enabled(cx).background)
|
||||
.when(self.disabled, |this| this.cursor_not_allowed())
|
||||
.when(!self.disabled, |this| {
|
||||
this.cursor_pointer()
|
||||
.hover(|hover| hover.bg(self.style.hovered(cx).background))
|
||||
.active(|active| active.bg(self.style.active(cx).background))
|
||||
.hover(|hover| hover.bg(style.hovered(cx).background))
|
||||
.active(|active| active.bg(style.active(cx).background))
|
||||
})
|
||||
.when_some(
|
||||
self.on_click.filter(|_| !self.disabled),
|
||||
|
@ -1,6 +1,6 @@
|
||||
use gpui::{AnyView, DefiniteLength};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::{prelude::*, SelectableButton};
|
||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
||||
|
||||
use super::button_icon::ButtonIcon;
|
||||
@ -55,6 +55,13 @@ impl Selectable for IconButton {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableButton for IconButton {
|
||||
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||
self.base = self.base.selected_style(style);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Clickable for IconButton {
|
||||
fn on_click(
|
||||
mut self,
|
||||
@ -109,12 +116,14 @@ impl RenderOnce for IconButton {
|
||||
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
|
||||
let is_disabled = self.base.disabled;
|
||||
let is_selected = self.base.selected;
|
||||
let selected_style = self.base.selected_style;
|
||||
|
||||
self.base.child(
|
||||
ButtonIcon::new(self.icon)
|
||||
.disabled(is_disabled)
|
||||
.selected(is_selected)
|
||||
.selected_icon(self.selected_icon)
|
||||
.when_some(selected_style, |this, style| this.selected_style(style))
|
||||
.size(self.icon_size)
|
||||
.color(self.icon_color),
|
||||
)
|
||||
|
@ -63,6 +63,13 @@ impl Selectable for ToggleButton {
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectableButton for ToggleButton {
|
||||
fn selected_style(mut self, style: ButtonStyle) -> Self {
|
||||
self.base.selected_style = Some(style);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Disableable for ToggleButton {
|
||||
fn disabled(mut self, disabled: bool) -> Self {
|
||||
self.base = self.base.disabled(disabled);
|
||||
|
@ -12,7 +12,7 @@ pub use crate::selectable::*;
|
||||
pub use crate::styles::{vh, vw};
|
||||
pub use crate::visible_on_hover::*;
|
||||
pub use crate::{h_stack, v_stack};
|
||||
pub use crate::{Button, ButtonSize, ButtonStyle, IconButton};
|
||||
pub use crate::{Button, ButtonSize, ButtonStyle, IconButton, SelectableButton};
|
||||
pub use crate::{ButtonCommon, Color, StyledExt};
|
||||
pub use crate::{Headline, HeadlineSize};
|
||||
pub use crate::{Icon, IconElement, IconPosition, IconSize};
|
||||
|
@ -59,153 +59,159 @@ pub struct WelcomePage {
|
||||
|
||||
impl Render for WelcomePage {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl IntoElement {
|
||||
h_stack().full().track_focus(&self.focus_handle).child(
|
||||
v_stack()
|
||||
.w_96()
|
||||
.gap_4()
|
||||
.mx_auto()
|
||||
.child(
|
||||
svg()
|
||||
.path("icons/logo_96.svg")
|
||||
.text_color(gpui::white())
|
||||
.w(px(96.))
|
||||
.h(px(96.))
|
||||
.mx_auto(),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_center()
|
||||
.child(Label::new("Code at the speed of thought")),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Button::new("choose-theme", "Choose a theme")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
theme_selector::toggle(
|
||||
workspace,
|
||||
&Default::default(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("choose-keymap", "Choose a keymap")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
base_keymap_picker::toggle(
|
||||
workspace,
|
||||
&Default::default(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("install-cli", "Install the CLI")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.app_mut()
|
||||
.spawn(
|
||||
|cx| async move { install_cli::install_cli(&cx).await },
|
||||
h_stack()
|
||||
.full()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.track_focus(&self.focus_handle)
|
||||
.child(
|
||||
v_stack()
|
||||
.w_96()
|
||||
.gap_4()
|
||||
.mx_auto()
|
||||
.child(
|
||||
svg()
|
||||
.path("icons/logo_96.svg")
|
||||
.text_color(gpui::white())
|
||||
.w(px(96.))
|
||||
.h(px(96.))
|
||||
.mx_auto(),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_center()
|
||||
.child(Label::new("Code at the speed of thought")),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Button::new("choose-theme", "Choose a theme")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
theme_selector::toggle(
|
||||
workspace,
|
||||
&Default::default(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("choose-keymap", "Choose a keymap")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|this, _, cx| {
|
||||
this.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
base_keymap_picker::toggle(
|
||||
workspace,
|
||||
&Default::default(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.ok();
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("install-cli", "Install the CLI")
|
||||
.full_width()
|
||||
.on_click(cx.listener(|_, _, cx| {
|
||||
cx.app_mut()
|
||||
.spawn(|cx| async move {
|
||||
install_cli::install_cli(&cx).await
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.p_3()
|
||||
.gap_2()
|
||||
.bg(cx.theme().colors().elevated_surface_background)
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.rounded_md()
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-vim",
|
||||
if VimModeSetting::get_global(cx).0 {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
)
|
||||
.detach_and_log_err(cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
v_stack()
|
||||
.p_3()
|
||||
.gap_2()
|
||||
.bg(cx.theme().colors().elevated_surface_background)
|
||||
.border_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.rounded_md()
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-vim",
|
||||
if VimModeSetting::get_global(cx).0 {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
.on_click(
|
||||
cx.listener(move |this, selection, cx| {
|
||||
this.update_settings::<VimModeSetting>(
|
||||
selection,
|
||||
cx,
|
||||
|setting, value| *setting = Some(value),
|
||||
);
|
||||
}),
|
||||
),
|
||||
)
|
||||
.on_click(cx.listener(
|
||||
move |this, selection, cx| {
|
||||
this.update_settings::<VimModeSetting>(
|
||||
selection,
|
||||
cx,
|
||||
|setting, value| *setting = Some(value),
|
||||
);
|
||||
},
|
||||
)),
|
||||
)
|
||||
.child(Label::new("Enable vim mode")),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-telemetry",
|
||||
if TelemetrySettings::get_global(cx).metrics {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
.child(Label::new("Enable vim mode")),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-telemetry",
|
||||
if TelemetrySettings::get_global(cx).metrics {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
)
|
||||
.on_click(
|
||||
cx.listener(move |this, selection, cx| {
|
||||
this.update_settings::<TelemetrySettings>(
|
||||
selection,
|
||||
cx,
|
||||
|settings, value| {
|
||||
settings.metrics = Some(value)
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
)
|
||||
.on_click(cx.listener(
|
||||
move |this, selection, cx| {
|
||||
this.update_settings::<TelemetrySettings>(
|
||||
selection,
|
||||
cx,
|
||||
|settings, value| settings.metrics = Some(value),
|
||||
);
|
||||
},
|
||||
)),
|
||||
)
|
||||
.child(Label::new("Send anonymous usage data")),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-crash",
|
||||
if TelemetrySettings::get_global(cx).diagnostics {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
.child(Label::new("Send anonymous usage data")),
|
||||
)
|
||||
.child(
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(
|
||||
Checkbox::new(
|
||||
"enable-crash",
|
||||
if TelemetrySettings::get_global(cx).diagnostics {
|
||||
ui::Selection::Selected
|
||||
} else {
|
||||
ui::Selection::Unselected
|
||||
},
|
||||
)
|
||||
.on_click(
|
||||
cx.listener(move |this, selection, cx| {
|
||||
this.update_settings::<TelemetrySettings>(
|
||||
selection,
|
||||
cx,
|
||||
|settings, value| {
|
||||
settings.diagnostics = Some(value)
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
)
|
||||
.on_click(cx.listener(
|
||||
move |this, selection, cx| {
|
||||
this.update_settings::<TelemetrySettings>(
|
||||
selection,
|
||||
cx,
|
||||
|settings, value| {
|
||||
settings.diagnostics = Some(value)
|
||||
},
|
||||
);
|
||||
},
|
||||
)),
|
||||
)
|
||||
.child(Label::new("Send crash reports")),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(Label::new("Send crash reports")),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ language = { path = "../language" }
|
||||
node_runtime = { path = "../node_runtime" }
|
||||
project = { path = "../project" }
|
||||
settings = { path = "../settings" }
|
||||
sqlez = { path = "../sqlez" }
|
||||
terminal = { path = "../terminal" }
|
||||
theme = { path = "../theme" }
|
||||
util = { path = "../util" }
|
||||
|
@ -651,9 +651,13 @@ impl Render for PanelButtons {
|
||||
&& panel.position_is_valid(position, cx)
|
||||
{
|
||||
let panel = panel.clone();
|
||||
menu = menu.entry(position.to_label(), None, move |cx| {
|
||||
panel.set_position(position, cx);
|
||||
})
|
||||
menu = menu.entry(
|
||||
format!("Dock {}", position.to_label()),
|
||||
None,
|
||||
move |cx| {
|
||||
panel.set_position(position, cx);
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
menu
|
||||
|
@ -1128,12 +1128,7 @@ impl Pane {
|
||||
if self.items.len() == 1 && should_activate {
|
||||
self.focus_handle.focus(cx);
|
||||
} else {
|
||||
self.activate_item(
|
||||
dbg!(index_to_activate),
|
||||
dbg!(should_activate),
|
||||
should_activate,
|
||||
cx,
|
||||
);
|
||||
self.activate_item(index_to_activate, should_activate, should_activate, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,12 @@ use std::path::Path;
|
||||
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
|
||||
use gpui::{Axis, WindowBounds};
|
||||
use gpui::{point, size, Axis, Bounds, WindowBounds};
|
||||
|
||||
use sqlez::{
|
||||
bindable::{Bind, Column, StaticColumnCount},
|
||||
statement::Statement,
|
||||
};
|
||||
|
||||
use util::{unzip_option, ResultExt};
|
||||
use uuid::Uuid;
|
||||
@ -20,6 +25,121 @@ use model::{
|
||||
|
||||
use self::model::DockStructure;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub(crate) struct SerializedAxis(pub(crate) gpui::Axis);
|
||||
impl sqlez::bindable::StaticColumnCount for SerializedAxis {}
|
||||
impl sqlez::bindable::Bind for SerializedAxis {
|
||||
fn bind(
|
||||
&self,
|
||||
statement: &sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<i32> {
|
||||
match self.0 {
|
||||
gpui::Axis::Horizontal => "Horizontal",
|
||||
gpui::Axis::Vertical => "Vertical",
|
||||
}
|
||||
.bind(statement, start_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlez::bindable::Column for SerializedAxis {
|
||||
fn column(
|
||||
statement: &mut sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<(Self, i32)> {
|
||||
String::column(statement, start_index).and_then(|(axis_text, next_index)| {
|
||||
Ok((
|
||||
match axis_text.as_str() {
|
||||
"Horizontal" => Self(Axis::Horizontal),
|
||||
"Vertical" => Self(Axis::Vertical),
|
||||
_ => anyhow::bail!("Stored serialized item kind is incorrect"),
|
||||
},
|
||||
next_index,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) struct SerializedWindowsBounds(pub(crate) WindowBounds);
|
||||
|
||||
impl StaticColumnCount for SerializedWindowsBounds {
|
||||
fn column_count() -> usize {
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
impl Bind for SerializedWindowsBounds {
|
||||
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||
let (region, next_index) = match self.0 {
|
||||
WindowBounds::Fullscreen => {
|
||||
let next_index = statement.bind(&"Fullscreen", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Maximized => {
|
||||
let next_index = statement.bind(&"Maximized", start_index)?;
|
||||
(None, next_index)
|
||||
}
|
||||
WindowBounds::Fixed(region) => {
|
||||
let next_index = statement.bind(&"Fixed", start_index)?;
|
||||
(Some(region), next_index)
|
||||
}
|
||||
};
|
||||
|
||||
statement.bind(
|
||||
®ion.map(|region| {
|
||||
(
|
||||
SerializedGlobalPixels(region.origin.x),
|
||||
SerializedGlobalPixels(region.origin.y),
|
||||
SerializedGlobalPixels(region.size.width),
|
||||
SerializedGlobalPixels(region.size.height),
|
||||
)
|
||||
}),
|
||||
next_index,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Column for SerializedWindowsBounds {
|
||||
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
|
||||
let (window_state, next_index) = String::column(statement, start_index)?;
|
||||
let bounds = match window_state.as_str() {
|
||||
"Fullscreen" => SerializedWindowsBounds(WindowBounds::Fullscreen),
|
||||
"Maximized" => SerializedWindowsBounds(WindowBounds::Maximized),
|
||||
"Fixed" => {
|
||||
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
|
||||
let x: f64 = x;
|
||||
let y: f64 = y;
|
||||
let width: f64 = width;
|
||||
let height: f64 = height;
|
||||
SerializedWindowsBounds(WindowBounds::Fixed(Bounds {
|
||||
origin: point(x.into(), y.into()),
|
||||
size: size(width.into(), height.into()),
|
||||
}))
|
||||
}
|
||||
_ => bail!("Window State did not have a valid string"),
|
||||
};
|
||||
|
||||
Ok((bounds, next_index + 4))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct SerializedGlobalPixels(gpui::GlobalPixels);
|
||||
impl sqlez::bindable::StaticColumnCount for SerializedGlobalPixels {}
|
||||
|
||||
impl sqlez::bindable::Bind for SerializedGlobalPixels {
|
||||
fn bind(
|
||||
&self,
|
||||
statement: &sqlez::statement::Statement,
|
||||
start_index: i32,
|
||||
) -> anyhow::Result<i32> {
|
||||
let this: f64 = self.0.into();
|
||||
let this: f32 = this as _;
|
||||
this.bind(statement, start_index)
|
||||
}
|
||||
}
|
||||
|
||||
define_connection! {
|
||||
// Current schema shape using pseudo-rust syntax:
|
||||
//
|
||||
@ -181,7 +301,7 @@ impl WorkspaceDb {
|
||||
/// Returns a serialized workspace for the given worktree_roots. If the passed array
|
||||
/// is empty, the most recent workspace is returned instead. If no workspace for the
|
||||
/// passed roots is stored, returns none.
|
||||
pub fn workspace_for_roots<P: AsRef<Path>>(
|
||||
pub(crate) fn workspace_for_roots<P: AsRef<Path>>(
|
||||
&self,
|
||||
worktree_roots: &[P],
|
||||
) -> Option<SerializedWorkspace> {
|
||||
@ -192,7 +312,7 @@ impl WorkspaceDb {
|
||||
let (workspace_id, workspace_location, bounds, display, docks): (
|
||||
WorkspaceId,
|
||||
WorkspaceLocation,
|
||||
Option<WindowBounds>,
|
||||
Option<SerializedWindowsBounds>,
|
||||
Option<Uuid>,
|
||||
DockStructure,
|
||||
) = self
|
||||
@ -230,7 +350,7 @@ impl WorkspaceDb {
|
||||
.get_center_pane_group(workspace_id)
|
||||
.context("Getting center group")
|
||||
.log_err()?,
|
||||
bounds,
|
||||
bounds: bounds.map(|bounds| bounds.0),
|
||||
display,
|
||||
docks,
|
||||
})
|
||||
@ -238,7 +358,7 @@ impl WorkspaceDb {
|
||||
|
||||
/// Saves a workspace using the worktree roots. Will garbage collect any workspaces
|
||||
/// that used this workspace previously
|
||||
pub async fn save_workspace(&self, workspace: SerializedWorkspace) {
|
||||
pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
|
||||
self.write(move |conn| {
|
||||
conn.with_savepoint("update_worktrees", || {
|
||||
// Clear out panes and pane_groups
|
||||
@ -367,7 +487,7 @@ impl WorkspaceDb {
|
||||
type GroupKey = (Option<GroupId>, WorkspaceId);
|
||||
type GroupOrPane = (
|
||||
Option<GroupId>,
|
||||
Option<Axis>,
|
||||
Option<SerializedAxis>,
|
||||
Option<PaneId>,
|
||||
Option<bool>,
|
||||
Option<String>,
|
||||
@ -536,7 +656,7 @@ impl WorkspaceDb {
|
||||
}
|
||||
|
||||
query! {
|
||||
pub async fn set_window_bounds(workspace_id: WorkspaceId, bounds: WindowBounds, display: Uuid) -> Result<()> {
|
||||
pub(crate) async fn set_window_bounds(workspace_id: WorkspaceId, bounds: SerializedWindowsBounds, display: Uuid) -> Result<()> {
|
||||
UPDATE workspaces
|
||||
SET window_state = ?2,
|
||||
window_x = ?3,
|
||||
@ -683,7 +803,7 @@ mod tests {
|
||||
|
||||
fn group(axis: Axis, children: Vec<SerializedPaneGroup>) -> SerializedPaneGroup {
|
||||
SerializedPaneGroup::Group {
|
||||
axis,
|
||||
axis: SerializedAxis(axis),
|
||||
flexes: None,
|
||||
children,
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::SerializedAxis;
|
||||
use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId};
|
||||
use anyhow::{Context, Result};
|
||||
use async_recursion::async_recursion;
|
||||
@ -5,7 +6,7 @@ use db::sqlez::{
|
||||
bindable::{Bind, Column, StaticColumnCount},
|
||||
statement::Statement,
|
||||
};
|
||||
use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView, WindowBounds};
|
||||
use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
|
||||
use project::Project;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
@ -54,13 +55,13 @@ impl Column for WorkspaceLocation {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct SerializedWorkspace {
|
||||
pub id: WorkspaceId,
|
||||
pub location: WorkspaceLocation,
|
||||
pub center_group: SerializedPaneGroup,
|
||||
pub bounds: Option<WindowBounds>,
|
||||
pub display: Option<Uuid>,
|
||||
pub docks: DockStructure,
|
||||
pub(crate) struct SerializedWorkspace {
|
||||
pub(crate) id: WorkspaceId,
|
||||
pub(crate) location: WorkspaceLocation,
|
||||
pub(crate) center_group: SerializedPaneGroup,
|
||||
pub(crate) bounds: Option<WindowBounds>,
|
||||
pub(crate) display: Option<Uuid>,
|
||||
pub(crate) docks: DockStructure,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Default)]
|
||||
@ -126,9 +127,9 @@ impl Bind for DockData {
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SerializedPaneGroup {
|
||||
pub(crate) enum SerializedPaneGroup {
|
||||
Group {
|
||||
axis: Axis,
|
||||
axis: SerializedAxis,
|
||||
flexes: Option<Vec<f32>>,
|
||||
children: Vec<SerializedPaneGroup>,
|
||||
},
|
||||
@ -183,7 +184,7 @@ impl SerializedPaneGroup {
|
||||
}
|
||||
|
||||
Some((
|
||||
Member::Axis(PaneAxis::load(axis, members, flexes)),
|
||||
Member::Axis(PaneAxis::load(axis.0, members, flexes)),
|
||||
current_active_pane,
|
||||
items,
|
||||
))
|
||||
|
@ -42,9 +42,9 @@ use node_runtime::NodeRuntime;
|
||||
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
|
||||
pub use pane::*;
|
||||
pub use pane_group::*;
|
||||
use persistence::DB;
|
||||
use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB};
|
||||
pub use persistence::{
|
||||
model::{ItemId, SerializedWorkspace, WorkspaceLocation},
|
||||
model::{ItemId, WorkspaceLocation},
|
||||
WorkspaceDb, DB as WORKSPACE_DB,
|
||||
};
|
||||
use postage::stream::Stream;
|
||||
@ -70,8 +70,9 @@ use util::ResultExt;
|
||||
use uuid::Uuid;
|
||||
pub use workspace_settings::{AutosaveSetting, WorkspaceSettings};
|
||||
|
||||
use crate::persistence::model::{
|
||||
DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
|
||||
use crate::persistence::{
|
||||
model::{DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup},
|
||||
SerializedAxis,
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
@ -625,7 +626,11 @@ impl Workspace {
|
||||
|
||||
if let Some(display_uuid) = display.uuid().log_err() {
|
||||
cx.background_executor()
|
||||
.spawn(DB.set_window_bounds(workspace_id, bounds, display_uuid))
|
||||
.spawn(DB.set_window_bounds(
|
||||
workspace_id,
|
||||
SerializedWindowsBounds(bounds),
|
||||
display_uuid,
|
||||
))
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
}
|
||||
@ -1187,7 +1192,7 @@ impl Workspace {
|
||||
mut save_intent: SaveIntent,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<Result<bool>> {
|
||||
if self.project.read(cx).is_read_only() {
|
||||
if self.project.read(cx).is_disconnected() {
|
||||
return Task::ready(Ok(true));
|
||||
}
|
||||
let dirty_items = self
|
||||
@ -2510,7 +2515,7 @@ impl Workspace {
|
||||
}
|
||||
|
||||
fn update_window_edited(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let is_edited = !self.project.read(cx).is_read_only()
|
||||
let is_edited = !self.project.read(cx).is_disconnected()
|
||||
&& self
|
||||
.items(cx)
|
||||
.any(|item| item.has_conflict(cx) || item.is_dirty(cx));
|
||||
@ -2989,7 +2994,7 @@ impl Workspace {
|
||||
flexes,
|
||||
bounding_boxes: _,
|
||||
}) => SerializedPaneGroup::Group {
|
||||
axis: *axis,
|
||||
axis: SerializedAxis(*axis),
|
||||
children: members
|
||||
.iter()
|
||||
.map(|member| build_serialized_pane_group(member, cx))
|
||||
@ -3266,6 +3271,7 @@ impl Workspace {
|
||||
let user_store = project.read(cx).user_store();
|
||||
|
||||
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||
cx.activate_window();
|
||||
let app_state = Arc::new(AppState {
|
||||
languages: project.read(cx).languages().clone(),
|
||||
workspace_store,
|
||||
@ -3634,7 +3640,7 @@ impl Render for Workspace {
|
||||
})),
|
||||
)
|
||||
.child(self.status_bar.clone())
|
||||
.children(if self.project.read(cx).is_read_only() {
|
||||
.children(if self.project.read(cx).is_disconnected() {
|
||||
Some(DisconnectedOverlay)
|
||||
} else {
|
||||
None
|
||||
@ -4764,8 +4770,7 @@ mod tests {
|
||||
});
|
||||
|
||||
// Deactivating the window saves the file.
|
||||
cx.simulate_deactivation();
|
||||
cx.executor().run_until_parked();
|
||||
cx.deactivate_window();
|
||||
item.update(cx, |item, _| assert_eq!(item.save_count, 1));
|
||||
|
||||
// Autosave on focus change.
|
||||
@ -4785,14 +4790,13 @@ mod tests {
|
||||
item.update(cx, |item, _| assert_eq!(item.save_count, 2));
|
||||
|
||||
// Deactivating the window still saves the file.
|
||||
cx.simulate_activation();
|
||||
cx.update(|cx| cx.activate_window());
|
||||
item.update(cx, |item, cx| {
|
||||
cx.focus_self();
|
||||
item.is_dirty = true;
|
||||
});
|
||||
cx.simulate_deactivation();
|
||||
cx.deactivate_window();
|
||||
|
||||
cx.executor().run_until_parked();
|
||||
item.update(cx, |item, _| assert_eq!(item.save_count, 3));
|
||||
|
||||
// Autosave after delay.
|
||||
|
@ -1,29 +0,0 @@
|
||||
[⬅ Back to Index](../index.md)
|
||||
|
||||
# Generating Theme Types
|
||||
|
||||
|
||||
## How to generate theme types:
|
||||
|
||||
Run a script
|
||||
|
||||
```bash
|
||||
./script/build-theme-types
|
||||
```
|
||||
|
||||
Types are generated in `styles/src/types/zed.ts`
|
||||
|
||||
|
||||
## How it works:
|
||||
|
||||
1. Rust types
|
||||
|
||||
The `crates/theme` contains theme types.
|
||||
Crate `schemars` used to generate a JSON schema from the theme structs.
|
||||
Every struct that represent theme type has a `#[derive(JsonSchema)]` attribute.
|
||||
|
||||
Task lotaked at `crates/xtask/src/main.rs` generates a JSON schema from the theme structs.
|
||||
|
||||
2. TypeScript types
|
||||
|
||||
Script `npm run build-types` from `styles` package generates TypeScript types from the JSON schema and saves them to `styles/src/types/zed.ts`.
|
@ -4,17 +4,12 @@ set -eu
|
||||
source script/lib/deploy-helpers.sh
|
||||
|
||||
if [[ $# < 2 ]]; then
|
||||
echo "Usage: $0 <production|staging|preview> <tag-name> (nightly is not yet supported)"
|
||||
echo "Usage: $0 <production|staging|preview|nightly> <tag-name>"
|
||||
exit 1
|
||||
fi
|
||||
environment=$1
|
||||
version=$2
|
||||
|
||||
if [[ ${environment} == "nightly" ]]; then
|
||||
echo "nightly is not yet supported"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export_vars_for_environment ${environment}
|
||||
image_id=$(image_id_for_version ${version})
|
||||
|
||||
|
@ -9,10 +9,7 @@ OUTPUT_FILE=$(pwd)/assets/licenses.md
|
||||
echo -e "# ###### THEME LICENSES ######\n" >> $OUTPUT_FILE
|
||||
|
||||
echo "Generating theme licenses"
|
||||
cd styles
|
||||
npm --silent ci
|
||||
npm run --silent build-licenses >> $OUTPUT_FILE
|
||||
cd ..
|
||||
cat crates/theme/src/themes/LICENSES >> $OUTPUT_FILE
|
||||
|
||||
echo -e "# ###### CODE LICENSES ######\n" >> $OUTPUT_FILE
|
||||
|
||||
|
@ -1,34 +0,0 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:import/typescript",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["@typescript-eslint", "import"],
|
||||
globals: {
|
||||
module: true,
|
||||
},
|
||||
settings: {
|
||||
"import/parsers": {
|
||||
"@typescript-eslint/parser": [".ts"],
|
||||
},
|
||||
"import/resolver": {
|
||||
typescript: true,
|
||||
node: true,
|
||||
},
|
||||
"import/extensions": [".ts"],
|
||||
},
|
||||
rules: {
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
semi: ["error", "never"],
|
||||
},
|
||||
}
|
2
styles/.gitignore
vendored
2
styles/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
coverage/
|
@ -1,3 +0,0 @@
|
||||
package-lock.json
|
||||
package.json
|
||||
target
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"semi": false,
|
||||
"printWidth": 80,
|
||||
"htmlWhitespaceSensitivity": "strict",
|
||||
"tabWidth": 4
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// Folder-specific settings
|
||||
//
|
||||
// For a full list of overridable settings, and general information on folder-specific settings,
|
||||
// see the documentation: https://docs.zed.dev/configuration/configuring-zed#folder-specific-settings
|
||||
{
|
||||
"languages": {
|
||||
"TypeScript": {
|
||||
"tab_size": 4
|
||||
},
|
||||
"TSX": {
|
||||
"tab_size": 4
|
||||
},
|
||||
"JavaScript": {
|
||||
"tab_size": 4
|
||||
},
|
||||
"JSON": {
|
||||
"tab_size": 4
|
||||
}
|
||||
}
|
||||
}
|
4372
styles/package-lock.json
generated
4372
styles/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,37 +0,0 @@
|
||||
{
|
||||
"name": "styles",
|
||||
"version": "1.0.0",
|
||||
"description": "Typescript app that builds Zed's themes",
|
||||
"main": "./src/build_themes.ts",
|
||||
"scripts": {
|
||||
"build": "ts-node ./src/build_themes.ts",
|
||||
"build-licenses": "ts-node ./src/build_licenses.ts",
|
||||
"build-tokens": "ts-node ./src/build_tokens.ts",
|
||||
"build-types": "ts-node ./src/build_types.ts",
|
||||
"test": "vitest"
|
||||
},
|
||||
"author": "Zed Industries (https://github.com/zed-industries/)",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@tokens-studio/types": "^0.2.3",
|
||||
"@types/chroma-js": "^2.4.0",
|
||||
"@types/node": "^18.14.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.1",
|
||||
"@typescript-eslint/parser": "^5.60.1",
|
||||
"@vitest/coverage-v8": "^0.32.0",
|
||||
"ayu": "^8.0.1",
|
||||
"chroma-js": "^2.4.2",
|
||||
"deepmerge": "^4.3.0",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.5",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"json-schema-to-typescript": "^13.0.2",
|
||||
"toml": "^3.0.0",
|
||||
"ts-deepmerge": "^6.0.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^5.1.5",
|
||||
"utility-types": "^3.10.0",
|
||||
"vitest": "^0.32.0",
|
||||
"zustand": "^4.3.8"
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
import * as fs from "fs"
|
||||
import toml from "toml"
|
||||
import { themes } from "./themes"
|
||||
import { ThemeConfig } from "./common"
|
||||
|
||||
const ACCEPTED_LICENSES_FILE = `${__dirname}/../../script/licenses/zed-licenses.toml`
|
||||
|
||||
// Use the cargo-about configuration file as the source of truth for supported licenses.
|
||||
function parse_accepted_toml(file: string): string[] {
|
||||
const buffer = fs.readFileSync(file).toString()
|
||||
|
||||
const obj = toml.parse(buffer)
|
||||
|
||||
if (!Array.isArray(obj.accepted)) {
|
||||
throw Error("Accepted license source is malformed")
|
||||
}
|
||||
|
||||
return obj.accepted
|
||||
}
|
||||
|
||||
function check_licenses(themes: ThemeConfig[]) {
|
||||
for (const theme of themes) {
|
||||
if (!theme.license_file) {
|
||||
throw Error(`Theme ${theme.name} should have a LICENSE file`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generate_license_file(themes: ThemeConfig[]) {
|
||||
check_licenses(themes)
|
||||
for (const theme of themes) {
|
||||
const license_text = fs.readFileSync(theme.license_file).toString()
|
||||
write_license(theme.name, license_text, theme.license_url)
|
||||
}
|
||||
}
|
||||
|
||||
function write_license(
|
||||
theme_name: string,
|
||||
license_text: string,
|
||||
license_url?: string
|
||||
) {
|
||||
process.stdout.write(
|
||||
license_url
|
||||
? `## [${theme_name}](${license_url})\n\n${license_text}\n********************************************************************************\n\n`
|
||||
: `## ${theme_name}\n\n${license_text}\n********************************************************************************\n\n`
|
||||
)
|
||||
}
|
||||
|
||||
const accepted_licenses = parse_accepted_toml(ACCEPTED_LICENSES_FILE)
|
||||
generate_license_file(themes)
|
@ -1,45 +0,0 @@
|
||||
import * as fs from "fs"
|
||||
import { tmpdir } from "os"
|
||||
import * as path from "path"
|
||||
import app from "./style_tree/app"
|
||||
import { Theme, create_theme } from "./theme/create_theme"
|
||||
import { themes } from "./themes"
|
||||
import { useThemeStore } from "./theme"
|
||||
|
||||
const assets_directory = `${__dirname}/../../assets`
|
||||
const temp_directory = fs.mkdtempSync(path.join(tmpdir(), "build-themes"))
|
||||
|
||||
function clear_themes(theme_directory: string) {
|
||||
if (!fs.existsSync(theme_directory)) {
|
||||
fs.mkdirSync(theme_directory, { recursive: true })
|
||||
} else {
|
||||
for (const file of fs.readdirSync(theme_directory)) {
|
||||
if (file.endsWith(".json")) {
|
||||
fs.unlinkSync(path.join(theme_directory, file))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
|
||||
|
||||
function write_themes(themes: Theme[], output_directory: string) {
|
||||
clear_themes(output_directory)
|
||||
for (const theme of themes) {
|
||||
const { setTheme } = useThemeStore.getState()
|
||||
setTheme(theme)
|
||||
|
||||
const style_tree = app()
|
||||
// Nathan: New elements will read directly from the theme colors.
|
||||
// Adding this during the transition. Afterwards, we can port all themes to Rust.
|
||||
style_tree.base_theme = theme
|
||||
const style_tree_json = JSON.stringify(style_tree, null, 2)
|
||||
const temp_path = path.join(temp_directory, `${theme.name}.json`)
|
||||
const out_path = path.join(output_directory, `${theme.name}.json`)
|
||||
fs.writeFileSync(temp_path, style_tree_json)
|
||||
fs.renameSync(temp_path, out_path)
|
||||
console.log(`- ${out_path} created`)
|
||||
}
|
||||
}
|
||||
|
||||
write_themes(all_themes, `${assets_directory}/themes`)
|
@ -1,88 +0,0 @@
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import { Theme, create_theme, useThemeStore } from "./common"
|
||||
import { themes } from "./themes"
|
||||
import { slugify } from "./utils/slugify"
|
||||
import { theme_tokens } from "./theme/tokens/theme"
|
||||
|
||||
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
|
||||
const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json")
|
||||
const METADATA_FILE = path.join(TOKENS_DIRECTORY, "$metadata.json")
|
||||
|
||||
function clear_tokens(tokens_directory: string) {
|
||||
if (!fs.existsSync(tokens_directory)) {
|
||||
fs.mkdirSync(tokens_directory, { recursive: true })
|
||||
} else {
|
||||
for (const file of fs.readdirSync(tokens_directory)) {
|
||||
if (file.endsWith(".json")) {
|
||||
fs.unlinkSync(path.join(tokens_directory, file))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type TokenSet = {
|
||||
id: string
|
||||
name: string
|
||||
selected_token_sets: { [key: string]: "enabled" }
|
||||
}
|
||||
|
||||
function build_token_set_order(theme: Theme[]): {
|
||||
token_set_order: string[]
|
||||
} {
|
||||
const token_set_order: string[] = theme.map((scheme) =>
|
||||
scheme.name.toLowerCase().replace(/\s+/g, "_")
|
||||
)
|
||||
return { token_set_order }
|
||||
}
|
||||
|
||||
function build_themes_index(theme: Theme[]): TokenSet[] {
|
||||
const themes_index: TokenSet[] = theme.map((scheme, index) => {
|
||||
const id = `${scheme.is_light ? "light" : "dark"}_${scheme.name
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, "_")}_${index}`
|
||||
const selected_token_sets: { [key: string]: "enabled" } = {}
|
||||
const token_set = scheme.name.toLowerCase().replace(/\s+/g, "_")
|
||||
selected_token_sets[token_set] = "enabled"
|
||||
|
||||
return {
|
||||
id,
|
||||
name: `${scheme.name} - ${scheme.is_light ? "Light" : "Dark"}`,
|
||||
selected_token_sets,
|
||||
}
|
||||
})
|
||||
|
||||
return themes_index
|
||||
}
|
||||
|
||||
function write_tokens(themes: Theme[], tokens_directory: string) {
|
||||
clear_tokens(tokens_directory)
|
||||
|
||||
for (const theme of themes) {
|
||||
const { setTheme } = useThemeStore.getState()
|
||||
setTheme(theme)
|
||||
|
||||
const file_name = slugify(theme.name) + ".json"
|
||||
const tokens = theme_tokens()
|
||||
const tokens_json = JSON.stringify(tokens, null, 2)
|
||||
const out_path = path.join(tokens_directory, file_name)
|
||||
fs.writeFileSync(out_path, tokens_json, { mode: 0o644 })
|
||||
console.log(`- ${out_path} created`)
|
||||
}
|
||||
|
||||
const theme_index_data = build_themes_index(themes)
|
||||
|
||||
const themes_json = JSON.stringify(theme_index_data, null, 2)
|
||||
fs.writeFileSync(TOKENS_FILE, themes_json, { mode: 0o644 })
|
||||
console.log(`- ${TOKENS_FILE} created`)
|
||||
|
||||
const token_set_order_data = build_token_set_order(themes)
|
||||
|
||||
const metadata_json = JSON.stringify(token_set_order_data, null, 2)
|
||||
fs.writeFileSync(METADATA_FILE, metadata_json, { mode: 0o644 })
|
||||
console.log(`- ${METADATA_FILE} created`)
|
||||
}
|
||||
|
||||
const all_themes: Theme[] = themes.map((theme) => create_theme(theme))
|
||||
|
||||
write_tokens(all_themes, TOKENS_DIRECTORY)
|
@ -1,62 +0,0 @@
|
||||
import * as fs from "fs/promises"
|
||||
import * as fsSync from "fs"
|
||||
import * as path from "path"
|
||||
import { compile } from "json-schema-to-typescript"
|
||||
|
||||
const BANNER = `/*
|
||||
* This file is autogenerated
|
||||
*/\n\n`
|
||||
const dirname = __dirname
|
||||
|
||||
async function main() {
|
||||
const schemas_path = path.join(dirname, "../../", "crates/theme/schemas")
|
||||
const schema_files = (await fs.readdir(schemas_path)).filter((x) =>
|
||||
x.endsWith(".json")
|
||||
)
|
||||
|
||||
const compiled_types = new Set()
|
||||
|
||||
for (const filename of schema_files) {
|
||||
const file_path = path.join(schemas_path, filename)
|
||||
const file_contents = await fs.readFile(file_path)
|
||||
const schema = JSON.parse(file_contents.toString())
|
||||
const compiled = await compile(schema, schema.title, {
|
||||
bannerComment: "",
|
||||
})
|
||||
const each_type = compiled.split("export")
|
||||
for (const type of each_type) {
|
||||
if (!type) {
|
||||
continue
|
||||
}
|
||||
compiled_types.add("export " + type.trim())
|
||||
}
|
||||
}
|
||||
|
||||
const output = BANNER + Array.from(compiled_types).join("\n\n")
|
||||
const output_path = path.join(dirname, "../../styles/src/types/zed.ts")
|
||||
|
||||
try {
|
||||
const existing = await fs.readFile(output_path)
|
||||
if (existing.toString() == output) {
|
||||
// Skip writing if it hasn't changed
|
||||
console.log("Schemas are up to date")
|
||||
return
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.code !== "ENOENT") {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
const types_dic = path.dirname(output_path)
|
||||
if (!fsSync.existsSync(types_dic)) {
|
||||
await fs.mkdir(types_dic)
|
||||
}
|
||||
await fs.writeFile(output_path, output)
|
||||
console.log(`Wrote Typescript types to ${output_path}`)
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error(e)
|
||||
process.exit(1)
|
||||
})
|
@ -1,34 +0,0 @@
|
||||
import chroma from "chroma-js"
|
||||
export * from "./theme"
|
||||
export * from "./theme/theme_config"
|
||||
export { chroma }
|
||||
|
||||
export const font_families = {
|
||||
ui_sans: "IBM Plex Sans",
|
||||
sans: "Zed Sans",
|
||||
mono: "Zed Mono",
|
||||
}
|
||||
|
||||
export const font_sizes = {
|
||||
"2xs": 10,
|
||||
xs: 12,
|
||||
sm: 14,
|
||||
md: 16,
|
||||
lg: 18,
|
||||
}
|
||||
|
||||
export type FontWeight = "normal" | "bold"
|
||||
|
||||
export const font_weights: { [key: string]: FontWeight } = {
|
||||
normal: "normal",
|
||||
bold: "bold",
|
||||
}
|
||||
|
||||
export const sizes = {
|
||||
px: 1,
|
||||
xs: 2,
|
||||
sm: 4,
|
||||
md: 6,
|
||||
lg: 8,
|
||||
xl: 12,
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
import { font_sizes, useTheme } from "../common"
|
||||
import { Layer, Theme } from "../theme"
|
||||
import { TextStyle, background } from "../style_tree/components"
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Button {
|
||||
export type Options = {
|
||||
layer: Layer
|
||||
background: keyof Theme["lowest"]
|
||||
color: keyof Theme["lowest"]
|
||||
variant: Button.Variant
|
||||
size: Button.Size
|
||||
shape: Button.Shape
|
||||
margin: {
|
||||
top?: number
|
||||
bottom?: number
|
||||
left?: number
|
||||
right?: number
|
||||
}
|
||||
states: {
|
||||
enabled?: boolean
|
||||
hovered?: boolean
|
||||
pressed?: boolean
|
||||
focused?: boolean
|
||||
disabled?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export type ToggleableOptions = Options & {
|
||||
active_background: keyof Theme["lowest"]
|
||||
active_color: keyof Theme["lowest"]
|
||||
}
|
||||
|
||||
/** Padding added to each side of a Shape.Rectangle button */
|
||||
export const RECTANGLE_PADDING = 2
|
||||
export const FONT_SIZE = font_sizes.sm
|
||||
export const ICON_SIZE = 14
|
||||
export const CORNER_RADIUS = 6
|
||||
|
||||
export const variant = {
|
||||
Default: "filled",
|
||||
Outline: "outline",
|
||||
Ghost: "ghost",
|
||||
} as const
|
||||
|
||||
export type Variant = (typeof variant)[keyof typeof variant]
|
||||
|
||||
export const shape = {
|
||||
Rectangle: "rectangle",
|
||||
Square: "square",
|
||||
} as const
|
||||
|
||||
export type Shape = (typeof shape)[keyof typeof shape]
|
||||
|
||||
export const size = {
|
||||
Small: "sm",
|
||||
Medium: "md",
|
||||
} as const
|
||||
|
||||
export type Size = (typeof size)[keyof typeof size]
|
||||
|
||||
export type BaseStyle = {
|
||||
corder_radius: number
|
||||
background: string | null
|
||||
padding: {
|
||||
top: number
|
||||
bottom: number
|
||||
left: number
|
||||
right: number
|
||||
}
|
||||
margin: Button.Options["margin"]
|
||||
button_height: number
|
||||
}
|
||||
|
||||
export type LabelButtonStyle = BaseStyle & TextStyle
|
||||
// export type IconButtonStyle = ButtonStyle
|
||||
|
||||
export const button_base = (
|
||||
options: Partial<Button.Options> = {
|
||||
variant: Button.variant.Default,
|
||||
shape: Button.shape.Rectangle,
|
||||
states: {
|
||||
hovered: true,
|
||||
pressed: true,
|
||||
},
|
||||
}
|
||||
): BaseStyle => {
|
||||
const theme = useTheme()
|
||||
|
||||
const layer = options.layer ?? theme.middle
|
||||
const color = options.color ?? "base"
|
||||
const background_color =
|
||||
options.variant === Button.variant.Ghost
|
||||
? null
|
||||
: background(layer, options.background ?? color)
|
||||
|
||||
const m = {
|
||||
top: options.margin?.top ?? 0,
|
||||
bottom: options.margin?.bottom ?? 0,
|
||||
left: options.margin?.left ?? 0,
|
||||
right: options.margin?.right ?? 0,
|
||||
}
|
||||
const size = options.size || Button.size.Medium
|
||||
const padding = 2
|
||||
|
||||
const base: BaseStyle = {
|
||||
background: background_color,
|
||||
corder_radius: Button.CORNER_RADIUS,
|
||||
padding: {
|
||||
top: padding,
|
||||
bottom: padding,
|
||||
left:
|
||||
options.shape === Button.shape.Rectangle
|
||||
? padding + Button.RECTANGLE_PADDING
|
||||
: padding,
|
||||
right:
|
||||
options.shape === Button.shape.Rectangle
|
||||
? padding + Button.RECTANGLE_PADDING
|
||||
: padding,
|
||||
},
|
||||
margin: m,
|
||||
button_height: 16,
|
||||
}
|
||||
|
||||
return base
|
||||
}
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
import { interactive, toggleable } from "../element"
|
||||
import { background, foreground } from "../style_tree/components"
|
||||
import { useTheme, Theme, Layer } from "../theme"
|
||||
import { Button } from "./button"
|
||||
|
||||
export type Margin = {
|
||||
top: number
|
||||
bottom: number
|
||||
left: number
|
||||
right: number
|
||||
}
|
||||
|
||||
interface IconButtonOptions {
|
||||
layer?: Theme["lowest"] | Theme["middle"] | Theme["highest"]
|
||||
color?: keyof Theme["lowest"]
|
||||
background_color?: keyof Theme["lowest"]
|
||||
margin?: Partial<Margin>
|
||||
variant?: Button.Variant
|
||||
size?: Button.Size
|
||||
}
|
||||
|
||||
type ToggleableIconButtonOptions = IconButtonOptions & {
|
||||
active_color?: keyof Theme["lowest"]
|
||||
active_background_color?: keyof Theme["lowest"]
|
||||
active_layer?: Layer
|
||||
active_variant?: Button.Variant
|
||||
}
|
||||
|
||||
export function icon_button(
|
||||
{ color, background_color, margin, layer, variant, size }: IconButtonOptions = {
|
||||
variant: Button.variant.Default,
|
||||
size: Button.size.Medium,
|
||||
}
|
||||
) {
|
||||
const theme = useTheme()
|
||||
|
||||
if (!color) color = "base"
|
||||
|
||||
const default_background =
|
||||
variant === Button.variant.Ghost
|
||||
? null
|
||||
: background(layer ?? theme.lowest, background_color ?? color)
|
||||
|
||||
const m = {
|
||||
top: margin?.top ?? 0,
|
||||
bottom: margin?.bottom ?? 0,
|
||||
left: margin?.left ?? 0,
|
||||
right: margin?.right ?? 0,
|
||||
}
|
||||
|
||||
const padding = {
|
||||
top: size === Button.size.Small ? 2 : 2,
|
||||
bottom: size === Button.size.Small ? 2 : 2,
|
||||
left: size === Button.size.Small ? 2 : 4,
|
||||
right: size === Button.size.Small ? 2 : 4,
|
||||
}
|
||||
|
||||
return interactive({
|
||||
base: {
|
||||
corner_radius: 6,
|
||||
padding: padding,
|
||||
margin: m,
|
||||
icon_width: 14,
|
||||
icon_height: 14,
|
||||
button_width: size === Button.size.Small ? 16 : 20,
|
||||
button_height: 14,
|
||||
},
|
||||
state: {
|
||||
default: {
|
||||
background: default_background,
|
||||
color: foreground(layer ?? theme.lowest, color),
|
||||
},
|
||||
hovered: {
|
||||
background: background(layer ?? theme.lowest, background_color ?? color, "hovered"),
|
||||
color: foreground(layer ?? theme.lowest, color, "hovered"),
|
||||
},
|
||||
clicked: {
|
||||
background: background(layer ?? theme.lowest, background_color ?? color, "pressed"),
|
||||
color: foreground(layer ?? theme.lowest, color, "pressed"),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function toggleable_icon_button({
|
||||
color,
|
||||
background_color,
|
||||
active_color,
|
||||
active_background_color,
|
||||
active_variant,
|
||||
margin,
|
||||
variant,
|
||||
size,
|
||||
active_layer,
|
||||
}: ToggleableIconButtonOptions) {
|
||||
if (!color) color = "base"
|
||||
|
||||
return toggleable({
|
||||
state: {
|
||||
inactive: icon_button({ color, background_color, margin, variant, size }),
|
||||
active: icon_button({
|
||||
color: active_color ? active_color : color,
|
||||
background_color: active_background_color ? active_background_color : background_color,
|
||||
margin,
|
||||
layer: active_layer,
|
||||
variant: active_variant || variant,
|
||||
size,
|
||||
}),
|
||||
},
|
||||
})
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export * from "./icon_button"
|
||||
export * from "./indicator"
|
||||
export * from "./input"
|
||||
export * from "./tab"
|
||||
export * from "./tab_bar_button"
|
||||
export * from "./text_button"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user