Studio 10
Peer Critique
We're going to start with peer critique of your personal tracking applications.
Color game
Spend some time playing this color guessing game.
Let's do a little experiment:
First, restrict yourself to only using rectangular color models (rgb(), hex, lab(), oklab()).
See what score and times you get.
Then, try using only cylindrical color models (hsl(), hwb(), lch(), oklch()).
Did you get a better or worse average score? What about average time?
Multiple Chats
We're going to build off the basic chat application you started working on last studio. Today, we're going to modify it to manage multiple chats rather than just one single chat.
-
Start from this starter code, which is effectively a solution to last week's studio. Run it and send a message in the chat. You should see the messages that other people send too. Read through the code to make sure you understand what's going on.
-
Before developing a UI to manage multiple chats, lets first try to manually create a different chat. At the top of the starter code there is a variable called
channel. You can see that this variable is used when you send a message (graffiti.post) and when you discover messages (graffiti.discover).- First try changing
channelto a different string. What happens to the existing chat messages? Can you still send new messages? - Tell a friend to use the same new channel string as you. Can you see their messages?
- You can effectively create a new chat by simply changing the channel that objects are being posted to and discovered from. We're going to develop a UI for managing chats that, under the hood, is effectively just changing the
channelstring.
- First try changing
-
Lets add a button to create a new chat by changing the channel to a random string. To do that:
- Make the channel into a signal rather than a constant variable so that it can reactively change:
const channel = ref("designftw-26");. After changing channel to a signal, you will also need to change how it is referenced in the code:- Within
graffiti.postchangechannels: [channel]tochannels: [channel.value]. - Within
useGraffitiDiscoverchange[channel]to() => [channel.value]. We are passing in a function because we wantuseGraffitiDiscoverto update every time the channel changes. If we simply passed in[channel.value]then that expression would be immediately evaluated to["designftw-26"]. - Make sure you can still send and receive messages.
- Within
- Now that
channelis a signal, create a function callednewChatthat assigns the channel signal to the result of crypto.randomUUID(). This is just a built in browser function that returns a random string (try it in the browser console). - Finally add a button labeled "New Chat" that calls the
newChatfunction when it is clicked. Make sure you are returning thenewChatfunction fromsetupor it will not be accessible in the template.
- Make the channel into a signal rather than a constant variable so that it can reactively change:
-
Now you should be able to click "New Chat", which will clear out the existing chat and allow you to send new messages. Unfortunately, if you refresh the page or click "New Chat" again, those messages will go away forever! And, there is no way to invite people to the same chat as you. Somehow we need to make the random chat channels we are creating both persistent and sharable. For that, we can create additional Graffiti objects, similar to the other chat messages.
- Modify the
newChatfunction so that rather than changing the channel signal, it posts a new Graffiti object representing a chat. Objects can include arbitrary JSON in theirvaluefield, so here we're going to make a new type of data for representing chats. Later on, you should make thetitleof the chat user-specified, but for now its OK to hardcode it.
await graffiti.post( { value: { activity: "Create", type: "Chat", channel: crypto.randomUUID(), title: "My Chat", // TODO: let the user specify this published: Date.now(), }, channels: ["designftw-26"], }, session.value, );- You can now post new chat objects but cannot see them. You always need to pair post with discover. You could start out by doing something like this:
const { objects: chats } = useGraffitiDiscover( ["designftw-26"], {} // Empty schema )Try visualizing the chats data in the template with
{{ chats }}. Unfortunately, you will see group chat data intermixed with chat message data! This is because we have used the same channel, "designftw-26", for both chat objects and the chat message objects. We can fix this by passing in a JSON Schema to filter for only chat objects. In particular, we can change the current schema{}, which matches any object, to a schema that only matches the chat objects. The schema should look something like this:{ properties: { value: { required: [], // Mark which properties are required (all of them should be required in this case) properties: { // Add properties specifications here } } } }You will need to use const for the
activityandtypeproperties, type string for thechannelandtitleproperties, and type number for thepublishedproperty. Feel free to ask AI to do this---JSON Schemas are widely used in web APIs and so AI models have been trained on a lot of examples of them.- Once you have filtered for chat objects, display the chat titles in a human-readable way using a
v-forloop. When a particular chat is clicked on, you should change the channel signal you set up before to the selected chat's channel. Now you should be able to select between different chats! - Finally, if you haven't already done so, make it possible for users to specify the title of the chat rather than it being hardcoded. This will make it much easier to find chats within the list.
- Modify the