Skip to content

Commit d53fdc2

Browse files
committed
fix: clean-up frontend components and wrap string as translatable
1 parent 7079d71 commit d53fdc2

8 files changed

Lines changed: 151 additions & 183 deletions

File tree

custom/SessionsHistory.vue

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,9 @@ import { useAgentStore } from './composables/useAgentStore';
5555
const agentStore = useAgentStore();
5656
5757
const h3Style = "text-gray-800 dark:text-gray-200 font-medium text-xl tracking-widest my-2"
58-
5958
const dayLabelFormatter = new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric' });
6059
const dayLabelWithYearFormatter = new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric', year: 'numeric' });
6160
62-
function getLocalDayKey(date: Date) {
63-
const year = date.getFullYear();
64-
const month = `${date.getMonth() + 1}`.padStart(2, '0');
65-
const day = `${date.getDate()}`.padStart(2, '0');
66-
67-
return `${year}-${month}-${day}`;
68-
}
69-
7061
const groupedSessions = computed(() => {
7162
const groups = new Map<string, { dayKey: string; label: string; sessions: ISessionsListItem[] }>();
7263
@@ -91,4 +82,13 @@ const groupedSessions = computed(() => {
9182
return Array.from(groups.values());
9283
});
9384
85+
86+
function getLocalDayKey(date: Date) {
87+
const year = date.getFullYear();
88+
const month = `${date.getMonth() + 1}`.padStart(2, '0');
89+
const day = `${date.getDate()}`.padStart(2, '0');
90+
91+
return `${year}-${month}-${day}`;
92+
}
93+
9494
</script>

custom/conversation_area/ConversationArea.vue

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,8 @@ const agentStore = useAgentStore();
8989
const agentTransitions = useAgentTransitions();
9090
const showScrollContainer = ref(true);
9191
const chatContainerRef = ref<HTMLElement | null>(null);
92-
9392
const messagesRefs = ref<Array<HTMLElement | null>>([]);
94-
93+
const useWaitingForHeight = ref(false);
9594
9695
/*
9796
* Whenever user sends a message, it adds a bottom spacer, that takes the remaining height
@@ -116,15 +115,60 @@ let messageResizeObserver: ResizeObserver | null = null;
116115
let observedLastUserMessageElement: HTMLElement | null = null;
117116
let observedLastAgentMessageElement: HTMLElement | null = null;
118117
119-
function resetSpacer() {
120-
showBottomSpacer.value = false;
121-
spacerHeight.value = 0;
122-
}
118+
onMounted(async () => {
119+
messageResizeObserver = new ResizeObserver(() => {
120+
updateSpacerHeight();
121+
});
122+
123+
await import('@incremark/theme/styles.css')
124+
await agentStore.fetchPlaceholderMessages()
125+
await refreshSpacerTracking();
126+
});
127+
128+
onUnmounted(() => {
129+
if (innerScrollContainerRef.value) {
130+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
131+
}
132+
133+
stopObservingLastMessages();
134+
messageResizeObserver?.disconnect();
135+
agentStore.stopPlaceholderAnimation();
136+
});
123137
124138
watch(() => agentStore.activeSessionId, () => {
125139
resetSpacer();
126140
});
127141
142+
watch(() => agentStore.activeSessionId, async () => {
143+
showScrollContainer.value = false;
144+
await nextTick();
145+
showScrollContainer.value = true;
146+
await refreshSpacerTracking();
147+
recalculateScroll();
148+
});
149+
150+
watch(() => props.messages.length, async () => {
151+
await refreshSpacerTracking();
152+
});
153+
154+
watch(scrollContainer, async () => {
155+
if (innerScrollContainerRef.value) {
156+
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
157+
}
158+
159+
if (scrollContainer.value) {
160+
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
161+
162+
innerScrollContainerRef.value.addEventListener('scroll', recalculateScroll);
163+
await refreshSpacerTracking();
164+
}
165+
})
166+
167+
function resetSpacer() {
168+
showBottomSpacer.value = false;
169+
spacerHeight.value = 0;
170+
}
171+
128172
function getLastMessageElement(role: 'user' | 'assistant') {
129173
const lastMessageIndex = props.messages.findLastIndex((message: IMessage) => message.role === role);
130174
return messagesRefs.value[lastMessageIndex] ?? null;
@@ -156,7 +200,6 @@ async function waitForRealHeight(role: 'user' | 'assistant'): Promise<number> {
156200
});
157201
}
158202
159-
const useWaitingForHeight = ref(false);
160203
async function updateSpacerHeight() {
161204
if (!showBottomSpacer.value) {
162205
return;
@@ -238,51 +281,4 @@ function recalculateScroll() {
238281
}
239282
}
240283
241-
watch(() => agentStore.activeSessionId, async () => {
242-
showScrollContainer.value = false;
243-
await nextTick();
244-
showScrollContainer.value = true;
245-
await refreshSpacerTracking();
246-
recalculateScroll();
247-
});
248-
249-
watch(() => props.messages.length, async () => {
250-
await refreshSpacerTracking();
251-
});
252-
253-
onMounted(async () => {
254-
messageResizeObserver = new ResizeObserver(() => {
255-
updateSpacerHeight();
256-
});
257-
258-
await import('@incremark/theme/styles.css')
259-
await agentStore.fetchPlaceholderMessages()
260-
await refreshSpacerTracking();
261-
});
262-
263-
onUnmounted(() => {
264-
if (innerScrollContainerRef.value) {
265-
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
266-
}
267-
268-
stopObservingLastMessages();
269-
messageResizeObserver?.disconnect();
270-
agentStore.stopPlaceholderAnimation();
271-
});
272-
273-
watch(scrollContainer, async () => {
274-
if (innerScrollContainerRef.value) {
275-
innerScrollContainerRef.value.removeEventListener('scroll', recalculateScroll);
276-
}
277-
278-
if (scrollContainer.value) {
279-
innerScrollContainerRef.value = scrollContainer.value.container.scrollEl;
280-
281-
innerScrollContainerRef.value.addEventListener('scroll', recalculateScroll);
282-
await refreshSpacerTracking();
283-
}
284-
})
285-
286-
287-
288284
</script>

custom/conversation_area/ProcessingTimeline.vue

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
class="ml-2 px-4 flex items-center gap-1 cursor-pointer select-none hover:opacity-80 tracking-wide font-medium text-sm text-listTableHeadingText dark:text-darkListTableHeadingText"
55
@click="isExpanded = !isExpanded"
66
>
7-
Thoughts
7+
{{ $t('Thoughts') }}
88
<span v-if="thinkingDuration > 0">({{ (thinkingDuration/1000).toFixed(2) }} s)</span>
99
<ThreeDotsAnimation v-if="isResponseInProgress || showFakeThinkingMessage" />
1010
<IconAngleDownOutline
@@ -59,11 +59,27 @@
5959
const thinkingDuration = ref(0);
6060
const scrollContainerRef = ref<InstanceType<typeof CustomAutoScrollContainer> | null>(null);
6161
const innerScrollContainerRef = ref<HTMLElement | null>(null);
62+
const isExpanded = ref(true);
63+
const ToolOrReasoningParts = computed(() => {
64+
return props.message.parts.filter((part: IPart) => part.type === 'data-tool-call' || part.type === 'reasoning');
65+
});
66+
const isResponseInProgress = computed(() =>{
67+
return props.isLastMessageInChat && agentStore.isResponseInProgress;
68+
});
69+
70+
const showFakeThinkingMessage = computed(() => {
71+
if (props.message.parts.length === 0) return true;
72+
return false;
73+
})
6274
6375
onMounted(() => {
6476
thinkingStartTime.value = Date.now();
6577
})
6678
79+
onUnmounted(() => {
80+
scrollContainerRef.value?.container.scrollEl?.removeEventListener('scroll', handleScroll);
81+
})
82+
6783
watch(scrollContainerRef, async () => {
6884
if (innerScrollContainerRef.value) {
6985
innerScrollContainerRef.value.removeEventListener('scroll', handleScroll);
@@ -75,34 +91,12 @@
7591
}
7692
})
7793
78-
onUnmounted(() => {
79-
scrollContainerRef.value?.container.scrollEl?.removeEventListener('scroll', handleScroll);
80-
})
81-
82-
function handleScroll() {
83-
scrollContainerRef.value?.handleScroll();
84-
}
85-
86-
const ToolOrReasoningParts = computed(() => {
87-
return props.message.parts.filter((part: IPart) => part.type === 'data-tool-call' || part.type === 'reasoning');
88-
});
89-
const isExpanded = ref(true);
90-
91-
const isResponseInProgress = computed(() =>{
92-
return props.isLastMessageInChat && agentStore.isResponseInProgress;
93-
});
94-
9594
watch(isResponseInProgress, (newValue: boolean) => {
9695
if (!newValue) {
9796
isExpanded.value = false;
9897
thinkingDuration.value = Date.now() - (thinkingStartTime.value ?? Date.now());
9998
}
10099
});
101-
102-
const showFakeThinkingMessage = computed(() => {
103-
if (props.message.parts.length === 0) return true;
104-
return false;
105-
})
106100
107101
const formatToolCallPart = (part: IPart, currentMessage: IMessage): IFormattedToolCallPart | null => {
108102
if (part.type !== 'data-tool-call' || part.data?.phase !== 'start') {
@@ -182,7 +176,9 @@
182176
return groupedParts;
183177
};
184178
185-
179+
function handleScroll() {
180+
scrollContainerRef.value?.handleScroll();
181+
}
186182
</script>
187183

188184
<style scoped>

custom/conversation_area/ReasoningRenderer.vue

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,16 @@ import type { IPart } from '../types';
3535
import { ref, computed, watch, defineAsyncComponent } from 'vue';
3636
import ThreeDotsAnimation from './ThreeDotsAnimation.vue';
3737
import { extractTitleAndTextFromReasoning } from '../utils';
38-
import CustomAutoScrollContainer from '../CustomAutoScrollContainer.vue';
39-
40-
const IncremarkContent = defineAsyncComponent(() => import('@incremark/vue').then(module => module.IncremarkContent))
4138
4239
const props = defineProps<{
4340
state?: IPart['state']
4441
text?: string
4542
}>();
4643
47-
const isStreaming = computed(() => props.state === 'streaming');
44+
const IncremarkContent = defineAsyncComponent(() => import('@incremark/vue').then(module => module.IncremarkContent))
45+
4846
const isExpanded = ref(true);
47+
const isStreaming = computed(() => props.state === 'streaming');
4948
const parsedReasoning = computed(() => extractTitleAndTextFromReasoning(props.text ?? ''));
5049
const reasoningTitle = computed(() => parsedReasoning.value.title ?? '');
5150
const reasoningText = computed(() => parsedReasoning.value.body);
@@ -56,8 +55,6 @@ watch(() => props.state, (newValue: IPart['state']) => {
5655
}
5756
});
5857
59-
60-
6158
</script>
6259

6360

custom/conversation_area/TextRenderer.vue

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,55 +17,54 @@
1717
:incremark-options="incremarkOptions"
1818
/>
1919
<p v-else class="text-red-500 py-2">
20-
Error occurred
20+
{{ $t('Error occurred') }}
2121
</p>
2222
</div>
2323
</template>
2424

25-
<script setup lang="ts">
25+
<script setup lang="ts">const isExpanded = ref(true);
26+
2627
import { computed, defineAsyncComponent, onMounted, ref, watch } from 'vue';
2728
import { useRouter } from 'vue-router';
2829
import { useAgentStore } from '../composables/useAgentStore';
2930
import { useCoreStore } from '@/stores/core';
3031
32+
const props = defineProps<{
33+
message: string | undefined,
34+
state: string | undefined,
35+
role: 'user' | 'assistant'
36+
}>();
37+
38+
const emit = defineEmits(['toggle-thoughts']);
39+
3140
const IncremarkContent = defineAsyncComponent(() => import('@incremark/vue').then(module => module.IncremarkContent))
3241
const ShikiCodeBlock = defineAsyncComponent(() => import('../incremark_code_renderers/IncremarkShikiCodeBlock.vue'))
3342
3443
const agentStore = useAgentStore();
3544
const coreStore = useCoreStore();
45+
const router = useRouter();
46+
47+
const isThoughtsExpanded = ref(true);
48+
49+
const content = computed(() => props.message)
50+
const isFinished = computed(() => props.state === 'done')
51+
const hasVegaLite = computed(() => props.message?.includes('```vega-lite'))
52+
const isStateStreaming = computed(() => props.state === 'streaming')
3653
3754
const incremarkComponents = {
3855
code: ShikiCodeBlock,
3956
};
40-
4157
const incremarkOptions = {
4258
gfm: true,
4359
math: { tex: true },
4460
containers: true,
4561
htmlTree: true,
4662
};
4763
48-
const router = useRouter();
49-
5064
onMounted(async () => {
5165
void import('katex/dist/katex.min.css')
5266
})
5367
54-
const props = defineProps<{
55-
message: string | undefined,
56-
state: string | undefined,
57-
role: 'user' | 'assistant'
58-
}>();
59-
60-
const emit = defineEmits(['toggle-thoughts']);
61-
62-
const content = computed(() => props.message)
63-
const isFinished = computed(() => props.state === 'done')
64-
const isThoughtsExpanded = ref(true);
65-
const hasVegaLite = computed(() => props.message?.includes('```vega-lite'))
66-
67-
const isStateStreaming = computed(() => props.state === 'streaming')
68-
6968
watch(isStateStreaming, (newValue: boolean) => {
7069
if (!newValue) {
7170
isThoughtsExpanded.value = false;
@@ -125,12 +124,6 @@
125124
126125
</script>
127126

128-
<style lang="scss">
129-
.incremark-paragraph {
130-
margin: 8px 0;
131-
}
132-
</style>
133-
134127
<style lang="scss">
135128
.incremark a.incremark-link,
136129
.incremark a.incremark-link:visited {
@@ -173,4 +166,8 @@ a.incremark-link::after {
173166
.incremark-list {
174167
list-style: disc;
175168
}
169+
170+
.incremark-paragraph {
171+
margin: 8px 0;
172+
}
176173
</style>

0 commit comments

Comments
 (0)