Skip to content

Commit 7737d8c

Browse files
authored
client: refactor more components to use setup to simplify them (#1594)
1 parent f01fd51 commit 7737d8c

10 files changed

+815
-1035
lines changed

client/src/components/AddPreview.vue

+173-210
Large diffs are not rendered by default.

client/src/components/Chat.vue

+113-182
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@
2020
<div ref="messages" @scroll="onScroll" class="messages grow">
2121
<div class="grow"><!-- Spacer --></div>
2222
<transition-group name="message">
23-
<div class="message" v-for="(msg, index) in chatMessagePast" :key="index">
24-
<div class="from">{{ msg.from.name }}</div>
25-
<div class="text">
26-
<ProcessedText :text="msg.text" @link-click="e => $emit('link-click', e)" />
27-
</div>
28-
</div>
29-
<div
30-
class="message recent"
23+
<ChatMsg
24+
:msg="msg"
25+
v-for="(msg, index) in chatMessagePast"
26+
:key="index"
27+
@link-click="emit('link-click', $event)"
28+
/>
29+
<ChatMsg
30+
:msg="msg"
31+
recent
3132
v-for="(msg, index) in chatMessageRecent"
3233
:key="chatMessagePast.length + index"
33-
>
34-
<!-- FIXME: reduce duplicated code by moving this to another component, preferably in this same file. -->
35-
<div class="from">{{ msg.from.name }}</div>
36-
<div class="text"><ProcessedText :text="msg.text" /></div>
37-
</div>
34+
@link-click="emit('link-click', $event)"
35+
/>
3836
</transition-group>
3937
</div>
4038
<div v-if="!stickToBottom" class="to-bottom">
@@ -74,163 +72,129 @@
7472
</div>
7573
</template>
7674

77-
<script lang="ts">
78-
import ProcessedText from "@/components/ProcessedText.vue";
79-
import { defineComponent, onUpdated, ref, Ref, nextTick, onMounted, onUnmounted } from "vue";
75+
<script lang="ts" setup>
76+
import { onUpdated, ref, Ref, nextTick, onMounted, onUnmounted } from "vue";
8077
import type { ChatMessage } from "ott-common/models/types";
8178
import { useConnection } from "@/plugins/connection";
8279
import { useRoomApi } from "@/util/roomapi";
8380
import { ServerMessageChat } from "ott-common/models/messages";
8481
import { useRoomKeyboardShortcuts } from "@/util/keyboard-shortcuts";
8582
import { useSfx } from "@/plugins/sfx";
83+
import ChatMsg from "./ChatMsg.vue";
8684
8785
const MSG_SHOW_TIMEOUT = 20000;
8886
89-
const Chat = defineComponent({
90-
name: "Chat",
91-
components: {
92-
ProcessedText,
93-
},
94-
emits: ["link-click"],
95-
setup() {
96-
const connection = useConnection();
97-
const roomapi = useRoomApi(connection);
98-
99-
const inputValue = ref("");
100-
const stickToBottom = ref(true);
101-
/**
102-
* When chat is activated, all messages are shown. and the
103-
* user can scroll through message history, type in chat, etc.
104-
* When chat is NOT activated, when messages are received,
105-
* they appear and fade away after `MSG_SHOW_TIMEOUT` ms.
106-
*/
107-
const activated = ref(false);
108-
const deactivateOnBlur = ref(false);
109-
/**
110-
* All past chat messages. They are are no longer
111-
* shown when deactivated.
112-
*/
113-
const chatMessagePast: Ref<ChatMessage[]> = ref([]);
114-
/**
115-
* All recent chat messages that are currently shown when deactivated.
116-
* They will fade away after `MSG_SHOW_TIMEOUT` ms, and moved into `chatMessagePast`.
117-
*/
118-
const chatMessageRecent: Ref<ChatMessage[]> = ref([]);
119-
const messages = ref();
120-
const chatInput: Ref<HTMLInputElement | undefined> = ref();
121-
122-
const shortcuts = useRoomKeyboardShortcuts();
123-
onMounted(() => {
124-
connection.addMessageHandler("chat", onChatReceived);
125-
if (shortcuts) {
126-
shortcuts.bind({ code: "KeyT" }, () => setActivated(true, false));
127-
} else {
128-
console.warn("No keyboard shortcuts available");
129-
}
130-
});
131-
132-
onUnmounted(() => {
133-
connection.removeMessageHandler("chat", onChatReceived);
134-
});
135-
136-
function focusChatInput() {
137-
chatInput.value?.focus();
138-
}
87+
const emit = defineEmits(["link-click"]);
88+
89+
const connection = useConnection();
90+
const roomapi = useRoomApi(connection);
91+
92+
const inputValue = ref("");
93+
const stickToBottom = ref(true);
94+
/**
95+
* When chat is activated, all messages are shown. and the
96+
* user can scroll through message history, type in chat, etc.
97+
* When chat is NOT activated, when messages are received,
98+
* they appear and fade away after `MSG_SHOW_TIMEOUT` ms.
99+
*/
100+
const activated = ref(false);
101+
const deactivateOnBlur = ref(false);
102+
/**
103+
* All past chat messages. They are are no longer
104+
* shown when deactivated.
105+
*/
106+
const chatMessagePast: Ref<ChatMessage[]> = ref([]);
107+
/**
108+
* All recent chat messages that are currently shown when deactivated.
109+
* They will fade away after `MSG_SHOW_TIMEOUT` ms, and moved into `chatMessagePast`.
110+
*/
111+
const chatMessageRecent: Ref<ChatMessage[]> = ref([]);
112+
const messages = ref();
113+
const chatInput: Ref<HTMLInputElement | undefined> = ref();
114+
115+
const shortcuts = useRoomKeyboardShortcuts();
116+
onMounted(() => {
117+
connection.addMessageHandler("chat", onChatReceived);
118+
if (shortcuts) {
119+
shortcuts.bind({ code: "KeyT" }, () => setActivated(true, false));
120+
} else {
121+
console.warn("No keyboard shortcuts available");
122+
}
123+
});
139124
140-
function isActivated(): boolean {
141-
return activated.value;
142-
}
125+
onUnmounted(() => {
126+
connection.removeMessageHandler("chat", onChatReceived);
127+
});
143128
144-
async function setActivated(value: boolean, manual = false): Promise<void> {
145-
activated.value = value;
146-
if (value) {
147-
if (manual) {
148-
deactivateOnBlur.value = false;
149-
} else {
150-
deactivateOnBlur.value = true;
151-
}
152-
await nextTick();
153-
focusChatInput();
154-
} else {
155-
chatInput.value?.blur();
156-
forceToBottom();
157-
}
158-
}
129+
function focusChatInput() {
130+
chatInput.value?.focus();
131+
}
159132
160-
const sfx = useSfx();
161-
function onChatReceived(msg: ServerMessageChat): void {
162-
chatMessageRecent.value.push(msg);
163-
setTimeout(expireChatMessage, MSG_SHOW_TIMEOUT);
164-
nextTick(enforceStickToBottom);
165-
sfx.play("pop");
133+
async function setActivated(value: boolean, manual = false): Promise<void> {
134+
activated.value = value;
135+
if (value) {
136+
if (manual) {
137+
deactivateOnBlur.value = false;
138+
} else {
139+
deactivateOnBlur.value = true;
166140
}
141+
await nextTick();
142+
focusChatInput();
143+
} else {
144+
chatInput.value?.blur();
145+
forceToBottom();
146+
}
147+
}
167148
168-
function expireChatMessage() {
169-
chatMessagePast.value.push(chatMessageRecent.value.splice(0, 1)[0]);
170-
}
149+
const sfx = useSfx();
150+
function onChatReceived(msg: ServerMessageChat): void {
151+
chatMessageRecent.value.push(msg);
152+
setTimeout(expireChatMessage, MSG_SHOW_TIMEOUT);
153+
nextTick(enforceStickToBottom);
154+
sfx.play("pop");
155+
}
171156
172-
/**
173-
* Performs the necessary actions to enact the stickToBottom behavior.
174-
*/
175-
function enforceStickToBottom() {
176-
const div = messages.value as HTMLDivElement;
177-
if (stickToBottom.value) {
178-
div.scrollTop = div.scrollHeight;
179-
}
180-
}
157+
function expireChatMessage() {
158+
chatMessagePast.value.push(chatMessageRecent.value.splice(0, 1)[0]);
159+
}
181160
182-
function onInputKeyDown(e: KeyboardEvent): void {
183-
if (e.key === "Enter") {
184-
e.preventDefault();
185-
if (inputValue.value.trim() !== "") {
186-
roomapi.chat(inputValue.value);
187-
}
188-
inputValue.value = "";
189-
stickToBottom.value = true;
190-
setActivated(false);
191-
} else if (e.key === "Escape") {
192-
e.preventDefault();
193-
setActivated(false);
194-
}
195-
}
161+
/**
162+
* Performs the necessary actions to enact the stickToBottom behavior.
163+
*/
164+
function enforceStickToBottom() {
165+
const div = messages.value as HTMLDivElement;
166+
if (stickToBottom.value) {
167+
div.scrollTop = div.scrollHeight;
168+
}
169+
}
196170
197-
function onScroll() {
198-
const div = messages.value as HTMLDivElement;
199-
const distToBottom = div.scrollHeight - div.clientHeight - div.scrollTop;
200-
stickToBottom.value = distToBottom === 0;
171+
function onInputKeyDown(e: KeyboardEvent): void {
172+
if (e.key === "Enter") {
173+
e.preventDefault();
174+
if (inputValue.value.trim() !== "") {
175+
roomapi.chat(inputValue.value);
201176
}
177+
inputValue.value = "";
178+
stickToBottom.value = true;
179+
setActivated(false);
180+
} else if (e.key === "Escape") {
181+
e.preventDefault();
182+
setActivated(false);
183+
}
184+
}
202185
203-
function forceToBottom() {
204-
stickToBottom.value = true;
205-
enforceStickToBottom();
206-
}
186+
function onScroll() {
187+
const div = messages.value as HTMLDivElement;
188+
const distToBottom = div.scrollHeight - div.clientHeight - div.scrollTop;
189+
stickToBottom.value = distToBottom === 0;
190+
}
207191
208-
onUpdated(enforceStickToBottom);
209-
210-
return {
211-
inputValue,
212-
stickToBottom,
213-
activated,
214-
chatMessagePast,
215-
chatMessageRecent,
216-
deactivateOnBlur,
217-
218-
onInputKeyDown,
219-
onScroll,
220-
focusChatInput,
221-
isActivated,
222-
setActivated,
223-
onChatReceived,
224-
enforceStickToBottom,
225-
forceToBottom,
226-
227-
messages,
228-
chatInput,
229-
};
230-
},
231-
});
192+
function forceToBottom() {
193+
stickToBottom.value = true;
194+
enforceStickToBottom();
195+
}
232196
233-
export default Chat;
197+
onUpdated(enforceStickToBottom);
234198
</script>
235199

236200
<style lang="scss" scoped>
@@ -300,39 +264,6 @@ $chat-message-bg: $background-color;
300264
align-items: baseline;
301265
}
302266
303-
.message {
304-
margin: 2px 0;
305-
padding: 4px;
306-
opacity: 0;
307-
transition: all 1s ease;
308-
309-
&:first-child {
310-
margin-top: auto;
311-
}
312-
313-
&.recent {
314-
opacity: 1;
315-
background: rgba(var(--v-theme-background), $alpha: 0.6);
316-
}
317-
318-
.from,
319-
.text {
320-
display: inline;
321-
margin: 3px 5px;
322-
word-wrap: break-word;
323-
overflow-wrap: anywhere;
324-
}
325-
326-
.from {
327-
font-weight: bold;
328-
margin-left: 0;
329-
}
330-
331-
@media screen and (max-width: $sm-max) {
332-
font-size: 0.8em;
333-
}
334-
}
335-
336267
.manual-activate {
337268
display: flex;
338269
align-self: flex-end;

0 commit comments

Comments
 (0)