Skip to content

Commit 6ce64d6

Browse files
committed
Use production API and read graph data locally
Default native clients to api.logseq.io while preserving explicit local overrides. Remove obsolete remote feed, references and task status reads. Verify local refresh preserves offline data and correct the shortcuts bundle check.
1 parent 61e6f07 commit 6ce64d6

19 files changed

Lines changed: 70 additions & 562 deletions

File tree

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Logseq uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed
2727

2828
Cloud Agent VMs are Linux. They cannot run Xcode, the iOS simulator, or `swift test`. Do not try to start those from this environment.
2929

30-
The Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app’s default API (`http://127.0.0.1:8787`) lives in a separate Logseq product.
30+
The Linux-runnable surface is the OCaml core in `shared/native/` (inbox capture, DataScript model, RPC, SQLite persistence). There is no in-repo HTTP server; the app's default API is `https://api.logseq.io`. Local sync testing can explicitly override it with `http://127.0.0.1:8787` from the separate Logseq server repository.
3131

3232
### OCaml core
3333

‎android/app/src/main/kotlin/com/logseq/app/AndroidPlatformServices.kt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import org.json.JSONArray
2020
import org.json.JSONObject
2121
import java.io.File
2222

23-
internal const val DEFAULT_BASE_URL = "http://127.0.0.1:8787"
23+
internal const val DEFAULT_BASE_URL = "https://api.logseq.io"
2424

2525
internal fun normalizedBaseUrl(value: String?): String =
2626
value?.trim().orEmpty().ifBlank { DEFAULT_BASE_URL }

‎android/app/src/main/kotlin/com/logseq/app/runtime/AndroidPlatformEffects.kt‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.logseq.app.runtime
22

33
import com.logseq.app.AndroidPlatformServices
44
import com.logseq.app.CognitoAuthProvider
5+
import com.logseq.app.DEFAULT_BASE_URL
56
import org.json.JSONArray
67
import org.json.JSONObject
78

