// The watch stream between devpage and a page: for each design the page
// shows, its scene, then patches of the nodes that changed, or its problems.
syntax = "proto3";
package devpage.design.v1;
service Designs {
rpc Watch(WatchRequest) returns (stream Update);
}
message WatchRequest {
// Every design the page shows, by address from the top of the served
// folder. A page holds one stream for all of them.
repeated string paths = 1;
}
message Update {
oneof body {
Scene scene = 1;
Patch patch = 2;
Problems problems = 3;
}
// The design this update is about, as the request named it.
string path = 4;
}
// A whole scene: its tree, each distinct image file the tree shows and font
// file its texts are set in, once, however many nodes use it, and whether it
// is themed — whether any `theme.` reference reached it.
message Scene {
Node root = 1;
repeated ImageFile images = 2;
bool themed = 3;
repeated FontFile fonts = 4;
}
// What changed, as operations on the scene last sent, applied in order, each
// naming its nodes by id; the image and font files they use that the scene
// last sent didn't have — only those — and whether the scene is themed now.
message Patch {
reserved 1;
repeated ImageFile images = 2;
bool themed = 3;
repeated FontFile fonts = 4;
repeated Op ops = 5;
}
// One operation of a patch.
message Op {
oneof op {
// The node with this node's id takes its own attributes; its children
// stay, and this node carries none.
Node change = 1;
Insert insert = 2;
// The node with this id goes, with its subtree.
NodeId remove = 3;
Move move = 4;
}
}
// A subtree placed under `parent`, right after its child `after` — or
// first, when `after` is unset.
message Insert {
NodeId parent = 1;
NodeId after = 2;
Node node = 3;
}
// The node `id`, with its subtree, placed under `parent` right after its
// child `after`, or first.
message Move {
NodeId id = 1;
NodeId parent = 2;
NodeId after = 3;
}
// A node's id: the element ids from the design's root through each instance
// down to the element that made it.
message NodeId {
repeated uint32 path = 1;
}
// An image file's bytes, PNG or JPEG, and its id: the SHA-256 of the bytes.
message ImageFile {
bytes id = 1;
bytes data = 2;
}
// A font file's bytes, TrueType or OpenType, and its id: the SHA-256 of the
// bytes.
message FontFile {
bytes id = 1;
bytes data = 2;
}
message Problems {
repeated string problems = 1;
}
// One node of a scene, every attribute resolved. A size is pixels, or -1
// for hug and -2 for fill. A fill is `fill` (one color) or `gradient`, never
// both.
message Node {
Kind kind = 1;
string name = 2;
float x = 3;
float y = 4;
float width = 5;
float height = 6;
float opacity = 7;
string on_click = 8;
Color fill = 9;
Color stroke = 10;
float stroke_width = 11;
repeated float radius = 12;
Shadow shadow = 13;
bool clip = 14;
Layout layout = 15;
float gap = 16;
repeated float padding = 17;
Align align = 18;
Align justify = 19;
Text text = 20;
repeated Node children = 21;
Gradient gradient = 22;
Vector vector = 23;
Image image = 24;
// Where the node came from, which no edit around it changes.
NodeId id = 25;
}
// A linear gradient: `angle` in degrees as in CSS, stops along its line.
message Gradient {
float angle = 1;
repeated Stop stops = 2;
}
// A color's value in each of the design's themes, each 0xRRGGBBAA; a color
// written as `#…` has the same value in both.
message Color {
uint32 light = 1;
uint32 dark = 2;
}
message Stop {
Color color = 1;
// From 0 to 1 along the gradient line.
float at = 2;
}
// A vector's SVG path data and its view box: min x, min y, width, height.
message Vector {
string d = 1;
repeated float view_box = 2;
}
// An image's address in the served folder and the id of the image file it
// shows, which the scene or a patch carries.
message Image {
string src = 1;
bytes id = 2;
}
enum Kind {
FRAME = 0;
TEXT = 1;
RECT = 2;
ELLIPSE = 3;
VECTOR = 4;
IMAGE = 5;
}
enum Layout {
NONE = 0;
ROW = 1;
COLUMN = 2;
}
enum Align {
START = 0;
CENTER = 1;
END = 2;
SPACE_BETWEEN = 3;
}
message Shadow {
float x = 1;
float y = 2;
float blur = 3;
float spread = 4;
Color color = 5;
}
message Text {
string content = 1;
float size = 2;
uint32 weight = 3;
Color color = 4;
float line_height = 5;
TextAlign align = 6;
// The id of the font file the text is set in, which the scene or a patch
// carries; empty for Inter, which the engine embeds.
bytes font = 7;
}
enum TextAlign {
TEXT_ALIGN_LEFT = 0;
TEXT_ALIGN_CENTER = 1;
TEXT_ALIGN_RIGHT = 2;
}