Release 1.11.0- Native file-system integration - #533
Conversation
|
21c948b to
a230cbd
Compare
| android:authorities="com.internxt.cloud.documents" | ||
| android:exported="true" | ||
| android:grantUriPermissions="true" | ||
| android:permission="android.permission.MANAGE_DOCUMENTS" |
| kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock, | ||
| kSecValueData as String: value, | ||
| ] | ||
| SecItemAdd(query as CFDictionary, nil) |
7666701 to
60e5f3c
Compare
|
Adds a pure-Kotlin HTTP client that talks directly to the Drive and Bridge APIs so the SAF DocumentsProvider can fetch folder contents and download links without the React Native bridge. Covers list/create/rename/move/trash on Drive (Bearer auth) and getDownloadLinks on Bridge (Basic auth with sha256(userId).hex derivation). Typed errors for 401/404/other/network; MockWebServer tests for parsing, auth headers, gateway-required headers, and error mapping.
- Wire AuthConfig.clientName/clientVersion through
BuildConfig.INTERNXT_CLIENT_NAME and BuildConfig.INTERNXT_CLIENT_VERSION,
populated by app/build.gradle from package.json. package.json is now the
single source of truth for the internxt-client/internxt-version headers.
- Extract JSON helpers (orEmpty, map, optStringOrNull, optLongFlexible)
from InternxtApiClient into JsonExtensions.kt; cover each branch in a
new JsonExtensionsTest.
- Rename InternxtApiClient.execute -> executeApiRequest.
- Expand InternxtApiClientTest: listFolderFolders, createFolder, null
optional fields, size given as a string, and 5xx -> ApiError. Add an
enqueueJson helper to cut response-stub boilerplate.
- Add @TamaraFinogina as CODEOWNER for the new documents/crypto/ directory.
…onstants in InternxtApiClientTest
…HttpClient configuration
InternxtDocumentsProvider.queryRoots() now reads credentials from EncryptedSharedPreferences via a new InternxtAuthManager and returns an empty cursor when no user is signed in, so "Internxt Drive" only appears in the system file picker while the app has an active session; credentials are written by a new RN bridge (InternxtAuthCredentialsModule) from signInThunk and refreshTokensThunk and cleared from signOutThunk, with both paths firing contentResolver.notifyChange(rootsUri) so the picker refreshes without restarting the app, while queryRoots() itself stays strictly synchronous and local-only to avoid freezing the system picker.
…t folder UUID synchronization
- Implement queryChildDocuments to paginate folders + files for a parent UUID
- Implement queryDocument to resolve real metadata via folders/{uuid}/meta
and files/{uuid}/meta, with a UUID-named placeholder fallback for
offline / transient failures
- Add InternxtApiClient.getFolder / getFile (404 → null) plus tests
- Introduce DocumentRowBuilder (column-keyed rows) and MimeTypes
(hand-rolled table + Android MimeTypeMap fallback) with tests
- Surface InternxtApiException + null auth-config via Log.w so silent
failures are no longer invisible
- Fix auth slice to sync newToken (not token) to native credentials so
the documents provider authenticates against drive endpoints
Replace the placeholder enumerator with real Drive folder browsing: paginate folders then files for a container, build FileProviderItem metadata (name, type, size, dates, capabilities) from Drive responses, and resolve identifiers via a typed folder/file id codec. Add a DriveAPIFactory that constructs an authenticated DriveAPI from the shared App Group keychain, and wire the new sources into the extension target.
Implement item(for:) so the system can resolve any identifier to a FileProviderItem: return the root container item, decode folder/file identifiers and fetch their metadata from the Drive API, and map 401 responses to NSFileProviderError.notAuthenticated so the system can re-request credentials.
Persist the Drive API base URL in the App Group keychain when credentials are written, so the File Provider extension can build authenticated Drive requests. Add a wrapper test asserting the native module receives driveBaseUrl.
Add FileProviderDomainManager.signalEnumeration to notify the working set enumerator, and call it once the File Provider domain is registered so the Files app refreshes Drive contents right after credentials change. Signal failures are logged and ignored to avoid blocking login.
Adds NetworkFacadeFactory and SharedKeychainCredentials to the File Provider extension so items can be downloaded from the network and decrypted on demand. Persists bridgeBaseUrl to the shared keychain and JSON-decodes bridgeUser/userId so the extension reads matching credentials.
Implement the write path in the NSFileProviderReplicatedExtension so the Files.app can create folders and upload files to Drive. createItem routes folder creation to the Drive API and file uploads through InternxtSwiftCore encryption plus network upload, then registers the file and returns the created NSFileProviderItem. Adds rename support via modifyItem and friendly non-crashing errors for offline/unauthenticated/generic failures.
…FileProviderError Revert the FriendlyError helper and fileProviderError factory; surface plain NSFileProviderError values while keeping the same error codes (noSuchItem, notAuthenticated, serverUnreachable).
Extract upload, download, mutation, and error-mapping logic out of the monolithic FileProviderExtension into dedicated services so the extension becomes a thin coordinator, easing testability and maintenance ahead of move/trash/versioning work.
Introduce a host-less InternxtFileProviderTests target covering the pure NSFileProviderError mapping logic now isolated in FileProviderErrorMapper.
Implement modifyItem move/rename and deleteItem-to-backend-trash in the File Provider extension. Item capabilities use .allowsDeleting (not .allowsTrashing) so the system routes deletes through deleteItem, which maps to the Drive backend trash endpoint instead of a local-only trash.
Add a per-folder snapshot/diff change-feed in the File Provider extension so working-set enumeration surfaces upload, create-folder, move, rename, trash and restore as changes. SyncAnchorStore persists the per-domain anchor; FileProviderModule exposes a native bridge so the host app can signal the enumerator on RN mutations.
Add a cross-platform InternxtSignalingModule with a single notifyParentChanged(parentUuid) bridge (symmetric to Android) and call it from the upload, create-folder, move, rename, trash and restore paths so the native File Provider change-feed refreshes the affected folder.
Android DocumentsProvider: - Fall back to the root (user) bucket when the destination folder's metadata has no bucket — the API only populates bucket on the root folder, so copies into subfolders failed with "Parent folder has no bucket". The resolved bucket is cached per process. - Serve queryDocument from a new in-memory DocumentRowCache populated by folder listings and invalidated on rename/move/delete and child refresh; cache-miss fetches now run off the binder thread. Callers that query from their main thread (e.g. Google PDF viewer) no longer crash with NetworkOnMainThreadException, since the caller's StrictMode policy propagates across binder. Adds DocumentRowCacheTest. iOS: - Embed InternxtFileProvider.appex into the app bundle (the Embed Foundation Extensions phase was empty, so the extension never shipped and the provider could not appear in Files.app). - Align the extension MARKETING_VERSION with the host app (1.10.0); a mismatched version prevents the extension from loading. - CocoaPods integration for the In (Podfile.lock checksum update).
- Document intentionally empty blocks (CallAwait closeQuietly catch, FileProviderEnumerator invalidate) - Mark unused NSFileProviderReplicatedExtension parameters with `_` in FileProviderExtension - Extract duplicated string literals into constants in Android DocumentRowBuilder, DocumentRowCache, MimeTypes and InternxtApiClient tests - Mock BaseLogger in auth.syncNativeCredentials.spec so the suite runs again
… it in setCredentials
e599696 to
01fb3f7
Compare
….plist, Expo.plist, and package.json
…p file extensions - Implement isChildDocument (ancestry walk via cached rows, API fallback) so clients holding a folder grant (Use this folder, Material Files, galleries) no longer fail with "Document X is not a descendant of Y" / "file corrupted". - Build file display names as plainName + type so copies and web-uploaded files show their extension. - Rename keeps the file type immutable (as iOS/web do); renaming to the same base name is a no-op instead of a server 409, and the API call sends plainName only.
…entRowBuilderTest
|