@@ -57,7 +58,7 @@ internal data class AndroidStorageState(
5758
return AndroidStorageState(
5859
databasePath = value["databasePath"] as? String ?: "",
5960
graphsDirectory = value["graphsDirectory"] as? String ?: "",
60-
baseUrl = value["baseUrl"] as? String ?: "http://127.0.0.1:8787",
61+
baseUrl = value["baseUrl"] as? String ?: DEFAULT_BASE_URL,
6162
selectedGraphId = value["selectedGraphId"] as? String ?: "",
6263
localGraphIds = localGraphIds,
6364
settings = AndroidHostSettings.fromPlatformValue(settings),
@@ -98,7 +99,7 @@ internal data class AndroidHostSettings(
9899
spellCheck = true,
99100
autoCorrection = true,
100101
sidebarTabs = emptyList(),
101-
baseUrl = "http://127.0.0.1:8787",
102+
baseUrl = DEFAULT_BASE_URL,
102103
version = "Development",
103104
revision = "Development",
104105
)

‎apple/Sources/Logseq/LGGraphLifecycle.swift‎

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ final class LGGraphLifecycle {
106106

107107
func connectStoredGraph() async -> Bool {
108108
let defaults = UserDefaults.standard
109-
let baseURL = defaults.string(forKey: "logseq.baseURL")
110-
?? "http://127.0.0.1:8787"
109+
let baseURL = LogseqSettingsPolicy.storedBaseURL(in: defaults)
111110
let storedGraphID = defaults.string(forKey: "logseq.selectedGraphId") ?? ""
112111
let graphID = storedGraphID.isEmpty ? nil : storedGraphID
113112
guard let accessToken = try? await authentication.accessToken() else {
@@ -144,8 +143,7 @@ final class LGGraphLifecycle {
144143
return resolution(succeeded: false)
145144
}
146145

147-
let baseURL = UserDefaults.standard.string(forKey: "logseq.baseURL")
148-
?? "http://127.0.0.1:8787"
146+
let baseURL = LogseqSettingsPolicy.storedBaseURL()
149147
let accessToken = (try? await authentication.accessToken()) ?? ""
150148
let isEncrypted = store.snapshot.graphs?
151149
.first(where: { $0.id == graphID })?.isEncrypted ?? false
@@ -188,8 +186,7 @@ final class LGGraphLifecycle {
188186
output: .discard
189187
)
190188
}
191-
let baseURL = UserDefaults.standard.string(forKey: "logseq.baseURL")
192-
?? "http://127.0.0.1:8787"
189+
let baseURL = LogseqSettingsPolicy.storedBaseURL()
193190
let accessToken = (try? await authentication.accessToken()) ?? ""
194191
if !accessToken.isEmpty {
195192
// The encrypted graph opens without a sync checkpoint while locked,
@@ -227,8 +224,7 @@ final class LGGraphLifecycle {
227224
defaults.set("", forKey: "logseq.selectedGraphId")
228225
let accessToken = (try? await authentication.accessToken()) ?? ""
229226
await store.configureAndSelectGraph(
230-
baseURL: defaults.string(forKey: "logseq.baseURL")
231-
?? "http://127.0.0.1:8787",
227+
baseURL: LogseqSettingsPolicy.storedBaseURL(in: defaults),
232228
token: accessToken,
233229
selectedGraphID: nil
234230
)

‎apple/Sources/Logseq/LogseqApp.swift‎

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,7 @@ public struct LogseqRootView : View {
232232
defaults.set("", forKey: "logseq.selectedGraphId")
233233
defaults.removeObject(forKey: "logseq.uiSession")
234234
store.configure(
235-
baseURL: defaults.string(forKey: "logseq.baseURL")
236-
?? "http://127.0.0.1:8787",
235+
baseURL: LogseqSettingsPolicy.storedBaseURL(in: defaults),
237236
token: "",
238237
refreshAfterApply: false
239238
)
@@ -512,8 +511,7 @@ public struct LogseqRootView : View {
512511
sidebarTabs: rawTabs.isEmpty
513512
? []
514513
: rawTabs.split(separator: ",").map { value in String(value) },
515-
baseURL: defaults.string(forKey: "logseq.baseURL")
516-
?? "http://127.0.0.1:8787",
514+
baseURL: LogseqSettingsPolicy.storedBaseURL(in: defaults),
517515
version: LogseqSettingsPolicy.version,
518516
revision: LogseqSettingsPolicy.revision
519517
)
@@ -540,8 +538,7 @@ public struct LogseqRootView : View {
540538
guard localLaunchResult == nil else { return }
541539
let graphID = UserDefaults.standard.string(forKey: "logseq.selectedGraphId") ?? ""
542540
let databasePath = databasePath
543-
let baseURL = UserDefaults.standard.string(forKey: "logseq.baseURL")
544-
?? "http://127.0.0.1:8787"
541+
let baseURL = LogseqSettingsPolicy.storedBaseURL()
545542
localLaunchResult = {
546543
LogseqAppDelegate.shared.reportLaunchStage("local_load_started")
547544
func configureGraph() {
@@ -781,7 +778,7 @@ public struct LogseqRootView : View {
781778
public func syncFromStoredConnection() async -> Bool {
782779
await waitForLocalLaunchLoad()
783780
let defaults = UserDefaults.standard
784-
let baseURL = defaults.string(forKey: "logseq.baseURL") ?? "http://127.0.0.1:8787"
781+
let baseURL = LogseqSettingsPolicy.storedBaseURL(in: defaults)
785782
guard let graphID = defaults.string(forKey: "logseq.selectedGraphId"), !graphID.isEmpty else {
786783
return false
787784
}

‎apple/Sources/Logseq/LogseqThemeSettings.swift‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ struct LogseqCommunityLink: Identifiable {
103103
}
104104

105105
enum LogseqSettingsPolicy {
106+
static let defaultBaseURL = "https://api.logseq.io"
107+
108+
static func storedBaseURL(in defaults: UserDefaults = .standard) -> String {
109+
let value = defaults.string(forKey: "logseq.baseURL")?
110+
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
111+
return value.isEmpty ? defaultBaseURL : value
112+
}
113+
106114
static let languages = [
107115
LogseqLanguageChoice(id: "system", title: "System"),
108116
LogseqLanguageChoice(id: "en", title: "English"),

‎apple/Sources/LogseqModel/ViewModel.swift‎

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,27 +1485,6 @@ private struct DeletePagePayload: Encodable {
14851485
performAsync(LogseqRPCRequest(method: "dispatch", params: LogseqRPCParams(action: "clearSelection")))
14861486
}
14871487

1488-
public func loadBlockReferences(_ uuid: String) {
1489-
performAsync(LogseqRPCRequest(
1490-
method: "dispatch",
1491-
params: LogseqRPCParams(action: "loadBlockReferences", payload: uuid)
1492-
))
1493-
}
1494-
1495-
public func loadPageReferences(_ uuid: String) {
1496-
performAsync(LogseqRPCRequest(
1497-
method: "dispatch",
1498-
params: LogseqRPCParams(action: "loadPageReferences", payload: uuid)
1499-
))
1500-
}
1501-
1502-
public func loadTagObjects(_ uuid: String) {
1503-
performAsync(LogseqRPCRequest(
1504-
method: "dispatch",
1505-
params: LogseqRPCParams(action: "loadTagObjects", payload: uuid)
1506-
))
1507-
}
1508-
15091488
public func clearRelated() {
15101489
performAsync(LogseqRPCRequest(method: "dispatch", params: LogseqRPCParams(action: "clearRelated")))
15111490
}
@@ -1898,8 +1877,7 @@ private struct DeletePagePayload: Encodable {
18981877
private static func corePriority(for action: String) -> LogseqCorePriority {
18991878
switch action {
19001879
case "outlinerEvent", "selectPage", "clearSelectedPage", "openNode", "closeNode",
1901-
"select", "clearSelection", "loadOlderJournals", "loadBlockReferences",
1902-
"loadPageReferences", "loadTagObjects", "searchNodes", "send", "sendTask",
1880+
"select", "clearSelection", "loadOlderJournals", "searchNodes", "send", "sendTask",
19031881
"addAsset", "addChildBlock", "updateBlock", "updateBlockStatus", "deleteBlock":
19041882
return .interaction
19051883
case "open", "configure", "refresh", "refreshGraphCatalog", "createSyncGraph", "openGraph",

‎apple/Tests/LogseqModelTests/LogseqModelTests.swift‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -764,12 +764,9 @@ private let testEmptySnapshotJSON = """
764764
await store.unlockGraph("secret")
765765
store.select(block)
766766
store.clearSelection()
767-
store.loadBlockReferences("block-1")
768-
store.loadPageReferences("page-1")
769-
store.loadTagObjects("tag-1")
770767
store.clearRelated()
771768

772-
try await waitUntil { recorder.all.count >= 11 }
769+
try await waitUntil { recorder.all.count >= 8 }
773770

774771
let expectedActionsAndPayloads: [(String, String?)] = [
775772
("selectPage", "page-1"),
@@ -779,9 +776,6 @@ private let testEmptySnapshotJSON = """
779776
("unlockGraph", "secret"),
780777
("select", "block-1"),
781778
("clearSelection", nil),
782-
("loadBlockReferences", "block-1"),
783-
("loadPageReferences", "page-1"),
784-
("loadTagObjects", "tag-1"),
785779
("clearRelated", nil),
786780
]
787781
for (action, payload) in expectedActionsAndPayloads {

‎scripts/verify-ios-shortcuts.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def metadata(bundle):
2727
assert [(item["UIApplicationShortcutItemType"], item["UIApplicationShortcutItemTitle"]) for item in items] == [
2828
("logseq://audio", "Voice"), ("logseq://capture", "Quick Add")
2929
], "Home Screen must expose Voice and Quick Add"
30-
assert info["CFBundleIdentifier"] == host_info["CFBundleIdentifier"] + ".widgets"
30+
assert info["CFBundleIdentifier"] == host_info["CFBundleIdentifier"] + ".shortcuts"
3131
assert info["NSExtension"]["NSExtensionPointIdentifier"] == "com.apple.widgetkit-extension"
3232
assert (widget / info["CFBundleExecutable"]).is_file()
3333
print("Verified four distinct app shortcuts and the embedded widget extension")

‎shared/src/logseq/core/api.ml‎

Lines changed: 0 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
module Json = Yojson.Basic
22
module Json_util = Yojson.Basic.Util
3-
module Model = Cache_model
43

54
type api_config =
65
{ base_url : string
@@ -28,12 +27,6 @@ type api_file_upload =
2827
; headers : (string * string) list
2928
}
3029

31-
type api_journal =
32-
{ uuid : string
33-
; title : string
34-
; journal_day : int
35-
}
36-
3730
type api_graph =
3831
{ id : string
3932
; name : string
@@ -96,19 +89,6 @@ let graph_path config suffix =
9689

9790
let json_body fields = Some (Json.to_string (`Assoc fields))
9891

99-
let recent_blocks_request config journal_day =
100-
request config "GET"
101-
(graph_path config
102-
("/blocks?journal-only=true&journal-day-at-most="
103-
^ string_of_int journal_day
104-
^ "&sort=created-at-desc&limit=100"))
105-
None
106-
107-
let task_statuses_request config =
108-
request config "GET"
109-
(graph_path config "/search?q=Status&types=properties&limit=100")
110-
None
111-
11292
let graphs_request config = request config "GET" "/graphs" None
11393

11494
let create_graph_request config name schema_version e2ee =
@@ -155,21 +135,6 @@ let encrypted_journal_page_request config uuid title name journal_day =
155135
("journal-day", `Int journal_day);
156136
])
157137

158-
let related_request config resource uuid collection =
159-
request config "GET"
160-
(graph_path config
161-
("/" ^ resource ^ "/" ^ url_encode uuid ^ "/" ^ collection ^ "?limit=100"))
162-
None
163-
164-
let block_references_request config uuid =
165-
related_request config "blocks" uuid "references"
166-
167-
let page_references_request config uuid =
168-
related_request config "pages" uuid "references"
169-
170-
let tag_objects_request config uuid =
171-
related_request config "tags" uuid "objects"
172-
173138
let page_fields page_id =
174139
match page_id with
175140
| None -> []
@@ -363,110 +328,6 @@ let update_block_status_request config uuid status =
363328
(graph_path config ("/blocks/" ^ url_encode uuid ^ "/properties/Status"))
364329
(json_body [ ("value", `String status) ])
365330

366-
let summary_of_json input =
367-
let uuid = string_member "uuid" input in
368-
let title = string_member "title" input in
369-
if uuid <> "" && title <> "" then
370-
Some ({ uuid; title } : Model.entity_summary)
371-
else None
372-
373-
let summaries_member name input =
374-
List.filter_map summary_of_json (list_member name input)
375-
376-
let status_of_json input =
377-
let uuid = string_member "uuid" input in
378-
let title = string_member "title" input in
379-
let icon = member "icon" input in
380-
if uuid <> "" && title <> "" then
381-
Some
382-
({
383-
uuid;
384-
title;
385-
ident = option_string_member "ident" input;
386-
icon_type = option_string_member "type" icon;
387-
icon_id = option_string_member "id" icon;
388-
icon_color = option_string_member "color" icon;
389-
}
390-
: Model.status)
391-
else None
392-
393-
let status_choices input =
394-
List.filter_map status_of_json (list_member "choices" input)
395-
396-
let statuses_from_property_body body =
397-
let input = Json.from_string body in
398-
match member "results" input with
399-
| `List properties ->
400-
(match
401-
List.find_map
402-
(fun property ->
403-
if string_member "ident" property = "logseq.property/status" then
404-
Some (status_choices property)
405-
else None)
406-
properties
407-
with
408-
| Some choices -> choices
409-
| None -> [])
410-
| _ -> status_choices input
411-
412-
let block_of_json fallback_time input =
413-
let uuid = string_member "uuid" input in
414-
let title = string_member "title" input in
415-
if uuid <> "" && title <> "" then
416-
Some
417-
({
418-
uuid;
419-
title;
420-
page_id = string_member "page-id" input;
421-
parent_id = option_string_member "parent-id" input;
422-
order = option_string_member "order" input;
423-
created_at =
424-
(let value = int_member "created-at" input in
425-
if value = 0 then fallback_time else value);
426-
updated_at =
427-
(let value = int_member "updated-at" input in
428-
if value = 0 then fallback_time else value);
429-
sync_status = "synced";
430-
tags = summaries_member "tags" input;
431-
references = summaries_member "references" input;
432-
breadcrumbs = summaries_member "breadcrumbs" input;
433-
status = status_of_json (member "status" input);
434-
is_asset = false;
435-
asset_type = option_string_member "asset-type" input;
436-
asset_size =
437-
(match member "asset-size" input with
438-
| `Int value -> Some value
439-
| _ -> None);
440-
asset_checksum = option_string_member "asset-checksum" input;
441-
local_path = None;
442-
journal = None;
443-
}
444-
: Model.block)
445-
else None
446-
447-
let blocks_member key input =
448-
List.filter_map (fun value -> block_of_json 0 value) (list_member key input)
449-
450-
let blocks_from_list_body key body = blocks_member key (Json.from_string body)
451-
452-
let journal_of_json input =
453-
let uuid = string_member "uuid" input in
454-
let day = int_member "journal-day" input in
455-
if uuid <> "" && day > 0 then
456-
Some
457-
({
458-
uuid;
459-
title = string_member "title" input;
460-
journal_day = day;
461-
}
462-
: api_journal)
463-
else None
464-
465-
let feed_from_body body =
466-
let input = Json.from_string body in
467-
( blocks_member "blocks" input
468-
, List.filter_map journal_of_json (list_member "journals" input) )
469-
470331
let bool_member default name input =
471332
match member name input with `Bool value -> value | _ -> default
472333

0 commit comments

Comments
 (0)