Преглед на файлове

add `read_image` api to `ui.clipboard` (#4144)

make it easy to read copied image from client clipboard.

---------

Co-authored-by: Falko Schindler <falko@zauberzeug.com>
liunux4odoo преди 4 месеца
родител
ревизия
068f6cddc6
променени са 2 файла, в които са добавени 49 реда и са изтрити 4 реда
  1. 37 1
      nicegui/functions/clipboard.py
  2. 12 3
      website/documentation/content/clipboard_documentation.py

+ 37 - 1
nicegui/functions/clipboard.py

@@ -1,7 +1,16 @@
-from .. import json
+import io
+from typing import Union
+
+from .. import json, optional_features
 from ..logging import log
 from .javascript import run_javascript
 
+try:
+    from PIL import Image as PIL_Image
+    optional_features.register('pillow')
+except ImportError:
+    pass
+
 
 async def read() -> str:
     """Read text from the clipboard.
@@ -36,3 +45,30 @@ def write(text: str) -> None:
             console.error('Clipboard API is only available in secure contexts (HTTPS or localhost).')
         }}
     ''')
+
+
+async def read_image() -> Union['PIL_Image.Image', None]:
+    """Read PIL images from the clipboard.
+
+    Note: This function only works in secure contexts (HTTPS or localhost) and requires Pillow to be installed.
+    """
+    if not optional_features.has('pillow'):
+        log.warning('Pillow is not installed, so we cannot read images from the clipboard.')
+        return None
+    content = await run_javascript('''
+        if (navigator.clipboard) {
+            const items = await navigator.clipboard.read();
+            for (const item of items) {
+                if (item.types.length > 0 && /^image/.test(item.types[0])) {
+                    return await item.getType(item.types[0]);
+                }
+            }
+        }
+        else {
+            console.error('Clipboard API is only available in secure contexts (HTTPS or localhost).');
+        }
+    ''', timeout=5)
+    if not content:
+        return None
+    buffer = io.BytesIO(content)
+    return PIL_Image.open(buffer)

+ 12 - 3
website/documentation/content/clipboard_documentation.py

@@ -4,7 +4,7 @@ from . import doc
 
 
 @doc.demo('Read and write to the clipboard', '''
-    The following demo shows how to use `ui.clipboard.read()` and `ui.clipboard.write()` to interact with the clipboard.
+    The following demo shows how to use `ui.clipboard.read()`, `ui.clipboard.write()` and `ui.clipboard.read_image()` to interact with the clipboard.
 
     Because auto-index page can be accessed by multiple browser tabs simultaneously, reading the clipboard is not supported on this page.
     This is only possible within page-builder functions decorated with `ui.page`, as shown in this demo.
@@ -15,11 +15,20 @@ def main_demo() -> None:
     # @ui.page('/')
     # async def index():
     with ui.column():  # HIDE
-        ui.button('Write', on_click=lambda: ui.clipboard.write('Hi!'))
+        ui.button('Write Text', on_click=lambda: ui.clipboard.write('Hi!'))
 
         async def read() -> None:
             ui.notify(await ui.clipboard.read())
-        ui.button('Read', on_click=read)
+        ui.button('Read Text', on_click=read)
+
+        async def read_image() -> None:
+            img = await ui.clipboard.read_image()
+            if not img:
+                ui.notify('You must copy an image to clipboard first.')
+            else:
+                image.set_source(img)
+        ui.button('Read Image', on_click=read_image)
+        image = ui.image().classes('w-72')
 
 
 @doc.demo('Client-side clipboard', '''