From 7bd38f3c74a18a800246afe25ab52a13b4cb9e18 Mon Sep 17 00:00:00 2001
From: Ren Amamiya <123083837+reyamir@users.noreply.github.com>
Date: Fri, 12 May 2023 08:34:08 +0700
Subject: [PATCH] update composer
---
package.json | 1 +
pnpm-lock.yaml | 13 ++++
src/renderer/index.css | 4 ++
src/shared/composer/imageUploader.tsx | 99 +++++++++++++++++++++++++++
src/shared/composer/modal.tsx | 27 ++------
src/shared/composer/types/post.tsx | 89 +++++++++++++++++++++++-
src/stores/composer.tsx | 4 +-
7 files changed, 211 insertions(+), 26 deletions(-)
create mode 100644 src/shared/composer/imageUploader.tsx
diff --git a/package.json b/package.json
index d555c128..7c7a7053 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
"react-virtuoso": "^4.3.5",
"remark-gfm": "^3.0.1",
"slate": "^0.94.1",
+ "slate-history": "^0.93.0",
"slate-react": "^0.94.0",
"swr": "^2.1.5",
"tailwind-merge": "^1.12.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9edd340d..668ef803 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -55,6 +55,9 @@ dependencies:
slate:
specifier: ^0.94.1
version: 0.94.1
+ slate-history:
+ specifier: ^0.93.0
+ version: 0.93.0(slate@0.94.1)
slate-react:
specifier: ^0.94.0
version: 0.94.0(react-dom@18.2.0)(react@18.2.0)(slate@0.94.1)
@@ -4275,6 +4278,16 @@ packages:
engines: { node: '>=8' }
dev: true
+ /slate-history@0.93.0(slate@0.94.1):
+ resolution:
+ { integrity: sha512-Gr1GMGPipRuxIz41jD2/rbvzPj8eyar56TVMyJBvBeIpQSSjNISssvGNDYfJlSWM8eaRqf6DAcxMKzsLCYeX6g== }
+ peerDependencies:
+ slate: '>=0.65.3'
+ dependencies:
+ is-plain-object: 5.0.0
+ slate: 0.94.1
+ dev: false
+
/slate-react@0.94.0(react-dom@18.2.0)(react@18.2.0)(slate@0.94.1):
resolution:
{ integrity: sha512-8LW3HdC3Rya+3E1Gm5voyXdEfQrJGvm0QYl0bgtW2C06Dh82imxhGIPqRv2sj8j2Zf869oJGNp2bGUoCuNBJ6g== }
diff --git a/src/renderer/index.css b/src/renderer/index.css
index 3b4e7114..52f83d3f 100644
--- a/src/renderer/index.css
+++ b/src/renderer/index.css
@@ -24,6 +24,10 @@
background-clip: padding-box;
}
+span[data-slate-placeholder] {
+ @apply top-0;
+}
+
@keyframes loop {
0% {
transform: translateX(0);
diff --git a/src/shared/composer/imageUploader.tsx b/src/shared/composer/imageUploader.tsx
new file mode 100644
index 00000000..adf0cb93
--- /dev/null
+++ b/src/shared/composer/imageUploader.tsx
@@ -0,0 +1,99 @@
+import PlusCircleIcon from '@shared/icons/plusCircle';
+
+import { createBlobFromFile } from '@utils/createBlobFromFile';
+
+import { open } from '@tauri-apps/api/dialog';
+import { Body, fetch } from '@tauri-apps/api/http';
+import { useState } from 'react';
+import { Transforms } from 'slate';
+import { useSlateStatic } from 'slate-react';
+
+export function ImageUploader() {
+ const editor = useSlateStatic();
+ const [loading, setLoading] = useState(false);
+
+ const insertImage = (editor, url) => {
+ const text = { text: url };
+ const image = { type: 'image', url, children: [text] };
+ Transforms.insertNodes(editor, image);
+ };
+
+ const openFileDialog = async () => {
+ const selected: any = await open({
+ multiple: false,
+ filters: [
+ {
+ name: 'Image',
+ extensions: ['png', 'jpeg', 'jpg', 'gif'],
+ },
+ ],
+ });
+ if (Array.isArray(selected)) {
+ // user selected multiple files
+ } else if (selected === null) {
+ // user cancelled the selection
+ } else {
+ setLoading(true);
+
+ const filename = selected.split('/').pop();
+ const file = await createBlobFromFile(selected);
+ const buf = await file.arrayBuffer();
+
+ try {
+ const res: { data: { file: { id: string } } } = await fetch('https://void.cat/upload?cli=false', {
+ method: 'POST',
+ timeout: 5,
+ headers: {
+ accept: '*/*',
+ 'Content-Type': 'application/octet-stream',
+ 'V-Filename': filename,
+ 'V-Description': 'Uploaded from https://lume.nu',
+ 'V-Strip-Metadata': 'true',
+ },
+ body: Body.bytes(buf),
+ });
+ const image = 'https://void.cat/d/' + res.data.file.id + '.webp';
+ // update parent state
+ insertImage(editor, image);
+ // reset loading state
+ setLoading(false);
+ } catch (error) {
+ // reset loading state
+ setLoading(false);
+ // handle error
+ if (error instanceof SyntaxError) {
+ // Unexpected token < in JSON
+ console.log('There was a SyntaxError', error);
+ } else {
+ console.log('There was an error', error);
+ }
+ }
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/src/shared/composer/modal.tsx b/src/shared/composer/modal.tsx
index 2d2ed562..f715ecaa 100644
--- a/src/shared/composer/modal.tsx
+++ b/src/shared/composer/modal.tsx
@@ -14,8 +14,6 @@ import { Dialog, Transition } from '@headlessui/react';
import { useAtom } from 'jotai';
import { Fragment, useState } from 'react';
-import PlusCircleIcon from '../icons/plusCircle';
-
export function ComposerModal() {
const [isOpen, setIsOpen] = useState(false);
const [composer] = useAtom(composerAtom);
@@ -78,29 +76,14 @@ export function ComposerModal() {