Detailed changes
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#e2dfe7",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#26232a",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#8b8792",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#576ddb",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#5852605c",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#e2dfe7",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#5852603d"
+ }
+ },
+ "border": {
+ "color": "#19171c",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#7e7887",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#19171c",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#7e7887",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#576ddb",
+ "selection": "#576ddb3d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#e2dfe7",
+ "size": 14
+ },
+ "border": {
+ "color": "#26232a",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000003d",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#19171c",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#e2dfe7",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#7e7887",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#576ddb",
+ "selection": "#576ddb3d"
+ },
+ "border": {
+ "color": "#26232a",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#e2dfe7",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#e2dfe7",
+ "size": 14,
+ "background": "#26232a",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#955ae77a",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#26232a",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#e2dfe7",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#585260",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#576ddb",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#8b87922e",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#26232a",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#8b87921f"
+ }
+ },
+ "border": {
+ "color": "#efecf4",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#655f6d",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#efecf4",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#655f6d",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#576ddb",
+ "selection": "#576ddb3d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#26232a",
+ "size": 14
+ },
+ "border": {
+ "color": "#e2dfe7",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000001f",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#efecf4",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#26232a",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#655f6d",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#576ddb",
+ "selection": "#576ddb3d"
+ },
+ "border": {
+ "color": "#e2dfe7",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#26232a",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#26232a",
+ "size": 14,
+ "background": "#e2dfe7",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#955ae73d",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#f1f1f1",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#1c1c1c",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#9c9c9c",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#4f8ff7",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#2b2b2b",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#f1f1f1",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#232323"
+ }
+ },
+ "border": {
+ "color": "#070707",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#474747",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#000000",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#474747",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#2472f2",
+ "selection": "#2472f23d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#f1f1f1",
+ "size": 14
+ },
+ "border": {
+ "color": "#232323",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#00000052",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#000000",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#f1f1f1",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#474747",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#2472f2",
+ "selection": "#2472f23d"
+ },
+ "border": {
+ "color": "#232323",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#f1f1f1",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#f1f1f1",
+ "size": 14,
+ "background": "#2b2b2b",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#3f15a380",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#2b2b2b",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#f8f8f8",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#474747",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#484bed",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#e3e3e3",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#2b2b2b",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#eaeaea"
+ }
+ },
+ "border": {
+ "color": "#d5d5d5",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#808080",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#ffffff",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#808080",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#2472f2",
+ "selection": "#2472f23d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#2b2b2b",
+ "size": 14
+ },
+ "border": {
+ "color": "#d5d5d5",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000001f",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#ffffff",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#2b2b2b",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#808080",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#2472f2",
+ "selection": "#2472f23d"
+ },
+ "border": {
+ "color": "#d5d5d5",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#2b2b2b",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#2b2b2b",
+ "size": 14,
+ "background": "#eaeaea",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#fce9b7",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#eee8d5",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#073642",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#93a1a1",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#268bd2",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#586e755c",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#eee8d5",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#586e753d"
+ }
+ },
+ "border": {
+ "color": "#002b36",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#839496",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#002b36",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#839496",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#268bd2",
+ "selection": "#268bd23d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#eee8d5",
+ "size": 14
+ },
+ "border": {
+ "color": "#073642",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000003d",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#002b36",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#eee8d5",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#839496",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#268bd2",
+ "selection": "#268bd23d"
+ },
+ "border": {
+ "color": "#073642",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#eee8d5",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#eee8d5",
+ "size": 14,
+ "background": "#073642",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#6c71c47a",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#073642",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#eee8d5",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#586e75",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#268bd2",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#93a1a12e",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#073642",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#93a1a11f"
+ }
+ },
+ "border": {
+ "color": "#fdf6e3",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#657b83",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#fdf6e3",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#657b83",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#268bd2",
+ "selection": "#268bd23d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#073642",
+ "size": 14
+ },
+ "border": {
+ "color": "#eee8d5",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000001f",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#fdf6e3",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#073642",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#657b83",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#268bd2",
+ "selection": "#268bd23d"
+ },
+ "border": {
+ "color": "#eee8d5",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#073642",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#073642",
+ "size": 14,
+ "background": "#eee8d5",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#6c71c43d",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#dfe2f1",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#293256",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#979db4",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#3d8fd1",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#5e66875c",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#dfe2f1",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#5e66873d"
+ }
+ },
+ "border": {
+ "color": "#202746",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#898ea4",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#202746",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#898ea4",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#3d8fd1",
+ "selection": "#3d8fd13d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#dfe2f1",
+ "size": 14
+ },
+ "border": {
+ "color": "#293256",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000003d",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#202746",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#dfe2f1",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#898ea4",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#3d8fd1",
+ "selection": "#3d8fd13d"
+ },
+ "border": {
+ "color": "#293256",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#dfe2f1",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#dfe2f1",
+ "size": 14,
+ "background": "#293256",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#6679cc7a",
"tab_icon_spacing": 8,
@@ -1261,7 +1261,7 @@
"left": 8
}
},
- "edit_contact": {
+ "contact_button": {
"family": "Zed Mono",
"color": "#293256",
"size": 14,
@@ -1378,6 +1378,149 @@
"corner_radius": 6
}
},
+ "contact_finder": {
+ "background": "#dfe2f1",
+ "corner_radius": 8,
+ "padding": 8,
+ "item": {
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 4
+ },
+ "corner_radius": 8,
+ "text": {
+ "family": "Zed Sans",
+ "color": "#5e6687",
+ "size": 14
+ },
+ "highlight_text": {
+ "family": "Zed Sans",
+ "color": "#3d8fd1",
+ "weight": "bold",
+ "size": 14
+ },
+ "active": {
+ "background": "#979db42e",
+ "text": {
+ "family": "Zed Sans",
+ "color": "#293256",
+ "size": 14
+ }
+ },
+ "hover": {
+ "background": "#979db41f"
+ }
+ },
+ "border": {
+ "color": "#f5f7ff",
+ "width": 1
+ },
+ "empty": {
+ "text": {
+ "family": "Zed Sans",
+ "color": "#6b7394",
+ "size": 14
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 12,
+ "right": 12,
+ "top": 8
+ }
+ },
+ "input_editor": {
+ "background": "#f5f7ff",
+ "corner_radius": 8,
+ "placeholder_text": {
+ "family": "Zed Sans",
+ "color": "#6b7394",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#3d8fd1",
+ "selection": "#3d8fd13d"
+ },
+ "text": {
+ "family": "Zed Mono",
+ "color": "#293256",
+ "size": 14
+ },
+ "border": {
+ "color": "#dfe2f1",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 7,
+ "left": 16,
+ "right": 16,
+ "top": 7
+ }
+ },
+ "shadow": {
+ "blur": 16,
+ "color": "#0000001f",
+ "offset": [
+ 0,
+ 2
+ ]
+ },
+ "max_width": 540,
+ "max_height": 420,
+ "query_editor": {
+ "background": "#f5f7ff",
+ "corner_radius": 6,
+ "text": {
+ "family": "Zed Mono",
+ "color": "#293256",
+ "size": 14
+ },
+ "placeholder_text": {
+ "family": "Zed Mono",
+ "color": "#6b7394",
+ "size": 14
+ },
+ "selection": {
+ "cursor": "#3d8fd1",
+ "selection": "#3d8fd13d"
+ },
+ "border": {
+ "color": "#dfe2f1",
+ "width": 1
+ },
+ "padding": {
+ "bottom": 4,
+ "left": 8,
+ "right": 8,
+ "top": 4
+ }
+ },
+ "row_height": 28,
+ "contact_avatar": {
+ "corner_radius": 10,
+ "width": 18
+ },
+ "contact_username": {
+ "family": "Zed Mono",
+ "color": "#293256",
+ "size": 14,
+ "padding": {
+ "left": 8
+ }
+ },
+ "contact_button": {
+ "family": "Zed Mono",
+ "color": "#293256",
+ "size": 14,
+ "background": "#dfe2f1",
+ "corner_radius": 12,
+ "padding": {
+ "left": 7,
+ "right": 7
+ }
+ }
+ },
"search": {
"match_background": "#6679cc3d",
"tab_icon_spacing": 8,
@@ -0,0 +1,175 @@
+use client::{ContactRequestStatus, User, UserStore};
+use editor::Editor;
+use gpui::{
+ color::Color, elements::*, platform::CursorStyle, Entity, LayoutContext, ModelHandle,
+ RenderContext, Task, View, ViewContext, ViewHandle,
+};
+use settings::Settings;
+use std::sync::Arc;
+use util::TryFutureExt;
+
+use crate::{RemoveContact, RequestContact};
+
+pub struct ContactFinder {
+ query_editor: ViewHandle<Editor>,
+ list_state: UniformListState,
+ potential_contacts: Arc<[Arc<User>]>,
+ user_store: ModelHandle<UserStore>,
+ contacts_search_task: Option<Task<Option<()>>>,
+}
+
+impl Entity for ContactFinder {
+ type Event = ();
+}
+
+impl View for ContactFinder {
+ fn ui_name() -> &'static str {
+ "ContactFinder"
+ }
+
+ fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
+ let theme = cx.global::<Settings>().theme.clone();
+ let user_store = self.user_store.clone();
+ let potential_contacts = self.potential_contacts.clone();
+ Flex::column()
+ .with_child(
+ ChildView::new(self.query_editor.clone())
+ .contained()
+ .with_style(theme.contact_finder.query_editor.container)
+ .boxed(),
+ )
+ .with_child(
+ UniformList::new(self.list_state.clone(), self.potential_contacts.len(), {
+ let theme = theme.clone();
+ move |range, items, cx| {
+ items.extend(range.map(|ix| {
+ Self::render_potential_contact(
+ &potential_contacts[ix],
+ &user_store,
+ &theme.contact_finder,
+ cx,
+ )
+ }))
+ }
+ })
+ .flex(1., false)
+ .boxed(),
+ )
+ .contained()
+ .with_style(theme.contact_finder.container)
+ .constrained()
+ .with_max_width(theme.contact_finder.max_width)
+ .with_max_height(theme.contact_finder.max_height)
+ .boxed()
+ }
+}
+
+impl ContactFinder {
+ pub fn new(user_store: ModelHandle<UserStore>, cx: &mut ViewContext<Self>) -> Self {
+ let query_editor = cx.add_view(|cx| {
+ Editor::single_line(Some(|theme| theme.contact_finder.query_editor.clone()), cx)
+ });
+
+ cx.subscribe(&query_editor, |this, _, event, cx| {
+ if let editor::Event::BufferEdited = event {
+ this.query_changed(cx)
+ }
+ })
+ .detach();
+ Self {
+ query_editor,
+ list_state: Default::default(),
+ potential_contacts: Arc::from([]),
+ user_store,
+ contacts_search_task: None,
+ }
+ }
+
+ fn render_potential_contact(
+ contact: &User,
+ user_store: &ModelHandle<UserStore>,
+ theme: &theme::ContactFinder,
+ cx: &mut LayoutContext,
+ ) -> ElementBox {
+ enum RequestContactButton {}
+
+ let contact_id = contact.id;
+ let request_status = user_store.read(cx).contact_request_status(&contact);
+
+ Flex::row()
+ .with_children(contact.avatar.clone().map(|avatar| {
+ Image::new(avatar)
+ .with_style(theme.contact_avatar)
+ .aligned()
+ .left()
+ .boxed()
+ }))
+ .with_child(
+ Label::new(
+ contact.github_login.clone(),
+ theme.contact_username.text.clone(),
+ )
+ .contained()
+ .with_style(theme.contact_username.container)
+ .aligned()
+ .left()
+ .boxed(),
+ )
+ .with_child(
+ MouseEventHandler::new::<RequestContactButton, _, _>(
+ contact.id as usize,
+ cx,
+ |_, _| {
+ let label = match request_status {
+ ContactRequestStatus::None | ContactRequestStatus::RequestReceived => {
+ "+"
+ }
+ ContactRequestStatus::RequestSent => "-",
+ ContactRequestStatus::Pending
+ | ContactRequestStatus::RequestAccepted => "…",
+ };
+
+ Label::new(label.to_string(), theme.contact_button.text.clone())
+ .contained()
+ .with_style(theme.contact_button.container)
+ .aligned()
+ .flex_float()
+ .boxed()
+ },
+ )
+ .on_click(move |_, cx| match request_status {
+ ContactRequestStatus::None => {
+ cx.dispatch_action(RequestContact(contact_id));
+ }
+ ContactRequestStatus::RequestSent => {
+ cx.dispatch_action(RemoveContact(contact_id));
+ }
+ _ => {}
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .boxed(),
+ )
+ .constrained()
+ .with_height(theme.row_height)
+ .boxed()
+ }
+
+ fn query_changed(&mut self, cx: &mut ViewContext<Self>) {
+ let query = self.query_editor.read(cx).text(cx);
+ let search_users = self
+ .user_store
+ .update(cx, |store, cx| store.fuzzy_search_users(query, cx));
+
+ self.contacts_search_task = Some(cx.spawn(|this, mut cx| {
+ async move {
+ let potential_contacts = search_users.await?;
+ this.update(&mut cx, |this, cx| {
+ this.potential_contacts = potential_contacts.into();
+ cx.notify();
+ });
+ Ok(())
+ }
+ .log_err()
+ }));
+ }
+}
@@ -1,20 +1,24 @@
+mod contact_finder;
+
use client::{Contact, ContactRequestStatus, User, UserStore};
+use contact_finder::ContactFinder;
use editor::Editor;
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{
+ actions,
elements::*,
geometry::{rect::RectF, vector::vec2f},
impl_actions,
platform::CursorStyle,
Element, ElementBox, Entity, LayoutContext, ModelHandle, MutableAppContext, RenderContext,
- Subscription, Task, View, ViewContext, ViewHandle,
+ Subscription, View, ViewContext, ViewHandle,
};
use serde::Deserialize;
use settings::Settings;
use std::sync::Arc;
-use util::TryFutureExt;
-use workspace::{AppState, JoinProject};
+use workspace::{AppState, JoinProject, Workspace};
+actions!(contacts_panel, [FindNewContacts]);
impl_actions!(
contacts_panel,
[RequestContact, RemoveContact, RespondToContactRequest]
@@ -26,16 +30,13 @@ enum ContactEntry {
IncomingRequest(Arc<User>),
OutgoingRequest(Arc<User>),
Contact(Arc<Contact>),
- PotentialContact(Arc<User>),
}
pub struct ContactsPanel {
entries: Vec<ContactEntry>,
match_candidates: Vec<StringMatchCandidate>,
- potential_contacts: Vec<Arc<User>>,
list_state: ListState,
user_store: ModelHandle<UserStore>,
- contacts_search_task: Option<Task<Option<()>>>,
user_query_editor: ViewHandle<Editor>,
_maintain_contacts: Subscription,
}
@@ -56,6 +57,7 @@ pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ContactsPanel::request_contact);
cx.add_action(ContactsPanel::remove_contact);
cx.add_action(ContactsPanel::respond_to_contact_request);
+ cx.add_action(ContactsPanel::find_new_contacts);
}
impl ContactsPanel {
@@ -69,7 +71,7 @@ impl ContactsPanel {
cx.subscribe(&user_query_editor, |this, _, event, cx| {
if let editor::Event::BufferEdited = event {
- this.query_changed(cx)
+ this.update_entries(cx)
}
})
.detach();
@@ -120,22 +122,14 @@ impl ContactsPanel {
theme,
cx,
),
- ContactEntry::PotentialContact(user) => Self::render_potential_contact(
- user.clone(),
- this.user_store.clone(),
- theme,
- cx,
- ),
}
}
}),
entries: Default::default(),
- potential_contacts: Default::default(),
match_candidates: Default::default(),
user_query_editor,
_maintain_contacts: cx
.observe(&app_state.user_store, |this, _, cx| this.update_entries(cx)),
- contacts_search_task: None,
user_store: app_state.user_store.clone(),
};
this.update_entries(cx);
@@ -347,9 +341,9 @@ impl ContactsPanel {
if request_status == ContactRequestStatus::Pending {
row.add_child(
- Label::new("…".to_string(), theme.edit_contact.text.clone())
+ Label::new("…".to_string(), theme.contact_button.text.clone())
.contained()
- .with_style(theme.edit_contact.container)
+ .with_style(theme.contact_button.container)
.aligned()
.flex_float()
.boxed(),
@@ -357,9 +351,9 @@ impl ContactsPanel {
} else {
row.add_children([
MouseEventHandler::new::<Reject, _, _>(user.id as usize, cx, |_, _| {
- Label::new("Reject".to_string(), theme.edit_contact.text.clone())
+ Label::new("Reject".to_string(), theme.contact_button.text.clone())
.contained()
- .with_style(theme.edit_contact.container)
+ .with_style(theme.contact_button.container)
.aligned()
.flex_float()
.boxed()
@@ -374,9 +368,9 @@ impl ContactsPanel {
.flex_float()
.boxed(),
MouseEventHandler::new::<Accept, _, _>(user.id as usize, cx, |_, _| {
- Label::new("Accept".to_string(), theme.edit_contact.text.clone())
+ Label::new("Accept".to_string(), theme.contact_button.text.clone())
.contained()
- .with_style(theme.edit_contact.container)
+ .with_style(theme.contact_button.container)
.aligned()
.boxed()
})
@@ -427,9 +421,9 @@ impl ContactsPanel {
if request_status == ContactRequestStatus::Pending {
row.add_child(
- Label::new("…".to_string(), theme.edit_contact.text.clone())
+ Label::new("…".to_string(), theme.contact_button.text.clone())
.contained()
- .with_style(theme.edit_contact.container)
+ .with_style(theme.contact_button.container)
.aligned()
.flex_float()
.boxed(),
@@ -437,9 +431,9 @@ impl ContactsPanel {
} else {
row.add_child(
MouseEventHandler::new::<Cancel, _, _>(user.id as usize, cx, |_, _| {
- Label::new("Cancel".to_string(), theme.edit_contact.text.clone())
+ Label::new("Cancel".to_string(), theme.contact_button.text.clone())
.contained()
- .with_style(theme.edit_contact.container)
+ .with_style(theme.contact_button.container)
.aligned()
.flex_float()
.boxed()
@@ -454,95 +448,6 @@ impl ContactsPanel {
row.constrained().with_height(theme.row_height).boxed()
}
- fn render_potential_contact(
- contact: Arc<User>,
- user_store: ModelHandle<UserStore>,
- theme: &theme::ContactsPanel,
- cx: &mut LayoutContext,
- ) -> ElementBox {
- enum RequestContactButton {}
-
- let request_status = user_store.read(cx).contact_request_status(&contact);
-
- Flex::row()
- .with_children(contact.avatar.clone().map(|avatar| {
- Image::new(avatar)
- .with_style(theme.contact_avatar)
- .aligned()
- .left()
- .boxed()
- }))
- .with_child(
- Label::new(
- contact.github_login.clone(),
- theme.contact_username.text.clone(),
- )
- .contained()
- .with_style(theme.contact_username.container)
- .aligned()
- .left()
- .boxed(),
- )
- .with_child(
- MouseEventHandler::new::<RequestContactButton, _, _>(
- contact.id as usize,
- cx,
- |_, _| {
- let label = match request_status {
- ContactRequestStatus::None | ContactRequestStatus::RequestReceived => {
- "+"
- }
- ContactRequestStatus::RequestSent => "-",
- ContactRequestStatus::Pending
- | ContactRequestStatus::RequestAccepted => "…",
- };
-
- Label::new(label.to_string(), theme.edit_contact.text.clone())
- .contained()
- .with_style(theme.edit_contact.container)
- .aligned()
- .flex_float()
- .boxed()
- },
- )
- .on_click(move |_, cx| match request_status {
- ContactRequestStatus::None => {
- cx.dispatch_action(RequestContact(contact.id));
- }
- ContactRequestStatus::RequestSent => {
- cx.dispatch_action(RemoveContact(contact.id));
- }
- _ => {}
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .boxed(),
- )
- .constrained()
- .with_height(theme.row_height)
- .boxed()
- }
-
- fn query_changed(&mut self, cx: &mut ViewContext<Self>) {
- self.update_entries(cx);
-
- let query = self.user_query_editor.read(cx).text(cx);
- let search_users = self
- .user_store
- .update(cx, |store, cx| store.fuzzy_search_users(query, cx));
-
- self.contacts_search_task = Some(cx.spawn(|this, mut cx| {
- async move {
- let potential_contacts = search_users.await?;
- this.update(&mut cx, |this, cx| {
- this.potential_contacts = potential_contacts;
- this.update_entries(cx);
- });
- Ok(())
- }
- .log_err()
- }));
- }
-
fn update_entries(&mut self, cx: &mut ViewContext<Self>) {
let user_store = self.user_store.read(cx);
let query = self.user_query_editor.read(cx).text(cx);
@@ -656,15 +561,6 @@ impl ContactsPanel {
}
}
- if !self.potential_contacts.is_empty() {
- self.entries.push(ContactEntry::Header("Add Contacts"));
- self.entries.extend(
- self.potential_contacts
- .iter()
- .map(|user| ContactEntry::PotentialContact(user.clone())),
- );
- }
-
self.list_state.reset(self.entries.len());
cx.notify();
}
@@ -692,6 +588,16 @@ impl ContactsPanel {
})
.detach();
}
+
+ fn find_new_contacts(
+ workspace: &mut Workspace,
+ _: &FindNewContacts,
+ cx: &mut ViewContext<Workspace>,
+ ) {
+ workspace.toggle_modal(cx, |cx, workspace| {
+ cx.add_view(|cx| ContactFinder::new(workspace.user_store().clone(), cx))
+ });
+ }
}
pub enum Event {}
@@ -706,7 +612,10 @@ impl View for ContactsPanel {
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
- let theme = &cx.global::<Settings>().theme.contacts_panel;
+ enum AddContact {}
+
+ let theme = cx.global::<Settings>().theme.clone();
+ let theme = &theme.contacts_panel;
Container::new(
Flex::column()
.with_child(
@@ -719,14 +628,18 @@ impl View for ContactsPanel {
.boxed(),
)
.with_child(
- Svg::new("icons/add-contact.svg")
- .with_color(theme.add_contact_icon.color)
- .constrained()
- .with_height(12.)
- .contained()
- .with_style(theme.add_contact_icon.container)
- .aligned()
- .boxed(),
+ MouseEventHandler::new::<AddContact, _, _>(0, cx, |_, _| {
+ Svg::new("icons/add-contact.svg")
+ .with_color(theme.add_contact_icon.color)
+ .constrained()
+ .with_height(12.)
+ .contained()
+ .with_style(theme.add_contact_icon.container)
+ .aligned()
+ .boxed()
+ })
+ .on_click(|_, cx| cx.dispatch_action(FindNewContacts))
+ .boxed(),
)
.constrained()
.with_height(32.)
@@ -21,6 +21,7 @@ pub struct Theme {
pub workspace: Workspace,
pub chat_panel: ChatPanel,
pub contacts_panel: ContactsPanel,
+ pub contact_finder: ContactFinder,
pub project_panel: ProjectPanel,
pub command_palette: CommandPalette,
pub picker: Picker,
@@ -240,7 +241,7 @@ pub struct ContactsPanel {
pub row_height: f32,
pub contact_avatar: ImageStyle,
pub contact_username: ContainedText,
- pub edit_contact: ContainedText,
+ pub contact_button: ContainedText,
pub tree_branch_width: f32,
pub tree_branch_color: Color,
pub shared_project: ProjectRow,
@@ -249,6 +250,19 @@ pub struct ContactsPanel {
pub hovered_unshared_project: ProjectRow,
}
+#[derive(Deserialize, Default)]
+pub struct ContactFinder {
+ #[serde(flatten)]
+ pub container: ContainerStyle,
+ pub max_width: f32,
+ pub max_height: f32,
+ pub query_editor: FieldEditor,
+ pub row_height: f32,
+ pub contact_avatar: ImageStyle,
+ pub contact_username: ContainedText,
+ pub contact_button: ContainedText,
+}
+
#[derive(Deserialize, Default)]
pub struct AddContactIcon {
#[serde(flatten)]
@@ -824,6 +824,10 @@ impl Workspace {
&self.status_bar
}
+ pub fn user_store(&self) -> &ModelHandle<UserStore> {
+ &self.user_store
+ }
+
pub fn project(&self) -> &ModelHandle<Project> {
&self.project
}
@@ -931,7 +935,7 @@ impl Workspace {
})
}
- // Returns the model that was toggled closed if it was open
+ /// Returns the modal that was toggled closed if it was open.
pub fn toggle_modal<V, F>(
&mut self,
cx: &mut ViewContext<Self>,
@@ -1,6 +1,7 @@
import Theme from "../themes/theme";
import chatPanel from "./chatPanel";
import { text } from "./components";
+import contactFinder from "./contactFinder";
import contactsPanel from "./contactsPanel";
import commandPalette from "./commandPalette";
import editor from "./editor";
@@ -24,6 +25,7 @@ export default function app(theme: Theme): Object {
projectPanel: projectPanel(theme),
chatPanel: chatPanel(theme),
contactsPanel: contactsPanel(theme),
+ contactFinder: contactFinder(theme),
search: search(theme),
breadcrumbs: {
...text(theme, "sans", "secondary"),
@@ -0,0 +1,42 @@
+import Theme from "../themes/theme";
+import picker from "./picker";
+import { backgroundColor, border, player, text } from "./components";
+
+export default function contactFinder(theme: Theme) {
+ return {
+ ...picker(theme),
+ maxWidth: 540.,
+ maxHeight: 420.,
+ queryEditor: {
+ background: backgroundColor(theme, 500),
+ cornerRadius: 6,
+ text: text(theme, "mono", "primary"),
+ placeholderText: text(theme, "mono", "placeholder", { size: "sm" }),
+ selection: player(theme, 1).selection,
+ border: border(theme, "secondary"),
+ padding: {
+ bottom: 4,
+ left: 8,
+ right: 8,
+ top: 4,
+ },
+ },
+ rowHeight: 28,
+ contactAvatar: {
+ cornerRadius: 10,
+ width: 18,
+ },
+ contactUsername: {
+ ...text(theme, "mono", "primary", { size: "sm" }),
+ padding: {
+ left: 8,
+ },
+ },
+ contactButton: {
+ ...text(theme, "mono", "primary", { size: "sm" }),
+ background: backgroundColor(theme, 100),
+ cornerRadius: 12,
+ padding: { left: 7, right: 7 }
+ },
+ }
+}
@@ -2,7 +2,7 @@ import Theme from "../themes/theme";
import { panel } from "./app";
import { backgroundColor, border, borderColor, iconColor, player, text } from "./components";
-export default function(theme: Theme) {
+export default function contactsPanel(theme: Theme) {
const project = {
guestAvatarSpacing: 4,
height: 24,
@@ -64,7 +64,7 @@ export default function(theme: Theme) {
left: 8,
},
},
- editContact: {
+ contactButton: {
...text(theme, "mono", "primary", { size: "sm" }),
background: backgroundColor(theme, 100),
cornerRadius: 12,