mirror of
https://github.com/acid-info/Kurate.git
synced 2025-01-12 17:04:07 +00:00
feat: add pictures to posts (#245)
This commit is contained in:
parent
0dba430838
commit
73eaeeba12
@ -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: [
|
||||
|
@ -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">
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
@ -17,4 +17,8 @@ export const MAX_DIMENSIONS = {
|
||||
width: 1440,
|
||||
height: 810,
|
||||
},
|
||||
POST_IMAGE: {
|
||||
width: 500,
|
||||
height: 500,
|
||||
},
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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'
|
||||
}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user