Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Chat): Possible to get files from storage to send on chats #657

Merged
merged 30 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9e5c85c
Start create browse files from chat to send them (WIP)
lgmarchi Sep 27, 2024
40bb768
Merge remote-tracking branch 'origin/dev' into 559-wire-up-browse-files
lgmarchi Oct 1, 2024
00905ea
Created other files page to just use it whem browse files from chats
lgmarchi Oct 1, 2024
892ab79
More progress to browse files and send into chats (WIP)
lgmarchi Oct 1, 2024
f0d5d66
Attaching files from constellation on Chatbar (WIP)
lgmarchi Oct 1, 2024
e36a8c4
Adapt code to upload files from storage
lgmarchi Oct 2, 2024
543270b
Possible to send files from storage into chats
lgmarchi Oct 2, 2024
1df3505
Add persistent state on attachments for chats
lgmarchi Oct 2, 2024
1754755
Merge branch 'dev' into 559-wire-up-browse-files
luisecm Oct 2, 2024
eb60c26
Refactor code to handle attachments count in chat messages
lgmarchi Oct 3, 2024
f8ea0fb
Merge remote-tracking branch 'origin/559-wire-up-browse-files' into 5…
lgmarchi Oct 3, 2024
360eba9
Fixed problem about send messages
lgmarchi Oct 3, 2024
b14f384
Update rule about return and don't send message
lgmarchi Oct 3, 2024
8ae61de
Remove unnecessary code
lgmarchi Oct 3, 2024
8b30259
Merge branch 'dev' into 559-wire-up-browse-files
lgmarchi Oct 3, 2024
6c8ac07
Merge branch 'dev' into 559-wire-up-browse-files
lgmarchi Oct 3, 2024
99585fd
chore(FileSharing): Tweak UI slightly
InfamousVague Oct 3, 2024
865fd93
Merge branch '559-wire-up-browse-files' of github.com:Satellite-im/Up…
InfamousVague Oct 3, 2024
63d42d2
fix(BrowseFiles): Fix up send button
InfamousVague Oct 3, 2024
547cffa
Merge remote-tracking branch 'origin/559-wire-up-browse-files' into 5…
lgmarchi Oct 3, 2024
3d14e33
Improve speed to show files on FileUploadPreview
lgmarchi Oct 3, 2024
463d6c6
Merge branch 'dev' into 559-wire-up-browse-files
luisecm Oct 3, 2024
a7047b1
Fix select same file from browse files
lgmarchi Oct 3, 2024
ae0e055
Merge remote-tracking branch 'origin/559-wire-up-browse-files' into 5…
lgmarchi Oct 3, 2024
9917c0d
Merge remote-tracking branch 'origin/dev' into 559-wire-up-browse-files
lgmarchi Oct 3, 2024
3c84383
Merge branch 'dev' into 559-wire-up-browse-files
lgmarchi Oct 4, 2024
a60425d
Merge remote-tracking branch 'origin/559-wire-up-browse-files' into 5…
lgmarchi Oct 4, 2024
bfa95f8
Fix problem when send same file from browse files into chats
lgmarchi Oct 4, 2024
e932ffd
Fix FileUploadPreview for local files
lgmarchi Oct 4, 2024
1241801
Fix deselect file on browse files, when it is opened with file selected
lgmarchi Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/lib/components/files/FileFolder.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
export let name = info.displayName
export let isRenaming: OperationState = OperationState.Initial
export let hook: string = ""
export let avoidOpenImageModal: boolean = false
export let onRename: (name: string, cancel: boolean) => Promise<boolean> = _ => Promise.resolve(true)
let hasFocus = false
let oldName = name
Expand Down Expand Up @@ -133,7 +134,7 @@
</div>
</section>

{#if openImageModal}
{#if openImageModal && !avoidOpenImageModal}
<Modal on:close={onCloseModal}>
<img class="img-preview-on-storage-on-modal" src={info.imageThumbnail} alt={name} />
</Modal>
Expand Down
14 changes: 13 additions & 1 deletion src/lib/components/ui/Modal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
export let withControls: boolean = false
export let hook: string = ""
export let escape: boolean = false
export let large: boolean = false

let clazz = ""
export { clazz as class }
Expand Down Expand Up @@ -40,7 +41,7 @@
<slot></slot>
</div>
{:else}
<div class="body {padded ? 'padded' : ''} {clazz}" on:click|stopPropagation>
<div class="body {padded ? 'padded' : ''} {large ? 'large' : ''} {clazz}" on:click|stopPropagation>
{#if withControls}
<Controls>
<slot name="controls"></slot>
Expand Down Expand Up @@ -105,6 +106,17 @@
align-items: center;
padding: var(--padding-minimal);
}

&.large {
min-width: 0;
width: calc(var(--max-component-width) * 2);
height: var(--max-component-width);

.content {
width: 100%;
height: 100%;
}
}
}
}

