feat: add pictures to posts (#245)

This commit is contained in:
Vojtech Simetka 2023-03-10 23:12:34 +01:00 committed by GitHub
parent 0dba430838
commit 73eaeeba12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 19 deletions

View File

@ -75,6 +75,7 @@ export class ZkitterAdapter implements Adapter {
post: {
text: '[open] What if radiation is hoax?',
timestamp: Date.now() - 9600000,
images: [],
},
messages: [
{
@ -99,6 +100,7 @@ export class ZkitterAdapter implements Adapter {
post: {
text: '[blocked] What does the cat say',
timestamp: Date.now() - 19600000,
images: ['https://via.placeholder.com/100x75'],
},
blocked: true,
messages: [
@ -129,6 +131,11 @@ export class ZkitterAdapter implements Adapter {
post: {
text: "[closed] I'll want to learn Spanish, what is the best way to do so?",
timestamp: Date.now() - 29600000,
images: [
'https://via.placeholder.com/100x75',
'https://via.placeholder.com/105x321',
'https://via.placeholder.com/119x321',
],
},
closed: true,
messages: [

View File

@ -8,6 +8,7 @@
export let label: string | undefined = undefined
export let icon: ComponentConstructor<IconProps> | undefined = undefined
export let variant: 'secondary' | 'primary' | 'overlay' = 'secondary'
export let multiple = false
</script>
<label class={`root ${variant} ${cls}`}>
@ -20,7 +21,7 @@
{label}
{/if}
<!-- svelte-ignore a11y-missing-attribute -->
<input type="file" {disabled} bind:files hidden />
<input type="file" {disabled} bind:files hidden {multiple} />
</label>
<style lang="scss">

View File

@ -9,18 +9,11 @@
<Card on:click>
<div class="content-wrapper">
<div class="imgs">
<!-- I HARD CODED SOME IMAGES TO STYLE THE SECTION AND LEFT THEM TO SHOW THE STRUCTURE IN USE -->
<!-- MORE THAN 3 IMAGES SHOULD HAVE A "PLUS" ICON OVER THE THIRD WITH COUNT OF EXTRA IMAGES -->
<div>
<img src="https://via.placeholder.com/300x500" alt="Placeholder for testing" />
</div>
<div>
<img src="https://via.placeholder.com/400x840" alt="Placeholder for testing" />
</div>
<div>
<img src="https://via.placeholder.com/100x75" alt="Placeholder for testing" />
</div>
{#each post.images as image}
<div>
<img src={image} alt="post" />
</div>
{/each}
</div>
<div class="post-content">{post.text}</div>
<div class="user-info">

View File

@ -5,30 +5,69 @@
import Header from '$lib/components/header.svelte'
import Textarea from '$lib/components/textarea.svelte'
import { profile } from '$lib/stores/profile'
import InputFile from '$lib/components/input-file.svelte'
import { resize } from '$lib/utils/image'
import { MAX_DIMENSIONS } from '$lib/constants'
import Close from './icons/close.svelte'
let cls: string | undefined = undefined
export { cls as class }
export let submit: (postText: string) => unknown
export let submit: (postText: string, images: string[]) => unknown
export let onBack: () => unknown = () => history.back()
export let label: string | undefined = 'Publish'
let postText = ''
let images: string[] = []
let x: number
let files: FileList
const removeImage = (index: number) => () => {
const newImages = [...images]
newImages.splice(index, 1)
images = newImages
}
async function resizeAndAddImages(files: FileList) {
try {
const imgs = []
for (let i = 0; i < files.length; i++) {
imgs.push(
await resize(files[i], MAX_DIMENSIONS.POST_IMAGE.width, MAX_DIMENSIONS.POST_IMAGE.height),
)
}
images = [...images, ...imgs]
} catch (error) {
console.error(error)
}
}
$: files && resizeAndAddImages(files)
</script>
<svelte:window bind:innerWidth={x} />
<div class={`root ${cls}`}>
<Header {onBack}>
<Button icon={Image} />
<InputFile icon={Image} bind:files multiple />
<Button
icon={Checkmark}
variant="primary"
{label}
on:click={() => submit(postText)}
on:click={() => submit(postText, images)}
disabled={!$profile.signer}
/>
</Header>
<div class="imgs">
{#each images as image, index}
<div class="img-wrapper">
<img src={image} alt="post" />
<div class="icon">
<Button icon={Close} variant="overlay" on:click={removeImage(index)} />
</div>
</div>
{/each}
</div>
<div class="post-content">
<Textarea bind:value={postText} placeholder="Write here..." autofocus />
</div>
@ -39,4 +78,35 @@
max-width: 450px;
margin-inline: auto;
}
.imgs {
margin-inline: auto;
max-width: 450px;
display: flex;
flex-direction: row;
gap: var(--spacing-6);
justify-content: flex-start;
align-items: center;
.img-wrapper {
flex-basis: 100%;
position: relative;
img {
max-height: 300px;
}
&:not(:only-child) img {
aspect-ratio: 1;
object-fit: cover;
width: 100%;
height: 100%;
}
.icon {
position: absolute;
right: var(--spacing-12);
top: var(--spacing-12);
}
}
}
</style>

View File

@ -17,4 +17,8 @@ export const MAX_DIMENSIONS = {
width: 1440,
height: 810,
},
POST_IMAGE: {
width: 500,
height: 500,
},
}

View File

@ -5,6 +5,7 @@ import { subscribeToPosts } from '$lib/services/posts'
export interface Post {
timestamp: number
text: string
images: string[]
}
interface PostData {
@ -28,6 +29,7 @@ async function fetchPosts() {
posts.add({
text: post.text,
timestamp: Date.now(),
images: [],
})
},
undefined,

View File

@ -32,7 +32,7 @@
// FIXME: This should be stored in persona and loaded
const TOKEN_POST_MIN_REP = 5
async function submit(postText: string) {
async function submit(postText: string, images: string[]) {
try {
const signer = $profile.signer
if (!signer) throw new Error('no signer')
@ -63,6 +63,7 @@
posts.add({
timestamp: Date.now(),
text: postText,
images,
})
state = 'post_submitted'
} catch (error) {

View File

@ -133,8 +133,8 @@
</PersonaDetail>
{:else if state === 'post_new'}
<PostNew
submit={(postText) => {
persona.posts.push({ timestamp: Date.now(), text: postText })
submit={(text, images) => {
persona.posts.push({ timestamp: Date.now(), text, images })
personas.updateDraft(personaIndex, persona)
state = 'posts'
}}