Skip to content

[cross_file] Updates cross_file to a package separated federated plugin - #11010

Open
bparrishMines wants to merge 453 commits into
flutter:mainfrom
bparrishMines:new_crossfile
Open

[cross_file] Updates cross_file to a package separated federated plugin #11010
bparrishMines wants to merge 453 commits into
flutter:mainfrom
bparrishMines:new_crossfile

Conversation

@bparrishMines

@bparrishMines bparrishMines commented Feb 12, 2026

Copy link
Copy Markdown
Contributor

Updates cross_file to a package separated federated plugin. Keeping the package separation is still debatable.

Follows the general design outlined at https://flutter.dev/go/flutter-file-system

Fixes flutter/flutter#91869

Implementation is split into

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

@bparrishMines bparrishMines added the federated: all_changes PR that contains changes for all packages for a federated plugin change label Feb 12, 2026
@bparrishMines bparrishMines changed the title New crossfile [cross_file] Updates cross_file to a package separated federated plugin Feb 12, 2026
@bparrishMines
bparrishMines marked this pull request as ready for review February 13, 2026 16:19
@bparrishMines

Copy link
Copy Markdown
Contributor Author

@stuartmorgan-g This is ready for initial review. The tests are mostly failing on missing integration tests, missing examples in cross_file_io, and the git deps. I can work on fixing these while the code is being reviewed.

@bparrishMines
bparrishMines requested a review from ditman February 13, 2026 16:21

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a significant and well-executed refactoring of cross_file into a federated plugin structure. The new architecture is clean and aligns with modern Flutter plugin conventions. I've identified a few areas for improvement related to dependency version consistency, native code safety, and asynchronous programming best practices, but overall this is a solid contribution.

Comment on lines +17 to +41
func tryCreateBookmarkedUrl(url: String) throws -> String? {
let nativeUrl = URL(string: url)!
let data = try nativeUrl.bookmarkData(
options: [],
includingResourceValuesForKeys: nil,
relativeTo: nil
)

var isStale: Bool = true
let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale)

if !isStale {
return bookmarkedUrl.absoluteString
}

return nil
}

func startAccessingSecurityScopedResource(url: String) throws -> Bool {
return URL(string: url)!.startAccessingSecurityScopedResource()
}

func stopAccessingSecurityScopedResource(url: String) throws {
URL(string: url)!.stopAccessingSecurityScopedResource()
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The use of force unwrapping (!) when creating a URL from a string is unsafe and can lead to a runtime crash if the url string is malformed. It's better to handle this potential failure gracefully, for example by using guard let and throwing an error.

  func tryCreateBookmarkedUrl(url: String) throws -> String? {
    guard let nativeUrl = URL(string: url) else {
      throw PigeonError(code: "invalid_url", message: "Invalid URL string: \(url)", details: nil)
    }
    let data = try nativeUrl.bookmarkData(
      options: [],
      includingResourceValuesForKeys: nil,
      relativeTo: nil
    )

    var isStale: Bool = true
    let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale)

    if !isStale {
      return bookmarkedUrl.absoluteString
    }

    return nil
  }

  func startAccessingSecurityScopedResource(url: String) throws -> Bool {
    guard let nativeUrl = URL(string: url) else {
      throw PigeonError(code: "invalid_url", message: "Invalid URL string: \(url)", details: nil)
    }
    return nativeUrl.startAccessingSecurityScopedResource()
  }

  func stopAccessingSecurityScopedResource(url: String) throws {
    guard let nativeUrl = URL(string: url) else {
      throw PigeonError(code: "invalid_url", message: "Invalid URL string: \(url)", details: nil)
    }
    nativeUrl.stopAccessingSecurityScopedResource()
  }

Comment thread packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart Outdated
Comment thread packages/cross_file/cross_file_io/lib/src/io_cross_file.dart Outdated
Comment thread packages/cross_file/cross_file_io/lib/src/io_cross_file.dart Outdated
Comment on lines +5 to +13
ext.kotlin_version = "2.2.21"
repositories {
google()
mavenCentral()
}

dependencies {
classpath("com.android.tools.build:gradle:8.13.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are inconsistent versions of Gradle, the Android Gradle Plugin (AGP), and Kotlin across the new packages and examples. For instance, this file uses AGP 8.13.1 and Kotlin 2.2.21, while other parts of the PR use older versions (e.g., AGP 8.9.1, Kotlin 2.1.0). To improve maintainability and prevent potential build issues, it would be beneficial to align these versions to a consistent, recent set across all the new Android projects.

@bparrishMines

Copy link
Copy Markdown
Contributor Author

@stuartmorgan-g This is ready for another review. I added the FileSystem implementation of XFile that the io implementation uses.

/// See [FileSystemXDirectory.fromCreationParams] for setting parameters
/// for a specific platform.
FileSystemXDirectory.fromUri(Uri uri)
: this(uri.toFilePath(windows: defaultTargetPlatform == TargetPlatform.windows));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, but we may need to add a static class-level override at some point that lets people change this for use in tests.


import '../cross_directory.dart';

/// A reference to a directory (or folder) within a devices scoped storage.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: device's

}

/// Instantiates a [ScopedStorageXFile] as a reference to a directory
/// (or folder) on the file system within a devices scoped storage.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: device's

how to access platform-specific feature.
* **Breaking Change** Removes `XFile.mimeType`.
* **Breaking Change** Removes `XFile.path`. This has been replaced by `FileSystemXFile.path`.
* **Breaking Change** Changes `XFile.name` to a method that returns `Future<String>` rather than a

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We usually use a single heading and then a sublist for multiple breaking changes; see https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog-style

import 'android_library.g.dart';
import 'android_scoped_storage_cross_file.dart';

/// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not for iOS and macOS ;)


let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger)

registrar.publish(plugin)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a comment here saying it's so that we get detachFromEngine, since this a really non-obvious aspect of the Flutter plugin APIs.


#if os(iOS)
import Flutter
import UIKit

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we use this?

import UIKit
#elseif os(macOS)
import FlutterMacOS
import Foundation

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already imported outside the platform-specific logic.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gotten confused about the current implementation state; why is there both ffigen code and pigeon code in the iOS implementation package?

#error("Unsupported platform.")
#endif

// Placeholder for adding tests.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, I forgot we don't do this via config-level excludes because of the way native unit and integration tests are combined for running on iOS.

Let's change this to a comment explaining why we don't do native unit testing for this package as an exception to general repo policy, so it's clear why this is a placeholder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cross_file] Platform-aware factories.

4 participants