| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 7 End-User License
 -    Agreement and JUCE Privacy Policy.
 - 
 -    End User License Agreement: www.juce.com/juce-7-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce::detail
 - {
 - 
 - /*
 -     Instances of this type can show and dismiss a content sharer.
 - 
 -     This is an interface rather than a concrete type so that platforms can pick an implementation at
 -     runtime if necessary.
 - */
 - struct ScopedContentSharerInterface
 - {
 -     virtual ~ScopedContentSharerInterface() = default;
 - 
 -     /*  Shows the content sharer.
 - 
 -         When the content sharer exits normally, it should send the result to the passed-in function.
 -         The passed-in function is safe to call from any thread at any time.
 -     */
 -     virtual void runAsync (ContentSharer::Callback callback)
 -     {
 -         jassertfalse;
 -         NullCheckedInvocation::invoke (callback, false, "Content sharing not available on this platform!");
 -     }
 - 
 -     /*  Forcefully closes the content sharer.
 - 
 -         This will be called when the content sharer handle has fallen out of scope.
 -         If the content sharer has already been closed by the user, this shouldn't do anything.
 -     */
 -     virtual void close() {}
 - 
 -     /*  Implemented differently for each platform. */
 -     static std::unique_ptr<ScopedContentSharerInterface> shareFiles (const Array<URL>&, Component*);
 -     static std::unique_ptr<ScopedContentSharerInterface> shareText (const String&, Component*);
 - 
 -     /*  Implemented below. */
 -     static std::unique_ptr<ScopedContentSharerInterface> shareImages (const Array<Image>&, std::unique_ptr<ImageFileFormat>, Component*);
 -     static std::unique_ptr<ScopedContentSharerInterface> shareData (MemoryBlock, Component*);
 - };
 - 
 - class TemporaryFilesDecorator : public ScopedContentSharerInterface,
 -                                 private AsyncUpdater
 - {
 - public:
 -     explicit TemporaryFilesDecorator (Component* parentIn)
 -         : parent (parentIn) {}
 - 
 -     void runAsync (ContentSharer::Callback cb) override
 -     {
 -         callback = std::move (cb);
 - 
 -         task = std::async (std::launch::async, [this]
 -         {
 -             std::tie (temporaryFiles, error) = prepareTemporaryFiles();
 -             triggerAsyncUpdate();
 -         });
 -     }
 - 
 -     void close() override
 -     {
 -         if (inner != nullptr)
 -             inner->close();
 -     }
 - 
 - private:
 -     virtual std::tuple<Array<URL>, String> prepareTemporaryFiles() const = 0;
 - 
 -     void handleAsyncUpdate() override
 -     {
 -         if (error.isNotEmpty())
 -         {
 -             NullCheckedInvocation::invoke (callback, false, error);
 -             return;
 -         }
 - 
 -         inner = shareFiles (temporaryFiles, parent);
 - 
 -         if (inner == nullptr)
 -         {
 -             NullCheckedInvocation::invoke (callback, false, TRANS ("Failed to create file sharer"));
 -             return;
 -         }
 - 
 -         inner->runAsync (callback);
 -     }
 - 
 -     Array<URL> temporaryFiles;
 -     String error;
 -     std::unique_ptr<ScopedContentSharerInterface> inner;
 -     ContentSharer::Callback callback;
 -     std::future<void> task;
 -     Component* parent = nullptr;
 - };
 - 
 - std::unique_ptr<ScopedContentSharerInterface> ScopedContentSharerInterface::shareImages (const Array<Image>& images,
 -                                                                                          std::unique_ptr<ImageFileFormat> format,
 -                                                                                          Component* parent)
 - {
 -     class Decorator : public TemporaryFilesDecorator
 -     {
 -     public:
 -         Decorator (Array<Image> imagesIn, std::unique_ptr<ImageFileFormat> formatIn, Component* parentIn)
 -             : TemporaryFilesDecorator (parentIn), images (std::move (imagesIn)), format (std::move (formatIn)) {}
 - 
 -     private:
 -         std::tuple<Array<URL>, String> prepareTemporaryFiles() const override
 -         {
 -             const auto extension = format->getFormatName().toLowerCase();
 - 
 -             Array<URL> result;
 - 
 -             for (const auto& image : images)
 -             {
 -                 File tempFile = File::createTempFile (extension);
 - 
 -                 if (! tempFile.create().wasOk())
 -                     return { Array<URL>{}, TRANS ("Failed to create temporary file") };
 - 
 -                 std::unique_ptr<FileOutputStream> outputStream (tempFile.createOutputStream());
 - 
 -                 if (outputStream == nullptr)
 -                     return { Array<URL>{}, TRANS ("Failed to open temporary file for writing") };
 - 
 -                 if (format->writeImageToStream (image, *outputStream))
 -                     result.add (URL (tempFile));
 -             }
 - 
 -             for (const auto& url : result)
 -                 jassertquiet (url.isLocalFile() && url.getLocalFile().existsAsFile());
 - 
 -             return { std::move (result), String{} };
 -         }
 - 
 -         Array<Image> images;
 -         std::unique_ptr<ImageFileFormat> format;
 -     };
 - 
 -     return std::make_unique<Decorator> (images,
 -                                         format == nullptr ? std::make_unique<PNGImageFormat>() : std::move (format),
 -                                         parent);
 - }
 - 
 - std::unique_ptr<ScopedContentSharerInterface> ScopedContentSharerInterface::shareData (MemoryBlock mb, Component* parent)
 - {
 -     class Decorator : public TemporaryFilesDecorator
 -     {
 -     public:
 -         Decorator (MemoryBlock mbIn, Component* parentIn)
 -             : TemporaryFilesDecorator (parentIn), mb (std::move (mbIn)) {}
 - 
 -     private:
 -         std::tuple<Array<URL>, String> prepareTemporaryFiles() const override
 -         {
 -             File tempFile = File::createTempFile ("data");
 - 
 -             if (! tempFile.create().wasOk())
 -                 return { Array<URL>{}, TRANS ("Failed to create temporary file") };
 - 
 -             std::unique_ptr<FileOutputStream> outputStream (tempFile.createOutputStream());
 - 
 -             if (outputStream == nullptr)
 -                 return { Array<URL>{}, TRANS ("Failed to open temporary file for writing") };
 - 
 -             size_t pos = 0;
 -             size_t totalSize = mb.getSize();
 - 
 -             while (pos < totalSize)
 -             {
 -                 size_t numToWrite = std::min ((size_t) 8192, totalSize - pos);
 - 
 -                 if (! outputStream->write (mb.begin() + pos, numToWrite))
 -                     return { Array<URL>{}, TRANS ("Failed to write to temporary file") };
 - 
 -                 pos += numToWrite;
 -             }
 - 
 -             return { Array<URL> { URL (tempFile) }, String{} };
 -         }
 - 
 -         MemoryBlock mb;
 -     };
 - 
 -     return std::make_unique<Decorator> (std::move (mb), parent);
 - }
 - 
 - } // namespace juce::detail
 
 
  |