Skip to content

Commit c69fd9d

Browse files
committed
Adopt GutenbergKit EditorConfigurationBuilder
1 parent d29f688 commit c69fd9d

File tree

7 files changed

+87
-70
lines changed

7 files changed

+87
-70
lines changed

Modules/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ let package = Package(
5353
.package(url: "https://github.com/zendesk/support_sdk_ios", from: "8.0.3"),
5454
// We can't use wordpress-rs branches nor commits here. Only tags work.
5555
.package(url: "https://github.com/Automattic/wordpress-rs", revision: "alpha-20250901"),
56-
.package(url: "https://github.com/wordpress-mobile/GutenbergKit", revision: "d81b8ca022d5db9e33f66bb93133a63d053426ee"),
56+
.package(url: "https://github.com/wordpress-mobile/GutenbergKit", revision: "f3e64e4d7edc60a5c09b84e9421aa80516231414"),
5757
.package(
5858
url: "https://github.com/Automattic/color-studio",
5959
revision: "bf141adc75e2769eb469a3e095bdc93dc30be8de"

WordPress/Classes/Models/Blog/Blog+Editor.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,22 @@ extension Blog {
4747
@objc public var isGutenbergEnabled: Bool {
4848
return editor == .gutenberg
4949
}
50+
51+
func getBlockEditorSettings() -> Data? {
52+
guard let data = rawBlockEditorSettings?.data else {
53+
return nil
54+
}
55+
56+
return data
57+
}
58+
59+
func setRawBlockEditorSettings(_ settings: Data) {
60+
guard let context = managedObjectContext else {
61+
return wpAssertionFailure("missing managed object context")
62+
}
63+
64+
let blob = NSEntityDescription.insertNewObject(forEntityName: "BlobEntity", into: context) as! BlobEntity
65+
blob.data = settings
66+
self.rawBlockEditorSettings = blob
67+
}
5068
}

WordPress/Classes/Services/BlockEditorCache.swift

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,20 @@ final class BlockEditorCache {
2121

2222
// MARK: - Block Settings
2323

24-
func saveBlockSettings(_ settings: [String: Any], for blogID: TaggedManagedObjectID<Blog>) {
24+
func saveBlockSettings(_ settings: Data, for blogID: TaggedManagedObjectID<Blog>) throws {
2525
let fileURL = makeBlockSettingsURL(for: blogID)
26-
27-
do {
28-
let data = try JSONSerialization.data(withJSONObject: settings, options: [.prettyPrinted])
29-
try data.write(to: fileURL)
30-
} catch {
31-
DDLogError("Failed to save block editor settings: \(error)")
32-
}
26+
try settings.write(to: fileURL)
3327
}
3428

35-
func getBlockSettings(for blogID: TaggedManagedObjectID<Blog>) -> [String: Any]? {
29+
func getBlockSettings(for blogID: TaggedManagedObjectID<Blog>) -> Data? {
3630
let fileURL = makeBlockSettingsURL(for: blogID)
3731

3832
guard FileManager.default.fileExists(atPath: fileURL.path) else {
3933
return nil
4034
}
4135

4236
do {
43-
let data = try Data(contentsOf: fileURL)
44-
let object = try JSONSerialization.jsonObject(with: data, options: [])
45-
return object as? [String: Any]
37+
return try Data(contentsOf: fileURL)
4638
} catch {
4739
DDLogError("Failed to load block editor settings: \(error)")
4840
// If the file is corrupted, delete it

WordPress/Classes/Services/RawBlockEditorSettingsService.swift

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import WordPressKit
44
import WordPressShared
55

66
final class RawBlockEditorSettingsService {
7+
78
private let blog: Blog
8-
private var refreshTask: Task<[String: Any], Error>?
9+
private var refreshTask: Task<Data, Error>?
910

1011
init(blog: Blog) {
1112
self.blog = blog
@@ -24,27 +25,6 @@ final class RawBlockEditorSettingsService {
2425
return service
2526
}
2627

27-
@MainActor
28-
private func fetchSettingsFromAPI() async throws -> [String: Any] {
29-
guard let remoteAPI = WordPressOrgRestApi(blog: blog) else {
30-
throw URLError(.unknown) // Should not happen
31-
}
32-
let result = await remoteAPI.get(path: "/wp-block-editor/v1/settings")
33-
switch result {
34-
case .success(let response):
35-
guard let dictionary = response as? [String: Any] else {
36-
throw NSError(domain: "RawBlockEditorSettingsService", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid response format"])
37-
}
38-
let blogID = TaggedManagedObjectID(blog)
39-
Task {
40-
await saveSettingsInBackground(dictionary, for: blogID)
41-
}
42-
return dictionary
43-
case .failure(let error):
44-
throw error
45-
}
46-
}
47-
4828
/// Refreshes the editor settings in the background.
4929
func refreshSettings() {
5030
Task { @MainActor in
@@ -53,7 +33,7 @@ final class RawBlockEditorSettingsService {
5333
}
5434

5535
@MainActor
56-
private func fetchSettings() async throws -> [String: Any] {
36+
private func fetchSettings() async throws -> Data {
5737
if let task = refreshTask {
5838
return try await task.value
5939
}
@@ -70,23 +50,55 @@ final class RawBlockEditorSettingsService {
7050
return try await task.value
7151
}
7252

53+
private func fetchSettingsFromAPI() async throws -> Data {
54+
guard let remoteAPI = WordPressOrgRestApi(blog: blog) else {
55+
throw URLError(.unknown)
56+
}
57+
58+
guard let remoteAPI = WordPressOrgRestApi(blog: blog) else {
59+
throw URLError(.unknown) // Should not happen
60+
}
61+
62+
let data: Data = try await remoteAPI.get(path: "/wp-block-editor/v1/settings").get()
63+
64+
let blogID = TaggedManagedObjectID(blog)
65+
saveSettingsInBackground(data, for: blogID)
66+
67+
return data
68+
}
69+
7370
/// Returns cached settings if available. If not, fetches the settings from
7471
/// the network.
7572
@MainActor
76-
func getSettings() async throws -> [String: Any] {
73+
func getSettings() async throws -> Data {
7774
// Return cached settings if available
7875
let blogID = TaggedManagedObjectID(blog)
7976
if let cachedSettings = await loadSettingsInBackground(for: blogID) {
8077
return cachedSettings
8178
}
8279
return try await fetchSettings()
8380
}
81+
82+
@MainActor
83+
func getSettingsString() async throws -> String {
84+
let data = try await getSettings()
85+
guard let string = String(data: data, encoding: .utf8) else {
86+
throw CocoaError(.fileReadCorruptFile)
87+
}
88+
return string
89+
}
8490
}
8591

86-
private func saveSettingsInBackground(_ settings: [String: Any], for blogID: TaggedManagedObjectID<Blog>) async {
87-
BlockEditorCache.shared.saveBlockSettings(settings, for: blogID)
92+
private func saveSettingsInBackground(_ settings: Data, for blogID: TaggedManagedObjectID<Blog>) {
93+
Task {
94+
do {
95+
try BlockEditorCache.shared.saveBlockSettings(settings, for: blogID)
96+
} catch {
97+
wpAssertionFailure("Unable to save block settings", userInfo: ["error": error])
98+
}
99+
}
88100
}
89101

90-
private func loadSettingsInBackground(for blogID: TaggedManagedObjectID<Blog>) async -> [String: Any]? {
102+
private func loadSettingsInBackground(for blogID: TaggedManagedObjectID<Blog>) async -> Data? {
91103
BlockEditorCache.shared.getBlockSettings(for: blogID)
92104
}

WordPress/Classes/Utility/Editor/EditorConfigurationBuilder+Blog.swift

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,5 @@ extension EditorConfigurationBuilder {
5555
}
5656
}
5757
self = self.setLocale(WordPressComLanguageDatabase().deviceLanguage.slug)
58-
59-
if !blog.isSelfHosted {
60-
let siteType: String = blog.isHostedAtWPcom ? "simple" : "atomic"
61-
do {
62-
self = self.setWebViewGlobals([
63-
try WebViewGlobal(name: "_currentSiteType", value: .string(siteType))
64-
])
65-
} catch {
66-
wpAssertionFailure("Failed to create WebViewGlobal", userInfo: ["error": "\(error)"])
67-
self = self.setWebViewGlobals([])
68-
}
69-
}
7058
}
7159
}

WordPress/Classes/ViewRelated/NewGutenberg/NewGutenbergViewController.swift

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -379,12 +379,12 @@ class NewGutenbergViewController: UIViewController, PostEditor, PublishingEditor
379379
}
380380
}
381381

382-
private func fetchBlockEditorSettings() async -> [String: Any]? {
382+
private func fetchBlockEditorSettings() async -> String? {
383383
let service = RawBlockEditorSettingsService.getService(forBlog: post.blog)
384384
service.refreshSettings()
385385

386386
do {
387-
let settings = try await service.getSettings()
387+
let settings = try await service.getSettingsString()
388388
return settings
389389
} catch {
390390
return nil
@@ -413,15 +413,15 @@ class NewGutenbergViewController: UIViewController, PostEditor, PublishingEditor
413413
}
414414
}
415415

416-
private func startEditor(with settings: [String: Any]? = nil) {
416+
private func startEditor(with settings: String? = nil) {
417417
guard !hasEditorStarted else { return }
418418
hasEditorStarted = true
419419

420420
if let settings {
421421
// TODO: `setEditorSettings` throws due to incompatibility between `[String: Any]`
422422
// and `[String: Encodable]`. The latter is now expected by
423423
// `GutenbergKitConfiguration.EditorSettings`. How should we reconcile this?
424-
let updatedConfig = self.editorViewController.configuration.toBuilder()
424+
let updatedConfig: GutenbergKit.EditorConfiguration = self.editorViewController.configuration.toBuilder()
425425
.setEditorSettings(settings)
426426
.build()
427427
self.editorViewController.updateConfiguration(updatedConfig)
@@ -1033,26 +1033,33 @@ extension EditorConfiguration {
10331033
siteApiNamespace.append("sites/\(siteDomain)/")
10341034
}
10351035

1036-
self = EditorConfiguration()
1036+
var builder = EditorConfigurationBuilder(blog: blog)
1037+
.setSiteApiNamespace(siteApiNamespace)
1038+
.setNamespaceExcludedPaths(["/wpcom/v2/following/recommendations", "/wpcom/v2/following/mine"])
1039+
.setAuthHeader(authHeader)
1040+
.setShouldUseThemeStyles(FeatureFlag.newGutenbergThemeStyles.enabled)
1041+
// Limited to Jetpack-connected sites until editor assets endpoint is available in WordPress core
1042+
.setShouldUsePlugins(EditorConfiguration.shouldEnablePlugins(for: blog, appPassword: applicationPassword))
1043+
.setLocale(WordPressComLanguageDatabase().deviceLanguage.slug)
1044+
1045+
if let blogUrl = blog.url {
1046+
builder = builder.setSiteUrl(blogUrl)
1047+
}
10371048

1038-
self.siteURL = blog.url ?? ""
1039-
self.siteApiRoot = siteApiRoot ?? ""
1040-
self.siteApiNamespace = siteApiNamespace
1041-
self.namespaceExcludedPaths = ["/wpcom/v2/following/recommendations", "/wpcom/v2/following/mine"]
1042-
self.authHeader = authHeader
1049+
if let siteApiRoot {
1050+
builder = builder.setSiteApiRoot(siteApiRoot)
10431051

1044-
self.themeStyles = FeatureFlag.newGutenbergThemeStyles.enabled
1045-
// Limited to Jetpack-connected sites until editor assets endpoint is available in WordPress core
1046-
if EditorConfiguration.shouldEnablePlugins(for: blog, appPassword: applicationPassword) {
1047-
self.plugins = true
1048-
if var editorAssetsEndpoint = URL(string: self.siteApiRoot) {
1052+
if var editorAssetsEndpoint = URL(string: siteApiRoot) {
10491053
editorAssetsEndpoint.appendPathComponent("wpcom/v2/")
10501054
if let namespace = siteApiNamespace.first {
10511055
editorAssetsEndpoint.appendPathComponent(namespace)
10521056
}
1057+
1058+
builder = builder.setEditorAssetsEndpoint(editorAssetsEndpoint)
10531059
}
10541060
}
1055-
self.locale = WordPressComLanguageDatabase().deviceLanguage.slug
1061+
1062+
self = builder.build()
10561063
}
10571064

10581065
/// Returns true if the plugins should be enabled for the given blog.

0 commit comments

Comments
 (0)