Expand Down
102 changes: 73 additions & 29 deletions src/lib/elements/FileUploadPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,46 +1,90 @@
<script lang="ts">
import { Button, Icon, Text } from "$lib/elements"
import { Shape, Size } from "$lib/enums"
import { Store } from "$lib/state/Store"
import type { Chat, FileInfo } from "$lib/types"
import { createEventDispatcher } from "svelte"

import { _ } from "svelte-i18n"
import { derived } from "svelte/store"

export let filesSelected: [File?, string?][] = []
export let activeChat: Chat

let chatAttachmentsToSend = Store.state.chatAttachmentsToSend

let filesSelectedFromStorage = derived(chatAttachmentsToSend, $chatAttachmentsToSend => {
return $chatAttachmentsToSend[activeChat.id]?.storageFiles || []
})

let filesSelected = derived(chatAttachmentsToSend, $chatAttachmentsToSend => {
return $chatAttachmentsToSend[activeChat.id]?.localFiles || []
})
const dispatcher = createEventDispatcher()
function removeFile(file: File | string) {
dispatcher("remove", file)
}
function removeFileFromStorage(file: FileInfo) {
dispatcher("removeFileFromStorage", file)
}
</script>

<div class="files-selected">
{#each filesSelected as [file, path]}
<div class="selected-file">
<div class="file-preview">
{#if file && file.type.startsWith("image")}
<img class="file-preview-image" src={URL.createObjectURL(file)} alt="" />
{:else}
<Icon icon={Shape.Document} />
{/if}
</div>
<div class="details">
<Text size={Size.Smallest}>{file ? file.name : path}</Text>
</div>
<div class="control">
<Button
icon
on:click={_ => {
if (file) {
removeFile(file)
} else if (path) {
removeFile(path)
}
}}>
<Icon icon={Shape.Trash} />
</Button>
{#if $filesSelected.length > 0 || $filesSelectedFromStorage.length > 0}
<div class="files-selected">
{#if $filesSelected.length > 0}
{#each $filesSelected as [file, path]}
<div class="selected-file">
<div class="file-preview">
{#if file && typeof file === "object" && file.type.startsWith("image")}
<img class="file-preview-image" src={URL.createObjectURL(file)} alt="" />
{:else}
<Icon icon={Shape.Document} />
{/if}
</div>
<div class="details">
<Text size={Size.Smallest}>{file && typeof file === "object" ? file.name : path}</Text>
</div>
<div class="control">
<Button
icon
on:click={_ => {
if (file) {
removeFile(file)
} else if (path) {
removeFile(path)
}
}}>
<Icon icon={Shape.Trash} />
</Button>
</div>
</div>
{/each}
{/if}

{#each $filesSelectedFromStorage as remoteFile (remoteFile.remotePath)}
<div class="selected-file">
<div class="file-preview">
{#if remoteFile && remoteFile.imageThumbnail?.startsWith("data:image")}
<img class="file-preview-image" src={remoteFile.imageThumbnail} alt="" />
{:else}
<Icon icon={Shape.Document} />
{/if}
</div>
<div class="details">
<Text size={Size.Smallest}>{remoteFile.displayName ?? remoteFile.name}</Text>
</div>
<div class="control">
<Button
icon
on:click={_ => {
removeFileFromStorage(remoteFile)
}}>
<Icon icon={Shape.Trash} />
</Button>
</div>
</div>
</div>
{/each}
</div>
{/each}
</div>
{/if}

<style lang="scss">
.files-selected {
Expand Down
55 changes: 34 additions & 21 deletions src/lib/layouts/Chatbar.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script lang="ts">
import { Button, Icon, Input, Label } from "$lib/elements"
import { Appearance, MessageAttachmentKind, MessagePosition, Shape, Size } from "$lib/enums"
import { Appearance, MessagePosition, Shape, Size } from "$lib/enums"
import { _ } from "svelte-i18n"
import Controls from "./Controls.svelte"
import { Store } from "$lib/state/Store"
Expand All @@ -9,26 +9,21 @@
import { RaygunStoreInstance, type FileAttachment } from "$lib/wasm/RaygunStore"
import { createEventDispatcher, onMount } from "svelte"
import { ConversationStore } from "$lib/state/conversation"
import type { Chat, GiphyGif, User } from "$lib/types"
import type { Chat, FileInfo, GiphyGif, User } from "$lib/types"
import { Message, PopupButton } from "$lib/components"
import { OperationState, type Message as MessageType } from "$lib/types"
import { FileEmbed, ImageEmbed, ProfilePicture, STLViewer } from "$lib/components"
import { type Message as MessageType } from "$lib/types"
import { ProfilePicture } from "$lib/components"
import CombinedSelector from "$lib/components/messaging/CombinedSelector.svelte"
import { checkMobile } from "$lib/utils/Mobile"
import { UIStore } from "$lib/state/ui"
import { emojiList, emojiRegexMap } from "$lib/components/messaging/emoji/EmojiList"
import { tempCDN } from "$lib/utils/CommonVariables"
import AudioEmbed from "$lib/components/messaging/embeds/AudioEmbed.svelte"
import VideoEmbed from "$lib/components/messaging/embeds/VideoEmbed.svelte"
import TextDocument from "$lib/components/messaging/embeds/TextDocument.svelte"
import { getValidPaymentRequest } from "$lib/utils/Wallet"
import { VoiceRTCMessageType } from "$lib/media/Voice"
import Text from "$lib/elements/Text.svelte"
import StoreResolver from "$lib/components/utils/StoreResolver.svelte"
import { emojiRegex } from "$lib/components/utils/Emoji"

export let replyTo: MessageType | undefined = undefined
export let filesSelected: [File?, string?][] = []
export let emojiClickHook: (emoji: string) => boolean
export let activeChat: Chat
export const typing: User[] = []
Expand All @@ -49,7 +44,6 @@
}

$: if (message) {
let messages = get(Store.state.chatMessagesToSend)
chatMessages.update(messages => {
messages[activeChat.id] = $message
return messages
Expand All @@ -58,19 +52,39 @@
}

async function sendMessage(text: string, isStickerOrGif: boolean = false) {
message.set("")
let filesSelected = get(Store.state.chatAttachmentsToSend)[activeChat.id]?.localFiles
let filesSelectedFromStorage: FileInfo[] = get(Store.state.chatAttachmentsToSend)[activeChat.id]?.storageFiles

if (text.trim() === "" && filesSelected && filesSelected.length > 0 && filesSelectedFromStorage && filesSelectedFromStorage.length > 0) {
return
}

let attachments: FileAttachment[] = []
filesSelected.forEach(([file, path]) => {
if (file) {
attachments.push({
file: file.name,
attachment: [file.stream(), file.size],
})
} else if (path) {

if (filesSelected && filesSelected.length > 0) {
filesSelected.forEach(([file, path]) => {
if (file) {
attachments.push({
file: file.name,
attachment: [file.stream(), file.size],
})
} else if (path) {
attachments.push({
file: path,
})
}
})
}

if (filesSelectedFromStorage && filesSelectedFromStorage.length > 0) {
filesSelectedFromStorage.forEach(file => {
attachments.push({
file: path,
file: file.remotePath,
})
}
})
})
}

let chat = get(Store.state.activeChat)
let txt = text.split("\n")
let result = replyTo ? await RaygunStoreInstance.reply(chat.id, replyTo.id, txt) : await RaygunStoreInstance.send(get(Store.state.activeChat).id, text.split("\n"), attachments)
Expand All @@ -79,7 +93,6 @@
ConversationStore.addPendingMessages(chat.id, res.message, txt)
})
if (!isStickerOrGif) {
message.set("")
chatMessages.update(messages => {
messages[activeChat.id] = ""
return messages
Expand Down
1 change: 1 addition & 0 deletions src/lib/state/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class GlobalStore {
},
}),
chatMessagesToSend: createPersistentState("uplink.chatMessagesToSend", {}),
chatAttachmentsToSend: createPersistentState("uplink.chatAttachmentsToSend", {}),
devices: {
input: createPersistentState("uplink.devices.input", "default"),
video: createPersistentState("uplink.devices.videoInput", "default"),
Expand Down
6 changes: 6 additions & 0 deletions src/lib/state/initial.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export interface IState {
}
activeChat: Writable<Chat>
chatMessagesToSend: Writable<{ [key: string]: string }>
chatAttachmentsToSend: Writable<{
[key: string]: {
localFiles: [File?, string?][]
storageFiles: FileInfo[]
}
}>
activeCall: Writable<Call | null>
pendingCall: Writable<Call | null>
toasts: Writable<{ [key: string]: [ToastMessage, NodeJS.Timeout] }>
Expand Down
Loading