ChatControls.svelte 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <script lang="ts">
  2. import { SvelteFlowProvider } from '@xyflow/svelte';
  3. import { slide } from 'svelte/transition';
  4. import { onDestroy, onMount } from 'svelte';
  5. import { mobile, showControls, showCallOverlay, showOverview } from '$lib/stores';
  6. import Modal from '../common/Modal.svelte';
  7. import Controls from './Controls/Controls.svelte';
  8. import CallOverlay from './MessageInput/CallOverlay.svelte';
  9. import Drawer from '../common/Drawer.svelte';
  10. import Overview from './Overview.svelte';
  11. import { Pane, PaneResizer } from 'paneforge';
  12. import EllipsisVertical from '../icons/EllipsisVertical.svelte';
  13. import { get } from 'svelte/store';
  14. export let history;
  15. export let models = [];
  16. export let chatId = null;
  17. export let chatFiles = [];
  18. export let params = {};
  19. export let eventTarget: EventTarget;
  20. export let submitPrompt: Function;
  21. export let stopResponse: Function;
  22. export let showMessage: Function;
  23. export let files;
  24. export let modelId;
  25. export let pane;
  26. let largeScreen = false;
  27. onMount(() => {
  28. // listen to resize 1024px
  29. const mediaQuery = window.matchMedia('(min-width: 1024px)');
  30. const handleMediaQuery = (e) => {
  31. if (e.matches) {
  32. largeScreen = true;
  33. } else {
  34. largeScreen = false;
  35. }
  36. };
  37. mediaQuery.addEventListener('change', handleMediaQuery);
  38. handleMediaQuery(mediaQuery);
  39. return () => {
  40. mediaQuery.removeEventListener('change', handleMediaQuery);
  41. };
  42. });
  43. onDestroy(() => {
  44. showControls.set(false);
  45. });
  46. $: if (!chatId) {
  47. showOverview.set(false);
  48. }
  49. </script>
  50. <SvelteFlowProvider>
  51. {#if !largeScreen}
  52. {#if $showControls}
  53. <Drawer
  54. show={$showControls}
  55. on:close={() => {
  56. showControls.set(false);
  57. }}
  58. >
  59. <div
  60. class=" {$showCallOverlay || $showOverview ? ' h-screen w-screen' : 'px-6 py-4'} h-full"
  61. >
  62. {#if $showCallOverlay}
  63. <div
  64. class=" h-full max-h-[100dvh] bg-white text-gray-700 dark:bg-black dark:text-gray-300 flex justify-center"
  65. >
  66. <CallOverlay
  67. bind:files
  68. {submitPrompt}
  69. {stopResponse}
  70. {modelId}
  71. {chatId}
  72. {eventTarget}
  73. on:close={() => {
  74. showControls.set(false);
  75. }}
  76. />
  77. </div>
  78. {:else if $showOverview}
  79. <Overview
  80. {history}
  81. on:nodeclick={(e) => {
  82. showMessage(e.detail.node.data.message);
  83. }}
  84. on:close={() => {
  85. showControls.set(false);
  86. }}
  87. />
  88. {:else}
  89. <Controls
  90. on:close={() => {
  91. showControls.set(false);
  92. }}
  93. {models}
  94. bind:chatFiles
  95. bind:params
  96. />
  97. {/if}
  98. </div>
  99. </Drawer>
  100. {/if}
  101. {:else}
  102. <!-- if $showControls -->
  103. <PaneResizer class="relative flex w-2 items-center justify-center bg-background">
  104. <div class="z-10 flex h-7 w-5 items-center justify-center rounded-sm">
  105. <EllipsisVertical />
  106. </div>
  107. </PaneResizer>
  108. <Pane
  109. bind:pane
  110. defaultSize={$showControls ? parseInt(localStorage.getItem('chat-controls-size') || '35') : 0}
  111. onResize={(size) => {
  112. if (size === 0) {
  113. showControls.set(false);
  114. } else {
  115. if (!$showControls) {
  116. showControls.set(true);
  117. }
  118. localStorage.setItem('chat-controls-size', size);
  119. }
  120. }}
  121. >
  122. <div class="pr-4 pb-8 flex max-h-full min-h-full" in:slide={{ duration: 200, axis: 'x' }}>
  123. <div
  124. class="w-full {$showOverview && !$showCallOverlay
  125. ? ' '
  126. : 'px-5 py-4 bg-white dark:shadow-lg dark:bg-gray-850 border border-gray-50 dark:border-gray-800'} rounded-lg z-50 pointer-events-auto overflow-y-auto scrollbar-hidden"
  127. >
  128. {#if $showCallOverlay}
  129. <div class="w-full h-full flex justify-center">
  130. <CallOverlay
  131. bind:files
  132. {submitPrompt}
  133. {stopResponse}
  134. {modelId}
  135. {chatId}
  136. {eventTarget}
  137. on:close={() => {
  138. showControls.set(false);
  139. }}
  140. />
  141. </div>
  142. {:else if $showOverview}
  143. <Overview
  144. {history}
  145. on:nodeclick={(e) => {
  146. showMessage(e.detail.node.data.message);
  147. }}
  148. on:close={() => {
  149. showControls.set(false);
  150. }}
  151. />
  152. {:else}
  153. <Controls
  154. on:close={() => {
  155. showControls.set(false);
  156. }}
  157. {models}
  158. bind:chatFiles
  159. bind:params
  160. />
  161. {/if}
  162. </div>
  163. </div>
  164. </Pane>
  165. {/if}
  166. </SvelteFlowProvider>