| 
							- /*
 -   ==============================================================================
 - 
 -    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.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    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
 - {
 - 
 - //==============================================================================
 - /**
 -     Some information about a document.
 - 
 -     Each instance represents some information about the document at the point when the instance
 -     was created.
 - 
 -     Instance information is not updated automatically. If you think some file information may
 -     have changed, create a new instance.
 - 
 -     @tags{Core}
 - */
 - class AndroidDocumentInfo
 - {
 - public:
 -     AndroidDocumentInfo() = default;
 - 
 -     /** True if this file really exists. */
 -     bool exists() const                 { return isJuceFlagSet (flagExists); }
 - 
 -     /** True if this is a directory rather than a file. */
 -     bool isDirectory() const;
 - 
 -     /** True if this is a file rather than a directory. */
 -     bool isFile() const                 { return type.isNotEmpty() && ! isDirectory(); }
 - 
 -     /** True if this process has permission to read this file.
 - 
 -         If this returns true, and the AndroidDocument refers to a file rather than a directory,
 -         then AndroidDocument::createInputStream should work on this document.
 -     */
 -     bool canRead() const                { return isJuceFlagSet (flagHasReadPermission) && type.isNotEmpty(); }
 - 
 -     /** True if this is a document that can be written, or a directory that can be modified.
 - 
 -         If this returns true, and the AndroidDocument refers to a file rather than a directory,
 -         then AndroidDocument::createOutputStream should work on this document.
 -     */
 -     bool canWrite() const
 -     {
 -         return isJuceFlagSet (flagHasWritePermission)
 -                && type.isNotEmpty()
 -                && (isNativeFlagSet (flagSupportsWrite)
 -                    || isNativeFlagSet (flagSupportsDelete)
 -                    || isNativeFlagSet (flagDirSupportsCreate));
 -     }
 - 
 -     /** True if this document can be removed completely from the filesystem. */
 -     bool canDelete() const              { return isNativeFlagSet (flagSupportsDelete); }
 - 
 -     /** True if this is a directory and adding child documents is supported. */
 -     bool canCreateChildren() const      { return isNativeFlagSet (flagDirSupportsCreate); }
 - 
 -     /** True if this document can be renamed. */
 -     bool canRename() const              { return isNativeFlagSet (flagSupportsRename); }
 - 
 -     /** True if this document can be copied. */
 -     bool canCopy() const                { return isNativeFlagSet (flagSupportsCopy); }
 - 
 -     /** True if this document can be moved. */
 -     bool canMove() const                { return isNativeFlagSet (flagSupportsMove); }
 - 
 -     /** True if this document isn't a physical file on storage. */
 -     bool isVirtual() const              { return isNativeFlagSet (flagVirtualDocument); }
 - 
 -     /** The user-facing name.
 - 
 -         This may or may not contain a file extension. For files identified by a URL, the MIME type
 -         is stored separately.
 -     */
 -     String getName() const              { return name; }
 - 
 -     /** The MIME type of this document. */
 -     String getType() const              { return isDirectory() ? String{} : type; }
 - 
 -     /** Timestamp when a document was last modified, in milliseconds since January 1, 1970 00:00:00.0 UTC.
 - 
 -         Use isLastModifiedValid() to determine whether or not the result of this
 -         function is valid.
 -     */
 -     int64 getLastModified() const       { return isJuceFlagSet (flagValidModified) ? lastModified : 0; }
 - 
 -     /** True if the filesystem provided a modification time. */
 -     bool isLastModifiedValid() const    { return isJuceFlagSet (flagValidModified); }
 - 
 -     /** The size of the document in bytes, if known.
 - 
 -         Use isSizeInBytesValid() to determine whether or not the result of this
 -         function is valid.
 -     */
 -     int64 getSizeInBytes() const        { return isJuceFlagSet (flagValidSize) ? sizeInBytes : 0; }
 - 
 -     /** True if the filesystem provided a size in bytes. */
 -     bool isSizeInBytesValid() const     { return isJuceFlagSet (flagValidSize); }
 - 
 -     /** @internal */
 -     class Args;
 - 
 - private:
 -     explicit AndroidDocumentInfo (Args);
 - 
 -     bool isNativeFlagSet (int flag) const { return (nativeFlags & flag) != 0; }
 -     bool isJuceFlagSet   (int flag) const { return (juceFlags   & flag) != 0; }
 - 
 -     /*  Native Android flags that might be set in the COLUMN_FLAGS for a particular document */
 -     enum
 -     {
 -         flagSupportsWrite       = 0x0002,
 -         flagSupportsDelete      = 0x0004,
 -         flagDirSupportsCreate   = 0x0008,
 -         flagSupportsRename      = 0x0040,
 -         flagSupportsCopy        = 0x0080,
 -         flagSupportsMove        = 0x0100,
 -         flagVirtualDocument     = 0x0200,
 -     };
 - 
 -     /*  Flags for other binary properties that aren't exposed in COLUMN_FLAGS */
 -     enum
 -     {
 -         flagExists              = 1 << 0,
 -         flagValidModified       = 1 << 1,
 -         flagValidSize           = 1 << 2,
 -         flagHasReadPermission   = 1 << 3,
 -         flagHasWritePermission  = 1 << 4,
 -     };
 - 
 -     String name;
 -     String type;
 -     int64 lastModified = 0;
 -     int64 sizeInBytes  = 0;
 -     int nativeFlags = 0, juceFlags = 0;
 - };
 - 
 - //==============================================================================
 - /**
 -     Represents a permission granted to an application to read and/or write to a particular document
 -     or tree.
 - 
 -     This class also contains static methods to request, revoke, and query the permissions of your
 -     app. These functions are no-ops on all platforms other than Android.
 - 
 -     @tags{Core}
 - */
 - class AndroidDocumentPermission
 - {
 - public:
 -     /** The url of the document with persisted permissions. */
 -     URL getUrl() const                          { return url; }
 - 
 -     /** The time when the permissions were persisted, in milliseconds since January 1, 1970 00:00:00.0 UTC. */
 -     int64 getPersistedTime() const              { return time; }
 - 
 -     /** True if the permission allows read access. */
 -     bool isReadPermission() const               { return read; }
 - 
 -     /** True if the permission allows write access. */
 -     bool isWritePermission() const              { return write; }
 - 
 -     /** Gives your app access to a particular document or tree, even after the device is rebooted.
 - 
 -         If you want to persist access to a folder selected through a native file chooser, make sure
 -         to pass the exact URL returned by the file picker. Do NOT call AndroidDocument::fromTree
 -         and then pass the result of getUrl to this function, as the resulting URL may differ from
 -         the result of the file picker.
 -     */
 -     static void takePersistentReadWriteAccess (const URL&);
 - 
 -     /** Revokes persistent access to a document or tree. */
 -     static void releasePersistentReadWriteAccess (const URL&);
 - 
 -     /** Returns all of the permissions that have previously been granted to the app, via
 -         takePersistentReadWriteAccess();
 -     */
 -     static std::vector<AndroidDocumentPermission> getPersistedPermissions();
 - 
 - private:
 -     URL url;
 -     int64 time = 0;
 -     bool read = false, write = false;
 - };
 - 
 - //==============================================================================
 - /**
 -     Provides access to a document on Android devices.
 - 
 -     In this context, a 'document' may be a file or a directory.
 - 
 -     The main purpose of this class is to provide access to files in shared storage on Android.
 -     On newer Android versions, such files cannot be accessed directly by a file path, and must
 -     instead be read and modified using a new URI-based DocumentsContract API.
 - 
 -     Example use-cases:
 - 
 -     - After showing the system open dialog to allow the user to open a file, pass the FileChooser's
 -       URL result to AndroidDocument::fromDocument. Then, you can use getInfo() to retrieve
 -       information about the file, and createInputStream to read from the file. Other functions allow
 -       moving, copying, and deleting the file.
 - 
 -     - Similarly to the 'open' use-case, you may use createOutputStream to write to a file, normally
 -       located using the system save dialog.
 - 
 -     - To allow reading or writing to a tree of files in shared storage, you can show the system
 -       open dialog in 'selects directories' mode, and pass the resulting URL to
 -       AndroidDocument::fromTree. Then, you can iterate the files in the directory, query them,
 -       and create new files. This is a good way to store multiple files that the user can access from
 -       other apps, and that will be persistent after uninstalling and reinstalling your app.
 - 
 -     Note that you probably do *not* need this class if your app only needs to access files in its
 -     own internal sandbox. juce::File instances should work as expected in that case.
 - 
 -     AndroidDocument is a bit like the DocumentFile class from the androidx extension library,
 -     in that it represents a single document, and is implemented using DocumentsContract functions.
 - 
 -     @tags{Core}
 - */
 - class AndroidDocument
 - {
 - public:
 -     /** Create a null document. */
 -     AndroidDocument();
 - 
 -     /** Create an AndroidDocument representing a file or directory at a particular path.
 - 
 -         This is provided for use on older API versions (lower than 19), or on other platforms, so
 -         that the same AndroidDocument API can be used regardless of the runtime platform version.
 - 
 -         If the runtime platform version is 19 or higher, and you wish to work with a URI obtained
 -         from a native file picker, use fromDocument() or fromTree() instead.
 - 
 -         If this function fails, hasValue() will return false on the returned document.
 -     */
 -     static AndroidDocument fromFile (const File& filePath);
 - 
 -     /** Create an AndroidDocument representing a single document.
 - 
 -         The argument should be a URL representing a document. Such URLs are returned by the system
 -         file-picker when it is not in folder-selection mode. If you pass a tree URL, this function
 -         will fail.
 - 
 -         This function may fail on Android devices with API level 18 or lower, and on non-Android
 -         platforms. If this function fails, hasValue() will return false on the returned document.
 -         If calling this function fails, you may want to retry creating an AndroidDocument
 -         with fromFile(), passing the result of URL::getLocalFile().
 -     */
 -     static AndroidDocument fromDocument (const URL& documentUrl);
 - 
 -     /** Create an AndroidDocument representing the root of a tree of files.
 - 
 -         The argument should be a URL representing a tree. Such URLs are returned by the system
 -         file-picker when it is in folder-selection mode. If you pass a URL referring to a document
 -         inside a tree, this will return a document referring to the root of the tree. If you pass
 -         a URL referring to a single file, this will fail.
 - 
 -         When targeting platform version 30 or later, access to the filesystem via file paths is
 -         heavily restricted, and access to shared storage must use a new URI-based system instead.
 -         At time of writing, apps uploaded to the Play Store must target API 30 or higher.
 -         If you want read/write access to a shared folder, you must:
 - 
 -         - Use a native FileChooser in canSelectDirectories mode, to allow the user to select a
 -           folder that your app can access. Your app will only have access to the contents of this
 -           directory; it cannot escape to the filesystem root. The system will not allow the user
 -           to grant access to certain locations, including filesystem roots and the Download folder.
 -         - Pass the URI that the user selected to fromTree(), and use the resulting AndroidDocument
 -           to read/write to the file system.
 - 
 -         This function may fail on Android devices with API level 20 or lower, and on non-Android
 -         platforms. If this function fails, hasValue() will return false on the returned document.
 -     */
 -     static AndroidDocument fromTree (const URL& treeUrl);
 - 
 -     AndroidDocument (const AndroidDocument&);
 -     AndroidDocument (AndroidDocument&&) noexcept;
 - 
 -     AndroidDocument& operator= (const AndroidDocument&);
 -     AndroidDocument& operator= (AndroidDocument&&) noexcept;
 - 
 -     ~AndroidDocument();
 - 
 -     /** True if the URLs of the two documents match. */
 -     bool operator== (const AndroidDocument&) const;
 - 
 -     /** False if the URLs of the two documents match. */
 -     bool operator!= (const AndroidDocument&) const;
 - 
 -     /** Attempts to delete this document, and returns true on success. */
 -     bool deleteDocument() const;
 - 
 -     /** Renames the document, and returns true on success.
 - 
 -         This may cause the document's URI and metadata to change, so ensure to invalidate any
 -         cached information about the document (URLs, AndroidDocumentInfo instances) after calling
 -         this function.
 -     */
 -     bool renameTo (const String& newDisplayName);
 - 
 -     /** Attempts to create a new nested document with a particular type and name.
 - 
 -         The type should be a standard MIME type string, e.g. "image/png", "text/plain".
 - 
 -         The file name doesn't need to contain an extension, as this information is passed via the
 -         type argument. If this document is File-based rather than URL-based, then an appropriate
 -         file extension will be chosen based on the MIME type.
 - 
 -         On failure, the returned AndroidDocument may be invalid, and will return false from hasValue().
 -     */
 -     AndroidDocument createChildDocumentWithTypeAndName (const String& type, const String& name) const;
 - 
 -     /** Attempts to create a new nested directory with a particular name.
 - 
 -         On failure, the returned AndroidDocument may be invalid, and will return false from hasValue().
 -     */
 -     AndroidDocument createChildDirectory (const String& name) const;
 - 
 -     /** True if this object actually refers to a document.
 - 
 -         If this function returns false, you *must not* call any function on this instance other
 -         than the special member functions to copy, move, and/or destruct the instance.
 -     */
 -     bool hasValue() const               { return pimpl != nullptr; }
 - 
 -     /** Like hasValue(), but allows declaring AndroidDocument instances directly in 'if' statements. */
 -     explicit operator bool() const      { return hasValue(); }
 - 
 -     /** Creates a stream for reading from this document. */
 -     std::unique_ptr<InputStream>  createInputStream()  const;
 - 
 -     /** Creates a stream for writing to this document. */
 -     std::unique_ptr<OutputStream> createOutputStream() const;
 - 
 -     /** Returns the content URL describing this document. */
 -     URL getUrl() const;
 - 
 -     /** Fetches information about this document. */
 -     AndroidDocumentInfo getInfo() const;
 - 
 -     /** Experimental: Attempts to copy this document to a new parent, and returns an AndroidDocument
 -         representing the copy.
 - 
 -         On failure, the returned AndroidDocument may be invalid, and will return false from hasValue().
 - 
 -         This function may fail if the document doesn't allow copying, and when using URI-based
 -         documents on devices with API level 23 or lower. On failure, the returned AndroidDocument
 -         will return false from hasValue(). In testing, copying was not supported on the Android
 -         emulator for API 24, 30, or 31, so there's a good chance this function won't work on real
 -         devices.
 - 
 -         @see AndroidDocumentInfo::canCopy
 -     */
 -     AndroidDocument copyDocumentToParentDocument (const AndroidDocument& target) const;
 - 
 -     /** Experimental: Attempts to move this document from one parent to another, and returns true on
 -         success.
 - 
 -         This may cause the document's URI and metadata to change, so ensure to invalidate any
 -         cached information about the document (URLs, AndroidDocumentInfo instances) after calling
 -         this function.
 - 
 -         This function may fail if the document doesn't allow moving, and when using URI-based
 -         documents on devices with API level 23 or lower.
 -     */
 -     bool moveDocumentFromParentToParent (const AndroidDocument& currentParent,
 -                                          const AndroidDocument& newParent);
 - 
 -     /** @internal */
 -     struct NativeInfo;
 - 
 -     /** @internal */
 -     NativeInfo getNativeInfo() const;
 - 
 - private:
 -     struct Utils;
 -     class Pimpl;
 - 
 -     explicit AndroidDocument (std::unique_ptr<Pimpl>);
 - 
 -     void swap (AndroidDocument& other) noexcept { std::swap (other.pimpl, pimpl); }
 - 
 -     std::unique_ptr<Pimpl> pimpl;
 - };
 - 
 - //==============================================================================
 - /**
 -     An iterator that visits child documents in a directory.
 - 
 -     Instances of this iterator can be created by calling makeRecursive() or
 -     makeNonRecursive(). The results of these functions can additionally be used
 -     in standard algorithms, and in range-for loops:
 - 
 -     @code
 -     AndroidDocument findFileWithName (const AndroidDocument& parent, const String& name)
 -     {
 -         for (const auto& child : AndroidDocumentIterator::makeNonRecursive (parent))
 -             if (child.getInfo().getName() == name)
 -                   return child;
 - 
 -           return AndroidDocument();
 -     }
 - 
 -     std::vector<AndroidDocument> findAllChildrenRecursive (const AndroidDocument& parent)
 -     {
 -         std::vector<AndroidDocument> children;
 -         std::copy (AndroidDocumentIterator::makeRecursive (doc),
 -                    AndroidDocumentIterator(),
 -                    std::back_inserter (children));
 -         return children;
 -     }
 -     @endcode
 - 
 -     @tags{Core}
 - */
 - class AndroidDocumentIterator final
 - {
 - public:
 -     using difference_type = std::ptrdiff_t;
 -     using pointer = void;
 -     using iterator_category = std::input_iterator_tag;
 - 
 -     /** Create an iterator that will visit each item in this directory. */
 -     static AndroidDocumentIterator makeNonRecursive (const AndroidDocument&);
 - 
 -     /** Create an iterator that will visit each item in this directory, and all nested directories. */
 -     static AndroidDocumentIterator makeRecursive (const AndroidDocument&);
 - 
 -     /** Creates an end/sentinel iterator. */
 -     AndroidDocumentIterator() = default;
 - 
 -     bool operator== (const AndroidDocumentIterator& other) const noexcept { return pimpl == nullptr && other.pimpl == nullptr; }
 -     bool operator!= (const AndroidDocumentIterator& other) const noexcept { return ! operator== (other); }
 - 
 -     /** Returns the document to which this iterator points. */
 -     AndroidDocument operator*() const;
 - 
 -     /** Moves this iterator to the next position. */
 -     AndroidDocumentIterator& operator++();
 - 
 -     /** Allows this iterator to be used directly in a range-for. */
 -     AndroidDocumentIterator begin() const { return *this; }
 - 
 -     /** Allows this iterator to be used directly in a range-for. */
 -     AndroidDocumentIterator end()   const { return AndroidDocumentIterator{}; }
 - 
 - private:
 -     struct Utils;
 -     struct Pimpl;
 - 
 -     explicit AndroidDocumentIterator (std::unique_ptr<Pimpl>);
 - 
 -     std::shared_ptr<Pimpl> pimpl;
 - };
 - 
 - } // namespace juce
 
 
  |