Release 1.11.0 — Native file-system integration (Android SAF + iOS File Provider)
This release makes Internxt Drive available directly in the operating system's file pickers and file managers on both platforms, with end-to-end encryption preserved throughout.
Android — Storage Access Framework (DocumentsProvider)
InternxtDocumentsProviderthat exposes Drive in the system file picker and Files apps, shown/hidden based on session state.InternxtApiClientusing the/infodownload-links endpoint,FileKeyDeriverbacked byCryptoService, dedicated HTTP clients with coroutine-based IO).createDocument, including multipart uploads, a foreground service with progress notifications and cancel support, and picker refresh afteion.InternxtAuthCredentialsModulesyncs credentials (including mnemonic, root folder UUID, and client name/version) fromReact Native to the native layer.
iOS — File Provider extension (Files app)
InternxtFileProviderextension target (replicated File Provider) wired into the Xcode project, with domain registration/removal on login/logout (PB-5920).item(for:).NSFileProviderError. - Live refresh: working-set change-feed signaling (`Shot/diff) so Files.app reflects changes made elsewhere; RNdrive mutations (uploads, folder creation, rename) now signal the File Provider.SharedAuthKeychainextended to JSON-encoded payloads with background-read accessibility, forwardingdriveBaseUrland theme preference to the extension via the App Group.Cross-platform / React Native
InternxtSignalingModuleandInternxtAuthCredentialsModuleJS wrappers; auth slice syncs native credentials on login/logout.CreateFileEntry,openDocumentexception handling, ETag handling in multipart uploads.