Skip to content

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

Merged
auto-submit[bot] merged 488 commits into
flutter:mainfrom
bparrishMines:new_crossfile
Sep 24, 2026
Merged

auto-submit[bot] merged 488 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.

@ditman

ditman commented Feb 19, 2026

Copy link
Copy Markdown
Member

Thanks for getting this done!

@stuartmorgan-g stuartmorgan-g left a comment

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.

Sorry for the mix of comment levels; some are high-level questions, and others are minor things that I wanted to flag before I forgot, that will apply regardless of whether bigger picture pieces change.

Comment thread packages/cross_file/cross_file/example/android/app/build.gradle Outdated
Comment thread packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj Outdated
Comment thread packages/cross_file/cross_file/example/ios/Flutter/Debug.xcconfig
Comment thread packages/cross_file/cross_file/example/README.md Outdated
Comment thread packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake Outdated
Comment thread packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake Outdated
/// macOS.
@immutable
base class DarwinScopedStorageXFileCreationParams
extends PlatformScopedStorageXFileCreationParams {

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.

Don't the file and directory classes need to inherit from the IO versions as well?

@bparrishMines bparrishMines Jun 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No these are there own implementation. The IO implementations are designed to not be permissions based and can be accessed freely. A URI passed to a ScopedStorage file implementation are considered to be temporarily accessible.

Comment thread packages/cross_file/cross_file_platform_interface/AUTHORS Outdated
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
version: 0.0.1
publish_to: none

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.

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is temporary because it was causing an failure in the CI

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.

Hm, new packages shouldn't fail CI. What was the error?

@bparrishMines

Copy link
Copy Markdown
Contributor Author

@stuartmorgan-g For 1 final review.

@stuartmorgan-g stuartmorgan-g left a comment

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.

LGTM!

🚢

@Gustl22

Gustl22 commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Cool, thank you for the work! 🎉

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

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD federated: all_changes PR that contains changes for all packages for a federated plugin change p: cross_file platform-android platform-ios platform-linux platform-macos platform-web platform-windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cross_file] Platform-aware factories.

5 participants