ShareChatModal.svelte 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <script lang="ts">
  2. import { getContext, onMount } from 'svelte';
  3. import fileSaver from 'file-saver';
  4. const { saveAs } = fileSaver;
  5. import { toast } from 'svelte-sonner';
  6. import { deleteSharedChatById, getChatById, shareChatById } from '$lib/apis/chats';
  7. import { chatId, modelfiles } from '$lib/stores';
  8. import { copyToClipboard } from '$lib/utils';
  9. import Modal from '../common/Modal.svelte';
  10. import Link from '../icons/Link.svelte';
  11. let chat = null;
  12. const i18n = getContext('i18n');
  13. const shareLocalChat = async () => {
  14. const _chat = chat;
  15. const sharedChat = await shareChatById(localStorage.token, $chatId);
  16. const chatShareUrl = `${window.location.origin}/s/${sharedChat.id}`;
  17. toast.success($i18n.t('Copied shared chat URL to clipboard!'));
  18. copyToClipboard(chatShareUrl);
  19. chat = await getChatById(localStorage.token, $chatId);
  20. };
  21. const shareChat = async () => {
  22. const _chat = chat.chat;
  23. console.log('share', _chat);
  24. toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
  25. const url = 'https://openwebui.com';
  26. // const url = 'http://localhost:5173';
  27. const tab = await window.open(`${url}/chats/upload`, '_blank');
  28. window.addEventListener(
  29. 'message',
  30. (event) => {
  31. if (event.origin !== url) return;
  32. if (event.data === 'loaded') {
  33. tab.postMessage(
  34. JSON.stringify({
  35. chat: _chat,
  36. modelfiles: $modelfiles.filter((modelfile) =>
  37. _chat.models.includes(modelfile.tagName)
  38. )
  39. }),
  40. '*'
  41. );
  42. }
  43. },
  44. false
  45. );
  46. };
  47. const downloadChat = async () => {
  48. const _chat = chat.chat;
  49. console.log('download', chat);
  50. const chatText = _chat.messages.reduce((a, message, i, arr) => {
  51. return `${a}### ${message.role.toUpperCase()}\n${message.content}\n\n`;
  52. }, '');
  53. let blob = new Blob([chatText], {
  54. type: 'text/plain'
  55. });
  56. saveAs(blob, `chat-${_chat.title}.txt`);
  57. };
  58. export let show = false;
  59. onMount(async () => {
  60. chatId.subscribe(async (value) => {
  61. chat = await getChatById(localStorage.token, value);
  62. console.log(chat);
  63. });
  64. });
  65. </script>
  66. <Modal bind:show size="sm">
  67. <div>
  68. <div class=" flex justify-between dark:text-gray-300 px-5 py-4">
  69. <div class=" text-lg font-medium self-center">{$i18n.t('Share Chat')}</div>
  70. <button
  71. class="self-center"
  72. on:click={() => {
  73. show = false;
  74. }}
  75. >
  76. <svg
  77. xmlns="http://www.w3.org/2000/svg"
  78. viewBox="0 0 20 20"
  79. fill="currentColor"
  80. class="w-5 h-5"
  81. >
  82. <path
  83. d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
  84. />
  85. </svg>
  86. </button>
  87. </div>
  88. <hr class=" dark:border-gray-800" />
  89. {#if chat}
  90. <div class="px-4 pt-4 pb-5 w-full flex flex-col justify-center">
  91. <div class=" text-sm dark:text-gray-300 mb-1">
  92. {#if chat.share_id}
  93. <a href="/s/{chat.share_id}" target="_blank"
  94. >You have shared this chat <span class=" underline">before</span>.</a
  95. >
  96. Click here to
  97. <button
  98. class="underline"
  99. on:click={async () => {
  100. const res = await deleteSharedChatById(localStorage.token, $chatId);
  101. if (res) {
  102. chat = await getChatById(localStorage.token, $chatId);
  103. }
  104. }}>delete this link</button
  105. > and create a new shared link.
  106. {:else}
  107. Messages you send after creating your link won't be shared. Users with the URL will be
  108. able to view the shared chat.
  109. {/if}
  110. </div>
  111. <div class="flex justify-end">
  112. <div class="flex flex-col items-end space-x-1 mt-1.5">
  113. <div class="flex gap-1">
  114. <button
  115. class=" self-center px-3.5 py-2 rounded-xl text-sm font-medium bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-white"
  116. type="button"
  117. on:click={() => {
  118. shareChat();
  119. show = false;
  120. }}
  121. >
  122. {$i18n.t('Share to OpenWebUI Community')}
  123. </button>
  124. <button
  125. class=" self-center flex items-center gap-1 px-3.5 py-2 rounded-xl text-sm font-medium bg-emerald-600 hover:bg-emerald-500 text-white"
  126. type="button"
  127. on:click={() => {
  128. shareLocalChat();
  129. show = false;
  130. }}
  131. >
  132. <Link />
  133. {#if chat.share_id}
  134. {$i18n.t('Update and Copy Link')}
  135. {:else}
  136. {$i18n.t('Copy Link')}
  137. {/if}
  138. </button>
  139. </div>
  140. <div class="flex gap-1 mt-1.5">
  141. <div class=" self-center text-gray-400 text-xs font-medium">{$i18n.t('or')}</div>
  142. <button
  143. class=" text-right rounded-full text-xs font-medium text-gray-700 dark:text-gray-500 underline"
  144. type="button"
  145. on:click={() => {
  146. downloadChat();
  147. show = false;
  148. }}
  149. >
  150. {$i18n.t('Download as a File')}
  151. </button>
  152. </div>
  153. </div>
  154. </div>
  155. </div>
  156. {/if}
  157. </div>
  158. </Modal>