From b005f43fd8c27f2fbe459f5c9687dd36a2dd171c Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Tue, 6 Oct 2026 10:08:14 +0000 Subject: [PATCH 1/2] Replace the Flutter Android app with a native Kotlin/Compose app - New android/ Gradle project (applicationId com.logseq.chat, AGP 9.1, compileSdk 36, Jetpack Compose via android.builtInKotlin) hosting the app previously driven by flutter/: Compose UI driven by LUI patch batches over the same liblogseq_chat_core.so JNI ABI. - Runtime ports of the Dart layer: native bridge, effect drain + scheduler, core bootstrap/catalog polling, graph lifecycle, platform effects/services, app entries, outliner commands, patch filter, dispatch, icons, Cognito OAuth via CustomTabs. - Compose extension hosts for the outliner editor, rich block content (markup, assets, embedded media WebView, math/code/cloze), native navigation stack, and search presentation; audio record/playback and attachment import dialogs. - Vendored dev.lui :lui module mirrors the LUI Kotlin backend surface (platform/android/lui on lui devin/android-kotlin); settings.gradle.kts automatically switches to includeBuild of ../lui/platform/android when that checkout exists. - Remove flutter/ entirely; repoint scripts, CI, docs, and .gitignore to android/. --- .github/workflows/e2e.yml | 6 - .gitignore | 2 +- AGENTS.md | 2 +- README.md | 35 +- .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-f3f9d216cd4f2c2405d1.json | 1219 ++++++++++++++ .../cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json | 475 ++++++ .../codemodel-v2-5c309d93a1473c4f858c.json | 60 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2026-10-06T10-01-44-0229.json | 92 ++ ...q_chat_jni-Debug-368a749d47f6911812ea.json | 117 ++ .../.cxx/Debug/666c1h3t/arm64-v8a/.ninja_deps | Bin 0 -> 6920 bytes .../.cxx/Debug/666c1h3t/arm64-v8a/.ninja_log | 3 + .../Debug/666c1h3t/arm64-v8a/CMakeCache.txt | 365 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 7816 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 +++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 6032 bytes .../arm64-v8a/CMakeFiles/CMakeOutput.log | 129 ++ .../CMakeFiles/TargetDirectories.txt | 3 + .../arm64-v8a/CMakeFiles/cmake.check_cache | 1 + .../logseq_chat_jni.dir/logseq_chat_jni.c.o | Bin 0 -> 59352 bytes .../666c1h3t/arm64-v8a/CMakeFiles/rules.ninja | 64 + .../arm64-v8a/additional_project_files.txt | 0 .../arm64-v8a/android_gradle_build.json | 38 + .../arm64-v8a/android_gradle_build_mini.json | 27 + .../.cxx/Debug/666c1h3t/arm64-v8a/build.ninja | 154 ++ .../666c1h3t/arm64-v8a/build_file_index.txt | 1 + .../666c1h3t/arm64-v8a/cmake_install.cmake | 54 + .../666c1h3t/arm64-v8a/compile_commands.json | 7 + .../arm64-v8a/compile_commands.json.bin | Bin 0 -> 879 bytes .../arm64-v8a/configure_fingerprint.bin | 28 + .../arm64-v8a/metadata_generation_command.txt | 18 + .../666c1h3t/arm64-v8a/prefab_config.json | 4 + .../arm64-v8a/symbol_folder_index.txt | 1 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-64ff77143cf6749202cc.json | 1219 ++++++++++++++ .../cmakeFiles-v1-3e7369e901c5c70ff58d.json | 475 ++++++ .../codemodel-v2-92d982066df4dfc8c207.json | 60 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2026-10-06T10-01-44-0447.json | 92 ++ ...q_chat_jni-Debug-9fe83448bfa47a4944a5.json | 117 ++ .../Debug/666c1h3t/armeabi-v7a/.ninja_deps | Bin 0 -> 6788 bytes .../Debug/666c1h3t/armeabi-v7a/.ninja_log | 3 + .../Debug/666c1h3t/armeabi-v7a/CMakeCache.txt | 365 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 5912 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 +++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 4128 bytes .../armeabi-v7a/CMakeFiles/CMakeOutput.log | 131 ++ .../CMakeFiles/TargetDirectories.txt | 3 + .../armeabi-v7a/CMakeFiles/cmake.check_cache | 1 + .../logseq_chat_jni.dir/logseq_chat_jni.c.o | Bin 0 -> 47468 bytes .../armeabi-v7a/CMakeFiles/rules.ninja | 64 + .../armeabi-v7a/additional_project_files.txt | 0 .../armeabi-v7a/android_gradle_build.json | 38 + .../android_gradle_build_mini.json | 27 + .../Debug/666c1h3t/armeabi-v7a/build.ninja | 154 ++ .../666c1h3t/armeabi-v7a/build_file_index.txt | 1 + .../666c1h3t/armeabi-v7a/cmake_install.cmake | 54 + .../armeabi-v7a/compile_commands.json | 7 + .../armeabi-v7a/compile_commands.json.bin | Bin 0 -> 920 bytes .../armeabi-v7a/configure_fingerprint.bin | 28 + .../metadata_generation_command.txt | 18 + .../666c1h3t/armeabi-v7a/prefab_config.json | 4 + .../armeabi-v7a/symbol_folder_index.txt | 1 + android/app/.cxx/Debug/666c1h3t/hash_key.txt | 25 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-41b0a89f291d57e40b0a.json | 1219 ++++++++++++++ .../cmakeFiles-v1-2c07039374e435828eae.json | 475 ++++++ .../codemodel-v2-a34f2e40999dcf7a38b8.json | 60 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2026-10-06T10-01-44-0584.json | 92 ++ ...q_chat_jni-Debug-75e028ed75280aebca99.json | 117 ++ .../app/.cxx/Debug/666c1h3t/x86/.ninja_deps | Bin 0 -> 7068 bytes .../app/.cxx/Debug/666c1h3t/x86/.ninja_log | 3 + .../.cxx/Debug/666c1h3t/x86/CMakeCache.txt | 365 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 5808 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 +++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 3904 bytes .../666c1h3t/x86/CMakeFiles/CMakeOutput.log | 126 ++ .../x86/CMakeFiles/TargetDirectories.txt | 3 + .../666c1h3t/x86/CMakeFiles/cmake.check_cache | 1 + .../logseq_chat_jni.dir/logseq_chat_jni.c.o | Bin 0 -> 43544 bytes .../Debug/666c1h3t/x86/CMakeFiles/rules.ninja | 64 + .../666c1h3t/x86/additional_project_files.txt | 0 .../666c1h3t/x86/android_gradle_build.json | 38 + .../x86/android_gradle_build_mini.json | 27 + .../app/.cxx/Debug/666c1h3t/x86/build.ninja | 154 ++ .../Debug/666c1h3t/x86/build_file_index.txt | 1 + .../Debug/666c1h3t/x86/cmake_install.cmake | 54 + .../Debug/666c1h3t/x86/compile_commands.json | 7 + .../666c1h3t/x86/compile_commands.json.bin | Bin 0 -> 870 bytes .../666c1h3t/x86/configure_fingerprint.bin | 28 + .../x86/metadata_generation_command.txt | 18 + .../Debug/666c1h3t/x86/prefab_config.json | 4 + .../666c1h3t/x86/symbol_folder_index.txt | 1 + .../.cmake/api/v1/query/client-agp/cache-v2 | 0 .../api/v1/query/client-agp/cmakeFiles-v1 | 0 .../api/v1/query/client-agp/codemodel-v2 | 0 .../reply/cache-v2-e9617ac8c3543573816a.json | 1219 ++++++++++++++ .../cmakeFiles-v1-136cb755cd94dfa0d0a9.json | 475 ++++++ .../codemodel-v2-2933ffa2bb6a77d0cf2c.json | 60 + ...irectory-.-Debug-f5ebdc15457944623624.json | 14 + .../reply/index-2026-10-06T10-01-44-0715.json | 92 ++ ...q_chat_jni-Debug-87618656bb91b5a76ec1.json | 117 ++ .../.cxx/Debug/666c1h3t/x86_64/.ninja_deps | Bin 0 -> 7076 bytes .../app/.cxx/Debug/666c1h3t/x86_64/.ninja_log | 3 + .../.cxx/Debug/666c1h3t/x86_64/CMakeCache.txt | 365 +++++ .../3.22.1-g37088a8/CMakeCCompiler.cmake | 72 + .../CMakeDetermineCompilerABI_C.bin | Bin 0 -> 7168 bytes .../3.22.1-g37088a8/CMakeSystem.cmake | 15 + .../CompilerIdC/CMakeCCompilerId.c | 803 +++++++++ .../CompilerIdC/CMakeCCompilerId.o | Bin 0 -> 5400 bytes .../x86_64/CMakeFiles/CMakeOutput.log | 126 ++ .../x86_64/CMakeFiles/TargetDirectories.txt | 3 + .../x86_64/CMakeFiles/cmake.check_cache | 1 + .../logseq_chat_jni.dir/logseq_chat_jni.c.o | Bin 0 -> 57672 bytes .../666c1h3t/x86_64/CMakeFiles/rules.ninja | 64 + .../x86_64/additional_project_files.txt | 0 .../666c1h3t/x86_64/android_gradle_build.json | 38 + .../x86_64/android_gradle_build_mini.json | 27 + .../.cxx/Debug/666c1h3t/x86_64/build.ninja | 154 ++ .../666c1h3t/x86_64/build_file_index.txt | 1 + .../Debug/666c1h3t/x86_64/cmake_install.cmake | 54 + .../666c1h3t/x86_64/compile_commands.json | 7 + .../666c1h3t/x86_64/compile_commands.json.bin | Bin 0 -> 875 bytes .../666c1h3t/x86_64/configure_fingerprint.bin | 28 + .../x86_64/metadata_generation_command.txt | 18 + .../Debug/666c1h3t/x86_64/prefab_config.json | 4 + .../666c1h3t/x86_64/symbol_folder_index.txt | 1 + .../debug/arm64-v8a/compile_commands.json | 7 + .../debug/armeabi-v7a/compile_commands.json | 7 + .../tools/debug/x86/compile_commands.json | 7 + .../tools/debug/x86_64/compile_commands.json | 7 + android/app/build.gradle.kts | 160 ++ .../AndroidAudioRecorderInstrumentedTest.kt | 0 .../chat/AndroidE2EECryptoDeviceTests.kt | 0 android/app/src/debug/AndroidManifest.xml | 4 + .../debug/res/xml/network_security_config.xml | 0 .../app/src/main/AndroidManifest.xml | 82 +- android/app/src/main/cpp/CMakeLists.txt | 16 + android/app/src/main/cpp/logseq_chat_jni.c | 265 +++ .../com/logseq/chat/AndroidAppEntryParser.kt | 0 .../com/logseq/chat/AndroidAssetImporter.kt | 0 .../com/logseq/chat/AndroidAudioPlayer.kt | 0 .../com/logseq/chat/AndroidAudioRecorder.kt | 0 .../logseq/chat/AndroidAudioTranscriber.kt | 0 .../logseq/chat/AndroidPlatformServices.kt | 13 + .../kotlin/com/logseq/chat/AndroidWidgets.kt | 0 .../com/logseq/chat/CognitoAuthProvider.kt | 0 .../kotlin/com/logseq/chat/CognitoOAuth.kt | 0 .../com/logseq/chat/LogseqChatApplication.kt | 5 + .../kotlin/com/logseq/chat/MainActivity.kt | 135 ++ .../main/kotlin/com/logseq/chat/NativeCore.kt | 44 + .../logseq/chat/runtime/AndroidAppEntry.kt | 155 ++ .../chat/runtime/AndroidGraphLifecycle.kt | 156 ++ .../chat/runtime/AndroidPlatformEffects.kt | 272 +++ .../com/logseq/chat/runtime/ChatRuntime.kt | 538 ++++++ .../com/logseq/chat/runtime/CoreBootstrap.kt | 132 ++ .../logseq/chat/runtime/CoreEffectExecutor.kt | 270 +++ .../chat/runtime/GraphCatalogAutoRefresh.kt | 115 ++ .../logseq/chat/runtime/LogseqChatIcons.kt | 82 + .../chat/runtime/LogseqChatNativeBridge.kt | 159 ++ .../com/logseq/chat/runtime/LuiDispatch.kt | 51 + .../com/logseq/chat/runtime/LuiPatchFilter.kt | 106 ++ .../logseq/chat/runtime/NativeEffectDrain.kt | 235 +++ .../chat/runtime/NativeRuntimeScheduler.kt | 54 + .../chat/runtime/OutlinerPlatformCommands.kt | 80 + .../com/logseq/chat/ui/LogseqChatApp.kt | 206 +++ .../com/logseq/chat/ui/LogseqChatTheme.kt | 45 + .../logseq/chat/ui/extensions/ChatDialogs.kt | 70 + .../chat/ui/extensions/ChatExtensions.kt | 162 ++ .../ui/extensions/OutlinerBlockContent.kt | 685 ++++++++ .../chat/ui/extensions/OutlinerEditor.kt | 194 +++ .../kotlin/logseq/chat/AndroidE2EECrypto.kt | 0 .../kotlin/logseq/chat/AndroidFilePaths.kt | 0 .../chat/AndroidGraphSnapshotDownloader.kt | 0 .../logseq/chat/AndroidHttpTransport.kt | 0 .../kotlin/logseq/chat/AndroidRuntimeLog.kt | 0 .../res/drawable-v21/launch_background.xml | 0 .../res/drawable/ic_launcher_foreground.xml | 0 .../res/drawable/ic_launcher_monochrome.xml | 0 .../main/res/drawable/ic_shortcut_capture.xml | 0 .../main/res/drawable/ic_shortcut_journal.xml | 0 .../main/res/drawable/ic_widget_capture.xml | 0 .../main/res/drawable/launch_background.xml | 0 .../main/res/drawable/widget_background.xml | 0 .../src/main/res/layout/widget_capture.xml | 0 .../main/res/layout/widget_today_journal.xml | 0 .../res/mipmap-anydpi-v26/ic_launcher.xml | 0 .../mipmap-anydpi-v26/ic_launcher_round.xml | 0 .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin .../mipmap-hdpi/ic_launcher_background.png | Bin .../mipmap-hdpi/ic_launcher_foreground.png | Bin .../mipmap-hdpi/ic_launcher_monochrome.png | Bin .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin .../mipmap-mdpi/ic_launcher_background.png | Bin .../mipmap-mdpi/ic_launcher_foreground.png | Bin .../mipmap-mdpi/ic_launcher_monochrome.png | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin .../mipmap-xhdpi/ic_launcher_background.png | Bin .../mipmap-xhdpi/ic_launcher_foreground.png | Bin .../mipmap-xhdpi/ic_launcher_monochrome.png | Bin .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin .../mipmap-xxhdpi/ic_launcher_background.png | Bin .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin .../mipmap-xxhdpi/ic_launcher_monochrome.png | Bin .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin .../mipmap-xxxhdpi/ic_launcher_background.png | Bin .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin .../mipmap-xxxhdpi/ic_launcher_monochrome.png | Bin .../app/src/main/res/raw/logseq_auth.json | 0 .../app/src/main/res/values-night/colors.xml | 0 .../app/src/main/res/values-night/styles.xml | 11 +- .../app/src/main/res/values/colors.xml | 0 .../app/src/main/res/values/strings.xml | 0 .../app/src/main/res/values/styles.xml | 11 +- .../src/main/res/xml/capture_widget_info.xml | 0 .../app/src/main/res/xml/file_paths.xml | 0 .../main/res/xml/network_security_config.xml | 0 .../app/src/main/res/xml/shortcuts.xml | 0 .../res/xml/today_journal_widget_info.xml | 0 .../logseq/chat/AndroidAppEntryParserTest.kt | 0 .../chat/AndroidAudioTranscriberTest.kt | 0 .../AndroidGraphSnapshotDownloaderTest.kt | 0 .../chat/AndroidPlatformServicesTest.kt | 6 - .../com/logseq/chat/AndroidRuntimeLogTest.kt | 0 .../AuthenticationActivityContractTest.kt | 0 .../com/logseq/chat/CognitoOAuthTest.kt | 0 .../logseq/chat/AndroidE2EECryptoTests.kt | 0 android/build.gradle.kts | 5 + android/gradle.properties | 8 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes .../gradle/wrapper/gradle-wrapper.properties | 0 android/gradlew | 163 ++ android/gradlew.bat | 90 + android/lui/build.gradle.kts | 47 + .../lui/src/main/kotlin/dev/lui/LuiBackend.kt | 135 ++ .../lui/src/main/kotlin/dev/lui/LuiEvent.kt | 32 + .../src/main/kotlin/dev/lui/LuiExtension.kt | 92 ++ .../lui/src/main/kotlin/dev/lui/LuiIcons.kt | 107 ++ .../lui/src/main/kotlin/dev/lui/LuiNode.kt | 32 + .../lui/src/main/kotlin/dev/lui/LuiProps.kt | 173 ++ .../src/main/kotlin/dev/lui/LuiRenderers.kt | 819 ++++++++++ .../lui/src/main/kotlin/dev/lui/LuiTheme.kt | 150 ++ android/settings.gradle.kts | 34 + docs/adr/001-real-time-graph-sync.md | 4 +- docs/agent-guide/001-lg-lui-rewrite.md | 6 +- ...1-lg-lui-rewrite_android-dogfood_report.md | 150 +- flutter/.gitignore | 48 - flutter/.metadata | 30 - flutter/README.md | 17 - flutter/analysis_options.yaml | 37 - flutter/android/.gitignore | 14 - flutter/android/app/build.gradle.kts | 86 - .../android/app/src/debug/AndroidManifest.xml | 7 - .../logseq_chat_flutter/MainActivity.kt | 284 ---- .../app/src/profile/AndroidManifest.xml | 7 - flutter/android/build.gradle.kts | 24 - flutter/android/fastlane/Appfile | 9 - flutter/android/fastlane/Fastfile | 31 - .../android/en-US/full_description.txt | 3 - .../android/en-US/short_description.txt | 1 - .../fastlane/metadata/android/en-US/title.txt | 1 - flutter/android/gradle.properties | 6 - flutter/android/settings.gradle.kts | 26 - flutter/lib/android_app_entry.dart | 158 -- flutter/lib/android_audio_playback.dart | 294 ---- flutter/lib/android_audio_recording.dart | 374 ----- flutter/lib/android_cloze.dart | 31 - flutter/lib/android_embedded_media.dart | 198 --- flutter/lib/android_graph_lifecycle.dart | 191 --- flutter/lib/android_imported_asset.dart | 60 - flutter/lib/android_math.dart | 34 - flutter/lib/android_outliner_commands.dart | 221 --- flutter/lib/android_platform_effects.dart | 531 ------ flutter/lib/core_bootstrap.dart | 155 -- flutter/lib/core_effect_executor.dart | 283 ---- flutter/lib/flutter_patch_applier.dart | 110 -- flutter/lib/graph_catalog_auto_refresh.dart | 120 -- flutter/lib/graph_catalog_polling_policy.dart | 6 - flutter/lib/logseq_chat_app_frame.dart | 10 - flutter/lib/logseq_chat_extensions.dart | 1244 -------------- flutter/lib/logseq_chat_icons.dart | 67 - flutter/lib/logseq_chat_native_bridge.dart | 403 ----- flutter/lib/logseq_chat_theme.dart | 223 --- flutter/lib/lui_dispatch.dart | 89 - flutter/lib/main.dart | 752 --------- flutter/lib/native_effect_drain.dart | 339 ---- flutter/lib/native_runtime_scheduler.dart | 49 - flutter/pubspec.lock | 398 ----- flutter/pubspec.yaml | 28 - flutter/test/android_app_entry_test.dart | 92 -- ...d_audio_playback_native_contract_test.dart | 41 - flutter/test/android_audio_playback_test.dart | 105 -- .../test/android_audio_recording_test.dart | 264 --- flutter/test/android_cloze_test.dart | 27 - flutter/test/android_embedded_media_test.dart | 64 - .../test/android_graph_lifecycle_test.dart | 321 ---- .../test/android_icon_button_layout_test.dart | 57 - .../test/android_launcher_assets_test.dart | 115 -- flutter/test/android_math_test.dart | 34 - .../test/android_outliner_commands_test.dart | 228 --- .../test/android_platform_effects_test.dart | 350 ---- flutter/test/android_widget_assets_test.dart | 43 - flutter/test/core_bootstrap_test.dart | 167 -- flutter/test/core_effect_executor_test.dart | 320 ---- flutter/test/flutter_patch_applier_test.dart | 339 ---- .../test/graph_catalog_auto_refresh_test.dart | 175 -- .../graph_catalog_polling_policy_test.dart | 31 - flutter/test/lazy_journal_list_test.dart | 58 - flutter/test/logseq_chat_app_frame_test.dart | 24 - flutter/test/logseq_chat_extensions_test.dart | 1456 ----------------- flutter/test/logseq_chat_icons_test.dart | 91 -- flutter/test/logseq_chat_theme_test.dart | 106 -- flutter/test/lui_dispatch_test.dart | 100 -- flutter/test/native_effect_drain_test.dart | 426 ----- .../test/native_runtime_scheduler_test.dart | 70 - flutter/test/search_layout_contract_test.dart | 26 - flutter/tool/check_release_jni.py | 16 - scripts/build-android-native.sh | 2 +- scripts/test-android-e2e-runner.sh | 18 +- scripts/test-android-e2e.sh | 12 +- scripts/test-android-native-script.sh | 33 +- scripts/test-no-skip-support.sh | 22 +- 336 files changed, 21590 insertions(+), 12358 deletions(-) create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cache-v2-f3f9d216cd4f2c2405d1.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-5c309d93a1473c4f858c.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0229.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-368a749d47f6911812ea.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_deps create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_log create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100755 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeOutput.log create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/build.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/build_file_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/prefab_config.json create mode 100644 android/app/.cxx/Debug/666c1h3t/arm64-v8a/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/cache-v2-64ff77143cf6749202cc.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/cmakeFiles-v1-3e7369e901c5c70ff58d.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/codemodel-v2-92d982066df4dfc8c207.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0447.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-9fe83448bfa47a4944a5.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.ninja_deps create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.ninja_log create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100755 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeOutput.log create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/prefab_config.json create mode 100644 android/app/.cxx/Debug/666c1h3t/armeabi-v7a/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/hash_key.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/cache-v2-41b0a89f291d57e40b0a.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/cmakeFiles-v1-2c07039374e435828eae.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/codemodel-v2-a34f2e40999dcf7a38b8.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0584.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-75e028ed75280aebca99.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.ninja_deps create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/.ninja_log create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100755 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeOutput.log create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/build.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cache-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cache-v2-e9617ac8c3543573816a.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-136cb755cd94dfa0d0a9.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/codemodel-v2-2933ffa2bb6a77d0cf2c.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0715.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-87618656bb91b5a76ec1.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.ninja_deps create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/.ninja_log create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeCache.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake create mode 100755 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/CMakeOutput.log create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/TargetDirectories.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/cmake.check_cache create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/rules.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/additional_project_files.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build_mini.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/build_file_index.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/cmake_install.cmake create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json create mode 100644 android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt create mode 100644 android/app/.cxx/tools/debug/arm64-v8a/compile_commands.json create mode 100644 android/app/.cxx/tools/debug/armeabi-v7a/compile_commands.json create mode 100644 android/app/.cxx/tools/debug/x86/compile_commands.json create mode 100644 android/app/.cxx/tools/debug/x86_64/compile_commands.json create mode 100644 android/app/build.gradle.kts rename {flutter/android => android}/app/src/androidTest/kotlin/com/logseq/chat/AndroidAudioRecorderInstrumentedTest.kt (100%) rename {flutter/android => android}/app/src/androidTest/kotlin/logseq/chat/AndroidE2EECryptoDeviceTests.kt (100%) create mode 100644 android/app/src/debug/AndroidManifest.xml rename {flutter/android => android}/app/src/debug/res/xml/network_security_config.xml (100%) rename {flutter/android => android}/app/src/main/AndroidManifest.xml (63%) create mode 100644 android/app/src/main/cpp/CMakeLists.txt create mode 100644 android/app/src/main/cpp/logseq_chat_jni.c rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidAppEntryParser.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidAudioTranscriber.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt (95%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/CognitoAuthProvider.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/com/logseq/chat/CognitoOAuth.kt (100%) create mode 100644 android/app/src/main/kotlin/com/logseq/chat/LogseqChatApplication.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/MainActivity.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/NativeCore.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidAppEntry.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidGraphLifecycle.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidPlatformEffects.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/ChatRuntime.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/CoreBootstrap.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/CoreEffectExecutor.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/GraphCatalogAutoRefresh.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatNativeBridge.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/LuiDispatch.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/LuiPatchFilter.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/NativeEffectDrain.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/NativeRuntimeScheduler.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/runtime/OutlinerPlatformCommands.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatApp.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatTheme.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatDialogs.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatExtensions.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerBlockContent.kt create mode 100644 android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerEditor.kt rename {flutter/android => android}/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/logseq/chat/AndroidFilePaths.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/logseq/chat/AndroidGraphSnapshotDownloader.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt (100%) rename {flutter/android => android}/app/src/main/kotlin/logseq/chat/AndroidRuntimeLog.kt (100%) rename {flutter/android => android}/app/src/main/res/drawable-v21/launch_background.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/ic_launcher_foreground.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/ic_launcher_monochrome.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/ic_shortcut_capture.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/ic_shortcut_journal.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/ic_widget_capture.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/launch_background.xml (100%) rename {flutter/android => android}/app/src/main/res/drawable/widget_background.xml (100%) rename {flutter/android => android}/app/src/main/res/layout/widget_capture.xml (100%) rename {flutter/android => android}/app/src/main/res/layout/widget_today_journal.xml (100%) rename {flutter/android => android}/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%) rename {flutter/android => android}/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%) rename {flutter/android => android}/app/src/main/res/mipmap-hdpi/ic_launcher.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-hdpi/ic_launcher_background.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-mdpi/ic_launcher.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-mdpi/ic_launcher_background.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xhdpi/ic_launcher.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png (100%) rename {flutter/android => android}/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png (100%) rename {flutter/android => android}/app/src/main/res/raw/logseq_auth.json (100%) rename {flutter/android => android}/app/src/main/res/values-night/colors.xml (100%) rename {flutter/android => android}/app/src/main/res/values-night/styles.xml (58%) rename {flutter/android => android}/app/src/main/res/values/colors.xml (100%) rename {flutter/android => android}/app/src/main/res/values/strings.xml (100%) rename {flutter/android => android}/app/src/main/res/values/styles.xml (59%) rename {flutter/android => android}/app/src/main/res/xml/capture_widget_info.xml (100%) rename {flutter/android => android}/app/src/main/res/xml/file_paths.xml (100%) rename {flutter/android => android}/app/src/main/res/xml/network_security_config.xml (100%) rename {flutter/android => android}/app/src/main/res/xml/shortcuts.xml (100%) rename {flutter/android => android}/app/src/main/res/xml/today_journal_widget_info.xml (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AndroidAppEntryParserTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AndroidAudioTranscriberTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AndroidGraphSnapshotDownloaderTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt (91%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AndroidRuntimeLogTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/AuthenticationActivityContractTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/com/logseq/chat/CognitoOAuthTest.kt (100%) rename {flutter/android => android}/app/src/test/kotlin/logseq/chat/AndroidE2EECryptoTests.kt (100%) create mode 100644 android/build.gradle.kts create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar rename {flutter/android => android}/gradle/wrapper/gradle-wrapper.properties (100%) create mode 100755 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/lui/build.gradle.kts create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiBackend.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiEvent.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiExtension.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiIcons.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiNode.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiProps.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt create mode 100644 android/lui/src/main/kotlin/dev/lui/LuiTheme.kt create mode 100644 android/settings.gradle.kts delete mode 100644 flutter/.gitignore delete mode 100644 flutter/.metadata delete mode 100644 flutter/README.md delete mode 100644 flutter/analysis_options.yaml delete mode 100644 flutter/android/.gitignore delete mode 100644 flutter/android/app/build.gradle.kts delete mode 100644 flutter/android/app/src/debug/AndroidManifest.xml delete mode 100644 flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt delete mode 100644 flutter/android/app/src/profile/AndroidManifest.xml delete mode 100644 flutter/android/build.gradle.kts delete mode 100644 flutter/android/fastlane/Appfile delete mode 100644 flutter/android/fastlane/Fastfile delete mode 100644 flutter/android/fastlane/metadata/android/en-US/full_description.txt delete mode 100644 flutter/android/fastlane/metadata/android/en-US/short_description.txt delete mode 100644 flutter/android/fastlane/metadata/android/en-US/title.txt delete mode 100644 flutter/android/gradle.properties delete mode 100644 flutter/android/settings.gradle.kts delete mode 100644 flutter/lib/android_app_entry.dart delete mode 100644 flutter/lib/android_audio_playback.dart delete mode 100644 flutter/lib/android_audio_recording.dart delete mode 100644 flutter/lib/android_cloze.dart delete mode 100644 flutter/lib/android_embedded_media.dart delete mode 100644 flutter/lib/android_graph_lifecycle.dart delete mode 100644 flutter/lib/android_imported_asset.dart delete mode 100644 flutter/lib/android_math.dart delete mode 100644 flutter/lib/android_outliner_commands.dart delete mode 100644 flutter/lib/android_platform_effects.dart delete mode 100644 flutter/lib/core_bootstrap.dart delete mode 100644 flutter/lib/core_effect_executor.dart delete mode 100644 flutter/lib/flutter_patch_applier.dart delete mode 100644 flutter/lib/graph_catalog_auto_refresh.dart delete mode 100644 flutter/lib/graph_catalog_polling_policy.dart delete mode 100644 flutter/lib/logseq_chat_app_frame.dart delete mode 100644 flutter/lib/logseq_chat_extensions.dart delete mode 100644 flutter/lib/logseq_chat_icons.dart delete mode 100644 flutter/lib/logseq_chat_native_bridge.dart delete mode 100644 flutter/lib/logseq_chat_theme.dart delete mode 100644 flutter/lib/lui_dispatch.dart delete mode 100644 flutter/lib/main.dart delete mode 100644 flutter/lib/native_effect_drain.dart delete mode 100644 flutter/lib/native_runtime_scheduler.dart delete mode 100644 flutter/pubspec.lock delete mode 100644 flutter/pubspec.yaml delete mode 100644 flutter/test/android_app_entry_test.dart delete mode 100644 flutter/test/android_audio_playback_native_contract_test.dart delete mode 100644 flutter/test/android_audio_playback_test.dart delete mode 100644 flutter/test/android_audio_recording_test.dart delete mode 100644 flutter/test/android_cloze_test.dart delete mode 100644 flutter/test/android_embedded_media_test.dart delete mode 100644 flutter/test/android_graph_lifecycle_test.dart delete mode 100644 flutter/test/android_icon_button_layout_test.dart delete mode 100644 flutter/test/android_launcher_assets_test.dart delete mode 100644 flutter/test/android_math_test.dart delete mode 100644 flutter/test/android_outliner_commands_test.dart delete mode 100644 flutter/test/android_platform_effects_test.dart delete mode 100644 flutter/test/android_widget_assets_test.dart delete mode 100644 flutter/test/core_bootstrap_test.dart delete mode 100644 flutter/test/core_effect_executor_test.dart delete mode 100644 flutter/test/flutter_patch_applier_test.dart delete mode 100644 flutter/test/graph_catalog_auto_refresh_test.dart delete mode 100644 flutter/test/graph_catalog_polling_policy_test.dart delete mode 100644 flutter/test/lazy_journal_list_test.dart delete mode 100644 flutter/test/logseq_chat_app_frame_test.dart delete mode 100644 flutter/test/logseq_chat_extensions_test.dart delete mode 100644 flutter/test/logseq_chat_icons_test.dart delete mode 100644 flutter/test/logseq_chat_theme_test.dart delete mode 100644 flutter/test/lui_dispatch_test.dart delete mode 100644 flutter/test/native_effect_drain_test.dart delete mode 100644 flutter/test/native_runtime_scheduler_test.dart delete mode 100644 flutter/test/search_layout_contract_test.dart delete mode 100644 flutter/tool/check_release_jni.py diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index abec6b8e..3d95e1ba 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -423,12 +423,6 @@ jobs: if: steps.duniverse.outputs.cache-hit != 'true' run: echo "duniverse cache miss; the duniverse job should have populated it" >&2 && exit 1 - - name: Set up Flutter - uses: subosito/flutter-action@v2 - with: - channel: stable - cache: true - - name: Set up Gradle uses: gradle/actions/setup-gradle@v4 diff --git a/.gitignore b/.gitignore index b85dc9f0..541ac8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,7 @@ local.properties Android/app/keystore.jks Android/app/keystore.properties Android/app/src/main/jniLibs/ -flutter/android/app/src/main/jniLibs/ +android/app/src/main/jniLibs/ tests/e2e/screenshots/ xcodebuild*.log diff --git a/AGENTS.md b/AGENTS.md index 8cea4b68..be3b8e05 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # Logseq Chat -Logseq Chat uses native SwiftUI on iOS and Flutter Material on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`. +Logseq Chat uses native SwiftUI on iOS and Kotlin/Jetpack Compose on Android, backed by an OCaml DataScript core. Canonical setup is in `README.md`. ## Testing diff --git a/README.md b/README.md index c28934f2..29579d80 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Logseq Chat -Logseq Chat is a native SwiftUI app for iOS and a Flutter Material app for -Android. Both clients share an OCaml application model and core, backed by +Logseq Chat is a native SwiftUI app for iOS and a Kotlin/Jetpack Compose +app for Android. Both clients share an OCaml application model and core, backed by the OCaml DataScript library and the lui reactive UI layer. Shared core sources live in `shared/src/logseq_chat/core`, with executable entry points @@ -12,7 +12,7 @@ in `shared/test/logseq_chat`, one alcotest suite per core module. The core test ## Repository layout - `apple/`: Swift package, app, extensions, Xcode workspace, and Apple tests. -- `flutter/`: Flutter Android app and its platform integration. +- `android/`: Kotlin/Jetpack Compose Android app and its platform integration. - `shared/src/`: OCaml application and core sources. - `shared/test/`: OCaml test suites. - `shared/native/`: Dune configuration and native bridges. @@ -38,24 +38,27 @@ directly. ## Android -Android is built exclusively from the Flutter project: +Android is a standard Gradle project: ```sh -cd flutter -flutter pub get -flutter run +cd android +./gradlew :app:assembleDebug +adb install -r app/build/outputs/apk/debug/app-debug.apk ``` -Build a debug APK or Play Store app bundle with: +Release builds use `:app:assembleRelease` / `:app:bundleRelease`. The e2e +profile APK used by `scripts/test-android-e2e.sh` is `:app:assembleProfile` +(`app/build/outputs/apk/profile/app-profile.apk`). JVM unit tests run with +`./gradlew test`. -```sh -cd flutter -flutter build apk --debug -flutter build appbundle --release -``` +The OCaml core shared library is built separately by +`scripts/build-android-native.sh` (per ABI), which installs +`liblogseq_chat_core.so` into `android/app/src/main/jniLibs/`; the Gradle +`buildAndroidNativeCore` task invokes it automatically (set +`-PlogseqChatRequireNativeCore=false` to compile Kotlin without it). -The Flutter Android host includes Capture and Journal app shortcuts, Capture -and Today’s Journal home-screen widgets, inbound sharing, deep links, native +The Android host includes Capture and Journal app shortcuts, Capture and +Today’s Journal home-screen widgets, inbound sharing, deep links, native authentication, media services, and the OCaml core JNI library. ## iPhone shortcuts and widgets @@ -82,7 +85,7 @@ the current environment. Use the supported gates instead: ```sh swift build --package-path apple --disable-sandbox --triple arm64-apple-ios17.0-simulator \ --sdk "$(xcrun --sdk iphonesimulator --show-sdk-path)" -(cd flutter && flutter analyze && flutter test) +(cd android && ./gradlew test) opam exec --switch=5.5.0 -- dune build @shared/test/runtest opam exec --switch=5.5.0 -- dune build @shared/native/runtest ./scripts/test-android-e2e-runner.sh diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cache-v2-f3f9d216cd4f2c2405d1.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cache-v2-f3f9d216cd4f2c2405d1.json new file mode 100644 index 00000000..bf9f8c3b --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cache-v2-f3f9d216cd4f2c2405d1.json @@ -0,0 +1,1219 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "arm64-v8a" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "arm64-v8a" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-dlltool" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "logseq_chat_jni" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "log-lib", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to a library." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/liblog.so" + }, + { + "name" : "logseq_chat_jni_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a" + }, + { + "name" : "logseq_chat_jni_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "logseq_chat_jni_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json new file mode 100644 index 00000000..44f0a12a --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json @@ -0,0 +1,475 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a", + "source" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-5c309d93a1473c4f858c.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-5c309d93a1473c4f858c.json new file mode 100644 index 00000000..b1ed2e9c --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/codemodel-v2-5c309d93a1473c4f858c.json @@ -0,0 +1,60 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : ".", + "targetIndexes" : + [ + 0 + ] + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "logseq_chat_jni", + "targetIndexes" : + [ + 0 + ] + } + ], + "targets" : + [ + { + "directoryIndex" : 0, + "id" : "logseq_chat_jni::@6890427a1f51a3e7e1df", + "jsonFile" : "target-logseq_chat_jni-Debug-368a749d47f6911812ea.json", + "name" : "logseq_chat_jni", + "projectIndex" : 0 + } + ] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a", + "source" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 00000000..3a67af9c --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0229.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0229.json new file mode 100644 index 00000000..f650ebc8 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0229.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest", + "root" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-5c309d93a1473c4f858c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-f3f9d216cd4f2c2405d1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-f3f9d216cd4f2c2405d1.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-d3ef75a51d65dc3d6c0d.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-5c309d93a1473c4f858c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-368a749d47f6911812ea.json b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-368a749d47f6911812ea.json new file mode 100644 index 00000000..d9b2b847 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-368a749d47f6911812ea.json @@ -0,0 +1,117 @@ +{ + "artifacts" : + [ + { + "path" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a/liblogseq_chat_jni.so" + } + ], + "backtrace" : 1, + "backtraceGraph" : + { + "commands" : + [ + "add_library", + "target_link_libraries" + ], + "files" : + [ + "CMakeLists.txt" + ], + "nodes" : + [ + { + "file" : 0 + }, + { + "command" : 0, + "file" : 0, + "line" : 12, + "parent" : 0 + }, + { + "command" : 1, + "file" : 0, + "line" : 16, + "parent" : 0 + } + ] + }, + "compileGroups" : + [ + { + "compileCommandFragments" : + [ + { + "fragment" : "-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC" + } + ], + "defines" : + [ + { + "define" : "logseq_chat_jni_EXPORTS" + } + ], + "language" : "C", + "sourceIndexes" : + [ + 0 + ], + "sysroot" : + { + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot" + } + } + ], + "id" : "logseq_chat_jni::@6890427a1f51a3e7e1df", + "link" : + { + "commandFragments" : + [ + { + "fragment" : "-static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments", + "role" : "flags" + }, + { + "backtrace" : 2, + "fragment" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/liblog.so", + "role" : "libraries" + }, + { + "fragment" : "-latomic -lm", + "role" : "libraries" + } + ], + "language" : "C", + "sysroot" : + { + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot" + } + }, + "name" : "logseq_chat_jni", + "nameOnDisk" : "liblogseq_chat_jni.so", + "paths" : + { + "build" : ".", + "source" : "." + }, + "sourceGroups" : + [ + { + "name" : "Source Files", + "sourceIndexes" : + [ + 0 + ] + } + ], + "sources" : + [ + { + "backtrace" : 1, + "compileGroupIndex" : 0, + "path" : "logseq_chat_jni.c", + "sourceGroupIndex" : 0 + } + ], + "type" : "SHARED_LIBRARY" +} diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_deps b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_deps new file mode 100644 index 0000000000000000000000000000000000000000..95cee824ca9e982cebe0ecd80d48f895bf5b626f GIT binary patch literal 6920 zcmd6s$#Wbv6vjme34|r=ggp>;n3nChY;&fH;*!5XC95^liq%phsV6fOROP^d0|)M$ z_0Ydo}SwK_8Mgl@?2Ja*LFh48hGFU z-;fU~Ej`tC;N`V6um)zDD}mi4ft zm6PkW(t&Da>QQgBw!&7HsULf1ZJ@PxR2iY`T+&?kg~^IPp&8oH)M}jy&CP%=u5F6? zkSi0if{;Jj(w(=~Q?lfD=sw!Udgtk`tKjJ&?2ltwmH3bqCzGywj4aG$AG*Im_i(Cp z&ys#9omUoxHi%nJeoYzsnFn5}o|Z$Yv*H)%Kba~9&E5}WV7VMBAsKwI#s^ad#VN5T zKX$s^D_f@3W={{QwWG^n(BP;MF6t zF>sG9@R(zOpt%yAh<0{UvAEe*ksWKt&Lp#|_ z&$$!D%5raVx!$~C_;MBrLf(U)R?d}qxz2sr8%QIa5;F(yLcf*1el~sF>w8+SEF=4m z!oyRk>ix`n5<5^Oowo7%c?6zXnLExFmn|*`c_(FlOnM>SMX3>+R?OSbPuzEp`%tLc7yaE0HL2YcwiPzz&liJwgf{@oz=0`K1RH1N^ z=bPC<$g9accqun95*r`5iEjuAc_q1rzI8$M$8K)+=Dfht#H+xt6Jam)IF-sqEI7&!7vdDp_pE>^6u_JrV!SCC^xnMgu59|Ot!TI0;WOTcb$DYy(= z4z2)Kf~&yQ;2N+8TnnxP*Ml3tjo>D5GuR7m0k?vE;5KkOxC7h??gDp%d%(TmKF|Xh PpkM(kf+esYEQ5alDW#6E literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_log b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_log new file mode 100644 index 00000000..bfa3ad8d --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/.ninja_log @@ -0,0 +1,3 @@ +# ninja log v5 +0 38 1791280904331696973 CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o ef768d21a41d860f +38 52 1791280904345696856 /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a/liblogseq_chat_jni.so 735efdfbb37f2117 diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeCache.txt b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeCache.txt new file mode 100644 index 00000000..38ab76bd --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeCache.txt @@ -0,0 +1,365 @@ +# This is the CMakeCache file. +# For build in directory: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a +# It was generated by CMake: /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=arm64-v8a + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/home/ubuntu/android-sdk/ndk/27.0.12077973 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=arm64-v8a + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/home/ubuntu/android-sdk/ndk/27.0.12077973 + +//Archiver +CMAKE_AR:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-dlltool + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a + +//Path to a program. +CMAKE_LINKER:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=logseq_chat_jni + +//Ranlib +CMAKE_RANLIB:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/arm64-v8a + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Path to a library. +log-lib:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/liblog.so + +//Value Computed by CMake +logseq_chat_jni_BINARY_DIR:STATIC=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a + +//Value Computed by CMake +logseq_chat_jni_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +logseq_chat_jni_SOURCE_DIR:STATIC=/home/ubuntu/repos/chat/android/app/src/main/cpp + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/ubuntu/repos/chat/android/app/src/main/cpp +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 00000000..41969caf --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "18.0.1") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..190a6e4f60db0b82b26e837e2de7a3da3d3fcb58 GIT binary patch literal 7816 zcmdT}Z*UvM6@RC*9654i*$GWTNGu?Q7!paA9a~ADi4!|S;5Z=-Ei^;VC*9dnBk9EH zZ0v+KX~|Hgd`SjAWLlsMr86WgZKi()($ey$rIQ&xloZG?ot8TMnMnuAgehh4(4fAz zx6hK#Hl^^XtGRvqe*50rce{JLZ&wHU`nUQN1vshjI1rbtcacr9BCuE%kZgh^%*T8M zTmmFkCos2ulS{DHO>y6J8j!e(l=Mon-b*i%a!lDnqJCL78;QsUm_pc24Zn~p*K@=5)aW?-k(yGC}- z3@ZJ*Mp9~n(v7GmhuQ@`VNUw=+%3n?OP`c>m~wlu@_5-X3$b*r7|Z91driBmlSJwL z58*@a(^E8TD`&vPShf@0n1A}zo``pMuj}skv=+$kMflKsy>8$p7?54Y&_PCt``(BcF+q zt!YWq^0{jn88v7I;MBs?MIeQ2NFfzuN;xSVpL>ggJs#)wmDVC#o%!2TeeBtGZyp*cy3uzq|9 zBYjGQ4dU~GEF%$f#zFcXKD!AZ+Yz)Kxz~4J-GlWH1f0g!$hHvTFTV8ZUxgo!px6@h z_pp!;MSORMs3g+&SE?^Bhl77wfzN~rM^J3h#>>^0E2?t(!hZGGh2Oyu{H9OfvUvjD z04wlJ?_}F^y_2hy!1Jwscz5DXcx*yFcZ9NQDGqrJ0g>+#K} zdMDA>`!sB85a1W*RX7g5)-zA5+8M&mB2T(dsf39>yhI6OUo4_J;xCsx`E_CcZ;!pV zLpgQFaJte8CnuJ{$+PHpr3p^{ec8d2)b6UcE8&J*E_tqL)5(C+ z5Ik2?ckZpq&W7>a*lcwH(wn1hHk%V@AN@E&{>Wj0^ZTDVhU0&t`AqL*_~9##M6kce zCw@fTpRw*)w@&b{BL7+q{~GeXD}^qOt4Ql4WuDd`N-JC<)^93)SgFu5LEo;}(s=(S zj1q6Jah%VTgb>m}Vlc^VR?I)*C#5|p4jhIYmH@8>+ejD_uK`Epy0FNFr`qMcZkrSg z%K9aea%}Oote-FO&657>BlrDYkoD)Ke~(K3BgvnTe5KkS(!ysWFYx;5q1cW{Gpx(a zG_neJ!bEqXGr2l)b!phbJZ-QB69!ss}OT6E1${gw8`g33u{WY^))l& zM2uuS-l2D{?K0Xs^$x>KC*x~7Gls6OO{^OlN)N>o#=3N(E71o1A~skb>F@8At%B05 zd_J_$uZF^lmxY>@792`nC#a#+!i`JU2R8(LIEJdCr10~uyA)CjyK!v&S6~5G=#?n< zg$uPitKlmg>rh=W**v2N&0JP$Scc)}P zxeEtjIdsUOpdBD7M~hZc-?a#A#DY@SpuQrfv3dgnbzjEpBJl4-QhytLLCU;CMCJvW z5Gv!NEND>QVVwgA2%RSIA0i!mV4g29fI1IhQE6#V8|8#nr-Z{0xC$$uA%WEm>S`94 z@*o5awf-tr9_{&>nlYd6JF?_JEf?M=INBwGz9WtA5Z6MIP(O;fzpimPl16$X7%7%> z!$q85<*a2pkSh*ZT6MS8(z#*HEE+kz=vLuI3$d(KFk>U>k)kuglWk4e*c;0f^u1=R zBbrD=+hgUdZksN&hM?GX%NW7w7~8TPrM7Ib3Z-1$w0kzEq8Sb@|KGj`(OWg~%#7~K z=Nu<*at{{p(*yhfZIp9Bw}(e5%V5;kvujt+E!r1TU+L3!-?Fn$)24T_ZI-NZ3^g6@ z@0eaH#iE(9u~@H}9vO~xb#-OhvmID(7rHvvj3#xrpSNNk%P!wtD1mL>Hj=YV@Zo&Ib)X{ub1*;-5GFpZ?Yx z{Gs~m{lQ=P+v-WR~PMtdKVM04vh z;DZqK%MI;jS+N|cg3%$LQ+Z#bQxwT_oGoHN#I6&1Re8Z;MlmHVMiVkl7c6Esio)lZ zouXe7r3Em?8>p<=gH*wm`Fwa(;zdELxP-+bN1oo#8@sIdx|F}qgMVA%5xL*89a?G0 z&O;vg`z1c%!M}q8;PZvx5!s&{H~c{2Pe`0&?Bj?lzH0w)9P@iA|B{psi}nB>Ls~b> z_&y`*aeUldnA|3e()CNHC5dOm-gDRJ+FQ&*>1osOaG7S5oeEl$OOl!+=e@-Nx7h-+Jnn$|zg163x}z zUzMD!ZR!SJUTK>5I%`Jwr1jo1(6c?YrTXQ4wi14ZxbD!7w^dEaI|_J{SqiUkTG zxP3nVGu_OBl2RYkrXgg=HtX~K2Gc<)>}{X>uO#)k9lqaSx~)c^?uXfb*58L%?fm2Y zo@rX@GhsiO|CUF8uKy2Mp5KFcinnUp=Qxn*(<~?{`_J%qu|WDVY?|6fc|Seu>2PoR z4|(*x_ar;9zBYwx87%)0A8MP!NZ#Kg($PWLKKsp-?fe9FNrd(Jp8TM^(Bg4I5s_G* z`JZE_29~NM#!>ikL3<827L+ zi86$F{om^z;6TKUWJo5~XIh5^F0%|#T?X>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..cc02e061cb2460aeb1ceba89944f167f96b488e6 GIT binary patch literal 6032 zcmdT|Z;V`36+drgXF9vHOxZ4l!j>{hRSN8zKRdfStp>JPTHIQ@q(Y=@>g3JL+u5-* z^M*HX)|D7bgb!c{q2Wstf@uV!reDMlvI|C==!a^eshAis65tah@q&!_u+C%Li&syW4Ep?#g1z>NHM*0J|;ATXo#_%F$-0zac@(t*xy{x#wA(y5-g@ zb$iw7x4f0YyzH?zJiF6tI-TC2Z~55CU?EW&@>^NAU81k#MJbd`U&!ZKC=8DtGBuQ(-hCqvOKnF!!04w%GiIWj9m$1V@eC0@b0bj!(g}!3h{)rmAr*d%=W9d+ zn-VAO=Apn@xrjpSb66SA8l!PWOUV->`}k4SCroVtn>ypRW$Y*S$RX@1yPOrencE9BbLOe8t+Apxk(xGcZCr!gWImE;zncddF&mJof#LsX+ieaHZhX=5%#5M z`QTuu?mEqS_O?PXUz{(N%6De(=r$azt4_=Q^RuN|-Lhtj`&U=1tNCJmf3-MQ+y{$av`*QJi}GSG z)y*2@)||GT>sR|7ub*@6uG7n*3y*`yS>0~VtZi)M?y;-=Ms99yu2xu^!G5BW)nuY1c%zVCFw#vD{(;}c%7b=y5$B!R8QTfu+Lx(E&pSbT(r2@^) zs#D>|#@FP^_zFKczD942FVPzIt%hCEpB$|_{O&*-*AQ7ASZRzY=$wnQjxF5-xF?g1UC59GFW_$kZpYd%j1M!{P=jZjzIjH} zVZknZKw_f7D*j~BNNgK>FOm5|Vt4XeiOi8i`bZ*^d{xtS4f>{%KgE8ey@E|V^GafR z&_%;?18oe6@nrf)EQK+#zfgN8c8$Q_u7o-$IQ*xV7lf%WPQ18(&4-3ODfr@P9m2mU zaPig-;XQ$;hA>jr1U?$VYXZkli&nlO@M|;_;Do@phj0SoFcHG<7yK~3Ebtv6zHjHc z5dOU2hw;Y*zB9z%5cmxt+_#S(MXj_2KaBqhc{`MS6z3PQZ{u$Qg7xPWe_i0gIx`+a z`x6kXGvhA_K5GC))TumxzX=G|pBeiE9;`p(yfTyM=Xx?A3*Wmv8lIQ^#8+3TByr-a z_)&$=HVL{<;j1`(ajB4fbyd4Q3_CUaafuWECMi?%gp?^B6+b6&;!jDLnir)^d=+O3 zU1dMnVZ?74*H04T^g^kH@i`SlnQ>khJ|VRK;)^c%EE68=CY?3EF#fXCc~1$)9Bxo} zO_={{*|SHs6wlzbM2z>B<77iiQeZnXIF1U>gYmM&zwCDd<3}Z4mpIwym zZzO(J znxkr#suER&8LCB9D3U0uLP7KmCW%%HrjO-e?}nL|yZ4_rcjI}8%62aM=^y++o*(w0 zsp4%UjNeh_EwG@qbf?tv3snBy_=_qTWqth5B(|XO%40sj_nht~&6B^!{B}Hz&dEQ2 z*ZooScd{?>cam`li!p>fjz7ZmHT3hFz#nm`uzz0zIE@0$X@LRRJ}6TWj+5f2HRkb* z{}3_qKXi9de^dsl&x_+niYULwIx7B6No0SLKJd@_Z&8SfzZ(%hWnFBK~(F{BK1pYW|l#=KLv-i1NP~ z;h*vt-9NdJu22ffA0_x)00~LwK98u55wRx^=}UmZC4;a4ms{SBK0*_<>i_@% literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeOutput.log b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeOutput.log new file mode 100644 index 00000000..f7fbfdef --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeOutput.log @@ -0,0 +1,129 @@ +The target system is: Android - 1 - aarch64 +The host system is: Linux - 6.8.0-1061-aws - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang +Build flags: -g;-DANDROID;-fdata-sections;-ffunction-sections;-funwind-tables;-fstack-protector-strong;-no-canonical-prefixes;-D_FORTIFY_SOURCE=2;-Wformat;-Werror=format-security; +Id flags: -c;--target=aarch64-none-linux-android26 + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.o" + +The C compiler identification is Clang, found in "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o" + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp + +Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_40f65 && [1/2] Building C object CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: aarch64-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + (in-process) + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple aarch64-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c +clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include" +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include" +#include "..." search starts here: +#include <...> search starts here: + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include +End of search list. +[2/2] Linking C executable cmTC_40f65 +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: aarch64-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_40f65 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtend_android.o + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + end of search list found + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + implicit include dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_40f65 && [1/2] Building C object CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: aarch64-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + ignore line: [ (in-process)] + ignore line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple aarch64-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +neon -target-feature +v8a -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c] + ignore line: [clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include"] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/aarch64-linux-android] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + ignore line: [End of search list.] + ignore line: [[2/2] Linking C executable cmTC_40f65] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: aarch64-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + link line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=4096 --hash-style=gnu --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o cmTC_40f65 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtend_android.o] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld] ==> ignore + arg [--sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot] ==> ignore + arg [-EL] ==> ignore + arg [--fix-cortex-a53-843419] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-zmax-page-size=4096] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [aarch64linux] ==> ignore + arg [-pie] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/system/bin/linker64] ==> ignore + arg [-o] ==> ignore + arg [cmTC_40f65] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtbegin_dynamic.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtbegin_dynamic.o] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + arg [--build-id=sha1] ==> ignore + arg [--no-rosegment] ==> ignore + arg [--no-undefined-version] ==> ignore + arg [--fatal-warnings] ==> ignore + arg [--no-undefined] ==> ignore + arg [CMakeFiles/cmTC_40f65.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [-lc] ==> lib [c] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtend_android.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtend_android.o] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-aarch64-android.a] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit libs: [-l:libunwind.a;dl;c;-l:libunwind.a;dl] + implicit objs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtbegin_dynamic.o;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/crtend_android.o] + implicit dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/aarch64;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit fwks: [] + + diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..081b5a51 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/logseq_chat_jni.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/edit_cache.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o new file mode 100644 index 0000000000000000000000000000000000000000..de22f504f16cbfad2876daa29c4952bfe8fc75ed GIT binary patch literal 59352 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 C;$X4> literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.ninja_log b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.ninja_log new file mode 100644 index 00000000..12126564 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/.ninja_log @@ -0,0 +1,3 @@ +# ninja log v5 +0 28 1791280904488695663 CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o 3293958b397491db +28 42 1791280904502695546 /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so 7bd06d0df84c57ed diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeCache.txt b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeCache.txt new file mode 100644 index 00000000..3df5ab6a --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeCache.txt @@ -0,0 +1,365 @@ +# This is the CMakeCache file. +# For build in directory: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a +# It was generated by CMake: /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//No help, variable specified on the command line. +ANDROID_ABI:UNINITIALIZED=armeabi-v7a + +//No help, variable specified on the command line. +ANDROID_NDK:UNINITIALIZED=/home/ubuntu/android-sdk/ndk/27.0.12077973 + +//No help, variable specified on the command line. +ANDROID_PLATFORM:UNINITIALIZED=android-26 + +//Path to a program. +CMAKE_ADDR2LINE:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-addr2line + +//No help, variable specified on the command line. +CMAKE_ANDROID_ARCH_ABI:UNINITIALIZED=armeabi-v7a + +//No help, variable specified on the command line. +CMAKE_ANDROID_NDK:UNINITIALIZED=/home/ubuntu/android-sdk/ndk/27.0.12077973 + +//Archiver +CMAKE_AR:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar + +//Flags used by the compiler during all build types. +CMAKE_ASM_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_ASM_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_ASM_FLAGS_RELEASE:STRING= + +//Choose the type of build, options are: None Debug Release RelWithDebInfo +// MinSizeRel ... +CMAKE_BUILD_TYPE:STRING=Debug + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING= + +//Flags used by the compiler during release builds. +CMAKE_CXX_FLAGS_RELEASE:STRING= + +//LLVM archiver +CMAKE_C_COMPILER_AR:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar + +//Generate index for LLVM archive +CMAKE_C_COMPILER_RANLIB:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING= + +//Flags used by the C compiler during MINSIZEREL builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds. +CMAKE_C_FLAGS_RELEASE:STRING= + +//Flags used by the C compiler during RELWITHDEBINFO builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Libraries linked by default with all C applications. +CMAKE_C_STANDARD_LIBRARIES:STRING=-latomic -lm + +//Path to a program. +CMAKE_DLLTOOL:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-dlltool + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING= + +//Flags used by the linker during DEBUG builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during MINSIZEREL builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during RELEASE builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during RELWITHDEBINFO builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//No help, variable specified on the command line. +CMAKE_EXPORT_COMPILE_COMMANDS:UNINITIALIZED=ON + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//No help, variable specified on the command line. +CMAKE_LIBRARY_OUTPUT_DIRECTORY:UNINITIALIZED=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a + +//Path to a program. +CMAKE_LINKER:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld + +//No help, variable specified on the command line. +CMAKE_MAKE_PROGRAM:UNINITIALIZED=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of modules during +// DEBUG builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of modules during +// MINSIZEREL builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of modules during +// RELEASE builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of modules during +// RELWITHDEBINFO builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump + +//Value Computed by CMake +CMAKE_PROJECT_DESCRIPTION:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_HOMEPAGE_URL:STATIC= + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=logseq_chat_jni + +//Ranlib +CMAKE_RANLIB:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib + +//Path to a program. +CMAKE_READELF:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf + +//No help, variable specified on the command line. +CMAKE_RUNTIME_OUTPUT_DIRECTORY:UNINITIALIZED=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of shared libraries +// during DEBUG builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of shared libraries +// during MINSIZEREL builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELEASE builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of shared libraries +// during RELWITHDEBINFO builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries +// during all build types. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during the creation of static libraries +// during DEBUG builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during the creation of static libraries +// during MINSIZEREL builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELEASE builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during the creation of static libraries +// during RELWITHDEBINFO builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Strip +CMAKE_STRIP:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip + +//No help, variable specified on the command line. +CMAKE_SYSTEM_NAME:UNINITIALIZED=Android + +//No help, variable specified on the command line. +CMAKE_SYSTEM_VERSION:UNINITIALIZED=26 + +//The CMake toolchain file +CMAKE_TOOLCHAIN_FILE:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Path to a library. +log-lib:FILEPATH=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/liblog.so + +//Value Computed by CMake +logseq_chat_jni_BINARY_DIR:STATIC=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a + +//Value Computed by CMake +logseq_chat_jni_IS_TOP_LEVEL:STATIC=ON + +//Value Computed by CMake +logseq_chat_jni_SOURCE_DIR:STATIC=/home/ubuntu/repos/chat/android/app/src/main/cpp + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_ADDR2LINE +CMAKE_ADDR2LINE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=22 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest +//ADVANCED property for variable: CMAKE_C_COMPILER_AR +CMAKE_C_COMPILER_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER_RANLIB +CMAKE_C_COMPILER_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES +CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_DLLTOOL +CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Name of external makefile project generator. +CMAKE_EXTRA_GENERATOR:INTERNAL= +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Ninja +//Generator instance identifier. +CMAKE_GENERATOR_INSTANCE:INTERNAL= +//Name of generator platform. +CMAKE_GENERATOR_PLATFORM:INTERNAL= +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Source directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/ubuntu/repos/chat/android/app/src/main/cpp +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//Platform information initialized +CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_READELF +CMAKE_READELF-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/usr/bin/uname +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake new file mode 100644 index 00000000..9c82f338 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake @@ -0,0 +1,72 @@ +set(CMAKE_C_COMPILER "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "Clang") +set(CMAKE_C_COMPILER_VERSION "18.0.1") +set(CMAKE_C_COMPILER_VERSION_INTERNAL "") +set(CMAKE_C_COMPILER_WRAPPER "") +set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") +set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") +set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") +set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") +set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") +set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") +set(CMAKE_C17_COMPILE_FEATURES "c_std_17") +set(CMAKE_C23_COMPILE_FEATURES "c_std_23") + +set(CMAKE_C_PLATFORM_ID "Linux") +set(CMAKE_C_SIMULATE_ID "") +set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") +set(CMAKE_C_SIMULATE_VERSION "") + + + + +set(CMAKE_AR "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar") +set(CMAKE_C_COMPILER_AR "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar") +set(CMAKE_RANLIB "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib") +set(CMAKE_C_COMPILER_RANLIB "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib") +set(CMAKE_LINKER "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld") +set(CMAKE_MT "") +set(CMAKE_COMPILER_IS_GNUCC ) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "4") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") +set(CMAKE_C_LIBRARY_ARCHITECTURE "") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "") +endif() + +set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") +if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) + set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") +endif() + + + + + +set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include") +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "-l:libunwind.a;dl;c;-l:libunwind.a;dl") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..cc974d32b45ceb27e7e90d498d061ab6c0804d69 GIT binary patch literal 5912 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 X1Fy{i83alxrZ@RbBlEH}2K@d7RzWH{ literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 00000000..9e3983b4 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-6.8.0-1061-aws") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "6.8.0-1061-aws") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + +include("/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "armv7-a") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 00000000..41b99d77 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..1f3413152b42f94bd309a8d7908ff13d328c6fa0 GIT binary patch literal 4128 zcmdT{TZkJ~82)D_lcbw%_Gax>jZ*7+*_kAp-Az}iyKcMfLN8JksoN4K$s`+_Wa4D9 zMyOYcC@RzoXwe73iikcG@dhd?f`||5gO61~AAAzAq6iB5{gZRDv#}LlJ>i`HdcOZZ zXU_R&a^J4K^NOO7YzmFiibS+0=3DfPPe$nySdX7p=P99`P@hzupc5PSw0F{ydUEzK zJsaIgCob%fM|x!S4V!5|7P?(=+o$F^lj+ePM_B9U)Vo? zV7lPc8kMT;F3wf0diee3eFnk|hi5iuadx<3BfApCbW(+io%=JZM7kGeAcPb#`lsO{dfS(X zJ`?mYP-Kf$Jf-LwE43L6q1_nPkv@TGQ6)UhBof&VaytxN->3~~%?yUfVc3qb?NwFa zu+7IwiwI|6;mwOwBo1q!AoVQ_%GZ#1W3?F!{>*-g+$DY43O%XcVNia7#1CM_cN0Y( zkiKW7ZyXxsS4jMzR(!WmbI> zCY*Z0ok*v%si`Xy1-=0ZaV`^lB8^mHbjkA?&1uubfoE`|>^SAB-E>-R!8UMvOwVzu zg(a&}H>=g<+E~MN?yw79qL@u4$F0o7WHFVo#*217o1DlLik3Bz-d-x@OUZO`dpqz;EJP}b3U zZG*B=*`!{kY{R*xLG-`SLMScDv3UPlp#$+7-=Q1ggY+V3$gh-mGyM@?OCUTST{+hQ z^C#;n6YY_(qDT7P)#IkVC0x?uh8{EYc(~jnZRpxIhnHZ78=S*hyrhqHO+3x)N_}wD z!ZAbp_U;m@bKsrn$H#DhlN2pPKmR3prW$?^1?;SGA$wgXzm^1~NS9|uBUI@?)9Av0 z#P&@+@)r6L8V{0H!*&}kk2 zA%86z-bihzwf;_3*YJ?2&Gb||Y zgt~_O9bo;%ECV;m6u7g(kG~z*en8N}Op)(VA#>g;@_dph=J9^9|0$*j`nu46Ec9P8 z#rnPx`k#cJ_f^F@`>>ykvzaMyMww#WV@#3Xl+e!$dW)b%LGKh4p8}*tiMBB1d4iIG zO57^vtbE?Jm&x!@g^0^|%|_WVT)S!%EzdIi;@7QY=O|U@bNxrrGiDF&Gc3<@EBTgZ zH)R4%&+QG@t+gF&KTpmBe$Gl#vIhH3jBU3o#kRi?!>^ydf!7rfSEhHXwo!LH+t|JT zmNBGUINF}>A#N&@0&W~#dw@=ZlKGzx8 z#{CIFWt+XQ_O@96*@N=g@RANU}icOJY2_yzHv58&}xlKXO5 z4_^B`c>ElLc&7q*LjgR_jk|380sEX3K&9=K0MF+2crXu2W5D(j_+Z@E5chZJIG+p9 zA_=>|272uS~#5VKqnj9xO1&$D%+U6P(mSXE@Xsi1pTg)0;u%6 zp$D%DywQN4JQF+M7hLZt2!rtB_3|5Ct~cF-_cZWc4&ceSMi1T_z{3{$c>Mm5cz3{0 U-VKJi4)3Qy5rhBGupj5~H?3_`YXATM literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeOutput.log b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeOutput.log new file mode 100644 index 00000000..09e343dd --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeOutput.log @@ -0,0 +1,131 @@ +The target system is: Android - 1 - armv7-a +The host system is: Linux - 6.8.0-1061-aws - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang +Build flags: -g;-DANDROID;-fdata-sections;-ffunction-sections;-funwind-tables;-fstack-protector-strong;-no-canonical-prefixes;-D_FORTIFY_SOURCE=2;-march=armv7-a;-mthumb;-Wformat;-Werror=format-security; +Id flags: -c;--target=armv7-none-linux-androideabi26 + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.o" + +The C compiler identification is Clang, found in "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o" + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp + +Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_ba0e7 && [1/2] Building C object CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: armv7-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + (in-process) + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple thumbv7-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=1 -target-cpu generic -target-feature +soft-float-abi -target-feature +vfp2 -target-feature +vfp2sp -target-feature +vfp3 -target-feature +vfp3d16 -target-feature +vfp3d16sp -target-feature +vfp3sp -target-feature -fp16 -target-feature -vfp4 -target-feature -vfp4d16 -target-feature -vfp4d16sp -target-feature -vfp4sp -target-feature -fp-armv8 -target-feature -fp-armv8d16 -target-feature -fp-armv8d16sp -target-feature -fp-armv8sp -target-feature -fullfp16 -target-feature +fp64 -target-feature +d32 -target-feature +neon -target-feature -sha2 -target-feature -aes -target-feature -fp16fml -target-abi aapcs-linux -mfloat-abi soft -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c +clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include" +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include" +#include "..." search starts here: +#include <...> search starts here: + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include +End of search list. +[2/2] Linking C executable cmTC_ba0e7 +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: armv7-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -EL -z now -z relro -z max-page-size=4096 -X --hash-style=gnu --eh-frame-hdr -m armelf_linux_eabi -pie -dynamic-linker /system/bin/linker -o cmTC_ba0e7 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/../lib -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtend_android.o + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + end of search list found + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + implicit include dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_ba0e7 && [1/2] Building C object CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: armv7-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + ignore line: [ (in-process)] + ignore line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple thumbv7-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=1 -target-cpu generic -target-feature +soft-float-abi -target-feature +vfp2 -target-feature +vfp2sp -target-feature +vfp3 -target-feature +vfp3d16 -target-feature +vfp3d16sp -target-feature +vfp3sp -target-feature -fp16 -target-feature -vfp4 -target-feature -vfp4d16 -target-feature -vfp4d16sp -target-feature -vfp4sp -target-feature -fp-armv8 -target-feature -fp-armv8d16 -target-feature -fp-armv8d16sp -target-feature -fp-armv8sp -target-feature -fullfp16 -target-feature +fp64 -target-feature +d32 -target-feature +neon -target-feature -sha2 -target-feature -aes -target-feature -fp16fml -target-abi aapcs-linux -mfloat-abi soft -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fno-signed-char -fgnuc-version=4.2.1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c] + ignore line: [clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include"] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/arm-linux-androideabi] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + ignore line: [End of search list.] + ignore line: [[2/2] Linking C executable cmTC_ba0e7] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: armv7-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + link line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -EL -z now -z relro -z max-page-size=4096 -X --hash-style=gnu --eh-frame-hdr -m armelf_linux_eabi -pie -dynamic-linker /system/bin/linker -o cmTC_ba0e7 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/../lib -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtend_android.o] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld] ==> ignore + arg [--sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot] ==> ignore + arg [-EL] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [-zmax-page-size=4096] ==> ignore + arg [-X] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [armelf_linux_eabi] ==> ignore + arg [-pie] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/system/bin/linker] ==> ignore + arg [-o] ==> ignore + arg [cmTC_ba0e7] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtbegin_dynamic.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtbegin_dynamic.o] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/../lib] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/../lib] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + arg [--build-id=sha1] ==> ignore + arg [--no-rosegment] ==> ignore + arg [--no-undefined-version] ==> ignore + arg [--fatal-warnings] ==> ignore + arg [--no-undefined] ==> ignore + arg [CMakeFiles/cmTC_ba0e7.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [-lc] ==> lib [c] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtend_android.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtend_android.o] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-arm-android.a] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/../lib] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit libs: [-l:libunwind.a;dl;c;-l:libunwind.a;dl] + implicit objs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtbegin_dynamic.o;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/crtend_android.o] + implicit dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/arm;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit fwks: [] + + diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..01453fd4 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/logseq_chat_jni.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/edit_cache.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o new file mode 100644 index 0000000000000000000000000000000000000000..f2961fc6352a0af7cb4022211b1fcf911fa69f28 GIT binary patch literal 47468 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 N{G^OaL@y8c{{TlyOvC^H literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/rules.ninja new file mode 100644 index 00000000..8a840d0a --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/CMakeFiles/rules.ninja @@ -0,0 +1,64 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: logseq_chat_jni +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# Rule for compiling C files. + +rule C_COMPILER__logseq_chat_jni_Debug + depfile = $DEP_FILE + deps = gcc + command = /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in + description = Building C object $out + + +############################################# +# Rule for linking C shared library. + +rule C_SHARED_LIBRARY_LINKER__logseq_chat_jni_Debug + command = $PRE_LINK && /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC $LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS $LINK_FLAGS -shared $SONAME_FLAG$SONAME -o $TARGET_FILE $in $LINK_PATH $LINK_LIBRARIES && $POST_BUILD + description = Linking C shared library $TARGET_FILE + restat = $RESTAT + + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/home/ubuntu/repos/chat/android/app/src/main/cpp -B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja -t targets + description = All primary targets available: + diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/additional_project_files.txt b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/additional_project_files.txt new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json new file mode 100644 index 00000000..ee7f501f --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json @@ -0,0 +1,38 @@ +{ + "buildFiles": [ + "/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": { + "logseq_chat_jni::@6890427a1f51a3e7e1df": { + "toolchain": "toolchain", + "abi": "armeabi-v7a", + "artifactName": "logseq_chat_jni", + "output": "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so", + "runtimeFiles": [] + } + }, + "toolchains": { + "toolchain": { + "cCompilerExecutable": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang.lld", + "cppCompilerExecutable": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++.lld" + } + }, + "cFileExtensions": [ + "c" + ], + "cppFileExtensions": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json new file mode 100644 index 00000000..f8ae5b8a --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json @@ -0,0 +1,27 @@ +{ + "buildFiles": [ + "/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": { + "logseq_chat_jni::@6890427a1f51a3e7e1df": { + "artifactName": "logseq_chat_jni", + "abi": "armeabi-v7a", + "output": "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so", + "runtimeFiles": [] + } + } +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja new file mode 100644 index 00000000..3205c329 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja @@ -0,0 +1,154 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: logseq_chat_jni +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/ +# ============================================================================= +# Object build statements for SHARED_LIBRARY target logseq_chat_jni + + +############################################# +# Order-only phony target for logseq_chat_jni + +build cmake_object_order_depends_target_logseq_chat_jni: phony || CMakeFiles/logseq_chat_jni.dir + +build CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o: C_COMPILER__logseq_chat_jni_Debug /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c || cmake_object_order_depends_target_logseq_chat_jni + DEFINES = -Dlogseq_chat_jni_EXPORTS + DEP_FILE = CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o.d + FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -fno-limit-debug-info -fPIC + OBJECT_DIR = CMakeFiles/logseq_chat_jni.dir + OBJECT_FILE_DIR = CMakeFiles/logseq_chat_jni.dir + TARGET_COMPILE_PDB = CMakeFiles/logseq_chat_jni.dir/ + TARGET_PDB = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.pdb + + +# ============================================================================= +# Link build statements for SHARED_LIBRARY target logseq_chat_jni + + +############################################# +# Link the shared library /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so + +build /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so: C_SHARED_LIBRARY_LINKER__logseq_chat_jni_Debug CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o | /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/liblog.so + LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -fno-limit-debug-info + LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments + LINK_LIBRARIES = /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/26/liblog.so -latomic -lm + OBJECT_DIR = CMakeFiles/logseq_chat_jni.dir + POST_BUILD = : + PRE_LINK = : + SONAME = liblogseq_chat_jni.so + SONAME_FLAG = -Wl,-soname, + TARGET_COMPILE_PDB = CMakeFiles/logseq_chat_jni.dir/ + TARGET_FILE = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so + TARGET_PDB = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.pdb + + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a && /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a && /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/home/ubuntu/repos/chat/android/app/src/main/cpp -B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +build liblogseq_chat_jni.so: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so + +build logseq_chat_jni: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a + +build all: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/armeabi-v7a/liblogseq_chat_jni.so + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake /home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake /home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt new file mode 100644 index 00000000..af439128 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt @@ -0,0 +1 @@ +/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/cmake_install.cmake b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/cmake_install.cmake new file mode 100644 index 00000000..58a293f4 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/ubuntu/repos/chat/android/app/src/main/cpp + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json new file mode 100644 index 00000000..b82eaaea --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json.bin b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json.bin new file mode 100644 index 0000000000000000000000000000000000000000..41ad48db9be5c03a9452eb89e0f8a7249e247520 GIT binary patch literal 920 zcmb`G&u`N(6vxZP*v5}_P&R&?cH=O;dh1XEhaR?Ol`1hhb)W&4$Z?$3G_i~0lo!QRT{sZw6Z`$}d(Y2ykM#}@56&u;rw13(@svCMy3uH?*Q{am-|1>t{ssQ`R`U7> zjNWG{*UClYxe@~%@!o~TX$ z*Mz9NDXlTC``=5d10%~TigGh9<&PK}aq)Mp;`1+;!_lWJ7}vT?~~XOua}Q(3s(y9gm`;NA!LhP+Q{ z>8Q3tCm&)Wy_~pEoEUH4gXBJNlU9z%8P=! zQqY_$Lj^wUR1k#xj_)dVe%I^^dM@3d1}v>63(4Zr!s_ZhtIO0|tD&O|EbCEDi&Cyv zN_(o6sm8tWTA%e-sGGRbT2CuiQe}j$Qb|)i5GKifgQjmoQ>%3<@k_f$D*Elf+|eq0J^_IcQe+xo1!1d z(kY8Z8-|pVUt-3-@xTk!({dzrk{yNq6R~1Y=YA+XOXWxj$>4+4KA19SPKliS+(k|> zLwd8kgrxig4^jIc z(}9EteAkV>sWh4qefVuRHIVZ$<5~?(NWwSWc(8+klit>?K)!~DXwUty%^>(+K{IOK z^Rj*jdZ_`EayX(B#@{$>|>Km>#> zCZPt8bQXiDgHNH~N)OE21@QnviPm%PlbE_(Yb$uI`*BR&>F&!Fn(ZU#j@ziUd2y~U zKJ-v649yQ?o;k0BUB~(Z=ti6A;eKP2?ERQ$MeM1c6k(4&96!G^WkTMA_T#Z?OZC_K zz3I(*`+DK>CJf|VcxmOCGOy0L%X>pL@~Y29Bz<-ZLNPsZ|a zihP98Q^-==*}ZcMo?6*C{wps#jJy@IKBjXJ@1fL~&AR1H=trKz(`y&%;tgm=tIg@z zh0P1R%qyGYlh@huM8h_IQ#Qm zo_%&)*<7c27ZMUj>5#oY7De@xJ!P6bq zK@)_h;NdVKVI-0L4{n`!^vKrU)A0N0;0&+}oC(eXXM=OVxnMUq51bD!02hLbz#ech zxCC4ZE(4c?E5MatFSrU^4Xy##g6qKb;0CY{+z9rA1K=ibGq?rZ3T^|pgFC>T;4aVu R37}vBEP^Gl3|7G1;7s18{y=O$HmTFbR79D&v5)XEyyv;s zCvj3uoBD6B_1^dMyyyG8=lG%I=!nnf6B7KwFDSJKh3KcU!?W~@uvjCy#r0yNXo8A1 ziMvpM7=VuG2Re`?u7^yd4Qdxbmf#`+5>X{8_Ux|iD(HdlP<@4P>y`F}W+4`C^03t_ zwq#czHgoi9ZT`O*Q?79s@uVIapRUNUSeZ-{Hb+pz(BFCThiJp%*V2l_5I0^7U+ z$T_`je7`vQ!biV4eC((HnoJ*8BO~8^?4A!d{dsk4_CW%d&sr&fQf9v-c*{!>{Q2

!&&N|xvNo3GUQNK* z0?NvHk}W`913Co!`{y<56y%GDcNp|@Q0`eYk?mLl=3!zF0x}m$cn$Kqz&`=m&5Nvn zP){D=Zk+tFfmr|G=J3tstc7pdDmWkoheEMHU0Sc0M%XHa?X9ucVDG@DaHgP_vf+cK zUCBe;I~eJS^oF~0j#IAeh(>iUGexqNl`WVRt7>P=NX9Bg9m^_Yayk=Q;b3t~*|zR6 zGfvnT?CI&#`?qd0di(W0!%PqMZ0*k&y1q5GeP$*-(-Skcr(@eRkji|YEIUv0noI(40|13gvxgwe+tLTie_U++5%t z9Rc6F81^rSId}Ml=mX_!*`UfX%;f+WUm)n;g*DHzKcr^K%-vJ3V zhuWaZ0)1JcUCyIi_n*0_z{hpgZ?L0)T)Xr zWZQiEUqTF}?PEBuQ63My-6*yG!j-s9T9n6U&r|B4r)YW&d@#@&1ZiatM731OXG>T| zm7HZeB43)ZwB_ukrSnnp04%h5CKaZU%mRH8BFVZa)<3Kc1gmbhn5{pH8 zqm`U)o1SV5Rnalas4m4B9=3{Qgtg;CsYvGkbsxE--*6wfWI76Y$0?X{MvB<70z+@Z z&k?$vJ;+Z6x2X8!Wc*HTU+QZ~ZR*a6q^1emytkUSO`%}s1LDV+c|06GRo9Y0#kJyV zoLC_)cP1JpBFC_o8)xN=vW)>n1QqT8f4eW(ye9PP;0@KF+O#v+@{Qo8rmSQ)FSA!S z<)n5^Q$FZ#YT2m-(Pac%4UM{h_)CqMDU5S@0#p&In>(u z$;Vg896KJ;yaTLb=8j-fn08r2N|s|rWb(@!CiaS_%a*EOmL>xPjpWl@zIE?ubzX6vHceq`fnR@2jI+dK#lSK{d*`3l?SsqsiP zMFd@Q^fYJ=CXe%|$k=j02h+VDj!1Xr*c~jkmO$AXc5`|1BvsvFb(yY~`^Nr9-H-QlBJP_@ z@nqb)p~I2k#$JFAaR{;mIW99$aBN_9-xYjYgu%-=q-=u)q#tAOeLICelJ47Iv8&Oe*8air>qn@#vr^2l=0mE8~;PSZ^KWHOFY6t~L-gV*KZ?BEHK;`& z2Dzz0Az2lSTw^FEcH&RIbI@^L%k|1R=06o2V+kAER<0`>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..2792ac3046e2211bc74b51f66c811f70bb7ef672 GIT binary patch literal 3904 zcmdT{No*Ts6n`CmpB&E=jfXp72%-Bwvm;xnfa7s|pRBa*wX=TRt*a@{gW;`wd zm7R)K<-jU732`VV!~qU$hYC@o3Iq}oNL&B`5)ua_HdTsLB>3L=|DB0x5m%n{|KHpG z_x|;b{a|)_Qc)C=q)?DnC8F=TTb5xD2B?3Hm1zFRkB|PW{lwPW9{wN*I64zMI-{M; z{>i$N*%gMPhrNDYTYo&(6P#H&GPCj@RWlg!gvO)KKI|bcID3Y)V0Pt5cI9Yx<UsV+<})tbvfX*z|)1;IC5vsN^nVyNj3yS(5)j)Z+L7|FwPEFZe~}as7e8$V&~ZK8j&8r-3Vcd z=)GHVA-&^CM4t$J1&G;V70)Ot-vocj3T!5Wh?X)_yL{r z2P8g#Ro@FJaKQO9dV$6hKX22$x{dNe(pxi)c4y=xN!f zUN&yF^3Ad_GBQ#~Ee^THa%RNv!cF2;H;f@Yoz_!><)P7JCSzud)f^Lqcn;-qAXL;x_|FcF=6}ty7 zmrSQz;O+o9*4@n|2iN+4dZ@UL=klEdDfjIr<)EhY#X_OOxUBuqabw~)K;v=kP+5q7ve0tm)S>R{W%!;H4n4aZF7;_b^xI#4TM*w(KLttk zi?H@|$a3de>L6{VkAw&BS1(3zb(C}tn8$^{1-OU8^u-#vi%zeRqx6Q5)1JRZd)C<3 z(ZCvcJ;fn+<6F!6t}deM8BxV{GUAI;VvG?vjO&OFG4ddgB9{Mei0>FFm^?y|g6-)Q zcpf8+7YO+xMjUmL5plv&7(PYC_zj9AyV zLjQ}<|H+8;bz}cIP9G!YJHUwb@;8j|52Po!iMW~hHuxvRxEE`oELuf z>Lg@s^qhFQx>wCQ^0$koUb9_G-?4Lk5Hl(4@673yQ(wNyQq5}lSc|!mV^*y*RRA5c zcg;NMjeDz%xgFE9+sCJKvy+p1vU9n)@$J*uTzlGZPU$J^^?#%hoE46`O)lRn=p;#Y zJrvCIU1n~NGJ707YGdVc(d{{~LyM)d#y literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeOutput.log b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeOutput.log new file mode 100644 index 00000000..ef8b754b --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeOutput.log @@ -0,0 +1,126 @@ +The target system is: Android - 1 - i686 +The host system is: Linux - 6.8.0-1061-aws - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang +Build flags: -g;-DANDROID;-fdata-sections;-ffunction-sections;-funwind-tables;-fstack-protector-strong;-no-canonical-prefixes;-D_FORTIFY_SOURCE=2;-Wformat;-Werror=format-security; +Id flags: -c;--target=i686-none-linux-android26 + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "CMakeCCompilerId.o" + +The C compiler identification is Clang, found in "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o" + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp + +Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_56afe && [1/2] Building C object CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: i686-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + (in-process) + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple i686-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu i686 -target-feature +ssse3 -tune-cpu generic -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fgnuc-version=4.2.1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c +clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include" +ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include" +#include "..." search starts here: +#include <...> search starts here: + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include +End of search list. +[2/2] Linking C executable cmTC_56afe +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: i686-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -z now -z relro --hash-style=gnu --eh-frame-hdr -m elf_i386 -pie -dynamic-linker /system/bin/linker -o cmTC_56afe /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtend_android.o + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + end of search list found + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + implicit include dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_56afe && [1/2] Building C object CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: i686-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + ignore line: [ (in-process)] + ignore line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple i686-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu i686 -target-feature +ssse3 -tune-cpu generic -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fgnuc-version=4.2.1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c] + ignore line: [clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include"] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/i686-linux-android] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + ignore line: [End of search list.] + ignore line: [[2/2] Linking C executable cmTC_56afe] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: i686-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + link line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -z now -z relro --hash-style=gnu --eh-frame-hdr -m elf_i386 -pie -dynamic-linker /system/bin/linker -o cmTC_56afe /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtend_android.o] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld] ==> ignore + arg [--sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_i386] ==> ignore + arg [-pie] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/system/bin/linker] ==> ignore + arg [-o] ==> ignore + arg [cmTC_56afe] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtbegin_dynamic.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtbegin_dynamic.o] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + arg [--build-id=sha1] ==> ignore + arg [--no-rosegment] ==> ignore + arg [--no-undefined-version] ==> ignore + arg [--fatal-warnings] ==> ignore + arg [--no-undefined] ==> ignore + arg [CMakeFiles/cmTC_56afe.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [-lc] ==> lib [c] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtend_android.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtend_android.o] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-i686-android.a] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit libs: [-l:libunwind.a;dl;c;-l:libunwind.a;dl] + implicit objs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtbegin_dynamic.o;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/crtend_android.o] + implicit dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/i386;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit fwks: [] + + diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..48fa49ec --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/logseq_chat_jni.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/edit_cache.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o new file mode 100644 index 0000000000000000000000000000000000000000..dbfd8fd3b51d7f317795d6c5afeecb0fc79bb5af GIT binary patch literal 43544 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 UR&3-W^9CVIq>-PAY?lH2-zAiqZU6uP literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/rules.ninja b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/rules.ninja new file mode 100644 index 00000000..0c30f536 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/CMakeFiles/rules.ninja @@ -0,0 +1,64 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the rules used to get the outputs files +# built from the input files. +# It is included in the main 'build.ninja'. + +# ============================================================================= +# Project: logseq_chat_jni +# Configurations: Debug +# ============================================================================= +# ============================================================================= + +############################################# +# Rule for compiling C files. + +rule C_COMPILER__logseq_chat_jni_Debug + depfile = $DEP_FILE + deps = gcc + command = /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=i686-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot $DEFINES $INCLUDES $FLAGS -MD -MT $out -MF $DEP_FILE -o $out -c $in + description = Building C object $out + + +############################################# +# Rule for linking C shared library. + +rule C_SHARED_LIBRARY_LINKER__logseq_chat_jni_Debug + command = $PRE_LINK && /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=i686-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC $LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS $LINK_FLAGS -shared $SONAME_FLAG$SONAME -o $TARGET_FILE $in $LINK_PATH $LINK_LIBRARIES && $POST_BUILD + description = Linking C shared library $TARGET_FILE + restat = $RESTAT + + +############################################# +# Rule for running custom commands. + +rule CUSTOM_COMMAND + command = $COMMAND + description = $DESC + + +############################################# +# Rule for re-running cmake. + +rule RERUN_CMAKE + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/home/ubuntu/repos/chat/android/app/src/main/cpp -B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 + description = Re-running CMake... + generator = 1 + + +############################################# +# Rule for cleaning all built files. + +rule CLEAN + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja $FILE_ARG -t clean $TARGETS + description = Cleaning all built files... + + +############################################# +# Rule for printing all primary targets available. + +rule HELP + command = /home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja -t targets + description = All primary targets available: + diff --git a/android/app/.cxx/Debug/666c1h3t/x86/additional_project_files.txt b/android/app/.cxx/Debug/666c1h3t/x86/additional_project_files.txt new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json b/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json new file mode 100644 index 00000000..4db74efc --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json @@ -0,0 +1,38 @@ +{ + "buildFiles": [ + "/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": { + "logseq_chat_jni::@6890427a1f51a3e7e1df": { + "toolchain": "toolchain", + "abi": "x86", + "artifactName": "logseq_chat_jni", + "output": "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so", + "runtimeFiles": [] + } + }, + "toolchains": { + "toolchain": { + "cCompilerExecutable": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang.lld", + "cppCompilerExecutable": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++.lld" + } + }, + "cFileExtensions": [ + "c" + ], + "cppFileExtensions": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json b/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json new file mode 100644 index 00000000..403e5ddf --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json @@ -0,0 +1,27 @@ +{ + "buildFiles": [ + "/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt" + ], + "cleanCommandsComponents": [ + [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "clean" + ] + ], + "buildTargetsCommandComponents": [ + "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja", + "-C", + "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "{LIST_OF_TARGETS_TO_BUILD}" + ], + "libraries": { + "logseq_chat_jni::@6890427a1f51a3e7e1df": { + "artifactName": "logseq_chat_jni", + "abi": "x86", + "output": "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so", + "runtimeFiles": [] + } + } +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/build.ninja b/android/app/.cxx/Debug/666c1h3t/x86/build.ninja new file mode 100644 index 00000000..c996e438 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/build.ninja @@ -0,0 +1,154 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 3.22 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: logseq_chat_jni +# Configurations: Debug +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + + +############################################# +# Set configuration variable for custom commands. + +CONFIGURATION = Debug +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/ +# ============================================================================= +# Object build statements for SHARED_LIBRARY target logseq_chat_jni + + +############################################# +# Order-only phony target for logseq_chat_jni + +build cmake_object_order_depends_target_logseq_chat_jni: phony || CMakeFiles/logseq_chat_jni.dir + +build CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o: C_COMPILER__logseq_chat_jni_Debug /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c || cmake_object_order_depends_target_logseq_chat_jni + DEFINES = -Dlogseq_chat_jni_EXPORTS + DEP_FILE = CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o.d + FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC + OBJECT_DIR = CMakeFiles/logseq_chat_jni.dir + OBJECT_FILE_DIR = CMakeFiles/logseq_chat_jni.dir + TARGET_COMPILE_PDB = CMakeFiles/logseq_chat_jni.dir/ + TARGET_PDB = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.pdb + + +# ============================================================================= +# Link build statements for SHARED_LIBRARY target logseq_chat_jni + + +############################################# +# Link the shared library /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so + +build /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so: C_SHARED_LIBRARY_LINKER__logseq_chat_jni_Debug CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o | /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/liblog.so + LANGUAGE_COMPILE_FLAGS = -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info + LINK_FLAGS = -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments + LINK_LIBRARIES = /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/26/liblog.so -latomic -lm + OBJECT_DIR = CMakeFiles/logseq_chat_jni.dir + POST_BUILD = : + PRE_LINK = : + SONAME = liblogseq_chat_jni.so + SONAME_FLAG = -Wl,-soname, + TARGET_COMPILE_PDB = CMakeFiles/logseq_chat_jni.dir/ + TARGET_FILE = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so + TARGET_PDB = /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.pdb + + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 && /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 && /home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake --regenerate-during-build -S/home/ubuntu/repos/chat/android/app/src/main/cpp -B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +build liblogseq_chat_jni.so: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so + +build logseq_chat_jni: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 + +build all: phony /home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86/liblogseq_chat_jni.so + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja: RERUN_CMAKE | /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake /home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake /home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake /home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt CMakeCache.txt CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt b/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt new file mode 100644 index 00000000..af439128 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt @@ -0,0 +1 @@ +/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/cmake_install.cmake b/android/app/.cxx/Debug/666c1h3t/x86/cmake_install.cmake new file mode 100644 index 00000000..aea93d0d --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/cmake_install.cmake @@ -0,0 +1,54 @@ +# Install script for directory: /home/ubuntu/repos/chat/android/app/src/main/cpp + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "/usr/local") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Install shared libraries without execute permission? +if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + set(CMAKE_INSTALL_SO_NO_EXE "1") +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "TRUE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump") +endif() + +if(CMAKE_INSTALL_COMPONENT) + set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +else() + set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +endif() + +string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT + "${CMAKE_INSTALL_MANIFEST_FILES}") +file(WRITE "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/${CMAKE_INSTALL_MANIFEST}" + "${CMAKE_INSTALL_MANIFEST_CONTENT}") diff --git a/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json b/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json new file mode 100644 index 00000000..daf0941d --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=i686-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin b/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin new file mode 100644 index 0000000000000000000000000000000000000000..17231f02cccfedde1a418a9833be3d20380fc1b4 GIT binary patch literal 870 zcmb`GO>Yx15Qalbq2(*k@O`R!t!CY()ussL&}JJchmtA<6}YUtUT!}2cs$!oL*?0!Ub`VVrG(6S*3l&xX!InIk|kwG-!9C{pg^*-|4*T95QcADJEQL z$I9}@jLoggkfLX$(p63Mah%3SEK{0^lIt-}*d_AZj-~Ia_&6qQw4|l+>ZEoItBlB9 zJ8O*Z{`YKFfpN+kN=h?!@_ULq`1G4r>DlLt;ppQfHrFVmyG6;#hh#JyBoLZZgtC*9 z!YiX4R4posN-xAe)v&DePo;BQHY;VYd`*S(Tuf>*w~=rV$j3l{a@v^a&8<8#rXa1jL+vR5_Qdz;LqYX76+3<&+xQxZ{DaM zRHy$E(OJP}Xd5OF{zi-_v~9b0&Zn}kP`g|Exw5x(A_~_Et=t5m(Zi2%7i@rg;6B&{ STi^kB2p)mQ;0XwRPk#Z?=j$T? literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin new file mode 100644 index 00000000..7f14d5ff --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin @@ -0,0 +1,28 @@ +C/C++ Structured Log\ +Z +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/additional_project_files.txtC +A +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  è¹»…‘4  Šó¥…‘4Y +W +U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json  è¹»…‘4¤ ‹ó¥…‘4^ +\ +Z/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json  è¹»…‘4” Œó¥…‘4K +I +G/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja  è¹»…‘4ϳ …ó¥…‘4O +M +K/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja.txt  è¹»…‘4T +R +P/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt  è¹»…‘4 ? �ó¥…‘4U +S +Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json  è¹»…‘4ï …ó¥…‘4Y +W +U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin  è¹»…‘4 æ …ó¥…‘4_ +] +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt  è¹»…‘4 +¬ �ó¥…‘4R +P +N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json  è¹»…‘4  ( �ó¥…‘4W +U +S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt  è¹»…‘4  R �ó¥…‘4C +A +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  è¹»…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt b/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt new file mode 100644 index 00000000..2afcceb4 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt @@ -0,0 +1,18 @@ + -H/home/ubuntu/repos/chat/android/app/src/main/cpp +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=x86 +-DCMAKE_ANDROID_ARCH_ABI=x86 +-DANDROID_NDK=/home/ubuntu/android-sdk/ndk/27.0.12077973 +-DCMAKE_ANDROID_NDK=/home/ubuntu/android-sdk/ndk/27.0.12077973 +-DCMAKE_TOOLCHAIN_FILE=/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86 +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86 +-DCMAKE_BUILD_TYPE=Debug +-B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86 +-GNinja + Build command args: [] + Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json b/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json new file mode 100644 index 00000000..e799de86 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "packages": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt b/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt new file mode 100644 index 00000000..01c03e5b --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt @@ -0,0 +1 @@ +/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cache-v2 b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cache-v2 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/cmakeFiles-v1 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/query/client-agp/codemodel-v2 new file mode 100644 index 00000000..e69de29b diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cache-v2-e9617ac8c3543573816a.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cache-v2-e9617ac8c3543573816a.json new file mode 100644 index 00000000..b3609ce2 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cache-v2-e9617ac8c3543573816a.json @@ -0,0 +1,1219 @@ +{ + "entries" : + [ + { + "name" : "ANDROID_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86_64" + }, + { + "name" : "ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973" + }, + { + "name" : "ANDROID_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "android-26" + }, + { + "name" : "CMAKE_ADDR2LINE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-addr2line" + }, + { + "name" : "CMAKE_ANDROID_ARCH_ABI", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "x86_64" + }, + { + "name" : "CMAKE_ANDROID_NDK", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973" + }, + { + "name" : "CMAKE_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Archiver" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_ASM_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_ASM_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_BUILD_TYPE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel ..." + } + ], + "type" : "STRING", + "value" : "Debug" + }, + { + "name" : "CMAKE_CACHEFILE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "This is the directory where this CMakeCache.txt was created" + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64" + }, + { + "name" : "CMAKE_CACHE_MAJOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Major version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "3" + }, + { + "name" : "CMAKE_CACHE_MINOR_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Minor version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "22" + }, + { + "name" : "CMAKE_CACHE_PATCH_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Patch version of cmake used to create the current loaded cache" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake" + }, + { + "name" : "CMAKE_CPACK_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to cpack program executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack" + }, + { + "name" : "CMAKE_CTEST_COMMAND", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to ctest program executable." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest" + }, + { + "name" : "CMAKE_CXX_FLAGS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_CXX_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_COMPILER_AR", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "LLVM archiver" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" + }, + { + "name" : "CMAKE_C_COMPILER_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Generate index for LLVM archive" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_C_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during debug builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "-Os -DNDEBUG" + }, + { + "name" : "CMAKE_C_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the compiler during release builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_C_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the C compiler during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "-O2 -g -DNDEBUG" + }, + { + "name" : "CMAKE_C_STANDARD_LIBRARIES", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Libraries linked by default with all C applications." + } + ], + "type" : "STRING", + "value" : "-latomic -lm" + }, + { + "name" : "CMAKE_DLLTOOL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-dlltool" + }, + { + "name" : "CMAKE_EXECUTABLE_FORMAT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Executable file format" + } + ], + "type" : "INTERNAL", + "value" : "ELF" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_EXPORT_COMPILE_COMMANDS", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "ON" + }, + { + "name" : "CMAKE_EXTRA_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of external makefile project generator." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator." + } + ], + "type" : "INTERNAL", + "value" : "Ninja" + }, + { + "name" : "CMAKE_GENERATOR_INSTANCE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Generator instance identifier." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_PLATFORM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator platform." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_GENERATOR_TOOLSET", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Name of generator toolset." + } + ], + "type" : "INTERNAL", + "value" : "" + }, + { + "name" : "CMAKE_HOME_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Source directory with the top level CMakeLists.txt file for this project" + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + { + "name" : "CMAKE_INSTALL_PREFIX", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install path prefix, prepended onto install directories." + } + ], + "type" : "PATH", + "value" : "/usr/local" + }, + { + "name" : "CMAKE_INSTALL_SO_NO_EXE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Install .so files without execute permission." + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_LIBRARY_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64" + }, + { + "name" : "CMAKE_LINKER", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" + }, + { + "name" : "CMAKE_MAKE_PROGRAM", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of modules during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_NM", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-nm" + }, + { + "name" : "CMAKE_NUMBER_OF_MAKEFILES", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "number of local generators" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_OBJCOPY", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objcopy" + }, + { + "name" : "CMAKE_OBJDUMP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-objdump" + }, + { + "name" : "CMAKE_PLATFORM_INFO_INITIALIZED", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Platform information initialized" + } + ], + "type" : "INTERNAL", + "value" : "1" + }, + { + "name" : "CMAKE_PROJECT_DESCRIPTION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_HOMEPAGE_URL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "" + }, + { + "name" : "CMAKE_PROJECT_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "logseq_chat_jni" + }, + { + "name" : "CMAKE_RANLIB", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Ranlib" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ranlib" + }, + { + "name" : "CMAKE_READELF", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Path to a program." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf" + }, + { + "name" : "CMAKE_ROOT", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to CMake installation." + } + ], + "type" : "INTERNAL", + "value" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22" + }, + { + "name" : "CMAKE_RUNTIME_OUTPUT_DIRECTORY", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of dll's." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of shared libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_SKIP_INSTALL_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when installing shared libraries, but are added when building." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_SKIP_RPATH", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If set, runtime paths are not added when using shared libraries." + } + ], + "type" : "BOOL", + "value" : "NO" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during all build types." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_DEBUG", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during DEBUG builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during MINSIZEREL builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELEASE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELEASE builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Flags used by the linker during the creation of static libraries during RELWITHDEBINFO builds." + } + ], + "type" : "STRING", + "value" : "" + }, + { + "name" : "CMAKE_STRIP", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "Strip" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip" + }, + { + "name" : "CMAKE_SYSTEM_NAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "Android" + }, + { + "name" : "CMAKE_SYSTEM_VERSION", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "No help, variable specified on the command line." + } + ], + "type" : "UNINITIALIZED", + "value" : "26" + }, + { + "name" : "CMAKE_TOOLCHAIN_FILE", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "The CMake toolchain file" + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "name" : "CMAKE_UNAME", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "uname command" + } + ], + "type" : "INTERNAL", + "value" : "/usr/bin/uname" + }, + { + "name" : "CMAKE_VERBOSE_MAKEFILE", + "properties" : + [ + { + "name" : "ADVANCED", + "value" : "1" + }, + { + "name" : "HELPSTRING", + "value" : "If this value is on, makefiles will be generated without the .SILENT directive, and all commands will be echoed to the console during the make. This is useful for debugging only. With Visual Studio IDE projects all commands are done without /nologo." + } + ], + "type" : "BOOL", + "value" : "FALSE" + }, + { + "name" : "log-lib", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Path to a library." + } + ], + "type" : "FILEPATH", + "value" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/liblog.so" + }, + { + "name" : "logseq_chat_jni_BINARY_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64" + }, + { + "name" : "logseq_chat_jni_IS_TOP_LEVEL", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "ON" + }, + { + "name" : "logseq_chat_jni_SOURCE_DIR", + "properties" : + [ + { + "name" : "HELPSTRING", + "value" : "Value Computed by CMake" + } + ], + "type" : "STATIC", + "value" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + } + ], + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-136cb755cd94dfa0d0a9.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-136cb755cd94dfa0d0a9.json new file mode 100644 index 00000000..bb851bac --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/cmakeFiles-v1-136cb755cd94dfa0d0a9.json @@ -0,0 +1,475 @@ +{ + "inputs" : + [ + { + "path" : "CMakeLists.txt" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android-legacy.toolchain.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/abis.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/platforms.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Determine.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystem.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInitialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Initialize.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Initialize.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Determine-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android/Determine-Compiler.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Determine-Compiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerId.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCompilerIdDetection.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ADSP-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMCC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/ARMClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/AppleClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Borland-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Bruce-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-DetermineCompilerInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Compaq-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Cray-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Embarcadero-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Fujitsu-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GHS-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/HP-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IAR-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Intel-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/MSVC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVHPC-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/NVIDIA-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PGI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/PathScale-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SCO-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SDCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/SunPro-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TI-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Watcom-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XL-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/XLClang-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/zOS-C-DetermineCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeFindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-FindBinUtils.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeSystemSpecificInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeGenericSystem.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeInitializeConfigs.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Linux.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/UnixPaths.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeLanguageInformation.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/Clang.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/GNU.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Compiler/CMakeCommonCompilerMacros.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang-C.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Platform/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/hooks/pre/Android-Clang.cmake" + }, + { + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/flags.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCommonLanguageInclude.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCCompiler.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompilerABI.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitIncludeInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseImplicitLinkInfo.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeParseLibraryArchitecture.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeTestCompilerCommon.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeDetermineCompileFeatures.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/Internal/FeatureTesting.cmake" + }, + { + "isCMake" : true, + "isExternal" : true, + "path" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompiler.cmake.in" + }, + { + "isGenerated" : true, + "path" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeCCompiler.cmake" + } + ], + "kind" : "cmakeFiles", + "paths" : + { + "build" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64", + "source" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + "version" : + { + "major" : 1, + "minor" : 0 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/codemodel-v2-2933ffa2bb6a77d0cf2c.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/codemodel-v2-2933ffa2bb6a77d0cf2c.json new file mode 100644 index 00000000..d027af1e --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/codemodel-v2-2933ffa2bb6a77d0cf2c.json @@ -0,0 +1,60 @@ +{ + "configurations" : + [ + { + "directories" : + [ + { + "build" : ".", + "jsonFile" : "directory-.-Debug-f5ebdc15457944623624.json", + "minimumCMakeVersion" : + { + "string" : "3.6.0" + }, + "projectIndex" : 0, + "source" : ".", + "targetIndexes" : + [ + 0 + ] + } + ], + "name" : "Debug", + "projects" : + [ + { + "directoryIndexes" : + [ + 0 + ], + "name" : "logseq_chat_jni", + "targetIndexes" : + [ + 0 + ] + } + ], + "targets" : + [ + { + "directoryIndex" : 0, + "id" : "logseq_chat_jni::@6890427a1f51a3e7e1df", + "jsonFile" : "target-logseq_chat_jni-Debug-87618656bb91b5a76ec1.json", + "name" : "logseq_chat_jni", + "projectIndex" : 0 + } + ] + } + ], + "kind" : "codemodel", + "paths" : + { + "build" : "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64", + "source" : "/home/ubuntu/repos/chat/android/app/src/main/cpp" + }, + "version" : + { + "major" : 2, + "minor" : 3 + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json new file mode 100644 index 00000000..3a67af9c --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/directory-.-Debug-f5ebdc15457944623624.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : ".", + "source" : "." + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0715.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0715.json new file mode 100644 index 00000000..b8423a34 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/index-2026-10-06T10-01-44-0715.json @@ -0,0 +1,92 @@ +{ + "cmake" : + { + "generator" : + { + "multiConfig" : false, + "name" : "Ninja" + }, + "paths" : + { + "cmake" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cmake", + "cpack" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/cpack", + "ctest" : "/home/ubuntu/android-sdk/cmake/3.22.1/bin/ctest", + "root" : "/home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22" + }, + "version" : + { + "isDirty" : false, + "major" : 3, + "minor" : 22, + "patch" : 1, + "string" : "3.22.1-g37088a8", + "suffix" : "g37088a8" + } + }, + "objects" : + [ + { + "jsonFile" : "codemodel-v2-2933ffa2bb6a77d0cf2c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + }, + { + "jsonFile" : "cache-v2-e9617ac8c3543573816a.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + { + "jsonFile" : "cmakeFiles-v1-136cb755cd94dfa0d0a9.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + } + ], + "reply" : + { + "client-agp" : + { + "cache-v2" : + { + "jsonFile" : "cache-v2-e9617ac8c3543573816a.json", + "kind" : "cache", + "version" : + { + "major" : 2, + "minor" : 0 + } + }, + "cmakeFiles-v1" : + { + "jsonFile" : "cmakeFiles-v1-136cb755cd94dfa0d0a9.json", + "kind" : "cmakeFiles", + "version" : + { + "major" : 1, + "minor" : 0 + } + }, + "codemodel-v2" : + { + "jsonFile" : "codemodel-v2-2933ffa2bb6a77d0cf2c.json", + "kind" : "codemodel", + "version" : + { + "major" : 2, + "minor" : 3 + } + } + } + } +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-87618656bb91b5a76ec1.json b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-87618656bb91b5a76ec1.json new file mode 100644 index 00000000..11c966d5 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/.cmake/api/v1/reply/target-logseq_chat_jni-Debug-87618656bb91b5a76ec1.json @@ -0,0 +1,117 @@ +{ + "artifacts" : + [ + { + "path" : "/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64/liblogseq_chat_jni.so" + } + ], + "backtrace" : 1, + "backtraceGraph" : + { + "commands" : + [ + "add_library", + "target_link_libraries" + ], + "files" : + [ + "CMakeLists.txt" + ], + "nodes" : + [ + { + "file" : 0 + }, + { + "command" : 0, + "file" : 0, + "line" : 12, + "parent" : 0 + }, + { + "command" : 1, + "file" : 0, + "line" : 16, + "parent" : 0 + } + ] + }, + "compileGroups" : + [ + { + "compileCommandFragments" : + [ + { + "fragment" : "-g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC" + } + ], + "defines" : + [ + { + "define" : "logseq_chat_jni_EXPORTS" + } + ], + "language" : "C", + "sourceIndexes" : + [ + 0 + ], + "sysroot" : + { + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot" + } + } + ], + "id" : "logseq_chat_jni::@6890427a1f51a3e7e1df", + "link" : + { + "commandFragments" : + [ + { + "fragment" : "-static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments", + "role" : "flags" + }, + { + "backtrace" : 2, + "fragment" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/liblog.so", + "role" : "libraries" + }, + { + "fragment" : "-latomic -lm", + "role" : "libraries" + } + ], + "language" : "C", + "sysroot" : + { + "path" : "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot" + } + }, + "name" : "logseq_chat_jni", + "nameOnDisk" : "liblogseq_chat_jni.so", + "paths" : + { + "build" : ".", + "source" : "." + }, + "sourceGroups" : + [ + { + "name" : "Source Files", + "sourceIndexes" : + [ + 0 + ] + } + ], + "sources" : + [ + { + "backtrace" : 1, + "compileGroupIndex" : 0, + "path" : "logseq_chat_jni.c", + "sourceGroupIndex" : 0 + } + ], + "type" : "SHARED_LIBRARY" +} diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/.ninja_deps b/android/app/.cxx/Debug/666c1h3t/x86_64/.ninja_deps new file mode 100644 index 0000000000000000000000000000000000000000..4ecec16f47d58dedf473634ff94b555777d4cfde GIT binary patch literal 7076 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 literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake new file mode 100644 index 00000000..94aeb412 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-6.8.0-1061-aws") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "6.8.0-1061-aws") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + +include("/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake") + +set(CMAKE_SYSTEM "Android-1") +set(CMAKE_SYSTEM_NAME "Android") +set(CMAKE_SYSTEM_VERSION "1") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "TRUE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 00000000..41b99d77 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,803 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif +#if defined(__CLASSIC_C__) +/* cv-qualifiers did not exist in K&R C */ +# define const +# define volatile +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ >= 800 +# define COMPILER_ID "XL" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__IBMC__) && !defined(__COMPILER_VER__) && __IBMC__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__BCC__) +# define COMPILER_ID "Bruce" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION % 10000) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(__VISUALDSPVERSION__) || defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" +#if defined(__VISUALDSPVERSION__) + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__SDCC_VERSION_MAJOR) || defined(SDCC) +# define COMPILER_ID "SDCC" +# if defined(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MAJOR DEC(__SDCC_VERSION_MAJOR) +# define COMPILER_VERSION_MINOR DEC(__SDCC_VERSION_MINOR) +# define COMPILER_VERSION_PATCH DEC(__SDCC_VERSION_PATCH) +# else + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) +# endif + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#if !defined(__STDC__) && !defined(__clang__) +# if defined(_MSC_VER) || defined(__ibmxl__) || defined(__IBMC__) +# define C_VERSION "90" +# else +# define C_VERSION +# endif +#elif __STDC_VERSION__ > 201710L +# define C_VERSION "23" +#elif __STDC_VERSION__ >= 201710L +# define C_VERSION "17" +#elif __STDC_VERSION__ >= 201000L +# define C_VERSION "11" +#elif __STDC_VERSION__ >= 199901L +# define C_VERSION "99" +#else +# define C_VERSION "90" +#endif +const char* info_language_standard_default = + "INFO" ":" "standard_default[" C_VERSION "]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +/* !defined(_MSC_VER) to exclude Clang's MSVC compatibility mode. */ +#if (defined(__clang__) || defined(__GNUC__) || \ + defined(__TI_COMPILER_VERSION__)) && \ + !defined(__STRICT_ANSI__) && !defined(_MSC_VER) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +# if defined(__CLASSIC_C__) +int main(argc, argv) int argc; char *argv[]; +# else +int main(int argc, char* argv[]) +# endif +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#ifdef COMPILER_VERSION_INTERNAL + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} +#endif diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/3.22.1-g37088a8/CompilerIdC/CMakeCCompilerId.o new file mode 100644 index 0000000000000000000000000000000000000000..3a2cad6f4d726e15d423c713166298d9afb43add GIT binary patch literal 5400 zcmdT|TWl0%6#i$nyIt6_P%3gai&sFHy>#0yNT8$^TEi^}A~v|0-JNbLyF1J5ELNi7 z!5bA#AU;TfCd6o>;YEE=9t_bCL*zk?J{S{>FB*O5gO?aF67igW&go2N2ZOwMaOa%! z{pa>y=KNES4sP3`DvDrI#75z2j0&+R?#lgA>=(Z}V9k?*OW6RFW z4+sg?E4n>uTGf$l$Q?@mGUKHRBu-7k#rx87!$TpYmA$<#`M_E z9S3l#l4j)0A2uvB9Z5+_=QKx1rC3P2o*W^VE1k++@vd+vK5yaDc&9QyB7~Y1!(HoR z_l4C(LWC4$xJ!t(6@c}{gb3d$Lh+5U7>E%RW3i1Owr4>c?%K4N-J)~BUWi$DOEz1B zH1i||{tu`-=WW%@GN+?vF_^|A@i zf?2VFRcutM6~qd9!zd-pTEgndWOC`gRf!_LO$j>R2|U?aIqbWlqp3`3T_Mw(StSOx>j#a20eY#2OIlGR$IPmcY!;d|yP33%y4grV3Y&{a z>h*e3D^5%#?>7p~aSn~Wpj0yg!sk@xo+ z-*9Wg5mi_~u(E}2m5cZ|EG*+tbKElixBGevo=G6($Znxb%u|+jv`0_CVO<6o{*dq; z5S!!ko>K?rMATQnLWrjUY7?vBsVK@{@j1xA4eu}|=&-;LG!RuXc!VY+O1OP?bVWGc z496nhhvSj5kB^ZaijU41nH?Dmha#~JstP$dUJG9XLv7-hYb^tq9R3AS$a!5`hC-sV z1w$Ytc=cuuhXgclAAJh?d{17vrhvTwzfK{0uk?VWmGlifJH;&0pm~s_!n`^KTq#71 zzYBWjw3QGU8s97NIi$I9R!Mwr3(k9vJB6{YUUMi-mWX3jjBoMa*fbf>dvL6laoH?E z$2c7x{8^BZ5XWlS9x)``>7ZR>e1WubAB^J(^%CQ~UJzu)cM;Azf^%{%S!V!iMnYU( zoKnNRb%^l~NWayCb4-MmcyNq!iS*luV?DSQOj#1RPR55x;Jhg`0OENt-b464XL!2) zVZuvzIp?u=PrJJwXohiClihd3 zIgUkfrU*wB$C&;mf#dMLcaa~*d6M)5ab&#L7$W1ru^wLEt%P%&)1>e5*t>6^5C=TC zcYhE1;(SQ@5g+~u>61SE66vRW_~)d*>BB!JJ%N)0!dkrb^hwltFTA+W;47h7&g+GO zWgHfo4cDZ=PmHPo_o8MQ6c2u0ahZ zVe18&G=_f5zVi3{%Z`=Rn^@`Tg_quisbX@2~&Z z4c7k|_y^VBA5cF+{`#+8CqI5uBC)-rwd#MsKv4dN1M=g&!|{0i@K0Jy<)1(IMYabM zNq+qSK!ftv1M*{EXMfIr2Vg<@&)ner@%|6We=HzBzN`NHn1)h;&_W#i%BhGZp-wVJM3aRe}*K^@o0e search starts here: + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android + /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include +End of search list. +[2/2] Linking C executable cmTC_c97e9 +Android (12027248, +pgo, +bolt, +lto, +mlgo, based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262) +Target: x86_64-none-linux-android26 +Thread model: posix +InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin + "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -z now -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -pie -dynamic-linker /system/bin/linker64 -o cmTC_c97e9 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtend_android.o + + + +Parsed C implicit include dir info from above output: rv=done + found start of include info + found start of implicit include info + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android] + add: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + end of search list found + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android] + collapse include dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + implicit include dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld\.lld|CMAKE_LINK_STARTFILE-NOTFOUND|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command(s):/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja cmTC_c97e9 && [1/2] Building C object CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: x86_64-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + ignore line: [ (in-process)] + ignore line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang" -cc1 -triple x86_64-none-linux-android26 -emit-obj -mrelax-all -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name CMakeCCompilerABI.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +sse4.2 -target-feature +popcnt -target-feature +cx16 -tune-cpu generic -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/CMakeTmp -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/CMakeTmp -resource-dir /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18 -dependency-file CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o.d -MT CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o -sys-header-deps -D ANDROID -D _FORTIFY_SOURCE=2 -isysroot /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include -internal-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include -internal-externc-isystem /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include -Wformat -ferror-limit 19 -femulated-tls -stack-protector 2 -fgnuc-version=4.2.1 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o -x c /home/ubuntu/android-sdk/cmake/3.22.1/share/cmake-3.22/Modules/CMakeCCompilerABI.c] + ignore line: [clang -cc1 version 18.0.1 based upon LLVM 18.0.1 default target x86_64-unknown-linux-gnu] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include"] + ignore line: [ignoring nonexistent directory "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/include"] + ignore line: [#include "..." search starts here:] + ignore line: [#include <...> search starts here:] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/include] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/x86_64-linux-android] + ignore line: [ /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include] + ignore line: [End of search list.] + ignore line: [[2/2] Linking C executable cmTC_c97e9] + ignore line: [Android (12027248 +pgo +bolt +lto +mlgo based on r522817) clang version 18.0.1 (https://android.googlesource.com/toolchain/llvm-project d8003a456d14a3deb8054cdaa529ffbf02d9b262)] + ignore line: [Target: x86_64-none-linux-android26] + ignore line: [Thread model: posix] + ignore line: [InstalledDir: /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin] + link line: [ "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld" --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -z now -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -pie -dynamic-linker /system/bin/linker64 -o cmTC_c97e9 /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtbegin_dynamic.o -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26 -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android -L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib --build-id=sha1 --no-rosegment --no-undefined-version --fatal-warnings --no-undefined CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a -l:libunwind.a -ldl -lc /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a -l:libunwind.a -ldl /home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtend_android.o] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/ld.lld] ==> ignore + arg [--sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot] ==> ignore + arg [-znow] ==> ignore + arg [-zrelro] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [-pie] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/system/bin/linker64] ==> ignore + arg [-o] ==> ignore + arg [cmTC_c97e9] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtbegin_dynamic.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtbegin_dynamic.o] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android] + arg [-L/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + arg [--build-id=sha1] ==> ignore + arg [--no-rosegment] ==> ignore + arg [--no-undefined-version] ==> ignore + arg [--fatal-warnings] ==> ignore + arg [--no-undefined] ==> ignore + arg [CMakeFiles/cmTC_c97e9.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [-lc] ==> lib [c] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] ==> lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] + arg [-l:libunwind.a] ==> lib [-l:libunwind.a] + arg [-ldl] ==> lib [dl] + arg [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtend_android.o] ==> obj [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtend_android.o] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] + remove lib [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/libclang_rt.builtins-x86_64-android.a] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android] + collapse library dir [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] ==> [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit libs: [-l:libunwind.a;dl;c;-l:libunwind.a;dl] + implicit objs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtbegin_dynamic.o;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26/crtend_android.o] + implicit dirs: [/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/18/lib/linux/x86_64;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/26;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android;/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib] + implicit fwks: [] + + diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/TargetDirectories.txt b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/TargetDirectories.txt new file mode 100644 index 00000000..f1ac4f36 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/TargetDirectories.txt @@ -0,0 +1,3 @@ +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/logseq_chat_jni.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/edit_cache.dir +/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/rebuild_cache.dir diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/cmake.check_cache b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/cmake.check_cache new file mode 100644 index 00000000..3dccd731 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o b/android/app/.cxx/Debug/666c1h3t/x86_64/CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o new file mode 100644 index 0000000000000000000000000000000000000000..87ea79aef829f04c6ecfeeaa7777df86374937c9 GIT binary patch literal 57672 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 STi_nJ4<3Mr;1LM>9{&Qe@a&iX literal 0 HcmV?d00001 diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin new file mode 100644 index 00000000..1df16ed1 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin @@ -0,0 +1,28 @@ +C/C++ Structured Log_ +] +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/additional_project_files.txtC +A +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ò¹»…‘4  �ô¥…‘4\ +Z +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build.json  ò¹»…‘4° �ô¥…‘4a +_ +]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build_mini.json  ò¹»…‘4  �ô¥…‘4N +L +J/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja  ò¹»…‘4ú³ ˆô¥…‘4R +P +N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja.txt  ò¹»…‘4W +U +S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build_file_index.txt  ò¹»…‘4 ? �ô¥…‘4X +V +T/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json  ò¹»…‘4ô ˆô¥…‘4\ +Z +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json.bin  ò¹»…‘4 ë ˆô¥…‘4b +` +^/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt  ò¹»…‘4 +» �ô¥…‘4U +S +Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json  ò¹»…‘4  ( �ô¥…‘4Z +X +V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt  ò¹»…‘4  U �ô¥…‘4C +A +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  ò¹»…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt b/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt new file mode 100644 index 00000000..73aaafe1 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt @@ -0,0 +1,18 @@ + -H/home/ubuntu/repos/chat/android/app/src/main/cpp +-DCMAKE_SYSTEM_NAME=Android +-DCMAKE_EXPORT_COMPILE_COMMANDS=ON +-DCMAKE_SYSTEM_VERSION=26 +-DANDROID_PLATFORM=android-26 +-DANDROID_ABI=x86_64 +-DCMAKE_ANDROID_ARCH_ABI=x86_64 +-DANDROID_NDK=/home/ubuntu/android-sdk/ndk/27.0.12077973 +-DCMAKE_ANDROID_NDK=/home/ubuntu/android-sdk/ndk/27.0.12077973 +-DCMAKE_TOOLCHAIN_FILE=/home/ubuntu/android-sdk/ndk/27.0.12077973/build/cmake/android.toolchain.cmake +-DCMAKE_MAKE_PROGRAM=/home/ubuntu/android-sdk/cmake/3.22.1/bin/ninja +-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64 +-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64 +-DCMAKE_BUILD_TYPE=Debug +-B/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64 +-GNinja + Build command args: [] + Version: 2 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json b/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json new file mode 100644 index 00000000..e799de86 --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json @@ -0,0 +1,4 @@ +{ + "enabled": false, + "packages": [] +} \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt b/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt new file mode 100644 index 00000000..024d1e4b --- /dev/null +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt @@ -0,0 +1 @@ +/home/ubuntu/repos/chat/android/app/build/intermediates/cxx/Debug/666c1h3t/obj/x86_64 \ No newline at end of file diff --git a/android/app/.cxx/tools/debug/arm64-v8a/compile_commands.json b/android/app/.cxx/tools/debug/arm64-v8a/compile_commands.json new file mode 100644 index 00000000..71022287 --- /dev/null +++ b/android/app/.cxx/tools/debug/arm64-v8a/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=aarch64-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/.cxx/tools/debug/armeabi-v7a/compile_commands.json b/android/app/.cxx/tools/debug/armeabi-v7a/compile_commands.json new file mode 100644 index 00000000..b82eaaea --- /dev/null +++ b/android/app/.cxx/tools/debug/armeabi-v7a/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/.cxx/tools/debug/x86/compile_commands.json b/android/app/.cxx/tools/debug/x86/compile_commands.json new file mode 100644 index 00000000..daf0941d --- /dev/null +++ b/android/app/.cxx/tools/debug/x86/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=i686-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/.cxx/tools/debug/x86_64/compile_commands.json b/android/app/.cxx/tools/debug/x86_64/compile_commands.json new file mode 100644 index 00000000..2a75acf2 --- /dev/null +++ b/android/app/.cxx/tools/debug/x86_64/compile_commands.json @@ -0,0 +1,7 @@ +[ +{ + "directory": "/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64", + "command": "/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=x86_64-none-linux-android26 --sysroot=/home/ubuntu/android-sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot -Dlogseq_chat_jni_EXPORTS -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -fPIC -o CMakeFiles/logseq_chat_jni.dir/logseq_chat_jni.c.o -c /home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c", + "file": "/home/ubuntu/repos/chat/android/app/src/main/cpp/logseq_chat_jni.c" +} +] \ No newline at end of file diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 00000000..a23c6f1b --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,160 @@ +import java.net.URLClassLoader + +plugins { + id("com.android.application") + + id("org.jetbrains.kotlin.plugin.compose") +} + +// The OCaml core .so is produced by scripts/build-android-native.sh; it +// takes minutes (and needs the OCaml cross toolchain), so Gradle calls it +// at most once per ABI unless the script is re-run. +val repoRoot = rootDir.parentFile +val androidAbi = providers.gradleProperty("logseqChatAndroidAbi").orNull ?: "arm64-v8a" +val nativeLibrary = File("src/main/jniLibs/$androidAbi/liblogseq_chat_core.so") + +val buildAndroidNativeCore = tasks.register("buildAndroidNativeCore") { + group = "build" + description = "Builds liblogseq_chat_core.so for $androidAbi via scripts/build-android-native.sh" + inputs.files( + "src/main/cpp/CMakeLists.txt", + "src/main/cpp/logseq_chat_jni.c", + ) + inputs.dir(File(repoRoot, "shared")) + inputs.files(File(repoRoot, "scripts/build-android-native.sh")) + outputs.file(nativeLibrary) + doLast { + val output = providers.exec { + workingDir(repoRoot) + environment("LOGSEQ_CHAT_ANDROID_ABI", androidAbi) + commandLine("bash", "scripts/build-android-native.sh") + } + output.result.get().assertNormalExitValue() + } +} + +// The native .so is only required when assembling an APK to run on a +// device/emulator; JVM unit tests and lint must work without it. Allow +// developers (and CI running `test`) to skip it. +val nativeCoreRequired = + providers.gradleProperty("logseqChatRequireNativeCore").map(String::toBoolean).orElse(true) + +android { + namespace = "com.logseq.chat" + compileSdk = 36 + ndkVersion = "27.0.12077973" + + defaultConfig { + applicationId = "com.logseq.chat" + minSdk = 26 + targetSdk = 36 + versionCode = 1 + versionName = "1.0.0" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + } + // E2E variant: debuggable like the previous profile APK the Maestro + // flows install via scripts/test-android-e2e.sh. + create("profile") { + initWith(getByName("debug")) + matchingFallbacks += "debug" + } + } + + buildFeatures { + compose = true + buildConfig = true + } + + packaging { + jniLibs { + // The JNI shim dlopen()s liblogseq_chat_core.so by soname, so + // native libraries must be extracted onto the device fs. + useLegacyPackaging = true + } + } + + externalNativeBuild { + cmake { + path = file("src/main/cpp/CMakeLists.txt") + version = "3.22.1" + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + isReturnDefaultValues = true + } + } + + sourceSets["main"].jniLibs.directories.add("src/main/jniLibs") +} + +tasks.named("preBuild") { + if (nativeCoreRequired.get()) { + dependsOn(buildAndroidNativeCore) + } +} + + + +// When the vendored :lui module is used (no ../lui/platform/android +// composite build), resolve the dev.lui:lui coordinate to it. +if (rootProject.findProject(":lui") != null) { + configurations.all { + resolutionStrategy.dependencySubstitution { + substitute(module("dev.lui:lui")).using(project(":lui")) + } + } +} + +dependencies { + // Resolved to ../lui/platform/android when the Kotlin LUI backend + // checkout is present (composite build substitution), otherwise to + // the vendored :lui module — see settings.gradle.kts. + implementation("dev.lui:lui") + + implementation(platform("androidx.compose:compose-bom:2025.09.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.foundation:foundation") + implementation("androidx.compose.foundation:foundation-layout") + implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-extended") + implementation("androidx.compose.runtime:runtime") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.activity:activity-compose:1.11.0") + implementation("androidx.lifecycle:lifecycle-runtime-compose") + implementation("androidx.browser:browser:1.8.0") + implementation("com.google.mlkit:genai-speech-recognition:1.0.0-alpha1") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2") + implementation("org.json:json:20251224") + + testImplementation("org.json:json:20251224") + testImplementation("junit:junit:4.13.2") + + androidTestImplementation("org.json:json:20251224") + androidTestImplementation("androidx.test.ext:junit:1.2.1") + androidTestImplementation("androidx.test:runner:1.6.2") + androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1") +} + + diff --git a/flutter/android/app/src/androidTest/kotlin/com/logseq/chat/AndroidAudioRecorderInstrumentedTest.kt b/android/app/src/androidTest/kotlin/com/logseq/chat/AndroidAudioRecorderInstrumentedTest.kt similarity index 100% rename from flutter/android/app/src/androidTest/kotlin/com/logseq/chat/AndroidAudioRecorderInstrumentedTest.kt rename to android/app/src/androidTest/kotlin/com/logseq/chat/AndroidAudioRecorderInstrumentedTest.kt diff --git a/flutter/android/app/src/androidTest/kotlin/logseq/chat/AndroidE2EECryptoDeviceTests.kt b/android/app/src/androidTest/kotlin/logseq/chat/AndroidE2EECryptoDeviceTests.kt similarity index 100% rename from flutter/android/app/src/androidTest/kotlin/logseq/chat/AndroidE2EECryptoDeviceTests.kt rename to android/app/src/androidTest/kotlin/logseq/chat/AndroidE2EECryptoDeviceTests.kt diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..2cdbe098 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/flutter/android/app/src/debug/res/xml/network_security_config.xml b/android/app/src/debug/res/xml/network_security_config.xml similarity index 100% rename from flutter/android/app/src/debug/res/xml/network_security_config.xml rename to android/app/src/debug/res/xml/network_security_config.xml diff --git a/flutter/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml similarity index 63% rename from flutter/android/app/src/main/AndroidManifest.xml rename to android/app/src/main/AndroidManifest.xml index 5bed7d5c..e1058991 100644 --- a/flutter/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,55 +1,65 @@ + + android:label="Logseq Chat" + android:networkSecurityConfig="@xml/network_security_config" + android:theme="@style/LaunchTheme"> - - - - + + + + + + + + + + + + + + + + + + android:pathPrefix="/callback" + android:scheme="logseqchat" /> - - + - + + - - + + android:exported="false" + android:label="@string/widget_journal_description"> @@ -67,7 +78,8 @@ + android:exported="false" + android:label="@string/widget_capture_description"> @@ -84,21 +96,5 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> - - - - - - - - - diff --git a/android/app/src/main/cpp/CMakeLists.txt b/android/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 00000000..ccc469e1 --- /dev/null +++ b/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.22.1) + +project(logseq_chat_jni C) + +# Thin JNI shim between com.logseq.chat.NativeCore and the +# liblogseq_chat_core.so C ABI (shared/native/logseq_chat_core_ffi.h). +# The OCaml core is delivered as a prebuilt shared library per ABI; this +# shim forwards every call and converts between jbyteArray (raw UTF-8 +# bytes, decoded by Kotlin as Charsets.UTF_8) and the core's const char* +# strings so non-ASCII text survives the round trip — NewStringUTF's +# modified UTF-8 would corrupt 4-byte sequences such as emoji. +add_library(logseq_chat_jni SHARED logseq_chat_jni.c) + +find_library(log-lib log) + +target_link_libraries(logseq_chat_jni ${log-lib}) diff --git a/android/app/src/main/cpp/logseq_chat_jni.c b/android/app/src/main/cpp/logseq_chat_jni.c new file mode 100644 index 00000000..73702280 --- /dev/null +++ b/android/app/src/main/cpp/logseq_chat_jni.c @@ -0,0 +1,265 @@ +// Thin JNI shim between com.logseq.chat.NativeCore and the +// liblogseq_chat_core.so C ABI (shared/native/logseq_chat_core_ffi.h). +// +// Symbols are resolved with dlopen/dlsym at first use so this shim links +// without the prebuilt core being present at CMake configure time — +// gradle produces the core .so during task execution via +// scripts/build-android-native.sh, after externalNativeBuild configures. +// +// String payloads cross the boundary as jbyteArray holding UTF-8 bytes: +// the core reads and returns standard UTF-8, while NewStringUTF uses +// modified UTF-8 and would corrupt 4-byte sequences (e.g. emoji) and any +// embedded NULs the wire format escapes. Kotlin decodes with +// Charsets.UTF_8. + +#include +#include +#include +#include + +typedef const char *(*lui_fn_iii)(int, int, int); +typedef const char *(*lui_fn_none)(void); +typedef const char *(*lui_fn_l)(long long); +typedef const char *(*lui_fn_ls)(long long, const char *); +typedef const char *(*lui_fn_li)(long long, int); +typedef const char *(*lui_fn_ld)(long long, double); +typedef const char *(*lui_fn_lll)(long long, long long, long long); +typedef const char *(*lui_fn_llls)(long long, long long, long long, const char *); +typedef const char *(*lui_fn_lls)(long long, long long, const char *); +typedef const char *(*lui_fn_lsssl)(long long, const char *, const char *, const char *, long long); +typedef const char *(*lui_fn_lis)(long long, int, const char *); +typedef const char *(*lui_fn_s)(const char *); +typedef const char *(*lui_fn_ss)(const char *, const char *); +typedef const char *(*lui_fn_sssss)(const char *, const char *, const char *, const char *, const char *); + +static void *core_handle = NULL; + +static void *core_symbol(const char *name) { + if (!core_handle) { + core_handle = dlopen("liblogseq_chat_core.so", RTLD_NOW | RTLD_GLOBAL); + if (!core_handle) return NULL; + } + return dlsym(core_handle, name); +} + +static char *jbytes_to_cstr(JNIEnv *env, jbyteArray bytes) { + if (!bytes) return NULL; + jsize length = (*env)->GetArrayLength(env, bytes); + char *buffer = malloc((size_t)length + 1); + if (!buffer) return NULL; + (*env)->GetByteArrayRegion(env, bytes, 0, length, (jbyte *)buffer); + buffer[length] = '\0'; + return buffer; +} + +static jbyteArray cstr_to_jbytes(JNIEnv *env, const char *text) { + if (!text) return NULL; + jsize length = (jsize)strlen(text); + jbyteArray bytes = (*env)->NewByteArray(env, length); + if (!bytes) return NULL; + (*env)->SetByteArrayRegion(env, bytes, 0, length, (const jbyte *)text); + return bytes; +} + +static jbyteArray call_none(JNIEnv *env, const char *symbol) { + lui_fn_none fn = (lui_fn_none)core_symbol(symbol); + return fn ? cstr_to_jbytes(env, fn()) : NULL; +} + +static jbyteArray call_l(JNIEnv *env, const char *symbol, jlong a) { + lui_fn_l fn = (lui_fn_l)core_symbol(symbol); + return fn ? cstr_to_jbytes(env, fn(a)) : NULL; +} + +static jbyteArray call_ls(JNIEnv *env, const char *symbol, jlong a, jbyteArray b) { + lui_fn_ls fn = (lui_fn_ls)core_symbol(symbol); + if (!fn) return NULL; + char *bs = jbytes_to_cstr(env, b); + const char *result = fn(a, bs); + jbyteArray out = cstr_to_jbytes(env, result); + free(bs); + return out; +} + +static jbyteArray call_s(JNIEnv *env, const char *symbol, jbyteArray a) { + lui_fn_s fn = (lui_fn_s)core_symbol(symbol); + if (!fn) return NULL; + char *as = jbytes_to_cstr(env, a); + const char *result = fn(as); + jbyteArray out = cstr_to_jbytes(env, result); + free(as); + return out; +} + +static jbyteArray call_ss(JNIEnv *env, const char *symbol, jbyteArray a, jbyteArray b) { + lui_fn_ss fn = (lui_fn_ss)core_symbol(symbol); + if (!fn) return NULL; + char *as = jbytes_to_cstr(env, a); + char *bs = jbytes_to_cstr(env, b); + const char *result = fn(as, bs); + jbyteArray out = cstr_to_jbytes(env, result); + free(as); + free(bs); + return out; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiInitialize( + JNIEnv *env, jclass clazz, jint platform, jint host, jint authentication) { + (void)clazz; + lui_fn_iii fn = (lui_fn_iii)core_symbol("logseq_chat_lui_initialize"); + return fn ? cstr_to_jbytes(env, fn(platform, host, authentication)) : NULL; +} + +JNIEXPORT jlong JNICALL Java_com_logseq_chat_NativeCore_luiRootNode( + JNIEnv *env, jclass clazz) { + (void)env; (void)clazz; + typedef long long (*root_fn)(void); + root_fn fn = (root_fn)core_symbol("logseq_chat_lui_root_node"); + return fn ? (jlong)fn() : 0; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiAppear( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_appear", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiPress( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_press", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiLongPress( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_long_press", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiSubmit( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_submit", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiChange( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_change", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiDismiss( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_dismiss", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiDoublePress( + JNIEnv *env, jclass clazz, jlong node) { + (void)clazz; + return call_l(env, "logseq_chat_lui_double_press", node); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiTextChanged( + JNIEnv *env, jclass clazz, jlong node, jbyteArray text) { + (void)clazz; + return call_ls(env, "logseq_chat_lui_text_changed", node, text); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiToggleChanged( + JNIEnv *env, jclass clazz, jlong node, jint checked) { + (void)clazz; + lui_fn_li fn = (lui_fn_li)core_symbol("logseq_chat_lui_toggle_changed"); + return fn ? cstr_to_jbytes(env, fn(node, checked)) : NULL; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiValueChanged( + JNIEnv *env, jclass clazz, jlong node, jdouble value) { + (void)clazz; + lui_fn_ld fn = (lui_fn_ld)core_symbol("logseq_chat_lui_value_changed"); + return fn ? cstr_to_jbytes(env, fn(node, value)) : NULL; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiPicked( + JNIEnv *env, jclass clazz, jlong node, jbyteArray payload) { + (void)clazz; + return call_ls(env, "logseq_chat_lui_picked", node, payload); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiVisibleRange( + JNIEnv *env, jclass clazz, jlong node, jlong first, jlong last) { + (void)clazz; + lui_fn_lll fn = (lui_fn_lll)core_symbol("logseq_chat_lui_visible_range"); + return fn ? cstr_to_jbytes(env, fn(node, first, last)) : NULL; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiScrollCompleted( + JNIEnv *env, jclass clazz, jlong node, jlong token, jbyteArray outcome) { + (void)clazz; + lui_fn_lls fn = (lui_fn_lls)core_symbol("logseq_chat_lui_scroll_completed"); + if (!fn) return NULL; + char *outcome_s = jbytes_to_cstr(env, outcome); + const char *result = fn(node, token, outcome_s); + jbyteArray out = cstr_to_jbytes(env, result); + free(outcome_s); + return out; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiExtensionEvent( + JNIEnv *env, jclass clazz, jlong node, jbyteArray identifier, jbyteArray name, + jbyteArray text, jlong value) { + (void)clazz; + lui_fn_lsssl fn = (lui_fn_lsssl)core_symbol("logseq_chat_lui_extension_event"); + if (!fn) return NULL; + char *id_s = jbytes_to_cstr(env, identifier); + char *name_s = jbytes_to_cstr(env, name); + char *text_s = jbytes_to_cstr(env, text); + const char *result = fn(node, id_s, name_s, text_s, value); + jbyteArray out = cstr_to_jbytes(env, result); + free(id_s); + free(name_s); + free(text_s); + return out; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiDispose( + JNIEnv *env, jclass clazz) { + (void)clazz; + return call_none(env, "logseq_chat_lui_dispose"); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiTakeEffect( + JNIEnv *env, jclass clazz) { + (void)clazz; + return call_none(env, "logseq_chat_lui_take_effect"); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiResolveEffect( + JNIEnv *env, jclass clazz, jlong effectId, jint succeeded, jbyteArray message) { + (void)clazz; + lui_fn_lis fn = (lui_fn_lis)core_symbol("logseq_chat_lui_resolve_effect"); + if (!fn) return NULL; + char *message_s = jbytes_to_cstr(env, message); + const char *result = fn(effectId, succeeded, message_s); + jbyteArray out = cstr_to_jbytes(env, result); + free(message_s); + return out; +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiApplySnapshot( + JNIEnv *env, jclass clazz, jbyteArray response) { + (void)clazz; + return call_s(env, "logseq_chat_lui_apply_snapshot", response); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_luiApplyHostUpdate( + JNIEnv *env, jclass clazz, jbyteArray kind, jbyteArray payload) { + (void)clazz; + return call_ss(env, "logseq_chat_lui_apply_host_update", kind, payload); +} + +JNIEXPORT jbyteArray JNICALL Java_com_logseq_chat_NativeCore_logseqChatCall( + JNIEnv *env, jclass clazz, jbyteArray request) { + (void)clazz; + return call_s(env, "logseq_chat_call", request); +} diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAppEntryParser.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidAppEntryParser.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAppEntryParser.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidAppEntryParser.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioTranscriber.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioTranscriber.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAudioTranscriber.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidAudioTranscriber.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt similarity index 95% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt index 7eac224d..43508135 100644 --- a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt +++ b/android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt @@ -227,6 +227,19 @@ class AndroidPlatformServices(private val activity: Activity) { preferences.edit().putString("logseq.selectedGraphId", graphId).apply() } + // WebSocket sync transport is being migrated; the core treats a false + // resolution as "sync unavailable" (see AndroidPlatformEffects). + fun syncNow(): Boolean = false + + // Asset paths the core emits are files-directory-relative; absolute + // paths pass through untouched. + fun resolveAssetPath(path: String): String = + if (path.isEmpty() || File(path).isAbsolute) { + path + } else { + resolveAppFile(activity.filesDir, path).path + } + fun deleteTemporaryFile(path: String) { val graphsDirectory = File(activity.filesDir, "graphs").canonicalFile val file = File(path).canonicalFile diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt b/android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt rename to android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/CognitoAuthProvider.kt b/android/app/src/main/kotlin/com/logseq/chat/CognitoAuthProvider.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/CognitoAuthProvider.kt rename to android/app/src/main/kotlin/com/logseq/chat/CognitoAuthProvider.kt diff --git a/flutter/android/app/src/main/kotlin/com/logseq/chat/CognitoOAuth.kt b/android/app/src/main/kotlin/com/logseq/chat/CognitoOAuth.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/com/logseq/chat/CognitoOAuth.kt rename to android/app/src/main/kotlin/com/logseq/chat/CognitoOAuth.kt diff --git a/android/app/src/main/kotlin/com/logseq/chat/LogseqChatApplication.kt b/android/app/src/main/kotlin/com/logseq/chat/LogseqChatApplication.kt new file mode 100644 index 00000000..128c36cc --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/LogseqChatApplication.kt @@ -0,0 +1,5 @@ +package com.logseq.chat + +import android.app.Application + +class LogseqChatApplication : Application() diff --git a/android/app/src/main/kotlin/com/logseq/chat/MainActivity.kt b/android/app/src/main/kotlin/com/logseq/chat/MainActivity.kt new file mode 100644 index 00000000..6953778f --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/MainActivity.kt @@ -0,0 +1,135 @@ +package com.logseq.chat + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.util.Log +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.logseq.chat.runtime.ChatRuntime +import com.logseq.chat.ui.LogseqChatApp +import kotlinx.coroutines.launch +import logseq.chat.AndroidE2EECrypto +import logseq.chat.AndroidHttpTransport +import logseq.chat.AndroidRuntimeLogLevel +import logseq.chat.AndroidRuntimeLogSource +import logseq.chat.AndroidRuntimeLogs + +class MainActivity : ComponentActivity() { + private lateinit var runtime: ChatRuntime + + override fun onCreate(savedInstanceState: Bundle?) { + AndroidE2EECrypto.initialize(applicationContext) + AndroidHttpTransport.initialize(applicationContext) + AndroidRuntimeLogs.shared.append( + AndroidRuntimeLogLevel.INFO, + AndroidRuntimeLogSource.UI, + "Android host started", + ) + super.onCreate(savedInstanceState) + enableEdgeToEdge() + + runtime = ChatRuntime(this, lifecycleScope) + runtime.start() + + setContent { + LogseqChatApp(runtime) + } + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + runtime.onLifecycleResumed(resumed = true) + try { + kotlinx.coroutines.awaitCancellation() + } finally { + runtime.onLifecycleResumed(resumed = false) + } + } + } + handleAppIntent(intent) + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + setIntent(intent) + if (runtime.authentication.handleCallback(intent.dataString)) return + handleAppIntent(intent) + } + + private fun handleAppIntent(intent: Intent?) { + if (intent == null) return + AndroidAppEntryParser.deepLinkKind(intent.dataString)?.let { kind -> + publishAppEntry(mapOf("kind" to kind)) + return + } + if (intent.action != Intent.ACTION_SEND && + intent.action != Intent.ACTION_SEND_MULTIPLE + ) { + return + } + AndroidAppEntryParser.sharedBlockText( + intent.getStringExtra(Intent.EXTRA_TEXT), + intent.getStringExtra(Intent.EXTRA_TITLE), + )?.let { text -> + publishAppEntry(mapOf("kind" to "shared-text", "text" to text)) + } + sharedUris(intent).forEach { uri -> + lifecycleScope.launch { + runtime.assetImporter.importShared(uri)?.let { asset -> + publishAppEntry(mapOf("kind" to "shared-asset", "asset" to asset)) + } + } + } + } + + private fun publishAppEntry(entry: Map) { + Log.i("LogseqChatAppEntry", "Publishing kind=${entry["kind"]}") + runtime.publishAppEntry(entry) + AndroidRuntimeLogs.shared.append( + AndroidRuntimeLogLevel.INFO, + AndroidRuntimeLogSource.UI, + "Received Android app entry kind=${entry["kind"]}", + ) + } + + @Suppress("DEPRECATION") + private fun sharedUris(intent: Intent): List = buildList { + intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)?.let(::addAll) + intent.getParcelableExtra(Intent.EXTRA_STREAM)?.let(::add) + intent.clipData?.let { clips -> + for (index in 0 until clips.itemCount) { + clips.getItemAt(index).uri?.let(::add) + } + } + }.distinct() + + @Deprecated("Android activity result callback") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (runtime.assetImporter.onActivityResult(requestCode, resultCode, data)) return + super.onActivityResult(requestCode, resultCode, data) + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray, + ) { + if (runtime.audioRecorder.onRequestPermissionsResult(requestCode, grantResults)) return + // Permissions the importer or other services may request fall + // through to the platform default. + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + + override fun onDestroy() { + if (::runtime.isInitialized) { + runtime.audioRecorder.cancel() + runtime.audioPlayer.release() + runtime.dispose() + } + super.onDestroy() + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/NativeCore.kt b/android/app/src/main/kotlin/com/logseq/chat/NativeCore.kt new file mode 100644 index 00000000..ac35d929 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/NativeCore.kt @@ -0,0 +1,44 @@ +package com.logseq.chat + +// JNI entry points into liblogseq_chat_core.so, exposed through the +// logseq_chat_jni shim library (app/src/main/cpp/logseq_chat_jni.c). +// +// Every string payload crosses as raw UTF-8 bytes: the core speaks +// standard UTF-8, so bypassing modified-UTF-8 jstrings keeps emoji and +// other 4-byte sequences intact. A null return means the native call +// failed to produce a response (the core returns an empty string on +// error, which likewise maps to null on the Kotlin side). +internal object NativeCore { + init { + System.loadLibrary("logseq_chat_jni") + } + + external fun luiInitialize(platform: Int, host: Int, authentication: Int): ByteArray? + external fun luiRootNode(): Long + external fun luiAppear(node: Long): ByteArray? + external fun luiPress(node: Long): ByteArray? + external fun luiLongPress(node: Long): ByteArray? + external fun luiSubmit(node: Long): ByteArray? + external fun luiChange(node: Long): ByteArray? + external fun luiDismiss(node: Long): ByteArray? + external fun luiDoublePress(node: Long): ByteArray? + external fun luiTextChanged(node: Long, text: ByteArray): ByteArray? + external fun luiToggleChanged(node: Long, checked: Int): ByteArray? + external fun luiValueChanged(node: Long, value: Double): ByteArray? + external fun luiPicked(node: Long, payload: ByteArray): ByteArray? + external fun luiVisibleRange(node: Long, first: Long, last: Long): ByteArray? + external fun luiScrollCompleted(node: Long, token: Long, outcome: ByteArray): ByteArray? + external fun luiExtensionEvent( + node: Long, + identifier: ByteArray, + name: ByteArray, + text: ByteArray, + value: Long, + ): ByteArray? + external fun luiDispose(): ByteArray? + external fun luiTakeEffect(): ByteArray? + external fun luiResolveEffect(effectId: Long, succeeded: Int, message: ByteArray): ByteArray? + external fun luiApplySnapshot(response: ByteArray): ByteArray? + external fun luiApplyHostUpdate(kind: ByteArray, payload: ByteArray): ByteArray? + external fun logseqChatCall(request: ByteArray): ByteArray? +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidAppEntry.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidAppEntry.kt new file mode 100644 index 00000000..07d18f2c --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidAppEntry.kt @@ -0,0 +1,155 @@ +package com.logseq.chat.runtime + +import java.util.ArrayDeque +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.json.JSONObject + +// Kotlin port of the former android_app_entry.dart + +// android_imported_asset.dart: intents arriving on MainActivity are +// normalized into entries (deep link, shared text, shared asset) and fed +// to the core once bootstrap finishes. +internal enum class AndroidAppEntryKind { OpenCapture, OpenJournal, SharedText, SharedAsset } + +internal data class AndroidImportedAsset( + val uuid: String, + val title: String, + val assetType: String, + val size: Long, + val checksum: String, + val localPath: String, +) { + fun coreRequest(targetBlockId: String? = null): String { + val payload = JSONObject() + .put("uuid", uuid) + .put("title", title) + .put("assetType", assetType) + .put("assetSize", size) + .put("assetChecksum", checksum) + .put("localPath", localPath) + if (!targetBlockId.isNullOrEmpty()) payload.put("targetBlockId", targetBlockId) + return JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject() + .put("action", "addAsset") + .put("payload", payload.toString()), + ) + .toString() + } + + companion object { + fun fromMap(value: Map): AndroidImportedAsset { + fun requiredString(key: String): String = + (value[key] as? String)?.takeIf(String::isNotEmpty) + ?: throw IllegalArgumentException("Imported asset is missing $key") + val size = (value["size"] as? Number)?.toLong() + ?: throw IllegalArgumentException("Imported asset has an invalid size") + require(size > 0) { "Imported asset has an invalid size" } + return AndroidImportedAsset( + uuid = requiredString("uuid"), + title = requiredString("title"), + assetType = requiredString("assetType"), + size = size, + checksum = requiredString("checksum"), + localPath = requiredString("localPath"), + ) + } + } +} + +internal data class AndroidAppEntry( + val kind: AndroidAppEntryKind, + val text: String? = null, + val asset: AndroidImportedAsset? = null, +) { + fun coreRequest(uuid: String, nowMilliseconds: Long): String { + require(kind == AndroidAppEntryKind.SharedText) { "$kind is not a text capture" } + return JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject() + .put("action", "send") + .put( + "payload", + JSONObject() + .put("text", text) + .put("uuid", uuid) + .put("now", nowMilliseconds) + .toString(), + ), + ) + .toString() + } + + companion object { + @Suppress("UNCHECKED_CAST") + fun fromMap(value: Map): AndroidAppEntry = when (value["kind"]) { + "open-capture" -> AndroidAppEntry(kind = AndroidAppEntryKind.OpenCapture) + "open-journal" -> AndroidAppEntry(kind = AndroidAppEntryKind.OpenJournal) + "shared-text" -> { + val text = value["text"] as? String + require(!text.isNullOrBlank()) { "A shared-text entry needs text" } + AndroidAppEntry(kind = AndroidAppEntryKind.SharedText, text = text) + } + "shared-asset" -> { + val asset = value["asset"] as? Map + ?: throw IllegalArgumentException("A shared-asset entry needs an asset") + AndroidAppEntry( + kind = AndroidAppEntryKind.SharedAsset, + asset = AndroidImportedAsset.fromMap(asset), + ) + } + else -> throw IllegalArgumentException( + "Unsupported Android app entry: ${value["kind"]}" + ) + } + } +} + +// Queued delivery: entries publish before the core is ready wait in +// `pending`; handlers run sequentially in publish order. +internal class AndroidAppEntryCoordinator( + private val scope: CoroutineScope, + private val handle: suspend (AndroidAppEntry) -> Unit, + private val onError: (Throwable) -> Unit = {}, +) { + private val pending = ArrayDeque() + private var ready = false + private var drainJob: Job? = null + + fun publish(value: Map) { + try { + pending.addLast(AndroidAppEntry.fromMap(value)) + if (ready) scheduleDrain() + } catch (error: Throwable) { + onError(error) + } + } + + fun markReady() { + ready = true + scheduleDrain() + } + + private fun scheduleDrain() { + if (drainJob?.isActive == true) return + drainJob = scope.launch { + while (ready && pending.isNotEmpty()) { + val entry = pending.removeFirst() + try { + handle(entry) + } catch (error: Throwable) { + pending.addFirst(entry) + onError(error) + break + } + } + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidGraphLifecycle.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidGraphLifecycle.kt new file mode 100644 index 00000000..e108a4f7 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidGraphLifecycle.kt @@ -0,0 +1,156 @@ +package com.logseq.chat.runtime + +import org.json.JSONObject + +// Kotlin port of the former android_graph_lifecycle.dart: openGraph / +// createGraph / unlockGraph effects, including the remote-snapshot +// download path for graphs that are not stored locally. +internal class AndroidGraphLifecycle( + private val callCore: suspend (String) -> String, + private val effects: AndroidPlatformEffects, + private val accessTokenProvider: suspend () -> String? = { "" }, + private val trace: (String) -> Unit = {}, +) { + suspend fun execute(effect: NativeEffect): NativeEffectResolution = try { + when (effect.kind) { + "create-graph" -> { + val created = call( + "createSyncGraph", + payload = JSONObject() + .put("name", effect.text) + .put("isEncrypted", effect.value == 1L) + .toString(), + ) + failure(created)?.let { return it } + val graphId = selectedGraphId(created) + if (graphId.isEmpty()) { + return NativeEffectResolution.Discard( + succeeded = false, + message = "The created graph has no selected identifier", + ) + } + openGraph(graphId) + } + "open-graph" -> openGraph(effect.text) + "unlock-graph" -> resolution(call("unlockGraph", payload = effect.text)) + else -> NativeEffectResolution.Discard( + succeeded = false, + message = "Unsupported Android graph effect: ${effect.kind}", + ) + } + } catch (error: Throwable) { + val message = "${failureCode(effect.kind)}\n$error" + trace("effect.failed kind=${effect.kind} message=${message.replace('\n', ' ')}") + NativeEffectResolution.Discard(succeeded = false, message = message) + } + + private fun failureCode(kind: String): String = when (kind) { + "create-graph" -> "graph_create_failed" + "open-graph" -> "graph_open_failed" + "unlock-graph" -> "graph_unlock_failed" + else -> "graph_operation_failed" + } + + private suspend fun openGraph(graphId: String): NativeEffectResolution { + trace("open.start graphId=$graphId") + val selected = call("selectGraph", payload = graphId) + failure(selected)?.let { return it } + trace("select.complete graphId=$graphId") + + val state = effects.loadStorageState() + val directory = "${state.graphsDirectory}/$graphId" + val isEncrypted = graphIsEncrypted(selected, graphId) + val isLocal = state.localGraphIds.contains(graphId) + trace("storage.loaded graphId=$graphId local=$isLocal") + val opened: String + if (isLocal) { + opened = call( + "openGraph", + payload = JSONObject() + .put("graphId", graphId) + .put("activePath", "$directory/graph.sqlite") + .put("checkpointPath", "$directory/sync.checkpoint") + .put("isEncrypted", isEncrypted) + .toString(), + ) + } else { + val token = accessTokenProvider() ?: "" + trace("snapshot.download.start graphId=$graphId baseUrl=${state.baseUrl}") + val artifact = effects.downloadGraphSnapshot( + baseUrl = state.baseUrl, + graphId = graphId, + accessToken = token, + workingDirectory = directory, + ) + trace("snapshot.download.complete graphId=$graphId path=${artifact.filePath}") + try { + trace("snapshot.import.start graphId=$graphId") + opened = call( + "importSnapshot", + payload = JSONObject() + .put("graphId", graphId) + .put("activePath", "$directory/graph.sqlite") + .put("checkpointPath", "$directory/sync.checkpoint") + .put("metadataBody", artifact.metadataBody) + .put("downloadPath", artifact.filePath) + .put("isEncrypted", isEncrypted) + .toString(), + ) + trace("snapshot.import.complete graphId=$graphId") + } finally { + effects.deleteTemporaryFile(artifact.filePath) + } + } + + failure(opened)?.let { return it } + effects.persistSelectedGraphId(graphId) + trace("selection.persist.complete graphId=$graphId") + trace("open.complete graphId=$graphId") + return NativeEffectResolution.CoreResponse(opened) + } + + private suspend fun call(action: String, payload: String? = null): String { + val params = JSONObject().put("action", action) + if (payload != null) params.put("payload", payload) + return callCore( + JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put("params", params) + .toString() + ) + } + + private fun resolution(response: String): NativeEffectResolution = + failure(response) ?: NativeEffectResolution.CoreResponse(response) + + private fun failure(response: String): NativeEffectResolution? { + val decoded = decodedResponse(response) + if (decoded.optBoolean("ok")) return null + val error = decoded.optJSONObject("error") + val code = error?.optString("code")?.takeIf(String::isNotEmpty) ?: "core_error" + val message = error?.optString("message")?.takeIf(String::isNotEmpty) + ?: "The OCaml core rejected the graph operation" + return NativeEffectResolution.Discard(succeeded = false, message = "$code\n$message") + } + + private fun selectedGraphId(response: String): String = + decodedResponse(response).optJSONObject("result") + ?.optString("selectedGraphId").orEmpty() + + private fun graphIsEncrypted(response: String, graphId: String): Boolean { + val graphs = decodedResponse(response).optJSONObject("result") + ?.optJSONArray("graphs") ?: return false + for (index in 0 until graphs.length()) { + val graph = graphs.optJSONObject(index) ?: continue + if (graph.optString("id") == graphId) return graph.optBoolean("isEncrypted") + } + return false + } + + private fun decodedResponse(response: String): JSONObject = try { + JSONObject(response) + } catch (error: Throwable) { + throw IllegalArgumentException("The native core response must be an object", error) + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidPlatformEffects.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidPlatformEffects.kt new file mode 100644 index 00000000..8a1a00bc --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/AndroidPlatformEffects.kt @@ -0,0 +1,272 @@ +package com.logseq.chat.runtime + +import com.logseq.chat.AndroidPlatformServices +import com.logseq.chat.CognitoAuthProvider +import org.json.JSONArray +import org.json.JSONObject + +// Kotlin port of the former android_platform_effects.dart. The previous +// version reached these through MethodChannels; here the Kotlin platform +// services are called directly — same operations, same SharedPreferences +// keys, same payloads. +internal interface AndroidAuthentication { + fun hasStoredSession(): Boolean + suspend fun restoreAccessToken(): String? + suspend fun signIn(): String + suspend fun signOut(): Unit +} + +internal class CognitoAndroidAuthentication( + private val provider: CognitoAuthProvider, +) : AndroidAuthentication { + override fun hasStoredSession(): Boolean = provider.hasStoredSession() + override suspend fun restoreAccessToken(): String? = provider.accessToken() + override suspend fun signIn(): String = provider.signIn() + override suspend fun signOut() = provider.signOut() +} + +internal data class AndroidStorageState( + val databasePath: String, + val graphsDirectory: String, + val baseUrl: String, + val selectedGraphId: String, + val localGraphIds: List, + val settings: AndroidHostSettings = AndroidHostSettings.defaults, + val composerDraft: String = "", +) { + val startupHostUpdates: List + get() = listOf( + AndroidHostUpdate(kind = "graph-loading", payload = "true"), + AndroidHostUpdate( + kind = "settings", + payload = JSONObject(settings.hostPayload).toString(), + ), + AndroidHostUpdate( + kind = "composer-draft", + payload = JSONObject.quote(composerDraft), + ), + ) + + companion object { + fun fromPlatformMap(value: Map): AndroidStorageState { + @Suppress("UNCHECKED_CAST") + val settings = value["settings"] as? Map + @Suppress("UNCHECKED_CAST") + val localGraphIds = (value["localGraphIds"] as? List) + ?.mapNotNull { it as? String } ?: emptyList() + return AndroidStorageState( + databasePath = value["databasePath"] as? String ?: "", + graphsDirectory = value["graphsDirectory"] as? String ?: "", + baseUrl = value["baseUrl"] as? String ?: "http://127.0.0.1:8787", + selectedGraphId = value["selectedGraphId"] as? String ?: "", + localGraphIds = localGraphIds, + settings = AndroidHostSettings.fromPlatformValue(settings), + composerDraft = value["composerDraft"] as? String ?: "", + ) + } + } +} + +internal data class AndroidHostUpdate(val kind: String, val payload: String) + +internal data class AndroidHostSettings( + val appearance: String, + val language: String, + val spellCheck: Boolean, + val autoCorrection: Boolean, + val sidebarTabs: List, + val baseUrl: String, + val version: String, + val revision: String, +) { + val hostPayload: Map + get() = mapOf( + "appearance" to appearance, + "language" to language, + "spellCheck" to spellCheck, + "autoCorrection" to autoCorrection, + "sidebarTabs" to sidebarTabs, + "baseURL" to baseUrl, + "version" to version, + "revision" to revision, + ) + + companion object { + val defaults = AndroidHostSettings( + appearance = "system", + language = "system", + spellCheck = true, + autoCorrection = true, + sidebarTabs = emptyList(), + baseUrl = "http://127.0.0.1:8787", + version = "Development", + revision = "Development", + ) + + fun fromPlatformValue(value: Map?): AndroidHostSettings { + if (value == null) return defaults + @Suppress("UNCHECKED_CAST") + val tabs = (value["sidebarTabs"] as? List) + ?.mapNotNull { it as? String } ?: defaults.sidebarTabs + return AndroidHostSettings( + appearance = value["appearance"] as? String ?: defaults.appearance, + language = value["language"] as? String ?: defaults.language, + spellCheck = value["spellCheck"] as? Boolean ?: defaults.spellCheck, + autoCorrection = value["autoCorrection"] as? Boolean ?: defaults.autoCorrection, + sidebarTabs = tabs, + baseUrl = value["baseURL"] as? String ?: defaults.baseUrl, + version = value["version"] as? String ?: defaults.version, + revision = value["revision"] as? String ?: defaults.revision, + ) + } + } +} + +internal data class AndroidDownloadedSnapshot( + val metadataBody: String, + val filePath: String, +) + +internal class AndroidPlatformEffects( + private val authentication: AndroidAuthentication, + private val platform: AndroidPlatformServices, + private val attachmentsImporter: suspend (String) -> List>, +) { + suspend fun initialAuthenticationCode(): Int = try { + if (authentication.hasStoredSession()) 3 else 1 + } catch (_: Throwable) { + 1 + } + + suspend fun restoreAccessToken(): String? = authentication.restoreAccessToken() + + fun loadStorageState(): AndroidStorageState = + AndroidStorageState.fromPlatformMap(platform.loadStorageState()) + + suspend fun coreStartupState( + accessToken: String, + storage: AndroidStorageState? = null, + ): CoreStartupState { + val resolved = storage ?: loadStorageState() + return CoreStartupState( + databasePath = resolved.databasePath, + graphsDirectory = resolved.graphsDirectory, + baseUrl = resolved.baseUrl, + selectedGraphId = resolved.selectedGraphId, + localGraphIds = resolved.localGraphIds, + accessToken = accessToken, + ) + } + + suspend fun execute(effect: NativeEffect): NativeEffectResolution = try { + when (effect.kind) { + "persist-composer-draft" -> { + platform.persistComposerDraft(effect.text) + NativeEffectResolution.Discard() + } + "save-settings" -> { + platform.saveSettings(effect.text) + NativeEffectResolution.Discard() + } + "open-external-url" -> NativeEffectResolution.Discard( + succeeded = platform.openExternalUrl(effect.text), + ) + "copy-runtime-log" -> { + platform.copyText(runtimeLogText(effect.text)) + NativeEffectResolution.Discard() + } + "refresh-runtime-log" -> { + val records = platform.refreshRuntimeLog( + source = effect.text, + flags = (effect.value ?: 0).toInt(), + ) + NativeEffectResolution.HostUpdate(kind = "runtime-log", payload = records) + } + "present-attachment" -> NativeEffectResolution.Discard( + succeeded = platform.presentAttachment(effect.text), + ) + "present-asset" -> NativeEffectResolution.Discard( + succeeded = platform.presentAsset(effect.metadata ?: ""), + ) + "present-page-share" -> NativeEffectResolution.Discard( + succeeded = platform.presentPageShare( + text = effect.text, + metadata = effect.metadata ?: "[]", + ), + ) + "sync-now" -> { + val succeeded = platform.syncNow() + NativeEffectResolution.Discard( + succeeded = succeeded, + message = if (succeeded) "" else + "Sync is unavailable while the WebSocket transport is being migrated", + ) + } + "delete-local-graph" -> NativeEffectResolution.Discard( + succeeded = platform.deleteLocalGraph(effect.text), + ) + "export-graph-database" -> NativeEffectResolution.Discard( + succeeded = platform.exportGraphDatabase(), + ) + "sign-in" -> { + val token = authentication.signIn() + if (token.isBlank()) { + NativeEffectResolution.Discard( + succeeded = false, + message = "Hosted sign-in did not return an access token", + ) + } else { + NativeEffectResolution.Discard() + } + } + "sign-out" -> { + authentication.signOut() + NativeEffectResolution.Discard() + } + else -> NativeEffectResolution.Discard( + succeeded = false, + message = "Unsupported Android platform effect: ${effect.kind}", + ) + } + } catch (error: Throwable) { + NativeEffectResolution.Failure(error.toString()) + } + + // Called through by the runtime for effect kinds handled in the app + // layer rather than the platform services (attachment pickers, audio + // recording) — the Kotlin importer returns the same map shape the + // MethodChannel produced. + suspend fun importAttachments(kind: String): List> = + attachmentsImporter(kind) + + suspend fun downloadGraphSnapshot( + baseUrl: String, + graphId: String, + accessToken: String, + workingDirectory: String, + ): AndroidDownloadedSnapshot { + val value = platform.downloadGraphSnapshot(baseUrl, graphId, accessToken, workingDirectory) + return AndroidDownloadedSnapshot( + metadataBody = value["metadataBody"] ?: error("Android did not return snapshot metadata"), + filePath = value["filePath"] ?: error("Android did not return a snapshot path"), + ) + } + + fun persistSelectedGraphId(graphId: String) = platform.persistSelectedGraphId(graphId) + fun deleteTemporaryFile(path: String) = platform.deleteTemporaryFile(path) + fun resolveAssetPath(path: String): String = platform.resolveAssetPath(path) + fun appendRuntimeLog(level: String, source: String, message: String) { + platform.appendRuntimeLog(level, source, message) + } + + private fun runtimeLogText(encoded: String): String { + val decoded = JSONArray(encoded) + return (0 until decoded.length()).joinToString("\n") { index -> + val entry = decoded.getJSONObject(index) + listOf("timestamp", "level", "source", "message") + .map { entry.optString(it) } + .filter(String::isNotEmpty) + .joinToString(" ") + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/ChatRuntime.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/ChatRuntime.kt new file mode 100644 index 00000000..8b025c47 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/ChatRuntime.kt @@ -0,0 +1,538 @@ +package com.logseq.chat.runtime + +import android.app.Activity +import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import com.logseq.chat.AndroidAssetImporter +import com.logseq.chat.AndroidAudioPlayer +import com.logseq.chat.AndroidAudioRecorder +import com.logseq.chat.AndroidAudioTranscriber +import com.logseq.chat.AndroidPlatformServices +import com.logseq.chat.CognitoAuthProvider +import dev.lui.LuiBackend +import dev.lui.LuiEvent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import logseq.chat.AndroidRuntimeLogLevel +import logseq.chat.AndroidRuntimeLogSource +import logseq.chat.AndroidRuntimeLogs +import org.json.JSONObject + +// Kotlin port of the former Dart app state: owns the LUI +// backend, the JNI bridge, the effect drain, bootstrap/restore, graph +// catalog polling, app entries (deep links + share intents), and +// outliner platform commands. Compose state fields drive LogseqChatApp. +internal class ChatRuntime( + private val activity: Activity, + private val scope: CoroutineScope, +) { + val platformServices = AndroidPlatformServices(activity) + val authentication = CognitoAuthProvider(activity.applicationContext, activity) + val assetImporter = AndroidAssetImporter(activity, scope) + val audioRecorder = AndroidAudioRecorder(activity) + val audioPlayer = AndroidAudioPlayer(activity) + + private val platformEffects = AndroidPlatformEffects( + authentication = CognitoAndroidAuthentication(authentication), + platform = platformServices, + attachmentsImporter = assetImporter::import, + ) + + val backend = LuiBackend( + onEvent = ::dispatch, + extensions = com.logseq.chat.ui.extensions.logseqChatExtensionRegistry( + resolveAssetPath = platformServices::resolveAssetPath, + ), + icons = logseqChatIconResolver, + ) + private val patchFilter = LuiPatchFilter { patch -> backend.applyJson(patch) } + private val bridge = LogseqChatNativeBridge(onPatch = ::applyPatch) + + private var coreEffects: CoreEffectExecutor? = null + private var effectDrain: NativeEffectDrain? = null + private var graphCatalogAutoRefresh: GraphCatalogAutoRefresh? = null + private val appEntries = AndroidAppEntryCoordinator(scope, ::handleAppEntry, ::reportError) + private val outlinerCommands = OutlinerPlatformCommandDispatcher(::handleOutlinerCommandBatch) + + var rootNodeId by mutableStateOf(null) + private set + var startupError by mutableStateOf(null) + private set + + @Volatile private var hasAuthenticatedSession = false + @Volatile private var hasOpenGraph = false + @Volatile private var appIsForeground = true + private var activeBootstrap: kotlinx.coroutines.Job? = null + private var activeBootstrapHadSession = false + private var appearance by mutableStateOf("system") + + val supportsAudioTranscription: Boolean get() = AndroidAudioTranscriber.isSupported() + + init { + bridge.onCoreIdle = { scope.launch { effectDrain?.drain(scope) } } + logRuntime("info", "ui", "Kotlin host initialized") + } + + fun start() { + scope.launch { + try { + val authenticationCode = platformEffects.initialAuthenticationCode() + val storage = platformEffects.loadStorageState() + appearance = storage.settings.appearance + + val graphLifecycle = AndroidGraphLifecycle( + callCore = bridge::callCore, + effects = platformEffects, + accessTokenProvider = platformEffects::restoreAccessToken, + trace = ::traceGraphLifecycle, + ) + val executor = CoreEffectExecutor( + callCore = bridge::callCore, + executePlatformEffect = NativeEffectExecutor(platformEffects::execute), + executeGraphEffect = NativeEffectExecutor(graphLifecycle::execute), + ) + coreEffects = executor + graphCatalogAutoRefresh = GraphCatalogAutoRefresh( + scope = scope, + callCore = bridge::callCore, + applyCoreResponse = ::applyCoreResponse, + trace = { traceGraphCatalogRefresh("automatic $it") }, + ) + val drain = NativeEffectDrain( + runtime = object : NativeEffectRuntime { + override fun takeEffect() = bridge.takeEffect() + override fun resolveEffect(id: Long, succeeded: Boolean, message: String) = + bridge.resolveEffect(id, succeeded, message) + override fun applySnapshot(response: String) = bridge.applySnapshot(response) + override fun applyHostUpdate(kind: String, payload: String) = + bridge.applyHostUpdate(kind, payload) + }, + execute = NativeEffectExecutor(::executeEffect), + applyPatch = ::applyPatch, + onError = ::reportError, + trace = ::traceNativeEffect, + afterCoreResponseApplied = outlinerCommands::deliver, + ) + drain.autosaveDrain = { scope.launch { drain.drain(scope) } } + effectDrain = drain + + val rootNode = bridge.initialize(authenticationCode = authenticationCode) + for (update in storage.startupHostUpdates) { + applyPatch(bridge.applyHostUpdate(update.kind, update.payload)) + } + rootNodeId = rootNode + scope.launch { drain.drain(scope) } + restoreCore(hasStoredSession = authenticationCode == 3, storage = storage) + } catch (error: Throwable) { + startupError = error + reportError(error) + } + } + } + + fun onLifecycleResumed(resumed: Boolean) { + appIsForeground = resumed + updateCatalogPolling("lifecycle") + } + + fun publishAppEntry(entry: Map) = appEntries.publish(entry) + + // --- LUI event dispatch --- + + private fun dispatch(event: LuiEvent) { + dispatchLuiEvent(event, bridge) + val drain = effectDrain ?: return + scope.launch { drain.drain(scope) } + } + + private fun applyPatch(patch: String) { + if (patch.isEmpty()) return + try { + patchFilter.applyJson(patch) + } catch (error: Throwable) { + reportError(error) + startupError = error + } + } + + private suspend fun applyCoreResponse(response: String) { + applyPatch(bridge.applySnapshot(response)) + outlinerCommands.deliver(response) + } + + private suspend fun sendOutlinerEvent(event: JSONObject) { + val response = bridge.callCore( + JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject() + .put("action", "outlinerEvent") + .put("payload", event.toString()), + ) + .toString() + ) + applyCoreResponse(response) + } + + // --- Effects --- + + private suspend fun executeEffect(effect: NativeEffect): NativeEffectResolution { + if (effect.kind == "present-attachment") { + return try { + if (effect.text == "audio") { + presentAudioRecording(null) + } else { + presentAttachment(effect.text, null) + } + NativeEffectResolution.Discard() + } catch (error: Throwable) { + reportError(error) + NativeEffectResolution.Failure(error.toString()) + } + } + val executor = coreEffects + ?: return NativeEffectResolution.Discard( + succeeded = false, + message = "The native core effect executor is unavailable", + ) + val resolution = executor.execute(effect) + if (effect.kind == "save-settings" && resolution.succeeded) { + runCatching { JSONObject(effect.text) }.getOrNull()?.let { + appearance = it.optString("appearance", "system") + } + } + if (effect.kind == "sign-in" && resolution.succeeded) { + restoreCore(hasStoredSession = true) + } + if (effect.kind == "sign-out" && resolution.succeeded) { + hasAuthenticatedSession = false + hasOpenGraph = false + graphCatalogAutoRefresh?.stopPeriodic() + } + if (resolution.succeeded && + effect.kind in setOf("open-graph", "unlock-graph", "create-graph") + ) { + hasOpenGraph = true + graphCatalogAutoRefresh?.stopPeriodic() + } + return resolution + } + + // --- Bootstrap / restore --- + + private fun restoreCore(hasStoredSession: Boolean, storage: AndroidStorageState? = null) { + val active = activeBootstrap + if (active != null) { + if (hasStoredSession && !activeBootstrapHadSession) { + scope.launch { + active.join() + restoreCore(hasStoredSession = true) + } + } + return + } + activeBootstrapHadSession = hasStoredSession + activeBootstrap = scope.launch { + try { + runCoreRestore(hasStoredSession, storage) + } finally { + activeBootstrap = null + } + } + } + + private suspend fun runCoreRestore(hasStoredSession: Boolean, storage: AndroidStorageState?) { + var accessToken = "" + if (hasStoredSession) { + try { + accessToken = platformEffects.restoreAccessToken() ?: "" + if (accessToken.isBlank()) { + error("The stored session did not return an access token") + } + } catch (error: Throwable) { + hasAuthenticatedSession = false + applyPatch( + bridge.applyHostUpdate( + kind = "authentication", + payload = JSONObject() + .put("state", "signedOut") + .put("errorMessage", error.toString()) + .toString(), + ) + ) + reportError(error) + } + } + hasAuthenticatedSession = accessToken.isNotBlank() + try { + logRuntime("info", "core", "Restoring core state") + val state = platformEffects.coreStartupState(accessToken, storage) + val restored = CoreBootstrap( + callCore = bridge::callCore, + trace = { traceGraphLifecycle("bootstrap $it") }, + ).restore(state) + applyCoreResponse(restored.catalogResponse) + graphCatalogAutoRefresh?.rememberCatalog(restored.catalogResponse) + applyPatch( + bridge.applyHostUpdate( + kind = "local-graph-ids", + payload = org.json.JSONArray(restored.localGraphIds).toString(), + ) + ) + hasOpenGraph = restored.graphResponse != null + restored.graphResponse?.let { applyCoreResponse(it) } + applyPatch(bridge.applyHostUpdate("graph-loading", "false")) + logRuntime("info", "core", "Core state restored") + appEntries.markReady() + updateCatalogPolling("restore") + } catch (error: Throwable) { + logRuntime("error", "core", error.toString()) + reportError(error) + applyPatch(bridge.applyHostUpdate("graph-loading", "false")) + } + } + + private fun updateCatalogPolling(reason: String) { + if (shouldPollGraphCatalog(hasAuthenticatedSession, hasOpenGraph, appIsForeground)) { + graphCatalogAutoRefresh?.startPeriodic() + scope.launch { graphCatalogAutoRefresh?.refresh() } + } else { + graphCatalogAutoRefresh?.stopPeriodic() + } + } + + // --- App entries (deep links + share intents) --- + + private suspend fun handleAppEntry(entry: AndroidAppEntry) { + logRuntime("info", "ui", "Handling Android app entry ${entry.kind}") + when (entry.kind) { + AndroidAppEntryKind.OpenCapture -> + applyPatch(bridge.applyHostUpdate("open-capture", "{}")) + AndroidAppEntryKind.OpenJournal -> applyAppEntryCoreRequest( + JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject().put("action", "clearSelectedPage"), + ) + .toString() + ) + AndroidAppEntryKind.SharedText -> applyAppEntryCoreRequest( + entry.coreRequest(newCoreUuid(), System.currentTimeMillis()) + ) + AndroidAppEntryKind.SharedAsset -> + addImportedAsset(requireNotNull(entry.asset), targetBlockId = null) + } + } + + private suspend fun applyAppEntryCoreRequest(request: String) { + val response = bridge.callCore(request) + val decoded = JSONObject(response) + if (!decoded.optBoolean("ok")) { + error("The native core rejected the Android app entry") + } + applyCoreResponse(response) + } + + // --- Attachments / audio --- + + suspend fun presentAttachment(kind: String, targetBlockId: String?) { + logRuntime("info", "ui", "Requesting $kind attachment") + val assets = assetImporter.import(kind) + logRuntime("info", "ui", "Imported ${assets.size} $kind attachment(s)") + for (asset in assets) { + addImportedAsset(AndroidImportedAsset.fromMap(asset), targetBlockId) + } + } + + private suspend fun addImportedAsset(asset: AndroidImportedAsset, targetBlockId: String?) { + val response = bridge.callCore(asset.coreRequest(targetBlockId)) + if (!JSONObject(response).optBoolean("ok")) { + error("The native core rejected ${asset.title}") + } + logRuntime("info", "core", "Added attachment ${asset.title}") + applyCoreResponse(response) + } + + suspend fun presentAudioRecording(targetBlockId: String?) { + // The recording sheet UI is presented by the app composable layer + // (ui/extensions/ChatDialogs + LogseqChatApp's dialog host). + val (asset, transcriptionEnabled) = + com.logseq.chat.ui.extensions.ChatDialogs.recordAudio( + audioRecorder, + supportsAudioTranscription, + ) ?: return + val response = bridge.callCore(asset.coreRequest(targetBlockId)) + if (!JSONObject(response).optBoolean("ok")) { + error("The native core rejected the recorded audio asset") + } + applyCoreResponse(response) + if (transcriptionEnabled) { + scope.launch { transcribeRecording(asset) } + } + } + + private suspend fun transcribeRecording(asset: RecordedAudioAsset) { + try { + logRuntime("info", "ui", "Audio transcription started") + val transcript = AndroidAudioTranscriber.transcribe(asset.localPath).trim() + if (transcript.isEmpty()) return + val response = bridge.callCore( + asset.transcriptCoreRequest( + transcriptUuid = "${asset.uuid}-transcript", + transcript = transcript, + ) + ) + applyCoreResponse(response) + logRuntime("info", "ui", "Audio transcription completed") + } catch (error: Throwable) { + reportError(error) + } + } + + // --- Outliner platform commands --- + + private suspend fun handleOutlinerCommandBatch(batch: OutlinerPlatformCommandBatch) { + for (command in batch.commands) { + when (command.type) { + "haptic" -> performHaptic(command.style) + "confirmDelete" -> confirmDeletion(command.uuids) + "setClipboardText" -> platformServices.copyText(command.text.orEmpty()) + "setClipboardReferences" -> platformServices.copyText( + command.uuids.joinToString("\n") { "[[$it]]" } + ) + "setClipboardURLs" -> platformServices.copyText( + command.uuids.joinToString("\n") { + "logseq://graph/${batch.graphName}?block-id=$it" + } + ) + "pickAttachment" -> presentAttachment("files", command.uuid) + "takePhoto" -> presentAttachment("camera", command.uuid) + "recordAudio" -> presentAudioRecording(command.uuid) + "focusBlock" -> Unit // autofocus handles it in the retained editor + } + } + } + + private fun performHaptic(style: String?) { + val view = activity.window.decorView + val constant = when (style) { + "selection" -> android.view.HapticFeedbackConstants.CLOCK_TICK + else -> android.view.HapticFeedbackConstants.LONG_PRESS + } + view.performHapticFeedback(constant) + } + + private suspend fun confirmDeletion(blockIds: List) { + if (blockIds.isEmpty()) return + val confirmed = com.logseq.chat.ui.extensions.ChatDialogs + .confirmDeletion(blockIds.size > 1) + if (confirmed) { + sendOutlinerEvent(JSONObject().put("type", "confirmDelete")) + } + } + + // --- Tracing / logging --- + + private fun reportError(error: Throwable) { + logRuntime("error", "ui", error.toString()) + Log.e("ChatRuntime", "Effect failed", error) + com.logseq.chat.ui.extensions.ChatDialogs.notifyError( + "Something went wrong: $error" + ) + } + + private fun traceNativeEffect(message: String) { + val interesting = listOf( + "kind=open-graph", "kind=create-graph", "kind=unlock-graph", + "kind=refresh-graphs", "kind=send-capture", "kind=send-task", + "kind=search-nodes", "patch", + ) + if (interesting.none(message::contains)) return + Log.d("NativeEffect", message) + logRuntime("info", "ui", message) + } + + private fun traceGraphLifecycle(message: String) { + Log.d("GraphLifecycle", message) + logRuntime("info", "core", message) + } + + private fun traceGraphCatalogRefresh(message: String) { + Log.d("GraphCatalog", message) + logRuntime("info", "core", message) + } + + private fun logRuntime(level: String, source: String, message: String) { + platformServices.appendRuntimeLog(level, source, message) + } + + fun dispose() { + graphCatalogAutoRefresh?.dispose() + effectDrain?.dispose() + bridge.onCoreIdle = null + bridge.close() + } + + val effectiveAppearance: String get() = appearance +} + +// Recorded audio asset produced by the recording sheet — payload shape +// matches the former android_audio_recording.dart. +internal data class RecordedAudioAsset( + val uuid: String, + val title: String, + val assetType: String, + val size: Long, + val checksum: String, + val localPath: String, +) { + fun coreRequest(targetBlockId: String?): String = JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject() + .put("action", "addAsset") + .put( + "payload", + JSONObject() + .put("uuid", uuid) + .put("title", title) + .put("assetType", assetType) + .put("assetSize", size) + .put("assetChecksum", checksum) + .put("localPath", localPath) + .apply { + if (!targetBlockId.isNullOrEmpty()) { + put("targetBlockId", targetBlockId) + } + } + .toString(), + ), + ) + .toString() + + fun transcriptCoreRequest(transcriptUuid: String, transcript: String): String = JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put( + "params", + JSONObject() + .put("action", "addChildBlock") + .put( + "payload", + JSONObject() + .put("uuid", transcriptUuid) + .put("title", transcript) + .put("parentId", uuid) + .toString(), + ), + ) + .toString() +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreBootstrap.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreBootstrap.kt new file mode 100644 index 00000000..a221cd7c --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreBootstrap.kt @@ -0,0 +1,132 @@ +package com.logseq.chat.runtime + +import org.json.JSONObject + +// Kotlin port of the former core_bootstrap.dart: restore the core's +// persisted state — open the catalog database, dispatch configure with +// baseUrl/graphId/token, then open the selected local graph when it is +// not encrypted. +internal data class CoreStartupState( + val databasePath: String, + val graphsDirectory: String, + val baseUrl: String, + val selectedGraphId: String, + val localGraphIds: List, + val accessToken: String, +) + +internal data class CoreBootstrapResult( + val catalogResponse: String, + val graphResponse: String?, + val localGraphIds: List, +) + +internal class CoreBootstrap( + private val callCore: suspend (String) -> String, + private val trace: (String) -> Unit = {}, +) { + suspend fun restore(state: CoreStartupState): CoreBootstrapResult { + val catalogResponse = call( + operation = "open catalog", + request = request(method = "open", path = state.databasePath), + ) + val catalog = successfulResult(catalogResponse, operation = "open catalog") + successfulResult( + call( + operation = "configure graph", + request = request( + method = "dispatch", + action = "configure", + payload = JSONObject() + .put("baseUrl", state.baseUrl) + .put("graphId", state.selectedGraphId) + .put("token", state.accessToken) + .toString(), + ), + ), + operation = "configure graph", + ) + + var graphResponse: String? = null + if (state.selectedGraphId.isNotEmpty() && + state.localGraphIds.contains(state.selectedGraphId) && + !graphIsEncrypted(catalog, state.selectedGraphId) + ) { + val directory = "${state.graphsDirectory}/${state.selectedGraphId}" + graphResponse = call( + operation = "open local graph", + request = request( + method = "dispatch", + action = "openGraph", + payload = JSONObject() + .put("graphId", state.selectedGraphId) + .put("activePath", "$directory/graph.sqlite") + .put("checkpointPath", "$directory/sync.checkpoint") + .put("isEncrypted", false) + .toString(), + ), + ) + successfulResult(graphResponse, operation = "open local graph") + } + + return CoreBootstrapResult( + catalogResponse = catalogResponse, + graphResponse = graphResponse, + localGraphIds = state.localGraphIds, + ) + } + + private suspend fun call(operation: String, request: String): String { + trace("$operation started") + val started = System.nanoTime() + try { + return callCore(request) + } finally { + trace("$operation completed durationMs=${(System.nanoTime() - started) / 1_000_000}") + } + } + + private fun graphIsEncrypted(catalog: JSONObject, graphId: String): Boolean { + val graphs = catalog.optJSONArray("graphs") ?: return false + for (index in 0 until graphs.length()) { + val graph = graphs.optJSONObject(index) ?: continue + if (graph.optString("id") == graphId) return graph.optBoolean("isEncrypted") + } + return false + } + + private fun successfulResult(encoded: String, operation: String): JSONObject { + val response = try { + JSONObject(encoded) + } catch (error: Throwable) { + throw IllegalStateException( + "Could not $operation: core response is not an object", + error, + ) + } + if (!response.optBoolean("ok")) { + val message = response.optJSONObject("error")?.optString("message") + throw IllegalStateException( + "Could not $operation: ${message ?: "unknown core error"}" + ) + } + return response.optJSONObject("result") ?: JSONObject() + } + + private fun request( + method: String, + action: String? = null, + payload: String? = null, + path: String? = null, + ): String { + val params = JSONObject() + if (action != null) params.put("action", action) + if (payload != null) params.put("payload", payload) + if (path != null) params.put("path", path) + return JSONObject() + .put("apiVersion", 1) + .put("method", method) + .put("params", params) + .toString() + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreEffectExecutor.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreEffectExecutor.kt new file mode 100644 index 00000000..9dfd7d36 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/CoreEffectExecutor.kt @@ -0,0 +1,270 @@ +package com.logseq.chat.runtime + +import java.util.UUID +import org.json.JSONObject + +// Kotlin port of the former core_effect_executor.dart. +// +// Routes each NativeEffect to its executor: +// - platform effect kinds → AndroidPlatformEffects +// - graph effect kinds → AndroidGraphLifecycle +// - everything else → a core `dispatch` RPC whose response is +// applied via applySnapshot when ok:true. +internal class CoreEffectExecutor( + private val callCore: suspend (String) -> String, + private val executePlatformEffect: NativeEffectExecutor, + private val executeGraphEffect: NativeEffectExecutor, + private val nowMilliseconds: () -> Long = { System.currentTimeMillis() }, + private val newUuid: () -> String = ::newCoreUuid, +) { + suspend fun execute(effect: NativeEffect): NativeEffectResolution { + if (effect.kind in platformEffectKinds) { + return executePlatformEffect.execute(effect) + } + if (effect.kind in graphEffectKinds) { + return executeGraphEffect.execute(effect) + } + return try { + val request = request(effect) + ?: return NativeEffectResolution.Discard( + succeeded = false, + message = "Unsupported LG effect: ${effect.kind}", + ) + val response = callCore(request.toString()) + resolution(response) + } catch (error: Throwable) { + NativeEffectResolution.Failure(error.toString()) + } + } + + private fun request(effect: NativeEffect): JSONObject? { + val action: String + var payload: String? = null + when (effect.kind) { + "send-capture" -> { + action = "send" + payload = JSONObject() + .put("text", effect.text) + .put("uuid", newUuid()) + .put("now", nowMilliseconds()) + .toString() + } + "send-task" -> { + action = "sendTask" + payload = JSONObject() + .put("text", effect.text) + .put("uuid", newUuid()) + .put("now", nowMilliseconds()) + .put("status", metadataObject(effect, "task status")) + .toString() + } + "search-nodes" -> { + action = "searchNodes" + payload = effect.text + } + "open-node" -> { + action = "openNode" + payload = JSONObject().put("uuid", effect.text).toString() + } + "close-node" -> action = "closeNode" + "select-sidebar-page" -> { + action = "selectPage" + payload = effect.text + } + "clear-selected-page" -> action = "clearSelectedPage" + "load-older-journals" -> action = "loadOlderJournals" + "set-page-favorite" -> { + action = "setPageFavorite" + payload = JSONObject() + .put("pageUuid", effect.text) + .put("favorite", effect.value == 1L) + .put("operationId", newUuid()) + .put("now", nowMilliseconds()) + .toString() + } + "delete-page" -> { + action = "deletePage" + payload = JSONObject() + .put("pageUuid", effect.text) + .put("operationId", newUuid()) + .put("now", nowMilliseconds()) + .toString() + } + "load-flashcards" -> { + action = "loadFlashcards" + payload = nowMilliseconds().toString() + } + "review-flashcard" -> { + action = "reviewFlashcard" + payload = JSONObject() + .put("uuid", requiredUuid(effect)) + .put("rating", effect.text) + .put("now", nowMilliseconds()) + .put("operationId", newUuid()) + .toString() + } + "refresh-graphs" -> action = "refresh" + "tap-outliner-block" -> return outlinerRequest( + JSONObject().put("type", "tapBlock").put("uuid", effect.text) + ) + "toggle-outliner-collapsed" -> return outlinerRequest( + JSONObject().put("type", "toggleCollapsed").put("uuid", effect.text) + ) + "long-press-outliner-block" -> return outlinerRequest( + JSONObject().put("type", "longPressBlock").put("uuid", effect.text) + ) + "add-root-block" -> return outlinerRequest( + JSONObject().put("type", "addRootBlock").put("uuid", effect.text) + ) + "drop-outliner-blocks" -> { + val placement = effect.metadata + ?: throw IllegalArgumentException( + "The outliner drop effect is missing its placement" + ) + return outlinerRequest( + JSONObject() + .put("type", "dropBlocks") + .put("targetUuid", effect.text) + .put("placement", placement) + ) + } + "set-outliner-task-status" -> { + val status = metadataObject(effect, "task status") + return outlinerRequest( + JSONObject() + .put("type", "setTaskStatus") + .put("uuid", effect.text) + .put("statusIdent", status.optString("ident")) + .put("statusUuid", status.optString("uuid")) + ) + } + "outliner-toolbar" -> return outlinerRequest( + JSONObject().put("type", "toolbar").put("action", effect.text) + ) + "choose-outliner-autocomplete" -> return outlinerRequest( + JSONObject().put("type", "chooseAutocomplete").put("value", effect.text) + ) + "save-outliner-editing" -> return outlinerRequest( + JSONObject().put("type", "saveEditing") + ) + "cancel-outliner-editing" -> return outlinerRequest( + JSONObject().put("type", "cancelEditing") + ) + "change-outliner-text" -> return outlinerRequest( + JSONObject() + .put("type", "textChanged") + .put("uuid", requiredUuid(effect)) + .put("title", effect.text) + .put("caretUTF16Offset", requiredValue(effect)) + ) + "return-outliner-editor" -> return outlinerRequest( + JSONObject() + .put("type", "returnPressed") + .put("uuid", requiredUuid(effect)) + .put("title", effect.text) + .put("caretUTF16Offset", requiredValue(effect)) + ) + "backspace-outliner-editor" -> return outlinerRequest( + JSONObject() + .put("type", "backspacePressed") + .put("uuid", requiredUuid(effect)) + .put("title", effect.text) + .put("selectionLength", requiredValue(effect)) + ) + "move-outliner-caret" -> return outlinerRequest( + JSONObject() + .put("type", "caretMoved") + .put("uuid", requiredUuid(effect)) + .put("caretUTF16Offset", requiredValue(effect)) + ) + else -> return null + } + return rpcRequest(action, payload) + } + + private fun outlinerRequest(event: JSONObject): JSONObject = + rpcRequest("outlinerEvent", event.toString()) + + private fun rpcRequest(action: String, payload: String?): JSONObject { + val params = JSONObject().put("action", action) + if (payload != null) params.put("payload", payload) + return JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put("params", params) + } + + private fun metadataObject(effect: NativeEffect, label: String): JSONObject { + val metadata = effect.metadata + ?: throw IllegalArgumentException( + "The ${effect.kind} effect is missing its $label" + ) + return try { + JSONObject(metadata) + } catch (error: Throwable) { + throw IllegalArgumentException( + "The ${effect.kind} $label must be an object", + error, + ) + } + } + + private fun requiredUuid(effect: NativeEffect): String = effect.uuid + ?: throw IllegalArgumentException( + "The ${effect.kind} effect is missing its UUID" + ) + + private fun requiredValue(effect: NativeEffect): Long = effect.value + ?: throw IllegalArgumentException( + "The ${effect.kind} effect is missing its integer value" + ) + + private fun resolution(response: String): NativeEffectResolution { + val decoded = try { + JSONObject(response) + } catch (error: Throwable) { + throw IllegalArgumentException( + "The native core response must be an object", + error, + ) + } + if (decoded.optBoolean("ok")) { + return NativeEffectResolution.CoreResponse(response) + } + val error = decoded.optJSONObject("error") + val code = error?.optString("code")?.takeIf(String::isNotEmpty) ?: "core_error" + val message = error?.optString("message")?.takeIf(String::isNotEmpty) + ?: "The OCaml core rejected the effect" + return NativeEffectResolution.Discard(succeeded = false, message = "$code\n$message") + } + + companion object { + private val platformEffectKinds = setOf( + "persist-composer-draft", + "present-attachment", + "present-asset", + "present-page-share", + "sync-now", + "delete-local-graph", + "save-settings", + "export-graph-database", + "open-external-url", + "refresh-runtime-log", + "copy-runtime-log", + "sign-in", + "sign-out", + ) + + private val graphEffectKinds = setOf( + "open-graph", + "unlock-graph", + "create-graph", + ) + } +} + +// Same shape as the Dart counterpart: microsecond timestamp hex twice. +internal fun newCoreUuid(): String { + val timestamp = (System.currentTimeMillis() * 1_000).toString(16) + return "$timestamp-${timestamp.padStart(32, '0').substring(0, 32)}" +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/GraphCatalogAutoRefresh.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/GraphCatalogAutoRefresh.kt new file mode 100644 index 00000000..f1fdad4c --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/GraphCatalogAutoRefresh.kt @@ -0,0 +1,115 @@ +package com.logseq.chat.runtime + +import java.util.concurrent.Executors +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.TimeUnit +import org.json.JSONObject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch + +// Kotlin port of the former graph_catalog_auto_refresh.dart + +// graph_catalog_polling_policy.dart. +internal fun shouldPollGraphCatalog( + authenticated: Boolean, + hasOpenGraph: Boolean, + foreground: Boolean, +): Boolean = authenticated && !hasOpenGraph && foreground + +internal class GraphCatalogAutoRefresh( + private val scope: CoroutineScope, + private val callCore: suspend (String) -> String, + private val applyCoreResponse: suspend (String) -> Unit, + private val trace: (String) -> Unit = {}, +) { + private val scheduler = Executors.newSingleThreadScheduledExecutor() + private var periodicTask: ScheduledFuture<*>? = null + private var activeRefresh: Job? = null + private var catalogFingerprint: String? = null + + fun rememberCatalog(response: String) { + catalogFingerprint = fingerprint(response) + } + + fun startPeriodic(intervalMillis: Long = 15_000) { + if (periodicTask != null) return + trace("periodic.start intervalMs=$intervalMillis") + periodicTask = scheduler.scheduleWithFixedDelay( + { scope.launch { runCatching { refresh() } } }, + intervalMillis, + intervalMillis, + TimeUnit.MILLISECONDS, + ) + } + + fun stopPeriodic() { + periodicTask?.cancel(false) + periodicTask = null + trace("periodic.stop") + } + + suspend fun refresh(): Boolean { + activeRefresh?.let { + it.join() + return true + } + val job = scope.launch { + run() + } + activeRefresh = job + job.join() + activeRefresh = null + return lastRefreshResult + } + + @Volatile private var lastRefreshResult: Boolean = false + + private suspend fun run() { + trace("refresh.start") + val response = callCore( + JSONObject() + .put("apiVersion", 1) + .put("method", "dispatch") + .put("params", JSONObject().put("action", "refreshGraphCatalog")) + .toString() + ) + val decoded = try { + JSONObject(response) + } catch (_: Throwable) { + null + } + if (decoded == null || !decoded.optBoolean("ok")) { + val error = decoded?.optJSONObject("error") + trace( + "refresh.rejected code=${error?.optString("code") ?: "unknown"} " + + "message=${error?.optString("message") ?: "Unknown core response"}" + ) + lastRefreshResult = false + return + } + val fingerprint = fingerprintFromEnvelope(decoded) + if (fingerprint != null && fingerprint == catalogFingerprint) { + trace("refresh.unchanged") + lastRefreshResult = true + return + } + applyCoreResponse(response) + catalogFingerprint = fingerprint + trace("refresh.complete") + lastRefreshResult = true + } + + private fun fingerprint(response: String): String? = try { + fingerprintFromEnvelope(JSONObject(response)) + } catch (_: Throwable) { + null + } + + private fun fingerprintFromEnvelope(envelope: JSONObject): String? = + envelope.optJSONObject("result")?.optJSONArray("graphs")?.toString() + + fun dispose() { + stopPeriodic() + scheduler.shutdownNow() + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt new file mode 100644 index 00000000..580dc82a --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt @@ -0,0 +1,82 @@ +package com.logseq.chat.runtime + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.Logout +import androidx.compose.material.icons.automirrored.filled.Send +import androidx.compose.material.icons.filled.* +import androidx.compose.material.icons.outlined.* +import androidx.compose.ui.graphics.vector.ImageVector +import dev.lui.LuiIconResolver + +// App icon vocabulary (the former logseq_chat_icons.dart) mapped onto +// Material Symbols vectors — same symbolic names the core emits. +internal val logseqChatAppIcons: Map = mapOf( + "outliner-bullet" to Icons.Filled.Circle, + "add" to Icons.Filled.Add, + "arrow-up" to Icons.Filled.KeyboardArrowUp, + "arrow-down" to Icons.Filled.KeyboardArrowDown, + "calendar" to Icons.Outlined.DateRange, + "chevron-down" to Icons.Filled.KeyboardArrowDown, + "chevron-right" to Icons.Filled.KeyboardArrowRight, + "close" to Icons.Filled.Close, + "composer-add" to Icons.Outlined.AddCircle, + "composer-file" to Icons.Filled.Add, + "composer-photo" to Icons.Filled.Add, + "disclosure-down" to Icons.Filled.KeyboardArrowDown, + "disclosure-right" to Icons.Filled.KeyboardArrowRight, + "graph-locked" to Icons.Outlined.Lock, + "document" to Icons.Outlined.Add, + "download" to Icons.Outlined.Share, + "flashcards" to Icons.Outlined.Star, + "folder" to Icons.Outlined.Star, + "graph-local" to Icons.Filled.Star, + "graph-remote" to Icons.Outlined.Star, + "history" to Icons.Filled.Refresh, + "logo" to Icons.Filled.Star, + "more-horiz" to Icons.Filled.MoreVert, + "more-vert" to Icons.Filled.MoreVert, + "navigation-back" to Icons.AutoMirrored.Filled.ArrowBack, + "open-external" to Icons.Filled.Share, + "refresh" to Icons.Filled.Refresh, + "search" to Icons.Filled.Search, + "send" to Icons.AutoMirrored.Filled.Send, + "selected" to Icons.Filled.CheckCircle, + "settings" to Icons.Outlined.Settings, + "share" to Icons.Outlined.Share, + "sidebar-toggle" to Icons.Filled.Menu, + "sign-out" to Icons.AutoMirrored.Filled.Logout, + "star" to Icons.Outlined.Star, + "star-filled" to Icons.Filled.Star, + "status-dot" to Icons.Filled.Circle, + "sync-status" to Icons.Filled.Refresh, + "task-backlog" to Icons.Outlined.Circle, + "task-canceled" to Icons.Outlined.Clear, + "task-doing" to Icons.Filled.Refresh, + "task-done" to Icons.Outlined.CheckCircle, + "task-review" to Icons.Outlined.CheckCircle, + "task-todo" to Icons.Outlined.Circle, + "terminal" to Icons.Filled.Star, + "toolbar-attachment" to Icons.Filled.Add, + "toolbar-audio" to Icons.Filled.Edit, + "toolbar-camera" to Icons.Filled.Add, + "toolbar-copy" to Icons.Filled.Edit, + "toolbar-copy-reference" to Icons.Filled.Edit, + "toolbar-copy-url" to Icons.Filled.Share, + "toolbar-delete" to Icons.Outlined.Delete, + "toolbar-hide-keyboard" to Icons.Filled.KeyboardArrowDown, + "toolbar-indent" to Icons.Filled.ArrowForward, + "toolbar-move-down" to Icons.Filled.KeyboardArrowDown, + "toolbar-move-up" to Icons.Filled.KeyboardArrowUp, + "toolbar-outdent" to Icons.Filled.ArrowBack, + "toolbar-tag" to Icons.Filled.Tag, + "toolbar-task" to Icons.Outlined.CheckBox, + "toolbar-unselect" to Icons.Filled.Clear, + "trash" to Icons.Outlined.Delete, + "unselected" to Icons.Outlined.Circle, + "warning" to Icons.Filled.Warning, +) + +internal val logseqChatIconResolver = LuiIconResolver { name -> + logseqChatAppIcons[name] ?: LuiIconResolver.DEFAULT.icon(name) +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatNativeBridge.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatNativeBridge.kt new file mode 100644 index 00000000..5119e4e8 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatNativeBridge.kt @@ -0,0 +1,159 @@ +package com.logseq.chat.runtime + +import android.util.Log +import com.logseq.chat.NativeCore +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext + +// JNI bridge into liblogseq_chat_core.so — the Kotlin port of +// the former logseq_chat_native_bridge.dart. +// +// LUI event calls run through the scheduler's UI lane so patches +// produced mid-flight cannot interleave with a busy core RPC; the effect +// entry points (takeEffect / resolveEffect / applySnapshot / +// applyHostUpdate) return "" and re-queue while the core is busy. +// `call` runs the blocking JNI call on Dispatchers.Default, matching the +// Dart implementation's worker-isolate call. +internal class LogseqChatNativeBridge( + private val onPatch: (String) -> Unit = {}, + private val runtimeScheduler: NativeRuntimeScheduler = NativeRuntimeScheduler(), +) { + var onCoreIdle: (() -> Unit)? + get() = runtimeScheduler.onIdle + set(value) { + runtimeScheduler.onIdle = value + } + + val scheduler: NativeRuntimeScheduler get() = runtimeScheduler + + private fun decode(bytes: ByteArray?): String = bytes?.toString(Charsets.UTF_8).orEmpty() + + private fun encode(text: String): ByteArray = text.toByteArray(Charsets.UTF_8) + + private fun apply(patch: String) { + if (patch.isNotEmpty()) onPatch(patch) + } + + // platform 3 = AndroidOS, host 3 = the Android host slot the core + // renders for (the legacy Android host kind in + // shared/src/logseq_chat/native_bridge.ml; the Kotlin backend takes + // over that host profile). + fun initialize( + platformCode: Int = 3, + hostCode: Int = 3, + authenticationCode: Int = 1, + ): Long { + apply(decode(NativeCore.luiInitialize(platformCode, hostCode, authenticationCode))) + return NativeCore.luiRootNode() + } + + fun close() = runtimeScheduler.runUi { apply(decode(NativeCore.luiDispose())) } + + fun appear(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiAppear(node))) } + fun press(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiPress(node))) } + fun longPress(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiLongPress(node))) } + fun submit(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiSubmit(node))) } + fun change(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiChange(node))) } + fun dismiss(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiDismiss(node))) } + fun doublePress(node: Long) = runtimeScheduler.runUi { apply(decode(NativeCore.luiDoublePress(node))) } + + fun textChanged(node: Long, text: String) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiTextChanged(node, encode(text)))) + } + + fun toggleChanged(node: Long, checked: Boolean) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiToggleChanged(node, if (checked) 1 else 0))) + } + + fun valueChanged(node: Long, value: Double) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiValueChanged(node, value))) + } + + fun picked(node: Long, payload: String) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiPicked(node, encode(payload)))) + } + + fun visibleRange(node: Long, first: Long, last: Long) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiVisibleRange(node, first, last))) + } + + fun scrollCompleted(node: Long, token: Long, outcome: String) = runtimeScheduler.runUi { + apply(decode(NativeCore.luiScrollCompleted(node, token, encode(outcome)))) + } + + fun extensionEvent( + node: Long, + identifier: String, + name: String, + text: String, + value: Long, + ) = runtimeScheduler.runUi { + apply( + decode( + NativeCore.luiExtensionEvent( + node, + encode(identifier), + encode(name), + encode(text), + value, + ) + ) + ) + } + + // --- NativeEffectRuntime surface --- + + fun takeEffect(): String = + if (runtimeScheduler.isCoreBusy) "" else decode(NativeCore.luiTakeEffect()) + + fun resolveEffect(id: Long, succeeded: Boolean, message: String): String { + if (runtimeScheduler.isCoreBusy) { + runtimeScheduler.runUi { + apply(decode(NativeCore.luiResolveEffect(id, if (succeeded) 1 else 0, encode(message)))) + } + return "" + } + return decode(NativeCore.luiResolveEffect(id, if (succeeded) 1 else 0, encode(message))) + } + + fun applySnapshot(response: String): String { + if (runtimeScheduler.isCoreBusy) { + runtimeScheduler.runUi { + apply(decode(NativeCore.luiApplySnapshot(encode(response)))) + } + return "" + } + return decode(NativeCore.luiApplySnapshot(encode(response))) + } + + fun applyHostUpdate(kind: String, payload: String): String { + if (runtimeScheduler.isCoreBusy) { + runtimeScheduler.runUi { + apply(decode(NativeCore.luiApplyHostUpdate(encode(kind), encode(payload)))) + } + return "" + } + return decode(NativeCore.luiApplyHostUpdate(encode(kind), encode(payload))) + } + + // Core RPC ({apiVersion:1, method:open|dispatch, params:{...}}) — + // blocking JNI call on a background thread, serialized on the core lane. + suspend fun callCore(request: String): String = + runtimeScheduler.runCore { + withContext(Dispatchers.Default) { + decode(NativeCore.logseqChatCall(encode(request))) + } + } + + fun isLinked(): Boolean = runCatching { + NativeCore.luiRootNode() + true + }.getOrElse { + Log.w(TAG, "liblogseq_chat_core is not linked", it) + false + } + + private companion object { + const val TAG = "LogseqChatBridge" + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiDispatch.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiDispatch.kt new file mode 100644 index 00000000..b2701564 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiDispatch.kt @@ -0,0 +1,51 @@ +package com.logseq.chat.runtime + +import dev.lui.LuiEvent + +// Kotlin port of the former lui_dispatch.dart: LUI events → native +// bridge calls, including the extension (text, value) extraction the OCaml +// side reinterprets by identifier/name. +internal fun dispatchLuiEvent(event: LuiEvent, native: LogseqChatNativeBridge) { + when (event) { + is LuiEvent.Appear -> native.appear(event.node) + is LuiEvent.Press -> native.press(event.node) + is LuiEvent.LongPress -> native.longPress(event.node) + is LuiEvent.DoublePress -> native.doublePress(event.node) + is LuiEvent.Change -> native.change(event.node) + is LuiEvent.Submit -> native.submit(event.node) + is LuiEvent.Dismiss -> native.dismiss(event.node) + is LuiEvent.TextChanged -> native.textChanged(event.node, event.text) + is LuiEvent.ToggleChanged -> native.toggleChanged(event.node, event.checked) + is LuiEvent.ValueChanged -> native.valueChanged(event.node, event.value) + is LuiEvent.Picked -> native.picked(event.node, event.payload) + is LuiEvent.VisibleRange -> native.visibleRange(event.node, event.first, event.last) + is LuiEvent.ScrollCompleted -> + native.scrollCompleted(event.node, event.token, event.outcome) + is LuiEvent.Extension -> native.extensionEvent( + event.node, + event.identifier, + event.name, + extensionText(event.values), + extensionValue(event.values), + ) + } +} + +internal fun extensionText(values: Map): String { + for (key in listOf("uuid", "title", "query", "value")) { + (values[key] as? String)?.let { return it } + } + return "" +} + +internal fun extensionValue(values: Map): Long { + for (key in listOf("caret-utf16-offset", "selection-length", "count")) { + (values[key] as? Number)?.let { return it.toLong() } + } + return when (values["placement"]) { + "before" -> 0 + "inside" -> 1 + "after" -> 2 + else -> 0 + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiPatchFilter.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiPatchFilter.kt new file mode 100644 index 00000000..60a84a71 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/LuiPatchFilter.kt @@ -0,0 +1,106 @@ +package com.logseq.chat.runtime + +import org.json.JSONArray +import org.json.JSONObject + +// Kotlin port of the former Dart patch applier. +// +// Filters patch ops for presentation hints the Compose backend does not +// (or must not) honor — same drop rules as the Dart applier so core +// views keep working unmodified: +// - container-relative-frame(-inset): always dropped +// - selected on virtual-list: dropped +// - padding-horizontal/vertical on kinds other than row/column/grid/box +// - style-class on dialog/sheet +// - icon-placement unless leading/trailing on (toggle-)button +// - role unless "treeitem" on row/column/panel/card/box/list-item +// `size: icon` on buttons additionally synthesizes text-alignment:center +// so the glyph centers in the touch target. +internal class LuiPatchFilter( + private val apply: (String) -> Unit, +) { + private val nodeKinds = mutableMapOf() + private val ignoredProperties = mutableSetOf() + + fun applyJson(patch: String) { + val document = JSONObject(patch) + val operations = document.getJSONArray("ops") + val nextNodeKinds = HashMap(nodeKinds) + val nextIgnored = HashSet(ignoredProperties) + val compatible = JSONArray() + + for (index in 0 until operations.length()) { + val operation = operations.getJSONObject(index) + val name = operation.getString("op") + val id = if (operation.has("id")) operation.getLong("id") else null + when { + name == "create-node" && id != null -> + nextNodeKinds[id] = operation.getString("kind") + name == "drop-node" && id != null -> { + nextNodeKinds.remove(id) + nextIgnored.removeIf { it.startsWith("$id:") } + } + name == "set-prop" && id != null -> { + val property = operation.getString("property") + val key = "$id:$property" + if (isUnsupportedPresentationHint( + kind = nextNodeKinds[id], + property = property, + value = operation.opt("value"), + ) + ) { + nextIgnored.add(key) + continue + } + nextIgnored.remove(key) + if (property == "size" && + operation.opt("value") == "icon" && + nextNodeKinds[id] in setOf("button", "toggle-button") + ) { + compatible.put(operation) + compatible.put( + JSONObject() + .put("op", "set-prop") + .put("id", id) + .put("property", "text-alignment") + .put("value", "center") + ) + continue + } + } + name == "remove-prop" && id != null -> { + val property = operation.getString("property") + if (nextIgnored.remove("$id:$property")) continue + } + } + compatible.put(operation) + } + + apply(document.put("ops", compatible).toString()) + nodeKinds.clear() + nodeKinds.putAll(nextNodeKinds) + ignoredProperties.clear() + ignoredProperties.addAll(nextIgnored) + } + + companion object { + fun isUnsupportedPresentationHint( + kind: String?, + property: String, + value: Any?, + ): Boolean = when (property) { + "container-relative-frame", "container-relative-frame-inset" -> true + "selected" -> kind == "virtual-list" + "padding-horizontal", "padding-vertical" -> + kind !in setOf("row", "column", "grid", "box") + "style-class" -> kind == "dialog" || kind == "sheet" + "icon-placement" -> + (kind != "button" && kind != "toggle-button") || + (value != "leading" && value != "trailing") + "role" -> + value != "treeitem" || + kind !in setOf("row", "column", "panel", "card", "box", "list-item") + else -> false + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeEffectDrain.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeEffectDrain.kt new file mode 100644 index 00000000..5dd29622 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeEffectDrain.kt @@ -0,0 +1,235 @@ +package com.logseq.chat.runtime + +import java.util.concurrent.Executors +import java.util.concurrent.ScheduledFuture +import java.util.concurrent.TimeUnit +import org.json.JSONObject + +// Kotlin port of the former native_effect_drain.dart. +// +// The OCaml core queues host effects; takeEffect() dequeues one as +// {effect:{id,kind,text,uuid?,value?,metadata?}, patch}. The drain loop +// applies the patch, executes the effect, and feeds the resolution back: +// coreResponse → applySnapshot(response) +// hostUpdate → applyHostUpdate(kind, payload) +// discard → resolveEffect only +// plus a 1s-debounced outliner autosave after outliner text edits. +internal interface NativeEffectRuntime { + fun takeEffect(): String + fun resolveEffect(id: Long, succeeded: Boolean, message: String): String + fun applySnapshot(response: String): String + fun applyHostUpdate(kind: String, payload: String): String +} + +internal data class NativeEffect( + val id: Long, + val kind: String, + val text: String, + val uuid: String? = null, + val value: Long? = null, + val metadata: String? = null, +) + +internal enum class NativeEffectOutputKind { CoreResponse, HostUpdate, Discard } + +internal sealed class NativeEffectResolution( + val succeeded: Boolean, + val message: String, +) { + class CoreResponse(val response: String) : NativeEffectResolution(true, response) + class HostUpdate(val kind: String, val payload: String) : NativeEffectResolution(true, payload) + class Discard(succeeded: Boolean = true, message: String = "") : + NativeEffectResolution(succeeded, message) + class Failure(message: String) : NativeEffectResolution(false, message) +} + +internal fun interface NativeEffectExecutor { + suspend fun execute(effect: NativeEffect): NativeEffectResolution +} + +internal class NativeEffectDrain( + private val runtime: NativeEffectRuntime, + private val execute: NativeEffectExecutor, + private val applyPatch: (String) -> Unit, + private val onError: (Throwable) -> Unit = {}, + private val trace: (String) -> Unit = {}, + private val afterCoreResponseApplied: (suspend (String) -> Unit)? = null, + var outlinerAutosaveDelayMillis: Long = 1_000, +) { + private val autosaveScheduler = Executors.newSingleThreadScheduledExecutor() + private var autosaveTask: ScheduledFuture<*>? = null + + @Volatile private var autosavePending = false + @Volatile private var disposed = false + + private var activeDrain: kotlinx.coroutines.Job? = null + + // Reentrant: concurrent drain() calls join the in-flight loop. + suspend fun drain(scope: kotlinx.coroutines.CoroutineScope) { + if (disposed) return + val active = activeDrain + if (active != null && active.isActive) { + active.join() + return + } + val job = kotlinx.coroutines.Job() + activeDrain = job + kotlinx.coroutines.withContext(job) { run() } + activeDrain = null + } + + private suspend fun run() { + while (true) { + val encoded = runtime.takeEffect() + if (encoded.isEmpty()) { + if (autosavePending) { + autosavePending = false + executeOutlinerAutosave() + continue + } + return + } + + val dispatch = try { + EffectDispatch.decode(encoded) + } catch (error: Throwable) { + onError(error) + return + } + + apply(dispatch.patch, "dispatch kind=${dispatch.effect.kind}") + cancelOutlinerAutosaveBeforeExecuting(dispatch.effect) + trace("start id=${dispatch.effect.id} kind=${dispatch.effect.kind}") + val resolution = execute.execute(dispatch.effect) + trace( + "finish id=${dispatch.effect.id} kind=${dispatch.effect.kind} " + + "succeeded=${resolution.succeeded}" + ) + if (resolution.succeeded) { + when (resolution) { + is NativeEffectResolution.CoreResponse -> { + apply(runtime.applySnapshot(resolution.response), "applySnapshot") + afterCoreResponseApplied?.invoke(resolution.response) + scheduleOutlinerAutosaveIfNeeded(dispatch.effect, resolution.response) + } + is NativeEffectResolution.HostUpdate -> apply( + runtime.applyHostUpdate(resolution.kind, resolution.payload), + "applyHostUpdate kind=${resolution.kind}", + ) + else -> Unit + } + } + apply( + runtime.resolveEffect( + dispatch.effect.id, + resolution.succeeded, + resolution.message, + ), + "resolveEffect id=${dispatch.effect.id} succeeded=${resolution.succeeded}", + ) + } + } + + fun dispose() { + disposed = true + autosaveTask?.cancel(false) + autosaveTask = null + autosavePending = false + autosaveScheduler.shutdownNow() + } + + private fun cancelOutlinerAutosaveBeforeExecuting(effect: NativeEffect) { + if (!effect.kind.contains("outliner") || effect.kind == "move-outliner-caret") return + autosaveTask?.cancel(false) + autosaveTask = null + autosavePending = false + } + + private fun scheduleOutlinerAutosaveIfNeeded(effect: NativeEffect, response: String) { + val shouldSchedule = when (effect.kind) { + "choose-outliner-autocomplete" -> true + "change-outliner-text" -> !responseHasOutlinerAutocomplete(response) + else -> false + } + if (!shouldSchedule || disposed) return + autosaveTask?.cancel(false) + autosaveTask = autosaveScheduler.schedule({ + autosavePending = true + // Trigger the drain; the pending flag is consumed at the top + // of the loop where the queue is empty. + autosaveDrain?.invoke() + }, outlinerAutosaveDelayMillis, TimeUnit.MILLISECONDS) + } + + // The timer thread cannot suspend; the owning ChatRuntime installs a + // hook that launches drain() on its scope. + var autosaveDrain: (() -> Unit)? = null + + private fun responseHasOutlinerAutocomplete(response: String): Boolean = try { + val envelope = JSONObject(response) + val result = envelope.optJSONObject("result") + val state = result?.optJSONObject("outlinerState") + state?.has("autocomplete") == true + } catch (_: Exception) { + false + } + + private suspend fun executeOutlinerAutosave() { + try { + val resolution = execute.execute( + NativeEffect(id = 0, kind = "save-outliner-editing", text = "") + ) + if (!resolution.succeeded) { + error("Outliner autosave failed: ${resolution.message}") + } + check(resolution is NativeEffectResolution.CoreResponse) { + "Outliner autosave did not return a core response" + } + apply(runtime.applySnapshot(resolution.response), "applySnapshot(outliner-autosave)") + afterCoreResponseApplied?.invoke(resolution.response) + } catch (error: Throwable) { + onError(error) + } + } + + private fun apply(patch: String, source: String) { + if (patch.isNotEmpty()) { + trace("applying patch from $source chars=${patch.length}") + applyPatch(patch) + trace("applied patch from $source") + } else { + trace("empty patch from $source") + } + } +} + +internal class EffectDispatch private constructor( + val effect: NativeEffect, + val patch: String, +) { + companion object { + fun decode(encoded: String): EffectDispatch { + val decoded = JSONObject(encoded) + val effect = decoded.optJSONObject("effect") + ?: throw IllegalArgumentException("Effect dispatch is missing effect") + val patch = decoded.optString("patch") + if (!decoded.has("patch") || patch == null) { + throw IllegalArgumentException("Effect dispatch is missing patch") + } + if (!effect.has("id") || !effect.has("kind") || !effect.has("text")) { + throw IllegalArgumentException("Effect contains invalid required values") + } + return EffectDispatch( + effect = NativeEffect( + id = effect.getLong("id"), + kind = effect.getString("kind"), + text = effect.getString("text"), + uuid = effect.optString("uuid").takeIf(String::isNotEmpty), + value = if (effect.has("value")) effect.getLong("value") else null, + metadata = effect.optString("metadata").takeIf(String::isNotEmpty), + ), + patch = patch, + ) + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeRuntimeScheduler.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeRuntimeScheduler.kt new file mode 100644 index 00000000..615989b2 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/NativeRuntimeScheduler.kt @@ -0,0 +1,54 @@ +package com.logseq.chat.runtime + +import java.util.ArrayDeque +import java.util.concurrent.atomic.AtomicInteger +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock + +// Kotlin port of the former native_runtime_scheduler.dart. +// +// Core-bound work (async effect execution, RPC) serializes on `runCore`; +// UI-facing native calls (LUI event dispatches) go through `runUi` and +// are deferred while the core is busy so a patch produced mid-flight can +// never interleave with the runCore call the UI was racing. +internal class NativeRuntimeScheduler { + var onIdle: (() -> Unit)? = null + + private val deferredUiCalls = ArrayDeque<() -> Unit>() + private val coreMutex = Mutex() + private val pendingCoreCalls = AtomicInteger(0) + + val isCoreBusy: Boolean get() = pendingCoreCalls.get() > 0 + + suspend fun runCore(operation: suspend () -> T): T { + pendingCoreCalls.incrementAndGet() + try { + return coreMutex.withLock { + try { + operation() + } finally { + if (pendingCoreCalls.decrementAndGet() == 0) { + flushUiCalls() + onIdle?.invoke() + } + } + } + } catch (error: Throwable) { + throw error + } + } + + fun runUi(operation: () -> Unit) { + if (isCoreBusy) { + deferredUiCalls.addLast(operation) + return + } + operation() + } + + private fun flushUiCalls() { + while (deferredUiCalls.isNotEmpty()) { + deferredUiCalls.removeFirst()() + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/OutlinerPlatformCommands.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/OutlinerPlatformCommands.kt new file mode 100644 index 00000000..b7ef5e61 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/OutlinerPlatformCommands.kt @@ -0,0 +1,80 @@ +package com.logseq.chat.runtime + +import org.json.JSONObject + +// Kotlin port of the former android_outliner_commands.dart: decodes the +// outlinerCommands batch inside each core response and replays the +// platform-side commands (clipboard, haptics, attachment pickers, delete +// confirmation) exactly once per revision. +internal data class OutlinerPlatformCommand( + val type: String, + val style: String? = null, + val text: String? = null, + val uuid: String? = null, + val uuids: List = emptyList(), +) { + companion object { + fun fromJson(value: JSONObject): OutlinerPlatformCommand { + val uuids = value.optJSONArray("uuids") + return OutlinerPlatformCommand( + type = value.optString("type"), + style = value.optString("style").takeIf(String::isNotEmpty), + text = value.optString("text").takeIf(String::isNotEmpty), + uuid = value.optString("uuid").takeIf(String::isNotEmpty), + uuids = uuids?.let { array -> + (0 until array.length()).mapNotNull { array.optString(it).takeIf(String::isNotEmpty) } + } ?: emptyList(), + ) + } + } +} + +internal data class OutlinerPlatformCommandBatch( + val revision: Long, + val graphName: String, + val commands: List, + val selectedBlockIds: List = emptyList(), +) + +internal class OutlinerPlatformCommandDispatcher( + private val onBatch: suspend (OutlinerPlatformCommandBatch) -> Unit, +) { + private var lastRevision = 0L + + suspend fun deliver(response: String) { + val batch = decode(response) ?: return + if (batch.revision <= lastRevision) return + lastRevision = batch.revision + if (batch.commands.isNotEmpty()) onBatch(batch) + } + + companion object { + fun decode(response: String): OutlinerPlatformCommandBatch? { + val decoded = try { + JSONObject(response) + } catch (_: Throwable) { + return null + } + if (!decoded.optBoolean("ok")) return null + val result = decoded.optJSONObject("result") ?: return null + if (!result.has("outlinerCommandRevision") || !result.has("outlinerCommands")) { + return null + } + val values = result.optJSONArray("outlinerCommands") ?: return null + val selected = result.optJSONObject("outlinerState") + ?.optJSONArray("selectedBlockIds") + return OutlinerPlatformCommandBatch( + revision = result.getLong("outlinerCommandRevision"), + graphName = result.optString("graphName"), + commands = (0 until values.length()) + .mapNotNull { values.optJSONObject(it) } + .map(OutlinerPlatformCommand::fromJson) + .filter { it.type.isNotEmpty() }, + selectedBlockIds = selected?.let { array -> + (0 until array.length()) + .mapNotNull { array.optString(it).takeIf(String::isNotEmpty) } + } ?: emptyList(), + ) + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatApp.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatApp.kt new file mode 100644 index 00000000..6f21a6cf --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatApp.kt @@ -0,0 +1,206 @@ +package com.logseq.chat.ui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Checkbox +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableLongStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.dp +import com.logseq.chat.runtime.ChatRuntime +import com.logseq.chat.runtime.RecordedAudioAsset +import com.logseq.chat.ui.extensions.ChatDialogs +import kotlinx.coroutines.delay + +// Port of the former Dart app composable + app frame: +// Material theme + a plain surface hosting the LUI backend content, +// plus the modal hosts (audio recording sheet, delete confirmation, +// error snackbar) the runtime requests through ChatDialogs. +@Composable +internal fun LogseqChatApp(runtime: ChatRuntime) { + val systemDark = isSystemInDarkTheme() + val dark = when (runtime.effectiveAppearance) { + "light" -> false + "dark" -> true + else -> systemDark + } + MaterialTheme( + colorScheme = if (dark) LogseqChatTheme.darkScheme else LogseqChatTheme.lightScheme, + ) { + androidx.compose.runtime.CompositionLocalProvider( + dev.lui.LocalLuiThemeDark provides dark, + ) { + val snackbarHostState = remember { SnackbarHostState() } + Scaffold( + snackbarHost = { SnackbarHost(snackbarHostState) }, + ) { padding -> + Box( + modifier = Modifier + .fillMaxSize() + .padding(padding) + .windowInsetsPadding(WindowInsets.safeDrawing), + ) { + val rootId = runtime.rootNodeId + if (rootId != null) { + runtime.backend.Content(rootId) + } + } + } + val error = ChatDialogs.errorMessage + LaunchedEffect(error) { + if (error != null) { + snackbarHostState.showSnackbar(error) + ChatDialogs.clearError() + } + } + AudioRecordingDialog() + DeleteConfirmationDialog() + } + } +} + +@Composable +private fun AudioRecordingDialog() { + val request = ChatDialogs.recordingRequest ?: return + var elapsedSeconds by remember { mutableLongStateOf(0L) } + var error by remember { mutableStateOf(null) } + var busy by remember { mutableStateOf(false) } + + LaunchedEffect(request) { + try { + request.recorder.start() + } catch (failure: Throwable) { + request.result.complete(null) + return@LaunchedEffect + } + while (true) { + delay(1_000) + elapsedSeconds++ + } + } + + AlertDialog( + onDismissRequest = { + if (!busy) { + request.recorder.cancel() + request.result.complete(null) + } + }, + title = { Text("Recording") }, + text = { + Column { + Row(verticalAlignment = Alignment.CenterVertically) { + LinearProgressIndicator(modifier = Modifier.weight(1f)) + Text( + "%d:%02d".format(elapsedSeconds / 60, elapsedSeconds % 60), + modifier = Modifier.padding(start = 12.dp), + ) + } + if (request.transcriptionSupported) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(top = 8.dp), + ) { + Checkbox( + checked = request.transcriptionEnabled, + onCheckedChange = { request.transcriptionEnabled = it }, + ) + Text("Transcribe when finished") + } + } + error?.let { + Text( + it, + color = MaterialTheme.colorScheme.error, + modifier = Modifier.padding(top = 8.dp), + ) + } + } + }, + confirmButton = { + TextButton( + enabled = !busy, + modifier = Modifier.testTag("button.audio.stop"), + onClick = { + busy = true + runCatching { request.recorder.stop() } + .onSuccess { map -> + request.result.complete( + RecordedAudioAsset( + uuid = map["uuid"] as String, + title = map["title"] as String, + assetType = map["assetType"] as String, + size = (map["size"] as Number).toLong(), + checksum = map["checksum"] as String, + localPath = map["localPath"] as String, + ), + ) + } + .onFailure { failure -> + busy = false + error = failure.toString() + } + }, + ) { Text("Stop") } + }, + dismissButton = { + TextButton( + enabled = !busy, + onClick = { + request.recorder.cancel() + request.result.complete(null) + }, + ) { Text("Cancel") } + }, + ) +} + +@Composable +private fun DeleteConfirmationDialog() { + val request = ChatDialogs.deleteConfirmation ?: return + AlertDialog( + onDismissRequest = { request.result.complete(false) }, + title = { Text(if (request.multiple) "Delete blocks?" else "Delete block?") }, + text = { + Text( + if (request.multiple) { + "The selected blocks will be removed permanently." + } else { + "The selected block will be removed permanently." + } + ) + }, + confirmButton = { + TextButton( + modifier = Modifier.testTag("button.confirm-delete"), + onClick = { request.result.complete(true) }, + ) { Text("Delete") } + }, + dismissButton = { + TextButton(onClick = { request.result.complete(false) }) { Text("Cancel") } + }, + ) +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatTheme.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatTheme.kt new file mode 100644 index 00000000..94207862 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/LogseqChatTheme.kt @@ -0,0 +1,45 @@ +package com.logseq.chat.ui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Typography +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +// Port of the former Dart theme — M3 fidelity scheme seeded +// on the chat accent; the light/dark surfaces match the previous theme so +// backend-side token lookups (surface-container-* names in LuiTheme) +// resolve to the same colors the previous app showed. +internal object LogseqChatTheme { + val accent = Color(0xff2d6cdf) + val lightSurface = Color(0xfff8f9ff) + val darkSurface = Color(0xff101318) + + val lightScheme = lightColorScheme( + primary = accent, + surface = lightSurface, + surfaceContainerLowest = Color(0xffffffff), + surfaceContainerLow = Color(0xfff2f3f8), + surfaceContainer = Color(0xffeceef4), + surfaceContainerHigh = Color(0xffe6e8ef), + surfaceContainerHighest = Color(0xffe0e2ea), + ) + + val darkScheme = darkColorScheme( + primary = Color(0xff8fb5ff), + surface = darkSurface, + surfaceContainerLowest = Color(0xff0b0e12), + surfaceContainerLow = Color(0xff14171d), + surfaceContainer = Color(0xff181c22), + surfaceContainerHigh = Color(0xff1d2229), + surfaceContainerHighest = Color(0xff22272f), + ) +} + +internal fun logseqChatThemeMode(appearance: String): String = when (appearance) { + "light" -> "light" + "dark" -> "dark" + else -> "system" +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatDialogs.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatDialogs.kt new file mode 100644 index 00000000..b894c4a8 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatDialogs.kt @@ -0,0 +1,70 @@ +package com.logseq.chat.ui.extensions + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import com.logseq.chat.AndroidAudioRecorder +import com.logseq.chat.runtime.RecordedAudioAsset +import kotlinx.coroutines.CompletableDeferred + +internal data class AudioRecordingRequest( + val result: CompletableDeferred, + var transcriptionEnabled: Boolean, + val transcriptionSupported: Boolean, + val recorder: AndroidAudioRecorder, +) + +internal data class DeleteConfirmationRequest( + val multiple: Boolean, + val result: CompletableDeferred, +) + +// Modal requests surfaced by ChatRuntime effects/commands and rendered by +// the app composable — the Compose analogue of the previous app's +// dialog/bottom-sheet helpers. +internal object ChatDialogs { + var recordingRequest by mutableStateOf(null) + private set + var deleteConfirmation by mutableStateOf(null) + private set + var errorMessage by mutableStateOf(null) + private set + + suspend fun recordAudio( + recorder: AndroidAudioRecorder, + transcriptionSupported: Boolean, + ): Pair? { + val result = CompletableDeferred() + val request = AudioRecordingRequest( + result = result, + transcriptionEnabled = transcriptionSupported, + transcriptionSupported = transcriptionSupported, + recorder = recorder, + ) + recordingRequest = request + val asset = try { + result.await() + } finally { + recordingRequest = null + } + return asset?.let { it to request.transcriptionEnabled } + } + + suspend fun confirmDeletion(multiple: Boolean): Boolean { + val result = CompletableDeferred() + deleteConfirmation = DeleteConfirmationRequest(multiple, result) + try { + return result.await() + } finally { + deleteConfirmation = null + } + } + + fun notifyError(message: String) { + errorMessage = message + } + + fun clearError() { + errorMessage = null + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatExtensions.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatExtensions.kt new file mode 100644 index 00000000..592549de --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/ChatExtensions.kt @@ -0,0 +1,162 @@ +package com.logseq.chat.ui.extensions + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.unit.dp +import dev.lui.LuiExtensionContext +import dev.lui.LuiExtensionRegistry + +// Port of the former logseq_chat_extensions.dart — the chat-specific +// extension hosts. Fingerprints are generated by the OCaml core and must +// match byte-for-byte. +private const val EDITOR_FINGERPRINT = + "lui-extension-v1|15:outliner-editor|profiles:android/flutter," + + "ios/swiftui|standard-children:0|children:|" + + "properties:18:caret-utf16-offset:int:required:none,5:title:string:" + + "required:none,8:block-id:string:required:none|events:11:text-change[" + + "18:caret-utf16-offset:int:required,5:title:string:required],12:caret-change[" + + "18:caret-utf16-offset:int:required],6:return[18:caret-utf16-offset:int:" + + "required,5:title:string:required],9:backspace[16:selection-length:int:" + + "required,5:title:string:required]" +private const val RICH_FINGERPRINT = + "lui-extension-v1|22:outliner-block-content|profiles:android/flutter," + + "ios/swiftui|standard-children:0|children:|" + + "properties:10:asset-type:string:required:none,10:local-path:string:" + + "required:none,11:markup-json:string:required:none,12:is-completed:bool:" + + "required:none,18:youtube-target-url:string:required:none,5:title:string:" + + "required:none,8:block-id:string:required:none,8:is-asset:bool:required:none|" + + "events:10:drag-start[4:uuid:string:required],4:drop[4:uuid:string:required," + + "9:placement:string:required],4:edit[4:uuid:string:required],9:open-node[" + + "4:uuid:string:required]" +private const val NAVIGATION_FINGERPRINT = + "lui-extension-v1|23:native-navigation-stack|profiles:android/flutter," + + "ios/swiftui|standard-children:1|children:|" + + "properties:26:composer-dismissal-enabled:bool:required:none," + + "28:bottom-occupies-layout-space:bool:required:none,5:depth:int:required:none," + + "5:title:string:required:none|events:16:dismiss-composer[],4:back[" + + "5:count:int:required]" +private const val SEARCH_FINGERPRINT = + "lui-extension-v1|26:native-search-presentation|profiles:android/flutter," + + "ios/swiftui|standard-children:1|children:|" + + "properties:5:depth:int:required:none,5:query:string:required:none," + + "5:title:string:required:none,9:presented:bool:required:none|events:" + + "13:query-changed[5:query:string:required],4:back[5:count:int:required]," + + "7:dismiss[]" + +fun logseqChatExtensionRegistry( + resolveAssetPath: (String) -> String = { it }, +): LuiExtensionRegistry = LuiExtensionRegistry().apply { + register("outliner-editor", EDITOR_FINGERPRINT) { context -> + OutlinerEditor(context) + } + register("outliner-block-content", RICH_FINGERPRINT) { context -> + OutlinerBlockContent(context, resolveAssetPath) + } + register("native-navigation-stack", NAVIGATION_FINGERPRINT) { context -> + NavigationBoundary(context) + } + register("native-search-presentation", SEARCH_FINGERPRINT) { context -> + SearchPresentation(context) + } +} + +// Android hardware-back routing, mirroring the former PopScope semantics: +// composer dismissal takes precedence, then nav-stack back, then the +// system. +@Composable +private fun NavigationBoundary(context: LuiExtensionContext) { + val depth = context.int("depth") ?: 0 + val dismissesComposer = context.flag("composer-dismissal-enabled") + BackHandler(enabled = depth > 0 || dismissesComposer) { + if (dismissesComposer) { + context.emit("dismiss-composer") + } else if (depth > 0) { + context.emit("back", "count" to 1) + } + } + context.Children() +} + +// Modal search sheet — the core drives `query`; results are standard +// children rendered below the field. +@Composable +private fun SearchPresentation(context: LuiExtensionContext) { + val presented = context.flag("presented") + if (!presented) return + val title = context.string("title") ?: "" + val query = context.string("query") ?: "" + + BackHandler { + context.emit("dismiss") + } + Surface( + modifier = Modifier + .fillMaxSize() + .testTag("native-search-presentation"), + color = MaterialTheme.colorScheme.surface, + ) { + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 4.dp, vertical = 4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + IconButton(onClick = { context.emit("back", "count" to 1) }) { + Icon( + Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = "Back", + ) + } + var fieldValue by remember(query) { mutableStateOf(query) } + TextField( + value = fieldValue, + onValueChange = { + fieldValue = it + context.emit("query-changed", "query" to it) + }, + modifier = Modifier + .weight(1f) + .testTag("field.search"), + placeholder = { Text(title.ifEmpty { "Search" }) }, + singleLine = true, + ) + if (fieldValue.isNotEmpty()) { + IconButton( + onClick = { + fieldValue = "" + context.emit("query-changed", "query" to "") + }, + ) { + Icon(Icons.Filled.Close, contentDescription = "Clear") + } + } + } + Box(modifier = Modifier.fillMaxSize()) { + context.Children() + } + } + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerBlockContent.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerBlockContent.kt new file mode 100644 index 00000000..820a65b3 --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerBlockContent.kt @@ -0,0 +1,685 @@ +package com.logseq.chat.ui.extensions + +import android.content.ActivityNotFoundException +import android.content.Intent +import android.graphics.BitmapFactory +import android.net.Uri +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.PlayArrow +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.foundation.draganddrop.dragAndDropSource +import androidx.compose.foundation.draganddrop.dragAndDropTarget +import androidx.compose.ui.draganddrop.DragAndDropEvent +import androidx.compose.ui.draganddrop.DragAndDropTarget +import androidx.compose.ui.draganddrop.DragAndDropTransferData +import androidx.compose.ui.draganddrop.toAndroidDragEvent +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.viewinterop.AndroidView +import com.logseq.chat.AndroidAudioPlayer +import dev.lui.LuiExtensionContext +import java.io.File +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import org.json.JSONArray +import org.json.JSONObject + +// Port of _OutlinerBlockContent + markup/asset/embedded hosts from +// the former logseq_chat_extensions.dart, android_audio_playback.dart, +// android_embedded_media.dart, android_math.dart, android_cloze.dart. + +@OptIn(androidx.compose.foundation.ExperimentalFoundationApi::class) +@Composable +internal fun OutlinerBlockContent( + context: LuiExtensionContext, + resolveAssetPath: (String) -> String, +) { + val uuid = context.string("block-id") ?: "" + val title = context.string("title") ?: "" + val completed = context.flag("is-completed") + val isAsset = context.flag("is-asset") + + var rowHeightPx by remember { mutableIntStateOf(0) } + var dragHover by remember { mutableStateOf(false) } + var dragging by remember { mutableStateOf(false) } + val hoverColor by animateColorAsState( + if (dragHover) MaterialTheme.colorScheme.primaryContainer else Color.Transparent, + label = "dropHighlight", + ) + + val dropTarget = remember { + object : DragAndDropTarget { + override fun onDrop(event: DragAndDropEvent): Boolean { + dragHover = false + val clip = event.toAndroidDragEvent().clipData + val source = clip?.takeIf { it.itemCount > 0 } + ?.getItemAt(0)?.text?.toString() ?: return false + if (source == uuid) return false + val height = rowHeightPx.toFloat() + val localY = event.toAndroidDragEvent().y + context.emit( + "drop", + "uuid" to uuid, + "placement" to outlinerDropPlacement(localY, height), + ) + return true + } + + override fun onEntered(event: DragAndDropEvent) { + dragHover = true + } + + override fun onExited(event: DragAndDropEvent) { + dragHover = false + } + + override fun onEnded(event: DragAndDropEvent) { + dragHover = false + } + } + } + + val decoration = if (completed) TextDecoration.LineThrough else null + Box( + modifier = Modifier + .fillMaxWidth() + .onGloballyPositioned { rowHeightPx = it.size.height } + .background(hoverColor, RoundedCornerShape(8.dp)) + .dragAndDropSource( + drawDragDecoration = {}, + block = { + detectTapGestures( + onLongPress = { + dragging = true + context.emit("drag-start", "uuid" to uuid) + startTransfer( + DragAndDropTransferData( + android.content.ClipData.newPlainText("block", uuid), + ) + ) + dragging = false + }, + ) + }, + ) + .dragAndDropTarget( + shouldStartDragAndDrop = { true }, + target = dropTarget, + ) + .clickable { context.emit("edit", "uuid" to uuid) } + .testTag("outliner-block-content-$uuid"), + ) { + Column(modifier = Modifier.alpha(if (dragging) 0.35f else 1f)) { + if (isAsset) { + ProjectedAsset( + title = title, + assetType = context.string("asset-type") ?: "", + localPath = resolveAssetPath(context.string("local-path") ?: ""), + ) + } else { + ProjectedMarkup( + encoded = context.string("markup-json") ?: "", + fallback = title, + completedDecoration = decoration, + youtubeTargetUrl = context.string("youtube-target-url") ?: "", + onOpenNode = { context.emit("open-node", "uuid" to it) }, + ) + } + } + } +} + +internal fun outlinerDropPlacement(localY: Float, rowHeight: Float): String { + val height = if (rowHeight <= 0) 1f else rowHeight + return when { + localY < height * 0.25f -> "before" + localY > height * 0.75f -> "after" + else -> "inside" + } +} + +// --- markup-json --- + +@Composable +private fun ProjectedMarkup( + encoded: String, + fallback: String, + completedDecoration: TextDecoration?, + youtubeTargetUrl: String, + onOpenNode: (String) -> Unit, +) { + val nodes = remember(encoded) { decodeMarkup(encoded) } + if (nodes.isEmpty()) { + Text( + fallback, + style = MaterialTheme.typography.bodyMedium.copy( + textDecoration = completedDecoration + ), + ) + return + } + Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { + for ((index, chunk) in markupChunks(nodes).withIndex()) { + if (chunk.size == 1 && isRichNode(chunk.first())) { + MarkupRichNode(chunk.first(), youtubeTargetUrl, onOpenNode) + } else { + val annotated = markupAnnotatedString(chunk, completedDecoration) + MarkupInlineText( + annotated = annotated, + nodes = chunk, + modifier = Modifier + .fillMaxWidth() + .testTag("block.rich.inline.$index"), + onOpenNode = onOpenNode, + youtubeTargetUrl = youtubeTargetUrl, + ) + } + } + } +} + +private fun decodeMarkup(encoded: String): List { + if (encoded.isBlank()) return emptyList() + return try { + val array = JSONArray(encoded) + (0 until array.length()).mapNotNull { array.optJSONObject(it) } + } catch (_: Throwable) { + emptyList() + } +} + +private fun isRichNode(node: JSONObject): Boolean = node.optString("type") in setOf( + "quote", "math", "codeBlock", "video", "iframe", "youtubeTimestamp", "cloze", +) + +private fun markupChunks(nodes: List): List> { + val result = mutableListOf>() + var inline = mutableListOf() + for (node in nodes) { + if (isRichNode(node)) { + if (inline.isNotEmpty()) result.add(inline) + inline = mutableListOf() + result.add(listOf(node)) + } else { + inline.add(node) + } + } + if (inline.isNotEmpty()) result.add(inline) + return result +} + +private const val TAG_NODE = "lui.node" +private const val TAG_URL = "lui.url" +private const val TAG_TIMESTAMP = "lui.timestamp" + +private fun markupAnnotatedString( + nodes: List, + decoration: TextDecoration?, +): AnnotatedString = buildAnnotatedString { + for (node in nodes) appendNode(node, decoration) +} + +private fun AnnotatedString.Builder.appendNode(node: JSONObject, decoration: TextDecoration?) { + when (node.optString("type")) { + "text" -> withStyle(SpanStyle(textDecoration = decoration)) { + append(node.optString("text")) + } + "emphasis" -> { + val style = when (node.optString("style")) { + "bold" -> SpanStyle(fontWeight = FontWeight.Bold) + "italic" -> SpanStyle(fontStyle = FontStyle.Italic) + "underline" -> SpanStyle(textDecoration = TextDecoration.Underline) + "strikeThrough" -> SpanStyle(textDecoration = TextDecoration.LineThrough) + else -> SpanStyle() + } + withStyle(style.copy(textDecoration = decoration ?: style.textDecoration)) { + append(node.optString("text")) + } + } + "code" -> withStyle( + SpanStyle( + fontFamily = FontFamily.Monospace, + background = Color(0x33000000), + ) + ) { append(node.optString("text")) } + "nodeReference", "tagReference" -> { + val uuid = node.optString("uuid") + val label = node.optString("title").ifEmpty { uuid } + withStyle( + SpanStyle( + color = Color(0xff2d6cdf), + fontWeight = FontWeight.Medium, + ) + ) { + pushStringAnnotation(TAG_NODE, uuid) + append(label) + pop() + } + } + "link" -> { + val url = node.optString("url") + val children = node.optJSONArray("children") + pushStringAnnotation(TAG_URL, url) + withStyle(SpanStyle(color = Color(0xff2d6cdf))) { + if (children != null && children.length() > 0) { + for (i in 0 until children.length()) { + children.optJSONObject(i)?.let { appendNode(it, decoration) } + } + } else { + append(url) + } + } + pop() + } + "youtubeTimestamp" -> { + val seconds = node.optString("style") + pushStringAnnotation(TAG_TIMESTAMP, seconds) + withStyle( + SpanStyle( + color = Color(0xff2d6cdf), + fontFamily = FontFamily.Monospace, + ) + ) { + append(node.optString("text").ifEmpty { seconds }) + } + pop() + } + "math" -> append(node.optString("text")) + else -> append(node.optString("text")) + } +} + +@Composable +private fun MarkupInlineText( + annotated: AnnotatedString, + nodes: List, + modifier: Modifier, + onOpenNode: (String) -> Unit, + youtubeTargetUrl: String, +) { + val context = LocalContext.current + ClickableText( + text = annotated, + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurface + ), + modifier = modifier, + onClick = { offset -> + annotated.getStringAnnotations(TAG_NODE, offset, offset).firstOrNull() + ?.let { onOpenNode(it.item); return@ClickableText } + annotated.getStringAnnotations(TAG_URL, offset, offset).firstOrNull() + ?.let { openExternalUrl(context, it.item); return@ClickableText } + annotated.getStringAnnotations(TAG_TIMESTAMP, offset, offset).firstOrNull() + ?.let { + val seconds = it.item.toIntOrNull() ?: 0 + openExternalUrl( + context, + "$youtubeTargetUrl&t=${seconds}s".takeIf { youtubeTargetUrl.isNotEmpty() } + ?: it.item, + ) + } + }, + ) +} + +@Composable +private fun MarkupRichNode( + node: JSONObject, + youtubeTargetUrl: String, + onOpenNode: (String) -> Unit, +) { + when (node.optString("type")) { + "quote" -> Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 2.dp), + ) { + Box( + modifier = Modifier + .width(3.dp) + .height(20.dp) + .background( + MaterialTheme.colorScheme.outlineVariant, + RoundedCornerShape(2.dp), + ) + ) + Text( + node.optString("text"), + modifier = Modifier.padding(start = 10.dp), + style = MaterialTheme.typography.bodyMedium.copy( + fontStyle = FontStyle.Italic, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ), + ) + } + "math" -> AndroidMath(node.optString("text")) + "codeBlock" -> AndroidCodeBlock( + code = node.optString("text"), + language = node.optString("style"), + ) + "video" -> AndroidEmbeddedMedia(url = node.optString("url"), isVideo = true) + "iframe" -> AndroidEmbeddedMedia(url = node.optString("url"), isVideo = false) + "youtubeTimestamp" -> { + val seconds = node.optString("style").toIntOrNull() ?: 0 + val url = if (youtubeTargetUrl.isNotEmpty()) { + "$youtubeTargetUrl&t=${seconds}s" + } else { + node.optString("url") + } + AndroidEmbeddedMedia(url = url, isVideo = true, startSeconds = seconds) + } + "cloze" -> AndroidCloze(node.optString("text")) + else -> Text(node.optString("text"), style = MaterialTheme.typography.bodyMedium) + } +} + +// --- assets --- + +@Composable +private fun ProjectedAsset(title: String, assetType: String, localPath: String) { + when { + isImageAsset(assetType, localPath) && localPath.isNotEmpty() -> { + val bitmap = remember(localPath) { + runCatching { BitmapFactory.decodeFile(localPath)?.asImageBitmap() }.getOrNull() + } + if (bitmap != null) { + Image( + bitmap = bitmap, + contentDescription = title, + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)) + .testTag("asset.preview.image"), + contentScale = ContentScale.FillWidth, + ) + } else { + AssetFallback(title) + } + } + localPath.isNotEmpty() && isAudioAsset(assetType, localPath) -> + AndroidAudioPlaybackRow(title = title, path = localPath) + else -> AssetFallback(title) + } +} + +@Composable +private fun AssetFallback(title: String) { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon(Icons.Filled.Add, contentDescription = null) + Text(title, modifier = Modifier.padding(start = 8.dp)) + } +} + +internal fun isImageAsset(assetType: String, localPath: String): Boolean { + val normalized = assetType.lowercase().split(";").first().trim() + if (normalized.startsWith("image/")) return true + val extensions = setOf( + "png", "jpg", "jpeg", "gif", "webp", "bmp", "wbmp", "heic", "heif", "avif", + ) + if (normalized in extensions) return true + val dot = localPath.lastIndexOf('.') + if (dot < 0 || dot == localPath.length - 1) return false + return localPath.substring(dot + 1).lowercase() in extensions +} + +internal fun isAudioAsset(assetType: String, localPath: String): Boolean { + val normalized = assetType.lowercase().split(";").first().trim() + if (normalized.startsWith("audio/")) return true + val extensions = setOf("m4a", "aac", "mp3", "wav", "ogg", "opus", "flac") + if (normalized in extensions) return true + val dot = localPath.lastIndexOf('.') + if (dot < 0 || dot == localPath.length - 1) return false + return localPath.substring(dot + 1).lowercase() in extensions +} + +// --- audio playback (android_audio_playback.dart) --- + +@Composable +private fun AndroidAudioPlaybackRow(title: String, path: String) { + val context = LocalContext.current + val activity = context as? android.app.Activity + val player = remember { AndroidAudioPlayer(activity ?: context as android.app.Activity) } + var sessionId by remember { mutableIntStateOf(-1) } + var playing by remember { mutableStateOf(false) } + var progress by remember { mutableFloatStateOf(0f) } + var durationMs by remember { mutableIntStateOf(0) } + val scope = rememberCoroutineScope() + + DisposableEffect(Unit) { + onDispose { player.release() } + } + LaunchedEffect(playing, sessionId) { + while (playing && sessionId >= 0) { + val status = player.status(sessionId) + val position = (status["positionMs"] as? Number)?.toInt() ?: 0 + val duration = (status["durationMs"] as? Number)?.toInt() ?: durationMs + durationMs = duration + progress = if (duration > 0) position / duration.toFloat() else 0f + if (status["state"] == "completed" || status["state"] == "stopped") { + playing = false + progress = 0f + } + delay(200) + } + } + + Surface( + shape = RoundedCornerShape(12.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + modifier = Modifier.fillMaxWidth(), + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp), + ) { + IconButton( + onClick = { + scope.launch { + if (sessionId < 0) { + val result = player.start(path) + sessionId = (result["sessionId"] as? Number)?.toInt() ?: -1 + playing = sessionId >= 0 + } else if (playing) { + player.pause(sessionId) + playing = false + } else { + player.resume(sessionId) + playing = true + } + } + }, + modifier = Modifier.testTag("button.audio.play"), + ) { + Icon( + if (playing) Icons.Filled.Add else Icons.Filled.PlayArrow, + contentDescription = if (playing) "Pause" else "Play", + ) + } + Column(modifier = Modifier.weight(1f)) { + Text(title, style = MaterialTheme.typography.bodyMedium, maxLines = 1) + androidx.compose.material3.LinearProgressIndicator( + progress = { progress }, + modifier = Modifier.fillMaxWidth(), + ) + } + } + } +} + +// --- embedded media / math / cloze / code --- + +internal fun androidEmbeddedMediaUri(value: String, startSeconds: Int = 0): Uri? { + val uri = runCatching { Uri.parse(value.trim()) }.getOrNull() ?: return null + val scheme = uri.scheme ?: return null + if (scheme != "http" && scheme != "https") return null + val host = uri.host?.lowercase() ?: return null + val isYoutube = host == "youtu.be" || + host == "youtube.com" || + host.endsWith(".youtube.com") || + host == "youtube-nocookie.com" || + host.endsWith(".youtube-nocookie.com") + if (!isYoutube) return uri + val segments = uri.pathSegments + val videoId = when { + host == "youtu.be" -> segments.firstOrNull() + segments.firstOrNull() == "embed" -> segments.getOrNull(1) + uri.path == "/watch" -> uri.getQueryParameter("v") + else -> null + } ?: return null + if (!Regex("^[A-Za-z0-9_-]{6,}$").matches(videoId)) return null + val builder = Uri.Builder() + .scheme("https") + .authority("www.youtube-nocookie.com") + .appendPath("embed") + .appendPath(videoId) + .appendQueryParameter("playsinline", "1") + if (startSeconds > 0) builder.appendQueryParameter("start", "$startSeconds") + return builder.build() +} + +@Composable +internal fun AndroidEmbeddedMedia(url: String, isVideo: Boolean, startSeconds: Int = 0) { + val uri = remember(url, startSeconds) { androidEmbeddedMediaUri(url, startSeconds) } + if (uri == null) { + Text( + if (isVideo) "Invalid video URL" else "Invalid embed URL", + style = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurfaceVariant + ), + ) + return + } + AndroidView( + factory = { ctx -> + WebView(ctx).apply { + settings.javaScriptEnabled = true + settings.mediaPlaybackRequiresUserGesture = true + webViewClient = WebViewClient() + loadUrl(uri.toString()) + } + }, + modifier = Modifier + .fillMaxWidth() + .height(220.dp) + .clip(RoundedCornerShape(16.dp)) + .testTag("media.webview.loaded"), + ) +} + +@Composable +internal fun AndroidMath(expression: String) { + // No bundled TeX renderer — present the expression verbatim on a math + // surface (documented simplification vs the previous math renderer). + Surface( + shape = RoundedCornerShape(8.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + .testTag("block.rich.math.rendered"), + ) { + Text( + expression, + modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp), + style = MaterialTheme.typography.bodyLarge.copy( + fontFamily = FontFamily.Monospace + ), + ) + } +} + +@Composable +internal fun AndroidCloze(text: String) { + var revealed by remember { mutableStateOf(false) } + Surface( + shape = RoundedCornerShape(16.dp), + color = MaterialTheme.colorScheme.secondaryContainer, + modifier = Modifier + .testTag("button.cloze.reveal") + .clickable { revealed = !revealed }, + ) { + Text( + if (revealed) text else "Tap to reveal", + modifier = Modifier.padding(horizontal = 12.dp, vertical = 6.dp), + style = MaterialTheme.typography.bodySmall, + ) + } +} + +@Composable +internal fun AndroidCodeBlock(code: String, language: String) { + // Monospace block; full syntax highlighting is deferred (the previous + // app used package:highlighter — noted as a follow-up). + Surface( + shape = RoundedCornerShape(8.dp), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + modifier = Modifier + .fillMaxWidth() + .testTag("block.rich.code"), + ) { + Text( + code, + modifier = Modifier.padding(12.dp), + style = MaterialTheme.typography.bodySmall.copy( + fontFamily = FontFamily.Monospace + ), + ) + } +} + +private fun openExternalUrl(context: android.content.Context, url: String) { + if (url.isBlank()) return + try { + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + } catch (_: ActivityNotFoundException) { + } +} diff --git a/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerEditor.kt b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerEditor.kt new file mode 100644 index 00000000..b73ade3e --- /dev/null +++ b/android/app/src/main/kotlin/com/logseq/chat/ui/extensions/OutlinerEditor.kt @@ -0,0 +1,194 @@ +package com.logseq.chat.ui.extensions + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.KeyEventType +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onPreviewKeyEvent +import androidx.compose.ui.input.key.type +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId +import androidx.compose.ui.text.TextRange +import androidx.compose.ui.text.input.KeyboardCapitalization +import androidx.compose.ui.text.input.TextFieldValue +import dev.lui.LuiExtensionContext +import kotlinx.coroutines.delay + +// Port of the former _OutlinerEditor Dart implementation. +// +// The block title/caret are owned by the OCaml core. Local edits emit +// text-change (debounced 80ms), Enter emits return, backspace at offset 0 +// emits a structural backspace. Model acknowledgements echo locally +// published titles — those updates are swallowed so typing is never +// reverted mid-keystroke. +@Composable +internal fun OutlinerEditor(context: LuiExtensionContext) { + val blockId = context.string("block-id") ?: "" + val modelTitle = context.string("title") ?: "" + val modelCaret = context.int("caret-utf16-offset") ?: -1 + + val focusRequester = remember { FocusRequester() } + var value by remember { + mutableStateOf( + TextFieldValue(modelTitle, TextRange(modelCaret.coerceAtLeast(0))) + ) + } + var observedText by remember { mutableStateOf(value.text) } + var previousText by remember { mutableStateOf(modelTitle) } + var previousSelection by remember { mutableStateOf(value.selection) } + var rememberedModelTitle by remember { mutableStateOf(modelTitle) } + var rememberedModelCaret by remember { mutableIntStateOf(modelCaret) } + var applyingModel by remember { mutableStateOf(false) } + var debounceSeq by remember { mutableIntStateOf(0) } + val publishedTitles = remember { mutableStateListOf() } + + // Model → field sync (didUpdateWidget equivalent). + LaunchedEffect(modelTitle, modelCaret) { + val titleChanged = modelTitle != rememberedModelTitle + val caretChanged = modelCaret != rememberedModelCaret + rememberedModelTitle = modelTitle + rememberedModelCaret = modelCaret + val acknowledged = publishedTitles.indexOf(modelTitle) + if (acknowledged >= 0) { + repeat(acknowledged + 1) { publishedTitles.removeAt(0) } + return@LaunchedEffect + } + if (titleChanged || (caretChanged && value.text == modelTitle)) { + if (titleChanged) publishedTitles.clear() + applyingModel = true + debounceSeq++ + val offset = modelCaret.coerceIn(0, modelTitle.length) + value = TextFieldValue(modelTitle, TextRange(offset)) + observedText = modelTitle + applyingModel = false + } + } + + LaunchedEffect(Unit) { focusRequester.requestFocus() } + // Debounced text-change emission, cancelled by the next edit. + LaunchedEffect(debounceSeq) { + if (debounceSeq == 0) return@LaunchedEffect + delay(80) + val title = value.text + publishedTitles.add(title) + context.emit( + "text-change", + "title" to title, + "caret-utf16-offset" to caretOffset(value, title), + ) + } + DisposableEffect(Unit) { onDispose { debounceSeq++ } } + + fun emitStructuralBackspace() { + context.emit( + "backspace", + "title" to value.text, + "selection-length" to 0, + ) + } + + BasicTextField( + value = value, + onValueChange = { next -> + if (applyingModel) { + value = next + return@BasicTextField + } + val textChanged = next.text != observedText + if (textChanged) { + previousText = observedText + previousSelection = value.selection + } + observedText = next.text + val prior = value + value = next + + if (!textChanged && next.selection != prior.selection && next.selection.start >= 0) { + context.emit( + "caret-change", + "caret-utf16-offset" to next.selection.start, + ) + return@BasicTextField + } + if (!textChanged) return@BasicTextField + + val title = next.text + val caret = next.selection.start.coerceAtLeast(0) + val newline = caret - 1 + val singleInsertion = + title.length == previousText.length + 1 && + newline >= 0 && + newline < title.length && + title[newline] == '\n' && + title.removeRange(newline, newline + 1) == previousText + val replacedSelection = + !previousSelection.collapsed && + previousSelection.start >= 0 && + previousText.replaceRange( + previousSelection.start, + previousSelection.end, + "\n", + ) == title + if (singleInsertion || replacedSelection) { + debounceSeq++ // cancel pending text-change + val splitAt = if (replacedSelection) previousSelection.start else newline + val submitted = title.removeRange(splitAt, splitAt + 1) + val submittedCaret = splitAt.coerceIn(0, submitted.length) + applyingModel = true + value = TextFieldValue(submitted, TextRange(submittedCaret)) + observedText = submitted + applyingModel = false + publishedTitles.add(submitted) + context.emit( + "return", + "title" to submitted, + "caret-utf16-offset" to submittedCaret, + ) + } else { + debounceSeq++ // schedule text-change + } + }, + modifier = Modifier + .fillMaxWidth() + .focusRequester(focusRequester) + .testTag("field.outliner.block.$blockId") + .semantics { testTagsAsResourceId = true } + .onPreviewKeyEvent { event -> + if (event.type == KeyEventType.KeyDown && + event.key == Key.Backspace && + value.selection.collapsed && + value.selection.start == 0 + ) { + emitStructuralBackspace() + true + } else { + false + } + }, + textStyle = MaterialTheme.typography.bodyMedium.copy( + color = MaterialTheme.colorScheme.onSurface + ), + keyboardOptions = KeyboardOptions( + capitalization = KeyboardCapitalization.Sentences + ), + ) +} + +private fun caretOffset(value: TextFieldValue, text: String): Int = + if (value.selection.start < 0) text.length else value.selection.start diff --git a/flutter/android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt b/android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt rename to android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt diff --git a/flutter/android/app/src/main/kotlin/logseq/chat/AndroidFilePaths.kt b/android/app/src/main/kotlin/logseq/chat/AndroidFilePaths.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/logseq/chat/AndroidFilePaths.kt rename to android/app/src/main/kotlin/logseq/chat/AndroidFilePaths.kt diff --git a/flutter/android/app/src/main/kotlin/logseq/chat/AndroidGraphSnapshotDownloader.kt b/android/app/src/main/kotlin/logseq/chat/AndroidGraphSnapshotDownloader.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/logseq/chat/AndroidGraphSnapshotDownloader.kt rename to android/app/src/main/kotlin/logseq/chat/AndroidGraphSnapshotDownloader.kt diff --git a/flutter/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt b/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt rename to android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt diff --git a/flutter/android/app/src/main/kotlin/logseq/chat/AndroidRuntimeLog.kt b/android/app/src/main/kotlin/logseq/chat/AndroidRuntimeLog.kt similarity index 100% rename from flutter/android/app/src/main/kotlin/logseq/chat/AndroidRuntimeLog.kt rename to android/app/src/main/kotlin/logseq/chat/AndroidRuntimeLog.kt diff --git a/flutter/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable-v21/launch_background.xml rename to android/app/src/main/res/drawable-v21/launch_background.xml diff --git a/flutter/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/ic_launcher_foreground.xml rename to android/app/src/main/res/drawable/ic_launcher_foreground.xml diff --git a/flutter/android/app/src/main/res/drawable/ic_launcher_monochrome.xml b/android/app/src/main/res/drawable/ic_launcher_monochrome.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/ic_launcher_monochrome.xml rename to android/app/src/main/res/drawable/ic_launcher_monochrome.xml diff --git a/flutter/android/app/src/main/res/drawable/ic_shortcut_capture.xml b/android/app/src/main/res/drawable/ic_shortcut_capture.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/ic_shortcut_capture.xml rename to android/app/src/main/res/drawable/ic_shortcut_capture.xml diff --git a/flutter/android/app/src/main/res/drawable/ic_shortcut_journal.xml b/android/app/src/main/res/drawable/ic_shortcut_journal.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/ic_shortcut_journal.xml rename to android/app/src/main/res/drawable/ic_shortcut_journal.xml diff --git a/flutter/android/app/src/main/res/drawable/ic_widget_capture.xml b/android/app/src/main/res/drawable/ic_widget_capture.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/ic_widget_capture.xml rename to android/app/src/main/res/drawable/ic_widget_capture.xml diff --git a/flutter/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/launch_background.xml rename to android/app/src/main/res/drawable/launch_background.xml diff --git a/flutter/android/app/src/main/res/drawable/widget_background.xml b/android/app/src/main/res/drawable/widget_background.xml similarity index 100% rename from flutter/android/app/src/main/res/drawable/widget_background.xml rename to android/app/src/main/res/drawable/widget_background.xml diff --git a/flutter/android/app/src/main/res/layout/widget_capture.xml b/android/app/src/main/res/layout/widget_capture.xml similarity index 100% rename from flutter/android/app/src/main/res/layout/widget_capture.xml rename to android/app/src/main/res/layout/widget_capture.xml diff --git a/flutter/android/app/src/main/res/layout/widget_today_journal.xml b/android/app/src/main/res/layout/widget_today_journal.xml similarity index 100% rename from flutter/android/app/src/main/res/layout/widget_today_journal.xml rename to android/app/src/main/res/layout/widget_today_journal.xml diff --git a/flutter/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml similarity index 100% rename from flutter/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml rename to android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml diff --git a/flutter/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml similarity index 100% rename from flutter/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml rename to android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml diff --git a/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to android/app/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png rename to android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png diff --git a/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png rename to android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png diff --git a/flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png rename to android/app/src/main/res/mipmap-hdpi/ic_launcher_monochrome.png diff --git a/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to android/app/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png rename to android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png diff --git a/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png rename to android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png diff --git a/flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png rename to android/app/src/main/res/mipmap-mdpi/ic_launcher_monochrome.png diff --git a/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to android/app/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png rename to android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png diff --git a/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png rename to android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png diff --git a/flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png rename to android/app/src/main/res/mipmap-xhdpi/ic_launcher_monochrome.png diff --git a/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png rename to android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png diff --git a/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png rename to android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png diff --git a/flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png rename to android/app/src/main/res/mipmap-xxhdpi/ic_launcher_monochrome.png diff --git a/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png rename to android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png diff --git a/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png rename to android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png diff --git a/flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png similarity index 100% rename from flutter/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png rename to android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_monochrome.png diff --git a/flutter/android/app/src/main/res/raw/logseq_auth.json b/android/app/src/main/res/raw/logseq_auth.json similarity index 100% rename from flutter/android/app/src/main/res/raw/logseq_auth.json rename to android/app/src/main/res/raw/logseq_auth.json diff --git a/flutter/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml similarity index 100% rename from flutter/android/app/src/main/res/values-night/colors.xml rename to android/app/src/main/res/values-night/colors.xml diff --git a/flutter/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml similarity index 58% rename from flutter/android/app/src/main/res/values-night/styles.xml rename to android/app/src/main/res/values-night/styles.xml index 06952be7..9fe43a21 100644 --- a/flutter/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -2,16 +2,11 @@ - + diff --git a/flutter/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml similarity index 100% rename from flutter/android/app/src/main/res/values/colors.xml rename to android/app/src/main/res/values/colors.xml diff --git a/flutter/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml similarity index 100% rename from flutter/android/app/src/main/res/values/strings.xml rename to android/app/src/main/res/values/strings.xml diff --git a/flutter/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml similarity index 59% rename from flutter/android/app/src/main/res/values/styles.xml rename to android/app/src/main/res/values/styles.xml index cb1ef880..1ad78c3e 100644 --- a/flutter/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -2,16 +2,11 @@ - + diff --git a/flutter/android/app/src/main/res/xml/capture_widget_info.xml b/android/app/src/main/res/xml/capture_widget_info.xml similarity index 100% rename from flutter/android/app/src/main/res/xml/capture_widget_info.xml rename to android/app/src/main/res/xml/capture_widget_info.xml diff --git a/flutter/android/app/src/main/res/xml/file_paths.xml b/android/app/src/main/res/xml/file_paths.xml similarity index 100% rename from flutter/android/app/src/main/res/xml/file_paths.xml rename to android/app/src/main/res/xml/file_paths.xml diff --git a/flutter/android/app/src/main/res/xml/network_security_config.xml b/android/app/src/main/res/xml/network_security_config.xml similarity index 100% rename from flutter/android/app/src/main/res/xml/network_security_config.xml rename to android/app/src/main/res/xml/network_security_config.xml diff --git a/flutter/android/app/src/main/res/xml/shortcuts.xml b/android/app/src/main/res/xml/shortcuts.xml similarity index 100% rename from flutter/android/app/src/main/res/xml/shortcuts.xml rename to android/app/src/main/res/xml/shortcuts.xml diff --git a/flutter/android/app/src/main/res/xml/today_journal_widget_info.xml b/android/app/src/main/res/xml/today_journal_widget_info.xml similarity index 100% rename from flutter/android/app/src/main/res/xml/today_journal_widget_info.xml rename to android/app/src/main/res/xml/today_journal_widget_info.xml diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidAppEntryParserTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AndroidAppEntryParserTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidAppEntryParserTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AndroidAppEntryParserTest.kt diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidAudioTranscriberTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AndroidAudioTranscriberTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidAudioTranscriberTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AndroidAudioTranscriberTest.kt diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidGraphSnapshotDownloaderTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AndroidGraphSnapshotDownloaderTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidGraphSnapshotDownloaderTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AndroidGraphSnapshotDownloaderTest.kt diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt similarity index 91% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt index e7703801..3f562786 100644 --- a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt +++ b/android/app/src/test/kotlin/com/logseq/chat/AndroidPlatformServicesTest.kt @@ -61,12 +61,6 @@ class AndroidPlatformServicesTest { assertEquals(true, hasStoredToken("encrypted-token-envelope")) } - @Test - fun `void platform results are encoded as Flutter null`() { - assertEquals(null, flutterEncodableResult(Unit)) - assertEquals("value", flutterEncodableResult("value")) - } - @Test fun `asset titles cannot escape the Assets directory`() { assertEquals("photo.png", safeAssetTitle("../../photo.png")) diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidRuntimeLogTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AndroidRuntimeLogTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AndroidRuntimeLogTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AndroidRuntimeLogTest.kt diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/AuthenticationActivityContractTest.kt b/android/app/src/test/kotlin/com/logseq/chat/AuthenticationActivityContractTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/AuthenticationActivityContractTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/AuthenticationActivityContractTest.kt diff --git a/flutter/android/app/src/test/kotlin/com/logseq/chat/CognitoOAuthTest.kt b/android/app/src/test/kotlin/com/logseq/chat/CognitoOAuthTest.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/com/logseq/chat/CognitoOAuthTest.kt rename to android/app/src/test/kotlin/com/logseq/chat/CognitoOAuthTest.kt diff --git a/flutter/android/app/src/test/kotlin/logseq/chat/AndroidE2EECryptoTests.kt b/android/app/src/test/kotlin/logseq/chat/AndroidE2EECryptoTests.kt similarity index 100% rename from flutter/android/app/src/test/kotlin/logseq/chat/AndroidE2EECryptoTests.kt rename to android/app/src/test/kotlin/logseq/chat/AndroidE2EECryptoTests.kt diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 00000000..13a3403a --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,5 @@ +plugins { + id("com.android.application") version "9.1.0" apply false + id("com.android.library") version "9.1.0" apply false + id("org.jetbrains.kotlin.plugin.compose") version "2.4.0" apply false +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..d833c2ca --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,8 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.caching=true +org.gradle.parallel=true +android.useAndroidX=true +android.nonTransitiveRClass=true +# AGP 9 built-in Kotlin replaces the org.jetbrains.kotlin.android plugin. +android.builtInKotlin=true +kotlin.code.style=official diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..13372aef5e24af05341d49695ee84e5f9b594659 GIT binary patch literal 53636 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ⅅ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 H-+%o-(+5aQ literal 0 HcmV?d00001 diff --git a/flutter/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from flutter/android/gradle/wrapper/gradle-wrapper.properties rename to android/gradle/wrapper/gradle-wrapper.properties diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 00000000..e2f5a62a --- /dev/null +++ b/android/gradlew @@ -0,0 +1,163 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +app_path=$0 +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld -- "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='-Xmx64m -Xms64m' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it was, but + # possibly modified. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +# shellcheck disable=SC2086 +exec "$JAVACMD" $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \ + -classpath "$CLASSPATH" \ + -Dorg.gradle.appname="$APP_BASE_NAME" \ + org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/lui/build.gradle.kts b/android/lui/build.gradle.kts new file mode 100644 index 00000000..0e3332d6 --- /dev/null +++ b/android/lui/build.gradle.kts @@ -0,0 +1,47 @@ +plugins { + id("com.android.library") + + id("org.jetbrains.kotlin.plugin.compose") +} + +// Matches the dev.lui:lui coordinate the real platform/android backend +// publishes so Gradle dependency substitution can swap this module for +// the composite checkout unchanged. +group = "dev.lui" +version = "1.0.0" + +android { + namespace = "dev.lui" + compileSdk = 36 + + defaultConfig { + minSdk = 26 + } + + buildFeatures { + compose = true + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } + } +} + +dependencies { + implementation(platform("androidx.compose:compose-bom:2025.09.00")) + implementation("androidx.compose.ui:ui") + implementation("androidx.compose.foundation:foundation") + implementation("androidx.compose.foundation:foundation-layout") + implementation("androidx.compose.material3:material3") + implementation("androidx.compose.material:material-icons-extended") + implementation("androidx.compose.runtime:runtime") + implementation("androidx.compose.ui:ui-tooling-preview") + implementation("androidx.lifecycle:lifecycle-runtime-compose") +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiBackend.kt b/android/lui/src/main/kotlin/dev/lui/LuiBackend.kt new file mode 100644 index 00000000..5772d143 --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiBackend.kt @@ -0,0 +1,135 @@ +package dev.lui + +import android.util.Log +import androidx.compose.runtime.Composable +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject + +// Retained node store + patch-batch applier for the LUI wire protocol +// ({"generation": N, "ops": [...]}), plus the Compose entry point that +// renders it. +// +// Op vocabulary (shared/src ... lui_wire.ml): +// create-node {id,kind} create-extension {id,identifier,fingerprint} +// drop-node {id} set-prop / remove-prop {id,property[,value]} +// set-extension-prop / remove-extension-prop +// insert-child {parent,child,index} +// remove-child {parent,child} +// move-child {parent,child,index} +class LuiBackend( + val onEvent: (LuiEvent) -> Unit = {}, + val extensions: LuiExtensionRegistry = LuiExtensionRegistry(), + val icons: LuiIconResolver = LuiIconResolver.DEFAULT, +) { + private val nodes = LinkedHashMap() + + var generation: Long = 0 + private set + + fun node(id: Long): LuiNode? = nodes[id] + + fun childrenOf(id: Long): List = + nodes[id]?.children?.mapNotNull(nodes::get) ?: emptyList() + + fun clear() { + nodes.clear() + generation = 0 + } + + // Applies a patch batch. Returns true when anything changed; a + // malformed batch is dropped and reported (the core sends "" on + // error — the caller filters that out before we get here). + fun applyJson(raw: String?): Boolean { + if (raw.isNullOrEmpty()) return false + val batch = try { + JSONObject(raw) + } catch (error: JSONException) { + Log.w(TAG, "ignoring undecodable patch batch", error) + return false + } + val ops = batch.optJSONArray("ops") ?: return false + batch.optLong("generation").takeIf { it > 0 }?.let { generation = it } + var changed = false + for (index in 0 until ops.length()) { + val op = ops.optJSONObject(index) ?: continue + changed = applyOp(op) || changed + } + return changed + } + + private fun applyOp(op: JSONObject): Boolean = when (op.optString("op")) { + "create-node" -> { + val id = op.getLong("id") + nodes[id] = LuiNode(id, op.getString("kind")) + true + } + "create-extension" -> { + val id = op.getLong("id") + LuiNode(id, "extension").also { + it.identifier = op.getString("identifier") + it.fingerprint = op.optString("fingerprint") + nodes[id] = it + } + true + } + "drop-node" -> dropSubtree(op.getLong("id")) != null + "set-prop" -> nodes[op.getLong("id")]?.let { + it.properties[op.getString("property")] = op.opt("value") + true + } ?: false + "remove-prop" -> nodes[op.getLong("id")]?.let { + it.properties.remove(op.getString("property")) + true + } ?: false + "set-extension-prop" -> nodes[op.getLong("id")]?.let { + it.properties[op.getString("property")] = op.opt("value") + true + } ?: false + "remove-extension-prop" -> nodes[op.getLong("id")]?.let { + it.properties.remove(op.getString("property")) + true + } ?: false + "insert-child" -> nodes[op.getLong("parent")]?.let { parent -> + val child = op.getLong("child") + val index = op.getInt("index").coerceIn(0, parent.children.size) + parent.children.remove(child) + parent.children.add(index, child) + true + } ?: false + "remove-child" -> nodes[op.getLong("parent")]?.let { + it.children.remove(op.getLong("child")) + } ?: false + "move-child" -> nodes[op.getLong("parent")]?.let { parent -> + val child = op.getLong("child") + parent.children.remove(child) + val index = op.getInt("index").coerceIn(0, parent.children.size) + parent.children.add(index, child) + true + } ?: false + else -> { + Log.w(TAG, "unknown patch op: ${op.optString("op")}") + false + } + } + + private fun dropSubtree(id: Long): LuiNode? { + val node = nodes.remove(id) ?: return null + for (child in node.children.toList()) dropSubtree(child) + return node + } + + @Composable + fun Content(rootId: Long) { + LuiRoot(backend = this, rootId = rootId) + } + + internal fun dispatch(event: LuiEvent) = onEvent(event) + + companion object { + private const val TAG = "LuiBackend" + } +} + +internal fun JSONArray.stringList(): List = + (0 until length()).mapNotNull { optString(it).takeIf(String::isNotEmpty) } diff --git a/android/lui/src/main/kotlin/dev/lui/LuiEvent.kt b/android/lui/src/main/kotlin/dev/lui/LuiEvent.kt new file mode 100644 index 00000000..24bd1868 --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiEvent.kt @@ -0,0 +1,32 @@ +package dev.lui + +// User/host events produced by rendered nodes, dispatched back into the +// shared core. Mirrors the event surface of the other LUI backends +// (platform/android, platform/apple). +sealed class LuiEvent { + abstract val node: Long + + data class Appear(override val node: Long) : LuiEvent() + data class Press(override val node: Long) : LuiEvent() + data class LongPress(override val node: Long) : LuiEvent() + data class DoublePress(override val node: Long) : LuiEvent() + data class Change(override val node: Long) : LuiEvent() + data class Submit(override val node: Long) : LuiEvent() + data class Dismiss(override val node: Long) : LuiEvent() + data class TextChanged(override val node: Long, val text: String) : LuiEvent() + data class ToggleChanged(override val node: Long, val checked: Boolean) : LuiEvent() + data class ValueChanged(override val node: Long, val value: Double) : LuiEvent() + data class Picked(override val node: Long, val payload: String) : LuiEvent() + data class VisibleRange(override val node: Long, val first: Long, val last: Long) : LuiEvent() + data class ScrollCompleted(override val node: Long, val token: Long, val outcome: String) : LuiEvent() + + // Extension host event: `values` mirrors the identifier/name-keyed + // value map the host collects; the app layer reduces it to the + // (text, value) pair the FFI boundary expects. + data class Extension( + override val node: Long, + val identifier: String, + val name: String, + val values: Map, + ) : LuiEvent() +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiExtension.kt b/android/lui/src/main/kotlin/dev/lui/LuiExtension.kt new file mode 100644 index 00000000..04594df8 --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiExtension.kt @@ -0,0 +1,92 @@ +package dev.lui + +import androidx.compose.runtime.Composable + +// Extension host contract: the core creates `create-extension` nodes +// carrying an `identifier` (e.g. "outliner-editor") and a `fingerprint` +// for drift detection; the app registers composable builders per +// identifier. Properties arrive via set-extension-prop; host code emits +// named events with a values map the app reduces to the FFI (text, +// value) pair. +class LuiExtensionContext internal constructor( + val node: LuiNode, + private val backend: LuiBackend, +) { + val id: Long get() = node.id + val identifier: String get() = node.identifier.orEmpty() + + fun property(name: String): T? { + @Suppress("UNCHECKED_CAST") + return node.properties[name] as? T + } + + fun string(name: String): String? = node.string(name) + fun int(name: String): Int? = node.int(name) + fun double(name: String): Double? = node.double(name) + fun flag(name: String): Boolean = node.flag(name) + + fun emit(name: String, values: Map) { + backend.dispatch(LuiEvent.Extension(node.id, identifier, name, values)) + } + + fun emit(name: String, vararg values: Pair) = + emit(name, mapOf(*values)) + + // Renders the extension's standard children (extensions that accept + // them — e.g. native-navigation-stack's pushed content). + @Composable + fun Children() { + for (childId in node.children.toList()) { + androidx.compose.runtime.key(childId) { + LuiNodeView(backend, childId) + } + } + } +} + +fun interface LuiExtensionBuilder { + @Composable + fun Render(context: LuiExtensionContext) +} + +class LuiExtensionRegistry { + private data class Registration( + val fingerprint: String?, + val builder: LuiExtensionBuilder, + ) + + private val registrations = mutableMapOf() + + fun register( + identifier: String, + fingerprint: String? = null, + builder: LuiExtensionBuilder, + ) { + registrations[identifier] = Registration(fingerprint, builder) + } + + fun unregister(identifier: String) { + registrations.remove(identifier) + } + + // Null → render the unknown-extension placeholder. + // Mismatched fingerprints render an error surface instead of the + // component (same contract as the other backends). + fun resolve(node: LuiNode): Result { + val identifier = node.identifier ?: return Result.failure( + IllegalStateException("node ${node.id} is not an extension") + ) + val registration = registrations[identifier] + ?: return Result.failure(NoSuchElementException(identifier)) + val expected = registration.fingerprint + if (expected != null && expected != node.fingerprint) { + return Result.failure( + IllegalStateException( + "extension \"$identifier\" fingerprint mismatch: " + + "core sent \"${node.fingerprint}\", app registered \"$expected\"" + ) + ) + } + return Result.success(registration.builder) + } +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiIcons.kt b/android/lui/src/main/kotlin/dev/lui/LuiIcons.kt new file mode 100644 index 00000000..70d92fa3 --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiIcons.kt @@ -0,0 +1,107 @@ +package dev.lui + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.ArrowForward +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.automirrored.filled.Send +import androidx.compose.material.icons.automirrored.filled.Undo +import androidx.compose.material.icons.filled.* +import androidx.compose.ui.graphics.vector.ImageVector + +// Resolves the wire `icon` prop (a symbolic name such as +// "outliner-bullet" or "toolbar-sidebar") to an ImageVector. Apps can +// chain their own app-specific resolver in front of the default. +fun interface LuiIconResolver { + fun icon(name: String): ImageVector? + + fun or(other: LuiIconResolver): LuiIconResolver = LuiIconResolver { name -> + icon(name) ?: other.icon(name) + } + + companion object { + val DEFAULT = LuiIconResolver { name -> defaultIcons[name] } + + private val defaultIcons: Map = mapOf( + "add" to Icons.Filled.Add, + "add-circle" to Icons.Filled.AddCircle, + "arrow-back" to Icons.AutoMirrored.Filled.ArrowBack, + "arrow-forward" to Icons.AutoMirrored.Filled.ArrowForward, + "arrow-down" to Icons.Filled.ArrowDropDown, + "arrow-up" to Icons.Filled.KeyboardArrowUp, + "attach-file" to Icons.Filled.Add, + "audio-lines" to Icons.Filled.Star, + "audio-waveform" to Icons.Filled.Star, + "bell" to Icons.Filled.Notifications, + "bold" to Icons.Filled.Edit, + "bookmark" to Icons.Filled.Bookmark, + "brush" to Icons.Filled.Edit, + "calendar" to Icons.Filled.DateRange, + "camera" to Icons.Filled.Add, + "check" to Icons.Filled.Check, + "check-circle" to Icons.Filled.CheckCircle, + "chevron-down" to Icons.Filled.KeyboardArrowDown, + "chevron-left" to Icons.AutoMirrored.Filled.KeyboardArrowLeft, + "chevron-right" to Icons.AutoMirrored.Filled.KeyboardArrowRight, + "chevron-up" to Icons.Filled.KeyboardArrowUp, + "clock" to Icons.Filled.Star, + "close" to Icons.Filled.Close, + "cloud" to Icons.Filled.Star, + "code" to Icons.Filled.Edit, + "copy" to Icons.Filled.Add, + "dice" to Icons.Filled.Star, + "dots" to Icons.Filled.MoreVert, + "download" to Icons.Filled.Share, + "edit" to Icons.Filled.Edit, + "external-link" to Icons.Filled.Share, + "eye" to Icons.Filled.Star, + "file" to Icons.Filled.Add, + "flag" to Icons.Filled.Star, + "folder" to Icons.Filled.Star, + "hash" to Icons.Filled.Tag, + "heading" to Icons.Filled.Edit, + "history" to Icons.Filled.Star, + "home" to Icons.Filled.Home, + "image" to Icons.Filled.Star, + "info" to Icons.Filled.Info, + "italic" to Icons.Filled.Edit, + "link" to Icons.Filled.Share, + "list" to Icons.Filled.List, + "loader" to Icons.Filled.Refresh, + "lock" to Icons.Filled.Lock, + "logout" to Icons.Filled.ExitToApp, + "menu" to Icons.Filled.Menu, + "message" to Icons.Filled.Email, + "mic" to Icons.Filled.Edit, + "minus" to Icons.Filled.Clear, + "more-horizontal" to Icons.Filled.MoreVert, + "more-vertical" to Icons.Filled.MoreVert, + "paperclip" to Icons.Filled.Add, + "pause" to Icons.Filled.Star, + "pencil" to Icons.Filled.Edit, + "play" to Icons.Filled.PlayArrow, + "plus" to Icons.Filled.Add, + "refresh" to Icons.Filled.Refresh, + "search" to Icons.Filled.Search, + "send" to Icons.AutoMirrored.Filled.Send, + "settings" to Icons.Filled.Settings, + "share" to Icons.Filled.Share, + "sparkles" to Icons.Filled.Star, + "star" to Icons.Filled.Star, + "stop" to Icons.Filled.Close, + "sync" to Icons.Filled.Refresh, + "table" to Icons.Filled.List, + "tag" to Icons.Filled.Tag, + "task" to Icons.Filled.CheckCircle, + "trash" to Icons.Filled.Delete, + "undo" to Icons.AutoMirrored.Filled.Undo, + "upload" to Icons.Filled.Share, + "user" to Icons.Filled.Person, + "video" to Icons.Filled.PlayArrow, + "warning" to Icons.Filled.Warning, + "wifi" to Icons.Filled.Star, + "x" to Icons.Filled.Close, + ) + } +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiNode.kt b/android/lui/src/main/kotlin/dev/lui/LuiNode.kt new file mode 100644 index 00000000..54513cbd --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiNode.kt @@ -0,0 +1,32 @@ +package dev.lui + +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateMapOf + +// Retained UI node mirror, one per `create-node`/`create-extension` op on +// the LUI wire. Properties and children are Compose state so applying a +// patch batch recomposes only the touched subtrees. +class LuiNode internal constructor( + val id: Long, + var kind: String, +) { + // Extension nodes carry `identifier`/`fingerprint` instead of a kind. + var identifier: String? = null + var fingerprint: String = "" + + val properties = mutableStateMapOf() + val children = mutableStateListOf() + + val isExtension: Boolean get() = identifier != null + + fun string(name: String): String? = properties[name] as? String + fun int(name: String): Int? = (properties[name] as? Number)?.toInt() + fun long(name: String): Long? = (properties[name] as? Number)?.toLong() + fun double(name: String): Double? = (properties[name] as? Number)?.toDouble() + fun bool(name: String): Boolean = (properties[name] as? Boolean) == true + + fun flag(name: String): Boolean = int(name) != 0 && properties.containsKey(name) + + fun enabled(name: String, default: Boolean = false): Boolean = + if (properties.containsKey(name)) int(name) != 0 else default +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiProps.kt b/android/lui/src/main/kotlin/dev/lui/LuiProps.kt new file mode 100644 index 00000000..9a41650f --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiProps.kt @@ -0,0 +1,173 @@ +package dev.lui + +import androidx.compose.foundation.border +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.contentDescription +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.aspectRatio + +// Wire property → Compose mapping shared by every renderer. Property +// names are the kebab-case identifiers of schema/components.json. + +internal fun LuiNode.visible(): Boolean = !properties.containsKey("visible") || int("visible") != 0 + +@Composable +internal fun LuiNode.colorProp(name: String): Color? = + LuiTheme.color(string(name)) + +@Composable +internal fun LuiNode.shape(): RoundedCornerShape = + RoundedCornerShape((int("corner-radius") ?: 0).dp) + +@Composable +internal fun LuiNode.styleModifier(): Modifier { + var modifier: Modifier = Modifier + int("width")?.let { modifier = modifier.width(it.dp) } + int("height")?.let { modifier = modifier.height(it.dp) } + int("min-width")?.let { modifier = modifier.widthIn(min = it.dp) } + int("max-width")?.let { modifier = modifier.widthIn(max = it.dp) } + int("min-height")?.let { modifier = modifier.heightIn(min = it.dp) } + int("max-height")?.let { modifier = modifier.heightIn(max = it.dp) } + when (string("width-mode") ?: string("sizing")) { + "fill" -> modifier = modifier.fillMaxWidth() + else -> {} + } + if (flag("fill-width")) modifier = modifier.fillMaxWidth() + if (flag("fill-height") || flag("fill")) modifier = modifier.fillMaxHeight() + int("padding")?.let { modifier = modifier.padding(it.dp) } + int("padding-horizontal")?.let { modifier = modifier.padding(horizontal = it.dp) } + int("padding-vertical")?.let { modifier = modifier.padding(vertical = it.dp) } + int("padding-top")?.let { modifier = modifier.padding(top = it.dp) } + int("padding-bottom")?.let { modifier = modifier.padding(bottom = it.dp) } + int("padding-start")?.let { modifier = modifier.padding(start = it.dp) } + int("padding-end")?.let { modifier = modifier.padding(end = it.dp) } + val opacity = double("opacity") + if (opacity != null) modifier = modifier.alpha(opacity.toFloat().coerceIn(0f, 1f)) + string("accessibility-identifier")?.let { modifier = modifier.testTag(it) } + string("accessibility-label")?.let { label -> + modifier = modifier.semantics { contentDescription = label } + } + return modifier +} + +@Composable +internal fun LuiNode.surfaceModifier(): Modifier { + var modifier = styleModifier() + val radius = shape() + colorProp("background")?.let { modifier = modifier.background(it, radius) } + val borderColor = colorProp("border-color") + val borderWidth = int("border-width") + if (borderColor != null && borderWidth != null && borderWidth > 0) { + modifier = modifier.border(borderWidth.dp, borderColor, radius) + } + if ((int("corner-radius") ?: 0) > 0 || flag("clip")) { + modifier = modifier.clip(radius) + } + return modifier +} + +internal fun LuiNode.gapDp() = (int("gap") ?: 0).dp + +internal fun LuiNode.mainAxisAlignment(): androidx.compose.foundation.layout.Arrangement.Horizontal = + when (string("main-alignment")) { + "center" -> androidx.compose.foundation.layout.Arrangement.Center + "end" -> androidx.compose.foundation.layout.Arrangement.End + "space-between" -> androidx.compose.foundation.layout.Arrangement.SpaceBetween + "space-around" -> androidx.compose.foundation.layout.Arrangement.SpaceAround + "space-evenly" -> androidx.compose.foundation.layout.Arrangement.SpaceEvenly + else -> androidx.compose.foundation.layout.Arrangement.spacedBy(gapDp()) + } + +internal fun LuiNode.mainAxisVertical(): androidx.compose.foundation.layout.Arrangement.Vertical = + when (string("main-alignment")) { + "center" -> androidx.compose.foundation.layout.Arrangement.Center + "end", "bottom" -> androidx.compose.foundation.layout.Arrangement.Bottom + "space-between" -> androidx.compose.foundation.layout.Arrangement.SpaceBetween + "space-around" -> androidx.compose.foundation.layout.Arrangement.SpaceAround + "space-evenly" -> androidx.compose.foundation.layout.Arrangement.SpaceEvenly + else -> androidx.compose.foundation.layout.Arrangement.spacedBy(gapDp()) + } + +internal fun LuiNode.crossAxisHorizontal(): androidx.compose.ui.Alignment.Horizontal = + when (string("cross-alignment")) { + "center" -> androidx.compose.ui.Alignment.CenterHorizontally + "end" -> androidx.compose.ui.Alignment.End + else -> androidx.compose.ui.Alignment.Start + } + +internal fun LuiNode.crossAxisVertical(): androidx.compose.ui.Alignment.Vertical = + when (string("cross-alignment")) { + "center" -> androidx.compose.ui.Alignment.CenterVertically + "end", "bottom" -> androidx.compose.ui.Alignment.Bottom + else -> androidx.compose.ui.Alignment.Top + } + +internal fun LuiNode.textAlign(): TextAlign? = when (string("text-alignment")) { + "center" -> TextAlign.Center + "end", "right" -> TextAlign.End + "start", "left" -> TextAlign.Start + "justify" -> TextAlign.Justify + else -> null +} + +@Composable +internal fun LuiNode.textStyle(): TextStyle { + val base = when (string("size")) { + "sm" -> MaterialTheme.typography.bodySmall + "lg" -> MaterialTheme.typography.titleMedium + "heading" -> MaterialTheme.typography.headlineSmall + "display" -> MaterialTheme.typography.displaySmall + "icon" -> MaterialTheme.typography.bodyMedium + else -> MaterialTheme.typography.bodyMedium + } + return base.copy( + color = colorProp("foreground") ?: MaterialTheme.colorScheme.onSurface, + fontWeight = when (string("weight")) { + "bold", "semibold" -> FontWeight.SemiBold + "medium" -> FontWeight.Medium + "light" -> FontWeight.Light + else -> base.fontWeight + }, + fontStyle = if (string("style") == "italic") FontStyle.Italic else base.fontStyle, + ) +} + +@Composable +internal fun LuiNode.headingStyle(): TextStyle { + val theme = MaterialTheme.typography + val level = int("level") ?: int("heading-level") ?: 1 + val base = when (level) { + 1 -> theme.headlineLarge + 2 -> theme.headlineMedium + 3 -> theme.titleLarge + 4 -> theme.titleMedium + 5 -> theme.titleSmall + else -> theme.labelLarge + } + return base.copy(color = colorProp("foreground") ?: MaterialTheme.colorScheme.onSurface) +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt b/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt new file mode 100644 index 00000000..fe2637dc --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt @@ -0,0 +1,819 @@ +package dev.lui + +import android.util.Log +import androidx.compose.foundation.clickable +import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Badge +import androidx.compose.material3.BottomSheetDefaults +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Card +import androidx.compose.material3.Checkbox +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.ModalDrawerSheet +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.RadioButton +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.Slider +import androidx.compose.material3.Surface +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextField +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTagsAsResourceId +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupProperties + +private const val TAG = "LuiRender" + +@Composable +internal fun LuiRoot(backend: LuiBackend, rootId: Long) { + Box( + Modifier + .fillMaxSize() + .semantics { testTagsAsResourceId = true } + ) { + val root = backend.node(rootId) + if (root != null) { + for (childId in root.children.toList()) { + key(childId) { LuiNodeView(backend, childId) } + } + } + } +} + +@Composable +private fun key(id: Long, content: @Composable () -> T) = + androidx.compose.runtime.key(id) { content() } + +@Composable +internal fun LuiNodeView(backend: LuiBackend, id: Long) { + val node = backend.node(id) ?: return + if (!node.visible()) return + LuiTheme.NodeScope(node) { + if (node.isExtension) { + ExtensionView(backend, node) + } else { + NodeView(backend, node) + } + } +} + +@Composable +private fun ExtensionView(backend: LuiBackend, node: LuiNode) { + val result = backend.extensions.resolve(node) + result.onSuccess { builder -> + builder.Render(LuiExtensionContext(node, backend)) + }.onFailure { error -> + Surface( + modifier = Modifier.padding(8.dp), + color = MaterialTheme.colorScheme.errorContainer, + shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp), + ) { + Text( + text = "Extension \"${node.identifier}\" unavailable: ${error.message}", + modifier = Modifier.padding(12.dp), + color = MaterialTheme.colorScheme.onErrorContainer, + style = MaterialTheme.typography.bodySmall, + ) + } + } +} + +@Composable +private fun Children(backend: LuiBackend, node: LuiNode) { + for (childId in node.children.toList()) { + key(childId) { LuiNodeView(backend, childId) } + } +} + +@Composable +private fun AppearOnce(backend: LuiBackend, node: LuiNode) { + if (node.enabled("appear-enabled")) { + LaunchedEffect(node.id) { backend.dispatch(LuiEvent.Appear(node.id)) } + } +} + +// Emits the press/long-press/double-press gestures a node opted into. +@Composable +private fun Modifier.gestures(backend: LuiBackend, node: LuiNode): Modifier { + val hasLong = node.enabled("long-press-enabled") + val hasDouble = node.enabled("double-press-enabled") + val hasPress = node.enabled("press-enabled") || node.kind == "button" || + node.kind == "toggle-button" || node.kind == "link" || + node.kind == "menu-item" || node.kind == "bottom-tab" || + node.kind == "list-item" || node.kind == "radio" + return if (hasPress || hasLong || hasDouble) { + combinedClickable( + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + onLongClick = if (hasLong) { + { backend.dispatch(LuiEvent.LongPress(node.id)) } + } else null, + onDoubleClick = if (hasDouble) { + { backend.dispatch(LuiEvent.DoublePress(node.id)) } + } else null, + ) + } else this +} + +@Composable +private fun NodeView(backend: LuiBackend, node: LuiNode) { + AppearOnce(backend, node) + when (node.kind) { + "root", "box", "edge-inset", "view-that-fits" -> + Frame(backend, node) + "column" -> ColumnNode(backend, node) + "row" -> RowNode(backend, node) + "grid" -> GridNode(backend, node) + "stack", "overlay" -> StackNode(backend, node) + "scroll" -> ScrollNode(backend, node) + "list", "list-section" -> ListNode(backend, node) + "virtual-list" -> VirtualListNode(backend, node) + "spacer" -> SpacerNode(node) + "divider" -> HorizontalDivider( + modifier = node.styleModifier(), + color = node.colorProp("foreground") + ?: MaterialTheme.colorScheme.outlineVariant, + ) + "text", "label" -> TextNode(backend, node) + "heading" -> Text( + text = node.string("value") ?: node.string("title").orEmpty(), + modifier = node.styleModifier().gestures(backend, node), + style = node.headingStyle(), + ) + "paragraph" -> Text( + text = node.string("value").orEmpty(), + modifier = node.styleModifier().gestures(backend, node), + style = node.textStyle(), + ) + "kbd" -> Text( + text = node.string("value").orEmpty(), + modifier = node.styleModifier(), + style = node.textStyle().copy(fontFamily = FontFamily.Monospace), + ) + "icon" -> IconNode(backend, node) + "button", "toggle-button" -> ButtonNode(backend, node) + "link" -> Text( + text = node.string("value") ?: node.string("title").orEmpty(), + modifier = node.styleModifier().gestures(backend, node), + style = node.textStyle().copy( + color = MaterialTheme.colorScheme.primary, + ), + ) + "toggle", "switch" -> Switch( + checked = node.flag("checked"), + onCheckedChange = { backend.dispatch(LuiEvent.ToggleChanged(node.id, it)) }, + enabled = node.enabled("enabled", true), + modifier = node.styleModifier(), + ) + "checkbox" -> Checkbox( + checked = node.flag("checked"), + onCheckedChange = { backend.dispatch(LuiEvent.ToggleChanged(node.id, it)) }, + enabled = node.enabled("enabled", true), + modifier = node.styleModifier(), + ) + "radio" -> RadioButton( + selected = node.flag("checked") || node.flag("selected"), + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + enabled = node.enabled("enabled", true), + modifier = node.styleModifier(), + ) + "radio-group", "button-group", "toggle-group" -> + ColumnNode(backend, node) + "slider" -> Slider( + value = (node.double("value") ?: 0.0).toFloat(), + onValueChange = { + backend.dispatch(LuiEvent.ValueChanged(node.id, it.toDouble())) + }, + enabled = node.enabled("enabled", true), + modifier = node.styleModifier(), + ) + "progress" -> LinearProgressIndicator( + progress = { (node.double("progress-value") ?: 0.0).toFloat() }, + modifier = node.styleModifier().fillMaxWidth(), + ) + "spinner" -> CircularProgressIndicator( + modifier = node.styleModifier(), + color = node.colorProp("foreground") ?: MaterialTheme.colorScheme.primary, + ) + "text-field", "input", "secure-field", "textarea" -> + TextFieldNode(backend, node) + "search-field" -> TextFieldNode(backend, node) + "card", "panel", "bubble" -> CardNode(backend, node) + "alert" -> AlertNode(backend, node) + "toolbar", "status-bar", "breadcrumb" -> RowNode(backend, node) + "list-item" -> RowNode(backend, node) + "image", "file-image", "file-preview" -> ImageNode(backend, node) + "tabs", "bottom-tabs" -> TabsNode(backend, node) + "bottom-tab", "tab" -> ButtonNode(backend, node) + "menu-item" -> RowNode(backend, node) + "menu-trigger" -> MenuTrigger(backend, node) + "dropdown-menu", "context-menu" -> MenuNode(backend, node) + "dialog" -> DialogNode(backend, node) + "sheet" -> SheetNode(backend, node) + "drawer" -> DrawerNode(backend, node) + "popover", "tooltip" -> PopupNode(backend, node) + "toast" -> ToastNode(backend, node) + "tree" -> ColumnNode(backend, node) + "badge" -> BadgeNode(backend, node) + "br" -> Spacer(Modifier.height(4.dp)) + "media-surface" -> Surface( + modifier = node.styleModifier().fillMaxWidth(), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + ) {} + "file-picker" -> FilePickerNode(backend, node) + "select", "combobox" -> SelectNode(backend, node) + "number-stepper" -> StepperNode(backend, node) + "stepper" -> StepperNode(backend, node) + "step" -> Frame(backend, node) + "accordion", "table", "table-row", "table-cell", "timeline", + "timeline-item", "resizable", "split", "swipe-actions", + "swipe-action", "input-group", "input-group-actions", + "pagination", "list-section-header", "list-section-footer", + "avatar", "segmented-control" -> FallbackContainer(backend, node) + else -> FallbackContainer(backend, node) + } +} + +@Composable +private fun Frame(backend: LuiBackend, node: LuiNode) { + Box( + modifier = node + .surfaceModifier() + .gestures(backend, node), + ) { + Children(backend, node) + } +} + +@Composable +private fun ColumnNode(backend: LuiBackend, node: LuiNode) { + Column( + modifier = node.surfaceModifier().gestures(backend, node), + verticalArrangement = node.mainAxisVertical(), + horizontalAlignment = node.crossAxisHorizontal(), + ) { + for (childId in node.children.toList()) { + val child = backend.node(childId) ?: continue + if (!child.visible()) continue + val grow = child.double("grow") + key(childId) { + if (grow != null && grow > 0) { + Box(Modifier.weight(grow.toFloat())) { LuiNodeView(backend, childId) } + } else { + LuiNodeView(backend, childId) + } + } + } + } +} + +@Composable +private fun RowNode(backend: LuiBackend, node: LuiNode) { + Row( + modifier = node.surfaceModifier().gestures(backend, node), + horizontalArrangement = node.mainAxisAlignment(), + verticalAlignment = node.crossAxisVertical(), + ) { + for (childId in node.children.toList()) { + val child = backend.node(childId) ?: continue + if (!child.visible()) continue + val grow = child.double("grow") + key(childId) { + if (grow != null && grow > 0) { + Box(Modifier.weight(grow.toFloat())) { LuiNodeView(backend, childId) } + } else { + LuiNodeView(backend, childId) + } + } + } + } +} + +@Composable +private fun GridNode(backend: LuiBackend, node: LuiNode) { + val columns = (node.int("grid-columns") ?: 2).coerceAtLeast(1) + Column( + modifier = node.surfaceModifier().gestures(backend, node), + verticalArrangement = node.mainAxisVertical(), + ) { + val children = node.children.toList() + for (row in children.chunked(columns)) { + Row(horizontalArrangement = Arrangement.spacedBy(node.gapDp())) { + for (childId in row) { + key(childId) { + Box(Modifier.weight(1f)) { LuiNodeView(backend, childId) } + } + } + } + } + } +} + +@Composable +private fun StackNode(backend: LuiBackend, node: LuiNode) { + Box( + modifier = node.surfaceModifier().gestures(backend, node), + contentAlignment = when (node.string("cross-alignment")) { + "center" -> Alignment.Center + "end" -> Alignment.BottomEnd + else -> Alignment.TopStart + }, + ) { + Children(backend, node) + } +} + +@Composable +private fun ScrollNode(backend: LuiBackend, node: LuiNode) { + Column( + modifier = node + .surfaceModifier() + .gestures(backend, node) + .verticalScroll(rememberScrollState()), + verticalArrangement = node.mainAxisVertical(), + horizontalAlignment = node.crossAxisHorizontal(), + ) { + Children(backend, node) + } +} + +@Composable +private fun ListNode(backend: LuiBackend, node: LuiNode) { + Column( + modifier = node.surfaceModifier().gestures(backend, node), + verticalArrangement = node.mainAxisVertical(), + horizontalAlignment = node.crossAxisHorizontal(), + ) { + Children(backend, node) + } +} + +@Composable +private fun VirtualListNode(backend: LuiBackend, node: LuiNode) { + val listState = rememberLazyListState() + val trackRange = node.enabled("track-visible-range") + if (trackRange) { + LaunchedEffect(node.id) { + snapshotFlow { listState.firstVisibleItemIndex to listState.layoutInfo.visibleItemsInfo } + .collect { (first, visible) -> + val last = first + visible.size - 1 + backend.dispatch(LuiEvent.VisibleRange(node.id, first.toLong(), last.toLong())) + } + } + } + LazyColumn( + state = listState, + modifier = node.surfaceModifier().gestures(backend, node), + verticalArrangement = node.mainAxisVertical(), + horizontalAlignment = node.crossAxisHorizontal(), + ) { + for (childId in node.children.toList()) { + item(key = childId) { LuiNodeView(backend, childId) } + } + } +} + +@Composable +private fun SpacerNode(node: LuiNode) { + Spacer( + Modifier + .width((node.int("width") ?: 8).dp) + .height((node.int("height") ?: 8).dp) + ) +} + +@Composable +private fun TextNode(backend: LuiBackend, node: LuiNode) { + Text( + text = node.string("value") ?: node.string("title").orEmpty(), + modifier = node.styleModifier().gestures(backend, node), + style = node.textStyle(), + textAlign = node.textAlign(), + overflow = if (node.flag("wrap")) { + androidx.compose.ui.text.style.TextOverflow.Clip + } else { + androidx.compose.ui.text.style.TextOverflow.Ellipsis + }, + maxLines = node.int("max-lines") ?: Int.MAX_VALUE, + ) +} + +@Composable +private fun IconNode(backend: LuiBackend, node: LuiNode) { + val name = node.string("icon") ?: node.string("value") ?: return + val vector = backend.icons.icon(name) + if (vector != null) { + Icon( + imageVector = vector, + contentDescription = node.string("accessibility-label"), + tint = node.colorProp("foreground") ?: MaterialTheme.colorScheme.onSurface, + modifier = node.styleModifier().size((node.int("size-value") ?: 20).dp), + ) + } else { + Text( + text = name, + modifier = node.styleModifier(), + style = node.textStyle(), + ) + } +} + +@Composable +private fun ButtonNode(backend: LuiBackend, node: LuiNode) { + val variant = node.string("variant") ?: "filled" + val enabled = node.enabled("enabled", true) + val modifier = node.styleModifier() + val colors = ButtonDefaults.buttonColors( + containerColor = node.colorProp("background") ?: Color.Unspecified, + contentColor = node.colorProp("foreground") ?: Color.Unspecified, + ) + val content: @Composable androidx.compose.foundation.layout.RowScope.() -> Unit = { + node.string("icon")?.let { iconName -> + backend.icons.icon(iconName)?.let { + Icon(it, contentDescription = null, modifier = Modifier.size(18.dp)) + Spacer(Modifier.width(6.dp)) + } + } + node.string("value")?.let { Text(it) } + node.string("title")?.let { Text(it) } + Children(backend, node) + } + when (variant) { + "tonal", "secondary" -> FilledTonalButton( + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + enabled = enabled, + modifier = modifier, + colors = colors, + content = content, + ) + "outline", "outlined" -> OutlinedButton( + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + enabled = enabled, + modifier = modifier, + content = content, + ) + "ghost", "text" -> TextButton( + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + enabled = enabled, + modifier = modifier, + content = content, + ) + else -> Button( + onClick = { backend.dispatch(LuiEvent.Press(node.id)) }, + enabled = enabled, + modifier = modifier, + colors = colors, + content = content, + ) + } +} + +@Composable +private fun TextFieldNode(backend: LuiBackend, node: LuiNode) { + val propValue = node.string("value") ?: "" + var fieldValue by remember(node.id) { mutableStateOf(TextFieldValue(propValue)) } + // Keep local IME state in sync when the core patches `value` back. + if (fieldValue.text != propValue && !node.enabled("editing")) { + fieldValue = fieldValue.copy(text = propValue) + } + val focusRequester = remember { FocusRequester() } + val onSubmit: () -> Unit = { backend.dispatch(LuiEvent.Submit(node.id)) } + val fieldModifier = node + .styleModifier() + .focusRequester(focusRequester) + .fillMaxWidth() + val commonKeyboard = KeyboardOptions( + keyboardType = when { + node.kind == "secure-field" -> KeyboardType.Password + else -> KeyboardType.Text + }, + ) + val actions = KeyboardActions(onDone = { onSubmit() }, onSend = { onSubmit() }) + val change: (TextFieldValue) -> Unit = { newValue -> + fieldValue = newValue + backend.dispatch(LuiEvent.TextChanged(node.id, newValue.text)) + } + val visualTransformation = if (node.kind == "secure-field") { + PasswordVisualTransformation() + } else { + androidx.compose.ui.text.input.VisualTransformation.None + } + if (node.kind == "search-field") { + OutlinedTextField( + value = fieldValue, + onValueChange = change, + modifier = fieldModifier, + enabled = node.enabled("enabled", true), + placeholder = node.string("placeholder")?.let { { Text(it) } }, + leadingIcon = { + backend.icons.icon("search")?.let { + Icon(it, contentDescription = null) + } + }, + singleLine = true, + keyboardOptions = commonKeyboard, + keyboardActions = actions, + visualTransformation = visualTransformation, + ) + } else { + TextField( + value = fieldValue, + onValueChange = change, + modifier = fieldModifier, + enabled = node.enabled("enabled", true), + placeholder = node.string("placeholder")?.let { { Text(it) } }, + label = node.string("label")?.let { { Text(it) } }, + singleLine = node.kind != "textarea", + minLines = if (node.kind == "textarea") 3 else 1, + keyboardOptions = commonKeyboard, + keyboardActions = actions, + visualTransformation = visualTransformation, + ) + } + if (node.enabled("autofocus")) { + LaunchedEffect(node.id) { focusRequester.requestFocus() } + } +} + +@Composable +private fun CardNode(backend: LuiBackend, node: LuiNode) { + Card( + modifier = node.styleModifier().gestures(backend, node), + shape = node.shape(), + colors = androidx.compose.material3.CardDefaults.cardColors( + containerColor = node.colorProp("background") ?: Color.Unspecified, + contentColor = node.colorProp("foreground") ?: Color.Unspecified, + ), + ) { + Column( + modifier = Modifier.padding((node.int("padding") ?: 0).dp), + verticalArrangement = node.mainAxisVertical(), + horizontalAlignment = node.crossAxisHorizontal(), + ) { + Children(backend, node) + } + } +} + +@Composable +private fun AlertNode(backend: LuiBackend, node: LuiNode) { + Surface( + modifier = node.styleModifier().gestures(backend, node), + shape = node.shape(), + color = node.colorProp("background") ?: MaterialTheme.colorScheme.errorContainer, + contentColor = node.colorProp("foreground") ?: MaterialTheme.colorScheme.onErrorContainer, + ) { + Column( + modifier = Modifier.padding(12.dp), + verticalArrangement = node.mainAxisVertical(), + ) { + node.string("title")?.let { + Text(it, style = MaterialTheme.typography.titleSmall) + } + node.string("description")?.let { + Text(it, style = MaterialTheme.typography.bodySmall) + } + Children(backend, node) + } + } +} + +@Composable +private fun ImageNode(backend: LuiBackend, node: LuiNode) { + // LUI image sources are app-relative paths or remote URLs; the core + // supplies `url`/`path` props. Coil is intentionally not a LUI + // dependency — apps register an "image" extension instead; here we + // render a labelled placeholder when no loader is present. + Surface( + modifier = node.styleModifier().gestures(backend, node), + shape = node.shape(), + color = MaterialTheme.colorScheme.surfaceContainerHigh, + ) { + val label = node.string("accessibility-label") + ?: node.string("title") + ?: "image" + Box( + modifier = Modifier + .fillMaxWidth() + .height((node.int("height") ?: 120).dp), + contentAlignment = Alignment.Center, + ) { + Text(label, style = MaterialTheme.typography.bodySmall) + } + } +} + +@Composable +private fun TabsNode(backend: LuiBackend, node: LuiNode) { + // Children carry their own tab chrome; `active-index` marks the + // selected tab for button children that read `selected`. + Column( + modifier = node.surfaceModifier().gestures(backend, node), + ) { + Children(backend, node) + } +} + +@Composable +private fun MenuTrigger(backend: LuiBackend, node: LuiNode) { + Box { + Children(backend, node) + } +} + +@Composable +private fun MenuNode(backend: LuiBackend, node: LuiNode) { + if (!node.flag("open") && !node.enabled("open")) return + DropdownMenu( + expanded = true, + onDismissRequest = { backend.dispatch(LuiEvent.Dismiss(node.id)) }, + ) { + for (childId in node.children.toList()) { + val child = backend.node(childId) ?: continue + if (child.kind == "menu-item") { + DropdownMenuItem( + text = { + Text(child.string("title") ?: child.string("value").orEmpty()) + }, + onClick = { backend.dispatch(LuiEvent.Press(child.id)) }, + ) + } else { + key(childId) { LuiNodeView(backend, childId) } + } + } + } +} + +@Composable +private fun DialogNode(backend: LuiBackend, node: LuiNode) { + Dialog( + onDismissRequest = { backend.dispatch(LuiEvent.Dismiss(node.id)) }, + ) { + Surface( + modifier = node.styleModifier(), + shape = node.shape(), + color = node.colorProp("background") ?: MaterialTheme.colorScheme.surface, + ) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = node.mainAxisVertical(), + ) { + Children(backend, node) + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun SheetNode(backend: LuiBackend, node: LuiNode) { + ModalBottomSheet( + onDismissRequest = { backend.dispatch(LuiEvent.Dismiss(node.id)) }, + sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true), + containerColor = node.colorProp("background") + ?: MaterialTheme.colorScheme.surface, + ) { + Column( + modifier = node.styleModifier(), + verticalArrangement = node.mainAxisVertical(), + ) { + Children(backend, node) + } + } +} + +@Composable +private fun DrawerNode(backend: LuiBackend, node: LuiNode) { + // Rendered as a modal popup anchored to the start edge — the interim + // backend has no scaffold context to attach a real drawer to. + Popup( + alignment = Alignment.TopStart, + onDismissRequest = { backend.dispatch(LuiEvent.Dismiss(node.id)) }, + properties = PopupProperties(focusable = true), + ) { + ModalDrawerSheet( + modifier = node.styleModifier().fillMaxSize(0.9f), + ) { + Children(backend, node) + } + } +} + +@Composable +private fun PopupNode(backend: LuiBackend, node: LuiNode) { + Popup( + onDismissRequest = { backend.dispatch(LuiEvent.Dismiss(node.id)) }, + properties = PopupProperties(focusable = node.kind == "popover"), + ) { + Surface( + shape = node.shape(), + color = node.colorProp("background") ?: MaterialTheme.colorScheme.surfaceContainerHigh, + shadowElevation = 4.dp, + ) { + Box(Modifier.padding(8.dp)) { Children(backend, node) } + } + } +} + +@Composable +private fun ToastNode(backend: LuiBackend, node: LuiNode) { + Popup(alignment = Alignment.BottomCenter) { + Surface( + shape = androidx.compose.foundation.shape.RoundedCornerShape(24.dp), + color = node.colorProp("background") ?: MaterialTheme.colorScheme.inverseSurface, + contentColor = MaterialTheme.colorScheme.inverseOnSurface, + shadowElevation = 6.dp, + ) { + Box(Modifier.padding(horizontal = 16.dp, vertical = 10.dp)) { + Children(backend, node) + } + } + } +} + +@Composable +private fun BadgeNode(backend: LuiBackend, node: LuiNode) { + Badge(modifier = node.styleModifier()) { + Text(node.string("value") ?: node.string("title").orEmpty()) + } +} + +@Composable +private fun FilePickerNode(backend: LuiBackend, node: LuiNode) { + // The core opens pickers through effects; the node is a trigger. + Frame(backend, node) +} + +@Composable +private fun SelectNode(backend: LuiBackend, node: LuiNode) { + Frame(backend, node) +} + +@Composable +private fun StepperNode(backend: LuiBackend, node: LuiNode) { + Row( + modifier = node.styleModifier().gestures(backend, node), + verticalAlignment = Alignment.CenterVertically, + ) { + Children(backend, node) + } +} + +@Composable +private fun FallbackContainer(backend: LuiBackend, node: LuiNode) { + Log.d(TAG, "rendering '${node.kind}' as a plain container") + Column(modifier = node.surfaceModifier().gestures(backend, node)) { + Children(backend, node) + } +} diff --git a/android/lui/src/main/kotlin/dev/lui/LuiTheme.kt b/android/lui/src/main/kotlin/dev/lui/LuiTheme.kt new file mode 100644 index 00000000..cf6b0162 --- /dev/null +++ b/android/lui/src/main/kotlin/dev/lui/LuiTheme.kt @@ -0,0 +1,150 @@ +package dev.lui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.ui.graphics.Color +import org.json.JSONObject + +// Theme token scoping: nodes carry a `theme` prop — a JSON object mapping +// token names to either "#rrggbb[aa]" colors or {"light","dark"} adaptive +// pairs — and a `theme-mode` prop ("system"|"light"|"dark") that picks +// the effective brightness under this subtree. +data class LuiThemeTokens(val values: Map = emptyMap()) { + fun merge(raw: String?): LuiThemeTokens { + if (raw.isNullOrEmpty()) return this + val decoded = try { + JSONObject(raw) + } catch (_: Exception) { + return this + } + val merged = values.toMutableMap() + for (key in decoded.keys()) merged[key.lowercase()] = decoded.opt(key) + return LuiThemeTokens(merged) + } + + // Token value → color string for the active brightness. + fun resolve(name: String?, dark: Boolean): String? { + val value = values[name?.lowercase()] ?: return null + return when (value) { + is String -> value + is JSONObject -> (if (dark) value.optString("dark") else value.optString("light")) + .takeIf(String::isNotEmpty) + else -> null + } + } +} + +val LocalLuiThemeTokens = compositionLocalOf { LuiThemeTokens() } +val LocalLuiThemeDark = compositionLocalOf { false } + +object LuiTheme { + // Named colors fall back through the same palette the other LUI + // backends use (Material shadcn-style tokens, then base colors). + @Composable + @ReadOnlyComposable + fun color(name: String?, foreground: Boolean = false): Color? { + if (name == null) return null + val dark = LocalLuiThemeDark.current + val token = LocalLuiThemeTokens.current.resolve(name, dark) + token?.let { parseColor(it) }?.let { return it } + return schemeColor(name.lowercase(), MaterialTheme.colorScheme, foreground) + } + + fun parseColor(value: String?): Color? { + if (value == null) return null + var raw = value.removePrefix("#") + if (raw.length == 3 || raw.length == 4) { + raw = raw.toCharArray().joinToString("") { "$it$it" } + } + if (raw.length == 6) raw = "ff$raw" + else if (raw.length == 8) raw = raw.substring(6) + raw.substring(0, 6) + if (raw.length != 8) return null + val parsed = raw.toLongOrNull(16) ?: return null + return Color(parsed) + } + + private fun schemeColor(name: String, colors: ColorScheme, foreground: Boolean): Color? = + when (name) { + "transparent" -> Color.Transparent + "background" -> colors.surface + "foreground" -> colors.onSurface + "surface" -> colors.surface + "surface-container-lowest" -> colors.surfaceContainerLowest + "surface-container-low" -> colors.surfaceContainerLow + "surface-container" -> colors.surfaceContainer + "surface-container-high" -> colors.surfaceContainerHigh + "surface-container-highest" -> colors.surfaceContainerHighest + "surface-variant" -> colors.surfaceContainerHighest + "autocomplete-row-background" -> colors.surfaceContainerHigh + "glass" -> colors.surface.copy(alpha = 0.75f) + "glass-fallback" -> colors.surface.copy(alpha = 0.9f) + "bar" -> colors.surface.copy(alpha = 0.85f) + "primary" -> colors.primary + "primary-foreground" -> colors.onPrimary + "accent" -> if (foreground) colors.primary else colors.secondaryContainer + "accent-foreground" -> + if (foreground) colors.onPrimary else colors.onSecondaryContainer + "secondary" -> + if (foreground) colors.onSurfaceVariant else colors.secondaryContainer + "secondary-foreground" -> colors.onSecondaryContainer + "muted" -> colors.surfaceContainerHigh + "muted-foreground" -> colors.onSurfaceVariant + "destructive" -> colors.error + "destructive-foreground" -> colors.onError + "success" -> colors.tertiaryContainer + "success-foreground" -> colors.onTertiaryContainer + "warning" -> colors.secondaryContainer + "warning-foreground" -> colors.onSecondaryContainer + "error" -> colors.errorContainer + "error-foreground" -> colors.onErrorContainer + "border" -> colors.outlineVariant + "black" -> Color.Black + "white" -> Color.White + "red" -> Color.Red + "blue" -> Color.Blue + "green" -> Color.Green + "card" -> colors.surfaceContainerLowest + else -> Color.Transparent + } + + // Effective dark flag for a `theme-mode` prop value. + @Composable + fun darkForMode(mode: String?): Boolean = when (mode) { + "light" -> false + "dark" -> true + else -> isSystemInDarkTheme() + } + + @Composable + fun Provider(mode: String?, content: @Composable () -> Unit) { + val dark = darkForMode(mode) + MaterialTheme( + colorScheme = if (dark) darkColorScheme() else lightColorScheme(), + content = content, + ) + } + + @Composable + fun NodeScope(node: LuiNode, content: @Composable () -> Unit) { + val inherited = LocalLuiThemeTokens.current + val themeProp = node.string("theme") + val scoped = if (themeProp != null) inherited.merge(themeProp) else inherited + val mode = node.string("theme-mode") + val dark = if (mode != null) darkForMode(mode) else LocalLuiThemeDark.current + if (scoped !== inherited || mode != null) { + CompositionLocalProvider( + LocalLuiThemeTokens provides scoped, + LocalLuiThemeDark provides dark, + ) { content() } + } else { + content() + } + } +} diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 00000000..1a0e55ee --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,34 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +// The Kotlin/Jetpack Compose LUI backend is developed in the logseq/lui +// checkout at ../lui (platform/android on branch devin/android-kotlin). +// When that build exists it is consumed as a composite build, mirroring +// how apple/ path-deps ../lui/platform/apple. Until it lands, the app +// builds against the interim dev.lui implementation vendored in :lui — +// it implements the documented dev.lui surface (LuiBackend patch/node +// store, LuiTheme, node renderers, LuiExtensionRegistry) so swapping it +// for the real backend is a settings-only change. +val luiCheckoutBuild = File(rootDir, "../../lui/platform/android") +val useCheckoutLui = luiCheckoutBuild.isDirectory && + File(luiCheckoutBuild, "settings.gradle.kts").isFile + +if (useCheckoutLui) { + includeBuild(luiCheckoutBuild) +} else { + include(":lui") +} + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } +} + +include(":app") diff --git a/docs/adr/001-real-time-graph-sync.md b/docs/adr/001-real-time-graph-sync.md index b28fb189..a0d603c5 100644 --- a/docs/adr/001-real-time-graph-sync.md +++ b/docs/adr/001-real-time-graph-sync.md @@ -62,7 +62,7 @@ support: | Local metadata | Graph catalog, selection, pending writes, and checkpoints use versioned Transit records. Legacy `Marshal` metadata is intentionally treated as a cache miss; no old-cache migration is required. | | Local journal reads | OCaml maintains an incremental recent-journal projection and re-queries only affected blocks, rebuilding only when journal-page membership changes. | | iOS background sync | Background entry starts an immediate, bounded sync under a UIKit background assertion; `BGAppRefresh` is also registered for later catch-up. Each execution opens the persisted graph, submits pending semantic REST writes, and replays graph events from `appliedServerT` without graph-catalog or semantic refresh | -| Android sync transport | OCaml core, full-snapshot download/import, and the Flutter Android host's native WebSocket entity-change streaming are connected; device E2E remains pending | +| Android sync transport | OCaml core, full-snapshot download/import, and the Android host's native WebSocket entity-change streaming are connected; device E2E remains pending | | Encrypted graph sync | iOS Simulator E2E against local db-sync verifies encrypted first-open snapshot import, local key unlock and Keychain restore, semantic REST journal/block creation, authoritative WebSocket confirmation, ciphertext-only server storage, and kill/relaunch persistence | ## Decision @@ -75,7 +75,7 @@ endpoint with `ASWebAuthenticationSession`; Android uses Custom Tabs. Both use t authorization-code flow with S256 PKCE and a public app client without a secret. Authentication is exposed to the shared application model through a small platform -service implemented independently by SwiftUI and Flutter. OAuth state and tokens do +service implemented independently by SwiftUI and Android. OAuth state and tokens do not cross the OCaml graph boundary; the adapter supplies an access token only when the OCaml core requests an authenticated transport operation. diff --git a/docs/agent-guide/001-lg-lui-rewrite.md b/docs/agent-guide/001-lg-lui-rewrite.md index 35a25612..38849eeb 100644 --- a/docs/agent-guide/001-lg-lui-rewrite.md +++ b/docs/agent-guide/001-lg-lui-rewrite.md @@ -16,12 +16,12 @@ baseline on iOS and Android. - Move application state, reducers, effects, projections, and ordinary UI into LG and LUI. - Keep the LUI SwiftUI renderer native on Apple platforms. Render the same LG - model through LUI's Flutter backend on Android. + model through LUI's Android backend on Android. - Keep operating-system services in the existing Swift and Kotlin adapters. - Implement Logseq-specific editor, rich content, math, code, video, WebView, and media behavior as validated LUI extensions rather than standard LUI elements. -- Keep Android platform services in the Flutter Android host and its Kotlin +- Keep Android platform services in the Kotlin Android host and its Kotlin adapters. - Exclude Chat mode, its composer and send flow, and Chat-specific automatic scrolling from this rewrite. The Outliner keeps its current scroll position @@ -68,7 +68,7 @@ features. The following are authoritative evidence: ## Delivery gates 1. LG/LUI native runtime shell and reducer tests. -2. Shared LG model with SwiftUI and Flutter renderer parity tests. +2. Shared LG model with SwiftUI and Android renderer parity tests. 3. Virtualized keyed list, viewport events, anchor preservation, and imperative scroll tests on both hosts. 4. Native outliner editor extension and IME/caret stress tests. diff --git a/docs/agent-guide/001-lg-lui-rewrite_android-dogfood_report.md b/docs/agent-guide/001-lg-lui-rewrite_android-dogfood_report.md index f2140408..8b7e61b3 100644 --- a/docs/agent-guide/001-lg-lui-rewrite_android-dogfood_report.md +++ b/docs/agent-guide/001-lg-lui-rewrite_android-dogfood_report.md @@ -3,7 +3,7 @@ | Field | Value | |-------|-------| | Date | 2026-09-01 | -| Target | Android Flutter debug app on `logseq_android_36` and physical device `4a23a2e9` | +| Target | Android debug app on `logseq_android_36` and physical device `4a23a2e9` | | Scope | Full Android UI/UX and E2E parity with iOS | ## Summary @@ -48,7 +48,7 @@ behavior, and bottom-aligned Cancel/Add actions. **Fix Verification** -The Flutter host now renders one bounded Material sheet child with a vertical +The Android host now renders one bounded Material sheet child with a vertical form, flexible spacing, and a bottom-aligned action row. Maestro verified the field, toggle, disabled/enabled Add state, keyboard entry, and Cancel action. No LUI, patch-generation, or RenderFlex errors were logged. @@ -67,7 +67,7 @@ No LUI, patch-generation, or RenderFlex errors were logged. **Description** -The Flutter root scaffold did not consume Android system insets. Titles and +The Android root scaffold did not consume Android system insets. Titles and toolbar actions rendered underneath the status bar; the Graph picker overflow button was visible but its hit target was intercepted by the system bar. @@ -78,7 +78,7 @@ areas, and visible toolbar actions remain tappable. **Fix Verification** -The Android Flutter app frame now owns one root `SafeArea`. A widget regression +The Android app frame now owns one root `SafeArea`. A widget regression test verifies both top and bottom insets, and the overflow button is exposed as an identified accessibility button. The Settings popup now opens reliably. @@ -96,7 +96,7 @@ an identified accessibility button. The Settings popup now opens reliably. **Description** -Opening Settings pushed a modal route but rendered only its gray scrim. Flutter +Opening Settings pushed a modal route but rendered only its gray scrim. Android reported a flex child under unbounded width constraints: the shared iOS-style language radio picker placed every language in one row, while the Theme and Language selects themselves had no finite Material form width. @@ -150,7 +150,7 @@ text changes and rejects autocomplete selection while that block has a queued or in-flight text update. Two reducer regressions cover pending and in-flight ordering. The Android E2E waits for and selects the actual **E2E Project** row. The node/tag flow and the other nine signed-in Android modules pass in sequence; -LG passes 137 tests and Flutter passes 68 tests. +LG passes 137 tests and Android passes 68 tests. ### ISSUE-005: Authentication content is centered inside a narrow retained layer @@ -164,7 +164,7 @@ LG passes 137 tests and Flutter passes 68 tests. **Description** -The Flutter root `Stack` gives non-positioned children loose horizontal +The Android root `Stack` gives non-positioned children loose horizontal constraints. The authentication column used `grow`, which filled the vertical Flex axis, but retained its intrinsic 780-pixel width on a 1080-pixel emulator. The sign-in content therefore appeared left of the physical screen center. @@ -173,7 +173,7 @@ The sign-in content therefore appeared left of the physical screen center. **Fix Verification** -The Flutter authentication surface now stretches to the available width before +The Android authentication surface now stretches to the available width before an inner column centers its content. UIAutomator reports `screen.authentication` at `[0,132][1080,2337]`, and the signed-out Maestro flow passes against the actionable sign-in control. @@ -193,7 +193,7 @@ flow passes against the actionable sign-in control. **Description** LG correctly emitted the cross-platform `muted-foreground` token, but the LUI -Flutter backend did not map it into the Material `ColorScheme`. Unknown tokens +Android backend did not map it into the Material `ColorScheme`. Unknown tokens fell back to `Colors.transparent`. Supporting text, captions, statuses, and form guidance remained in the accessibility tree while becoming invisible. @@ -201,9 +201,9 @@ form guidance remained in the accessibility tree while becoming invisible. LUI now maps `muted-foreground` to Material 3 `onSurfaceVariant`. The fix and a backend regression test are pushed as commit -`09631149799f358f55fb6fc13bfa73dfb07e9cf2`; the app pins only its Flutter +`09631149799f358f55fb6fc13bfa73dfb07e9cf2`; the app pins only its Android backend to that compatible revision. All 74 tests on that LUI revision pass, -the Logseq Chat Flutter suite passes 68 tests, and physical-device screenshots +the Logseq Chat Android suite passes 68 tests, and physical-device screenshots show both page guidance and empty-state descriptions at the expected secondary contrast. @@ -233,7 +233,7 @@ primary action. Android now uses a compact level-three page title and a centered Material empty state with a cloud icon, secondary explanation, filled Add action, and a lower-emphasis Refresh action. iOS retains its existing main-branch layout. -A Flutter-profile LG regression pins the title level, full-width layout, +A Android-profile LG regression pins the title level, full-width layout, empty-state presence, action priority, and Material icon names. ![Material Graph picker empty state](android-dogfood/screenshots/issue-006-graph-picker-material.png) @@ -258,7 +258,7 @@ made the new app difficult to distinguish from an existing Logseq installation. **Fix Verification** -Both Flutter and Apple LG profiles now render **Logseq Chat** from the shared +Both Android and Apple LG profiles now render **Logseq Chat** from the shared authentication view. A cross-host LG regression rejects the old standalone name. Android also uses the full product name for clipboard content and the system share chooser. The signed-out Maestro flow asserts the product name @@ -292,7 +292,7 @@ fragile. The foreground and monochrome vectors now scale around the 108-unit viewport center with an additional 14% inset. The monochrome asset uses an opaque black mask so Android 13+ can apply wallpaper-derived themed colors correctly. A -Flutter resource regression keeps the canonical Android and Flutter-host assets +Android resource regression keeps the canonical Android and Android-host assets identical and pins their pivot, scale, and monochrome semantics. ![Balanced adaptive icon](android-dogfood/screenshots/issue-009-launcher-safe-zone-fixed.png) @@ -310,7 +310,7 @@ identical and pins their pivot, scale, and monochrome semantics. **Description** The Android Audio recording command was routed to `ACTION_OPEN_DOCUMENT` and -the Flutter manifest did not request `RECORD_AUDIO`. Android therefore could +the Android manifest did not request `RECORD_AUDIO`. Android therefore could only pick an existing audio file, while iOS recorded, inserted, and played a new voice note inline. @@ -321,7 +321,7 @@ permission at runtime, writes the result into the graph asset metadata path, hashes it with SHA-256, and inserts it through the authoritative core `addAsset` action. Audio assets render as a Material inline player backed by Android `MediaPlayer`, with play, pause, progress, error recovery, and lifecycle -cleanup. Flutter passes 86 tests, Kotlin unit tests and debug APK compilation +cleanup. Android passes 86 tests, Kotlin unit tests and debug APK compilation pass. The dedicated physical-device instrumentation APK was blocked before execution by MIUI's USB installation confirmation (`INSTALL_FAILED_USER_RESTRICTED`), so the report does not claim a hardware recording pass yet. @@ -333,12 +333,12 @@ so the report does not claim a hardware recording pass yet. | Severity | high | | Category | functional / parity / rich content | | View | Journal and page outliner rich blocks | -| Repro Video | N/A; deterministic Flutter renderer behavior | +| Repro Video | N/A; deterministic Android renderer behavior | | Status | Fixed and verified on emulator | **Description** -Flutter rendered video and iframe nodes as a play icon plus their raw URL, +Android rendered video and iframe nodes as a play icon plus their raw URL, rendered math as italic TeX source, and rendered cloze text as an always-visible static chip. The nodes had parity identifiers but not iOS-equivalent behavior. @@ -348,7 +348,7 @@ YouTube and iframe content now use a lightweight Material preview and create a system WebView only after an explicit tap, preserving lazy-list scrolling. YouTube URLs are normalized to `youtube-nocookie.com`, unsafe schemes are rejected, and timestamp blocks update the embed start time. LaTeX is typeset -with a pure Flutter renderer and malformed expressions retain a readable +with a pure Android renderer and malformed expressions retain a readable fallback. Cloze content now reveals and hides through a Material action chip. Code blocks use selectable, horizontally scrollable syntax-highlighted text with light and dark Material color palettes; parsed syntax trees are cached so @@ -370,7 +370,7 @@ than accepting a placeholder. **Description** -A long press emitted the selection/drag-start event, but Flutter rows were not +A long press emitted the selection/drag-start event, but Android rows were not draggable and did not accept drops. The core supported before, inside, and after placement, while the Android surface could never publish one. @@ -396,7 +396,7 @@ second block, and verifies the LG extension receives the target UUID and **Description** iOS schedules the authoritative core `saveEditing` event one second after text -changes settle. The Flutter Android effect drain did not recognize or schedule +changes settle. The Android effect drain did not recognize or schedule that action, so an edit could remain in the transient editor state indefinitely unless a later structural action happened to commit it. @@ -432,7 +432,7 @@ core restoration, failures, and attachment imports append records without reading privileged global logcat data. Kotlin tests cover bounds, filtering, ordering, and JSON escaping. Android Settings E2E now requires visible `INFO` records for both UI and Core sources. On the rebuilt emulator app, **Check -log** displayed real Android host, Flutter host, and core-effect records; +log** displayed real Android host, Android host, and core-effect records; level, order, and source controls updated immediately, Copy and Refresh dispatched without an error, and Done returned to Settings. @@ -448,7 +448,7 @@ dispatched without an error, and Done returned to Settings. **Description** -The Flutter Android host launched the system document or camera intent but did +The Android host launched the system document or camera intent but did not receive its result. Selected files therefore never entered app storage or the authoritative core asset model. @@ -478,7 +478,7 @@ The visible list stayed stale until the user explicitly tapped **Refresh**. **Fix Verification** -The Flutter host now starts a coalescing foreground refresh loop after session +The Android host now starts a coalescing foreground refresh loop after session restore, stops it in the background and on sign-out, and immediately refreshes again on resume. Device logging exposed that the first implementation sent the selected-graph `refresh` action, so restore and resume both ended in @@ -501,19 +501,19 @@ rejection, overlap, periodic scheduling, and timer cancellation. **Description** -LUI Flutter rendered the semantic `list` primitive as an eager `Column`. A -real catalog overflowed the viewport by 2296 pixels, displayed Flutter's +LUI Android rendered the semantic `list` primitive as an eager `Column`. A +real catalog overflowed the viewport by 2296 pixels, displayed Android's yellow/black failure stripe, and made the remaining graphs unreachable. ![Graphs overflow before fix](android-dogfood/screenshots/issue-017-graphs-overflow-before.png) **Fix Verification** -Flutter now maps `list` to a native lazy `ListView`, matching SwiftUI's native +Android now maps `list` to a native lazy `ListView`, matching SwiftUI's native `List` semantics without changing the Apple backend. The full page scrolls, starts at the Refresh action, and logs no RenderFlex error. The LUI fix is pushed as commit `9512238e40248f664d7a870565360436818410ac`; all 77 LUI tests -and all 112 Logseq Chat Flutter tests pass. +and all 112 Logseq Chat Android tests pass. ![Scrollable Graphs page](android-dogfood/screenshots/issue-017-graphs-scrollable-fixed.png) @@ -544,9 +544,9 @@ a lower-emphasis refresh action, consistent icons, and clear catalog sections. Android now renders one 16dp-inset, 12dp-gap action row. **Add graph** is a filled primary Material button, **Refresh** is a tonal secondary button, both are equal width with native icons and 48dp touch targets, and the catalog -continues below as a lazy native list. The implementation is Flutter-only; +continues below as a lazy native list. The implementation is Android-only; SwiftUI retains the main-branch native List rows. LG passes 144 tests and -Flutter passes 112 tests. Emulator event logs prove Refresh reaches +Android passes 112 tests. Emulator event logs prove Refresh reaches `refresh-graphs` and succeeds, while Add graph opens and dismisses the existing Material form sheet. @@ -578,9 +578,9 @@ height. **Root Cause** -The Flutter-only Capture/Search row incorrectly declared `grow: 1` inside the +The Android-only Capture/Search row incorrectly declared `grow: 1` inside the bottom stack. LUI correctly translated that value to an `Expanded`, but the -bottom stack is measured with unbounded intrinsic height. Flutter therefore +bottom stack is measured with unbounded intrinsic height. Android therefore could not lay out the flex child, which removed the complete mutually-exclusive bottom chrome from the rendered surface. @@ -594,7 +594,7 @@ behavior. All 144 LG tests pass. A freshly rebuilt debug APK was installed on the emulator with the populated graph preserved: Capture/Search remained anchored above the navigation bar, Capture expanded and dismissed through the native Back flow, Search opened its Material full-screen presentation, and no -Flutter, RenderFlex, or overflow exception was logged. +Android, RenderFlex, or overflow exception was logged. ![Restored journal bottom chrome](android-dogfood/screenshots/issue-019-bottom-chrome-fixed.png) @@ -629,18 +629,18 @@ secondary text, and an anchored Cancel/Apply action hierarchy. **Root Cause** LUI's `select` authoring element discarded `:label`, and all three validation -boundaries independently rejected `AccessibilityLabel` on a Select. Flutter +boundaries independently rejected `AccessibilityLabel` on a Select. Android therefore had no field name to render, while adding the property only in the app caused the retained LG runtime to reject the complete Settings tree. **Fix Verification** -LUI now retains the select label in the closed protocol. Flutter renders it as +LUI now retains the select label in the closed protocol. Android renders it as a persistent Material `InputDecorator` label; the Apple backend accepts the same accessibility metadata without changing its visual SwiftUI picker. The Android form uses tonal cards, readable supporting text, native switches, and an anchored equal-width secondary/primary action row. LUI passes 201 tests, -Logseq Chat LG passes 144 tests, Flutter passes 112 tests, and the rebuilt debug +Logseq Chat LG passes 144 tests, Android passes 112 tests, and the rebuilt debug app renders Theme and Language distinctly with no protocol or layout error. ![Settings form after redesign](android-dogfood/screenshots/issue-020-settings-form-fixed.png) @@ -672,19 +672,19 @@ the remaining scrollable area. **Root Cause** The shared sheet exposed the Runtime log screen and its navigation toolbar as -two sibling children. Flutter bottom sheets compose their single content slot +two sibling children. Android bottom sheets compose their single content slot as an overlay, so the navigation toolbar was painted over the screen's first filter toolbar. SwiftUI's native sheet backend handles those navigation children separately and did not exhibit the problem. **Fix Verification** -Flutter now receives one bounded vertical sheet child. The Runtime log screen +Android now receives one bounded vertical sheet child. The Runtime log screen owns the flexible region, while an equal-width secondary **Refresh** and primary **Done** row is anchored below it. SwiftUI retains the existing native navigation toolbar path. The new RED test first proved the old multi-child, overlay-toolbar contract, then passed after the layout change; all 144 LG and -112 Flutter tests remain green. On the rebuilt emulator, every filter was +112 Android tests remain green. On the rebuilt emulator, every filter was independently tappable, Copy and Refresh dispatched, and Done returned to the Settings sheet. @@ -703,7 +703,7 @@ Settings sheet. **Description** Tapping the full-width **Tabs** row leaves the main Settings sheet unchanged. -The Flutter event log records the row's Press event every time, so this is not +The Android event log records the row's Press event every time, so this is not a missing hit target or Maestro selector failure; the navigation action is lost after it reaches the LG bridge. The user therefore cannot configure tab visibility or ordering on Android. @@ -722,7 +722,7 @@ Tabs configuration screen, with a clear path back to Settings. **Root Cause** The Press action correctly set `settings-tabs-open`. Rendering the destination -then created Flutter icon-only tab-reordering buttons whose authoring maps used +then created Android icon-only tab-reordering buttons whose authoring maps used `accessibility-label`; LUI buttons expose that semantic through `label`. Because the required label was absent from the retained protocol, the backend rejected the entire destination patch and left the previous Settings tree on @@ -731,9 +731,9 @@ screen. **Fix Verification** The reordering controls now publish valid button labels. A new regression test -dispatches Press through the rendered Flutter row and verifies that Tabs +dispatches Press through the rendered Android row and verifies that Tabs replaces the main Settings screen, covering the real path rather than directly -sending a model action. All 145 LG tests and 112 Flutter tests pass. The rebuilt +sending a model action. All 145 LG tests and 112 Android tests pass. The rebuilt debug APK entered `screen.settings.tabs` during Android Settings E2E. ### ISSUE-023: Tabs sheet overlaps its back action and misaligns every row @@ -748,7 +748,7 @@ debug APK entered `screen.settings.tabs` during Android Settings E2E. **Description** -After navigation succeeds, the Flutter sheet paints the **Settings** back +After navigation succeeds, the Android sheet paints the **Settings** back action over the large **Visible tabs** heading. The tab rows float around the horizontal center instead of forming full-width Material settings rows, with large irregular gaps between labels, selection state, and reorder arrows. @@ -764,7 +764,7 @@ Evidence: Android Settings E2E artifact **Fix Verification** -Flutter now receives one bounded vertical sheet child: a growing Tabs screen +Android now receives one bounded vertical sheet child: a growing Tabs screen and a separate full-width **Back to Settings** footer. The Android-only screen uses a compact heading, a native lazy list, 56dp tonal rows, leading tab state, and trailing reorder controls with stable labels and identifiers. The shared @@ -799,7 +799,7 @@ SearchBar and remain navigable through the native Android back stack. Targeted effect logging proved that every query update reached the LG bridge, the `search-nodes` effect executed successfully, and the final core response contained three results. The result `list` was nested in a growing vertical -search surface without its own `grow` constraint. Flutter therefore laid out +search surface without its own `grow` constraint. Android therefore laid out the populated list at zero height. SwiftUI's native `List` expands by default, which is why the shared view had not exposed the same failure on iOS. @@ -841,9 +841,9 @@ isolate when it tried to dispatch composer events into LG. `refreshGraphCatalog` now returns a dedicated lightweight graph-catalog patch containing only graph metadata. LG applies only those owned fields and preserves the active composer, journal rows, navigation, and editor state. Unchanged -catalogs are also skipped by the Flutter host. Automatic polling runs only while +catalogs are also skipped by the Android host. Automatic polling runs only while the authenticated graph picker is foreground; opening a graph stops it so OCaml -network discovery cannot contend with editor input. Core, LG, and Flutter +network discovery cannot contend with editor input. Core, LG, and Android regressions cover patch identity, editor-state preservation, polling policy, unchanged-catalog skipping, and changed-catalog application. The rebuilt APK then completed the full Composer lifecycle E2E without another @@ -872,12 +872,12 @@ NavigationStack back button. **Fix Verification** -The Flutter header now switches its leading action from the sidebar menu to an +The Android header now switches its leading action from the sidebar menu to an `arrow_back` action whenever the LG app-navigation depth is non-zero. The button uses `button.navigation.back`, has the accessibility label **Back**, and pops exactly one LG route. The host check keeps the shared SwiftUI renderer unchanged. The new regression failed before the control existed and now passes; -all 146 LG tests, focused Flutter extension/icon tests, Flutter analysis, and +all 146 LG tests, focused Android extension/icon tests, Android analysis, and the complete Android Material Navigation E2E pass on the rebuilt APK. ### ISSUE-027: Core restore contends with LG and causes restart ANR @@ -901,7 +901,7 @@ after catalog polling was disabled for an open graph. The 22:14 Android ANR shows the Dart/UI thread blocked in `pthread_mutex_lock`, while Dart workers were executing the same `liblogseq_chat_core.so`. Core and LG share one OCaml runtime lock, but the -Flutter bridge allowed background Core FFI and foreground LG FFI to enter it +Android bridge allowed background Core FFI and foreground LG FFI to enter it concurrently. Startup `appear`, accessibility, or input dispatch therefore waited on long graph restore work. The platform log recorded 398 and 169 skipped frames and a 5.083-second focus-event timeout. @@ -912,7 +912,7 @@ A native-runtime scheduler now serializes all Core requests. While Core owns the runtime, LG UI calls are queued on the Dart side instead of blocking the UI thread; they flush in order when Core becomes idle, then effect draining resumes. Three focused scheduler tests cover lock ownership, Core ordering, UI -ordering, and idle notification. Effect/extension tests and Flutter analysis +ordering, and idle notification. Effect/extension tests and Android analysis pass. The rebuilt APK completed three consecutive forced restarts with sidebar interaction each time, and Android DropBox contains no ANR newer than the pre-fix 22:14 record. @@ -933,7 +933,7 @@ Android rendered the ordinary block bullet from a full Material circle glyph, making it much larger and heavier than iOS. Task rows then added a second generic 16dp status icon beside it. The two independent controls looked crowded, and status colors from the shared `task-*` palette were unsupported by -the Flutter backend and could resolve to transparent. The status context menu +the Android backend and could resolve to transparent. The status context menu also required a long press, and its standard `accent` foreground token rendered its labels and icons transparent. @@ -943,14 +943,14 @@ status glyph, and 24pt alignment slots. **Fix Verification** -Flutter now paints a dedicated centered 7dp bullet behind the existing zoom +Android now paints a dedicated centered 7dp bullet behind the existing zoom target and a centered 22dp task glyph behind the existing status target. Task states use the same row foreground as iOS, and retained rows reactively swap the icon without introducing Android-only status colors. SwiftUI continues -through its original icon/button path. LUI Flutter now opens menu-only buttons on primary +through its original icon/button path. LUI Android now opens menu-only buttons on primary tap and maps the shared `accent` and `destructive` tokens to Material primary and error roles. The 147-test LG suite covers marker geometry and retained-row -updates; LUI's 79 Flutter tests cover menu activation and semantic colors. A +updates; LUI's 79 Android tests cover menu activation and semantic colors. A rebuilt debug APK was installed on the emulator, where primary tap opened the visible native menu and selecting Done immediately produced the full-ring check glyph and completed text treatment. A follow-up icon-source comparison found @@ -958,7 +958,7 @@ that Android still used materially different silhouettes for backlog, doing, review, and done (ellipsis, calendar, rectangular comment, and broken-ring check). Those now use the closest native Material equivalents to iOS's dashed circle/progress ring/comment-check/full-ring check semantics. The complete -121-test Flutter suite and `flutter analyze` pass, and the rebuilt debug APK +121-test JVM suite and `gradlew test` pass, and the rebuilt debug APK shows the Done marker as a centered full-ring check without changing SwiftUI. ![Aligned Android outliner markers](ui-comparison/android/markers/journals-after.png) @@ -976,26 +976,26 @@ shows the Done marker as a centered full-ring check without changing SwiftUI. **Description** The shared selection toolbar supplied iOS's icon-plus-caption buttons with a -46pt fixed height. Flutter correctly rejected the unsupported top icon +46pt fixed height. Android correctly rejected the unsupported top icon placement, but the remaining Material button needed a 48dp minimum target and -rendered red vertical overflow warnings across every action. Plain Flutter +rendered red vertical overflow warnings across every action. Plain Android outliner rows also used a `box` to preserve editor gestures, so they could not project the selected state that iOS shows immediately after a long press. **Fix Verification** -Flutter now receives seven icon-only Material actions with stable accessibility +Android now receives seven icon-only Material actions with stable accessibility labels, 48dp targets, compact spacing, and horizontal scrolling retained for narrow screens. SwiftUI keeps its existing captioned Liquid Glass toolbar. -LUI Flutter now supports `selected` on a generic box, exposes the state to +LUI Android now supports `selected` on a generic box, exposes the state to semantics, and paints the standard Material secondary-container selection surface; the shared outliner projects its selected signal onto the existing gesture-compatible row box. The dedicated visual Maestro flow confirms all seven actions are visible with no overflow and the selected row is visibly -highlighted. LUI's 80 tests, the LG 148-test suite, the app's 121 Flutter tests, -and `flutter analyze` all pass. +highlighted. LUI's 80 tests, the LG 148-test suite, the app's 121 Android tests, +and `gradlew test` all pass. -### ISSUE-030: Flutter modal roots lose their accessibility identifiers +### ISSUE-030: Android modal roots lose their accessibility identifiers | Field | Value | |-------|-------| @@ -1007,7 +1007,7 @@ and `flutter analyze` all pass. The Graphs screen loaded and refreshed correctly, but its Android E2E could not address the visible delete confirmation dialog by -`dialog.graph-delete`. The same omission affected every Flutter dialog and +`dialog.graph-delete`. The same omission affected every Android dialog and bottom-sheet root, making Settings and form workflows vulnerable to false inaction reports and inaccessible automation. @@ -1023,7 +1023,7 @@ but the foreground surface exposed none to Android accessibility. LUI now applies the declared accessibility identifier to the actual dialog or sheet surface. New widget tests cover both modal kinds and failed before the -fix. All 80 LUI Flutter tests, 121 application Flutter tests, and both analyze +fix. All 80 LUI Android tests, 121 application Android tests, and both analyze gates pass. On the rebuilt APK, the Graphs E2E now long-presses the local graph row using the native Android context-menu gesture, addresses the visible delete dialog and its actions, cancels it, opens the Add graph sheet, verifies @@ -1045,7 +1045,7 @@ the candidate toolbar but did not insert the selected tag. **Root Cause** -The Flutter editor synchronously dispatched every intermediate text value into +The Android editor synchronously dispatched every intermediate text value into LG, so a single keyboard burst repeatedly crossed the Dart/OCaml boundary on the UI thread. LG then discarded `ChooseOutlinerAutocomplete` whenever a text-change effect was pending or in flight. This avoided stale selection @@ -1053,19 +1053,19 @@ state by throwing away the user's action instead of preserving its order. **Fix Verification** -Flutter now coalesces an ordinary editor text burst for 80ms and publishes only +Android now coalesces an ordinary editor text burst for 80ms and publishes only the latest title and caret, while newline and disposal cancel the pending timer. LG queues the candidate-choice effect behind pending and in-flight text -changes instead of dropping it. The focused Flutter regression failed with +changes instead of dropping it. The focused Android regression failed with three immediate events before the change and now observes one latest event; the LG regression failed because the choice was absent and now verifies exact -effect ordering. All 122 Flutter tests, Flutter analysis, and all 148 LG tests +effect ordering. All 122 Android tests, Android analysis, and all 148 LG tests pass. On the rebuilt APK, the complete node/tag E2E types `#E2E Pro`, selects `E2E Project`, verifies the inserted tag chip and tagged-node navigation, and finishes without an ANR. The separately observed cold-start ANR was not caused by editor input. Android -reported `Application does not have a focused window` while the debug Flutter +reported `Application does not have a focused window` while the debug Android process was still initializing and compiling JIT code on the emulator. Startup phase logs now distinguish binding, first frame, platform-state load, bridge load, LUI initialization, and root mounting so a future launch failure can be @@ -1111,13 +1111,13 @@ the same asset rendered as a paperclip rather than an image. `addAsset` returned a full snapshot. LG intentionally preserves the active lazy-list window across unrelated full snapshots, so the new row was omitted. -The core also normalizes `image/png` to `png`, while Flutter only recognized +The core also normalizes `image/png` to `png`, while Android only recognized MIME values beginning with `image/`. **Fix Verification** Journal asset insertion now returns a bounded structural outliner splice built -from the live visible context. The Flutter renderer recognizes both MIME types -and normalized image extensions. Core and Flutter regressions failed before -the fixes; all core tests, all 122 Flutter tests, analysis, and the Android +from the live visible context. The Android renderer recognizes both MIME types +and normalized image extensions. Core and Android regressions failed before +the fixes; all core tests, all 122 Android tests, analysis, and the Android image-share E2E now pass with the preview visible in the current journal. diff --git a/flutter/.gitignore b/flutter/.gitignore deleted file mode 100644 index 79f7ecab..00000000 --- a/flutter/.gitignore +++ /dev/null @@ -1,48 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release - -# Widget Preview related -.widget_preview/ diff --git a/flutter/.metadata b/flutter/.metadata deleted file mode 100644 index 952556d9..00000000 --- a/flutter/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "6655482ec06e547f90abf8ae7590466f4415978d" - channel: "stable" - -project_type: app - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 6655482ec06e547f90abf8ae7590466f4415978d - base_revision: 6655482ec06e547f90abf8ae7590466f4415978d - - platform: android - create_revision: 6655482ec06e547f90abf8ae7590466f4415978d - base_revision: 6655482ec06e547f90abf8ae7590466f4415978d - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/flutter/README.md b/flutter/README.md deleted file mode 100644 index 4102aea4..00000000 --- a/flutter/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# logseq_chat_flutter - -A new Flutter project. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/flutter/analysis_options.yaml b/flutter/analysis_options.yaml deleted file mode 100644 index 45dee414..00000000 --- a/flutter/analysis_options.yaml +++ /dev/null @@ -1,37 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -analyzer: - exclude: - - build/** - - android/** - - ios/** - - web/** - - windows/** - - linux/** - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/flutter/android/.gitignore b/flutter/android/.gitignore deleted file mode 100644 index be3943c9..00000000 --- a/flutter/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/flutter/android/app/build.gradle.kts b/flutter/android/app/build.gradle.kts deleted file mode 100644 index 5eed7dde..00000000 --- a/flutter/android/app/build.gradle.kts +++ /dev/null @@ -1,86 +0,0 @@ -plugins { - id("com.android.application") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -val repoRoot = rootProject.projectDir.parentFile.parentFile -val flutterNativeLibrary = repoRoot.resolve( - "flutter/android/app/src/main/jniLibs/arm64-v8a/liblogseq_chat_core.so", -) - -tasks.register("buildAndroidNativeCore") { - workingDir = repoRoot - commandLine("bash", "scripts/build-android-native.sh") - inputs.files( - fileTree(repoRoot.resolve("shared/native")), - fileTree(repoRoot.resolve("shared/src")), - fileTree(repoRoot.resolve("datascript-ocaml-native")), - repoRoot.resolve("scripts/bootstrap-android-ocaml.sh"), - repoRoot.resolve("scripts/build-android-native.sh"), - repoRoot.resolve("scripts/build-android-sqlite.sh"), - repoRoot.resolve("scripts/build-mobile-ocaml.sh"), - ) - outputs.file(flutterNativeLibrary) -} - -tasks.named("preBuild") { - dependsOn("buildAndroidNativeCore") -} - -dependencies { - implementation("androidx.browser:browser:1.8.0") - implementation("com.google.mlkit:genai-speech-recognition:1.0.0-alpha1") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2") - testImplementation("junit:junit:4.13.2") - testImplementation("org.json:json:20251224") - androidTestImplementation("androidx.test:core:1.6.1") - androidTestImplementation("androidx.test:rules:1.6.1") - androidTestImplementation("androidx.test:runner:1.6.1") - androidTestImplementation("androidx.test.ext:junit:1.3.0") -} - -android { - namespace = "com.logseq.chat" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.logseq.chat" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = 26 - targetSdk = flutter.targetSdkVersion - // Uses the version code from pubspec.yaml. When using split APKs, 1000 * ABI_VERSION - // is added automatically by Flutter. (https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions) - // You can force using the value of versionCode by specifying the `-P force-version-code-ignoring-abi=true` - // flag during build. - versionCode = flutter.versionCode - versionName = flutter.versionName - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -kotlin { - compilerOptions { - jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 - } -} - -flutter { - source = "../.." -} diff --git a/flutter/android/app/src/debug/AndroidManifest.xml b/flutter/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/flutter/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt b/flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt deleted file mode 100644 index 7455e8b8..00000000 --- a/flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt +++ /dev/null @@ -1,284 +0,0 @@ -package com.logseq.chat - -import android.content.Intent -import android.net.Uri -import android.util.Log -import io.flutter.embedding.engine.FlutterEngine -import io.flutter.embedding.android.FlutterActivity -import io.flutter.plugin.common.EventChannel -import io.flutter.plugin.common.MethodChannel -import java.util.ArrayDeque -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import logseq.chat.AndroidE2EECrypto -import logseq.chat.AndroidHttpTransport -import logseq.chat.AndroidRuntimeLogLevel -import logseq.chat.AndroidRuntimeLogSource -import logseq.chat.AndroidRuntimeLogs - -internal fun flutterEncodableResult(value: Any?): Any? = if (value == Unit) null else value - -class MainActivity : FlutterActivity() { - init { - System.loadLibrary("logseq_chat_core") - } - - override fun onCreate(savedInstanceState: android.os.Bundle?) { - AndroidE2EECrypto.initialize(applicationContext) - AndroidHttpTransport.initialize(applicationContext) - AndroidRuntimeLogs.shared.append( - AndroidRuntimeLogLevel.INFO, - AndroidRuntimeLogSource.UI, - "Android host started", - ) - super.onCreate(savedInstanceState) - assetImporter = AndroidAssetImporter(this, scope) - handleAppIntent(intent) - } - - private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) - private val authentication by lazy { CognitoAuthProvider(applicationContext, this) } - private val platformServices by lazy { AndroidPlatformServices(this) } - private lateinit var assetImporter: AndroidAssetImporter - private val audioRecorder by lazy { AndroidAudioRecorder(this) } - private val audioPlayer by lazy { AndroidAudioPlayer(this) } - private val pendingAppEntries = ArrayDeque>() - private var appEntrySink: EventChannel.EventSink? = null - - override fun configureFlutterEngine(flutterEngine: FlutterEngine) { - super.configureFlutterEngine(flutterEngine) - EventChannel( - flutterEngine.dartExecutor.binaryMessenger, - appEntryChannel, - ).setStreamHandler(object : EventChannel.StreamHandler { - override fun onListen(arguments: Any?, events: EventChannel.EventSink) { - appEntrySink = events - while (pendingAppEntries.isNotEmpty()) { - events.success(pendingAppEntries.removeFirst()) - } - } - - override fun onCancel(arguments: Any?) { - appEntrySink = null - } - }) - MethodChannel( - flutterEngine.dartExecutor.binaryMessenger, - authenticationChannel - ).setMethodCallHandler { call, result -> - scope.launch { - runCatching { - when (call.method) { - "hasStoredSession" -> authentication.hasStoredSession() - "restoreAccessToken" -> authentication.accessToken() - "signIn" -> authentication.signIn() - "signOut" -> authentication.signOut() - else -> throw NotImplementedError(call.method) - } - }.onSuccess { value -> result.success(flutterEncodableResult(value)) }.onFailure { error -> - if (error is NotImplementedError) { - result.notImplemented() - } else { - result.error( - "authentication_failed", - error.message ?: error.toString(), - null - ) - } - } - } - } - MethodChannel( - flutterEngine.dartExecutor.binaryMessenger, - platformChannel - ).setMethodCallHandler { call, result -> - scope.launch { - runCatching { - when (call.method) { - "loadStorageState" -> platformServices.loadStorageState() - "persistComposerDraft" -> platformServices.persistComposerDraft( - call.argument("draft").orEmpty() - ) - "saveSettings" -> platformServices.saveSettings( - requireNotNull(call.argument("settings")) - ) - "openExternalUrl" -> platformServices.openExternalUrl( - call.argument("url").orEmpty() - ) - "copyText" -> platformServices.copyText( - call.argument("text").orEmpty() - ) - "refreshRuntimeLog" -> platformServices.refreshRuntimeLog( - call.argument("source").orEmpty(), - call.argument("flags") ?: 0, - ) - "appendRuntimeLog" -> platformServices.appendRuntimeLog( - call.argument("level").orEmpty(), - call.argument("source").orEmpty(), - call.argument("message").orEmpty(), - ) - "presentAttachment" -> platformServices.presentAttachment( - call.argument("kind").orEmpty() - ) - "importAttachments" -> assetImporter.import( - call.argument("kind").orEmpty() - ) - "presentAsset" -> platformServices.presentAsset( - call.argument("metadata").orEmpty() - ) - "presentPageShare" -> platformServices.presentPageShare( - call.argument("text").orEmpty(), - call.argument("metadata") ?: "[]", - ) - "startAudioRecording" -> audioRecorder.start() - "supportsAudioTranscription" -> AndroidAudioTranscriber.isSupported() - "stopAudioRecording" -> withContext(Dispatchers.IO) { - audioRecorder.stop() - } - "cancelAudioRecording" -> audioRecorder.cancel() - "transcribeAudio" -> withContext(Dispatchers.IO) { - AndroidAudioTranscriber.transcribe( - call.argument("path").orEmpty(), - ) - } - "startAudioPlayback" -> audioPlayer.start( - call.argument("path").orEmpty() - ) - "pauseAudioPlayback" -> audioPlayer.pause( - requireNotNull(call.argument("sessionId")) - ) - "resumeAudioPlayback" -> audioPlayer.resume( - requireNotNull(call.argument("sessionId")) - ) - "audioPlaybackStatus" -> audioPlayer.status( - requireNotNull(call.argument("sessionId")) - ) - "stopAudioPlayback" -> audioPlayer.stop( - requireNotNull(call.argument("sessionId")) - ) - "syncNow" -> false - "deleteLocalGraph" -> platformServices.deleteLocalGraph( - call.argument("graphId").orEmpty() - ) - "exportGraphDatabase" -> platformServices.exportGraphDatabase() - "downloadGraphSnapshot" -> platformServices.downloadGraphSnapshot( - baseUrl = call.argument("baseUrl").orEmpty(), - graphId = call.argument("graphId").orEmpty(), - accessToken = call.argument("accessToken").orEmpty(), - workingDirectory = call.argument("workingDirectory").orEmpty(), - ) - "persistSelectedGraphId" -> platformServices.persistSelectedGraphId( - call.argument("graphId").orEmpty(), - ) - "deleteTemporaryFile" -> platformServices.deleteTemporaryFile( - call.argument("path").orEmpty(), - ) - else -> throw NotImplementedError(call.method) - } - }.onSuccess { value -> result.success(flutterEncodableResult(value)) }.onFailure { error -> - if (error is NotImplementedError) { - result.notImplemented() - } else { - result.error( - "platform_effect_failed", - error.message ?: error.toString(), - null, - ) - } - } - } - } - } - - override fun onNewIntent(intent: Intent) { - super.onNewIntent(intent) - setIntent(intent) - if (authentication.handleCallback(intent.dataString)) return - handleAppIntent(intent) - } - - private fun handleAppIntent(intent: Intent?) { - if (intent == null) return - AndroidAppEntryParser.deepLinkKind(intent.dataString)?.let { kind -> - publishAppEntry(mapOf("kind" to kind)) - return - } - if (intent.action != Intent.ACTION_SEND && intent.action != Intent.ACTION_SEND_MULTIPLE) { - return - } - AndroidAppEntryParser.sharedBlockText( - intent.getStringExtra(Intent.EXTRA_TEXT), - intent.getStringExtra(Intent.EXTRA_TITLE), - )?.let { text -> - publishAppEntry(mapOf("kind" to "shared-text", "text" to text)) - } - sharedUris(intent).forEach { uri -> - scope.launch { - assetImporter.importShared(uri)?.let { asset -> - publishAppEntry(mapOf("kind" to "shared-asset", "asset" to asset)) - } - } - } - } - - private fun publishAppEntry(entry: Map) { - val sink = appEntrySink - Log.i( - "LogseqChatAppEntry", - "Publishing kind=${entry["kind"]} delivery=${if (sink == null) "queued" else "live"}", - ) - if (sink == null) { - pendingAppEntries.addLast(entry) - } else { - sink.success(entry) - } - AndroidRuntimeLogs.shared.append( - AndroidRuntimeLogLevel.INFO, - AndroidRuntimeLogSource.UI, - "Received Android app entry kind=${entry["kind"]}", - ) - } - - @Suppress("DEPRECATION") - private fun sharedUris(intent: Intent): List = buildList { - intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM)?.let(::addAll) - intent.getParcelableExtra(Intent.EXTRA_STREAM)?.let(::add) - intent.clipData?.let { clips -> - for (index in 0 until clips.itemCount) { - clips.getItemAt(index).uri?.let(::add) - } - } - }.distinct() - - @Deprecated("Android activity result callback") - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (assetImporter.onActivityResult(requestCode, resultCode, data)) return - super.onActivityResult(requestCode, resultCode, data) - } - - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray, - ) { - if (audioRecorder.onRequestPermissionsResult(requestCode, grantResults)) return - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - } - - override fun onDestroy() { - audioRecorder.cancel() - audioPlayer.release() - scope.cancel() - super.onDestroy() - } - - private companion object { - const val authenticationChannel = "com.logseq.chat/authentication" - const val platformChannel = "com.logseq.chat/platform" - const val appEntryChannel = "com.logseq.chat/app-entry" - } -} diff --git a/flutter/android/app/src/profile/AndroidManifest.xml b/flutter/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index 399f6981..00000000 --- a/flutter/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/flutter/android/build.gradle.kts b/flutter/android/build.gradle.kts deleted file mode 100644 index dbee657b..00000000 --- a/flutter/android/build.gradle.kts +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() -rootProject.layout.buildDirectory.value(newBuildDir) - -subprojects { - val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) - project.layout.buildDirectory.value(newSubprojectBuildDir) -} -subprojects { - project.evaluationDependsOn(":app") -} - -tasks.register("clean") { - delete(rootProject.layout.buildDirectory) -} diff --git a/flutter/android/fastlane/Appfile b/flutter/android/fastlane/Appfile deleted file mode 100644 index f87d70f5..00000000 --- a/flutter/android/fastlane/Appfile +++ /dev/null @@ -1,9 +0,0 @@ -# This file contains the Flutter Android distribution configuration. -# You can find the documentation at https://docs.fastlane.tools - -require('dotenv') -Dotenv.load('../../../App.env') -package_name(ENV['PRODUCT_BUNDLE_IDENTIFIER']) - -# Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one -json_key_file("fastlane/apikey.json") diff --git a/flutter/android/fastlane/Fastfile b/flutter/android/fastlane/Fastfile deleted file mode 100644 index ffab2fd2..00000000 --- a/flutter/android/fastlane/Fastfile +++ /dev/null @@ -1,31 +0,0 @@ -# This file contains the fastlane.tools configuration for Flutter Android. -# You can find the documentation at https://docs.fastlane.tools - -require('dotenv') -Dotenv.load '../../../App.env' - -default_platform(:android) - -desc "Build Flutter Android App" -lane :build do |options| - mode = options[:release] ? "--release" : "--debug" - sh("cd ../.. && flutter build apk #{mode}") -end - -desc "Test Flutter Android App" -lane :test do - sh("cd ../.. && flutter test") -end - -desc "Assemble Flutter Android App Bundle" -lane :assemble do - sh("cd ../.. && flutter build appbundle --release") -end - -desc "Deploy Flutter Android App to Google Play" -lane :release do - assemble - upload_to_play_store( - aab: '../build/app/outputs/bundle/release/app-release.aab' - ) -end diff --git a/flutter/android/fastlane/metadata/android/en-US/full_description.txt b/flutter/android/fastlane/metadata/android/en-US/full_description.txt deleted file mode 100644 index fa3e4aad..00000000 --- a/flutter/android/fastlane/metadata/android/en-US/full_description.txt +++ /dev/null @@ -1,3 +0,0 @@ -Logseq Chat brings fast capture, journals, search, graph navigation, and focused editing to Android. - -Use home-screen widgets and app shortcuts to open today’s journal or capture a thought immediately. Your Logseq graph remains the center of the experience, with a responsive Android interface designed around Material conventions. diff --git a/flutter/android/fastlane/metadata/android/en-US/short_description.txt b/flutter/android/fastlane/metadata/android/en-US/short_description.txt deleted file mode 100644 index b4a8ae69..00000000 --- a/flutter/android/fastlane/metadata/android/en-US/short_description.txt +++ /dev/null @@ -1 +0,0 @@ -Capture ideas and work with your Logseq graphs anywhere. diff --git a/flutter/android/fastlane/metadata/android/en-US/title.txt b/flutter/android/fastlane/metadata/android/en-US/title.txt deleted file mode 100644 index 55c912b6..00000000 --- a/flutter/android/fastlane/metadata/android/en-US/title.txt +++ /dev/null @@ -1 +0,0 @@ -Logseq Chat diff --git a/flutter/android/gradle.properties b/flutter/android/gradle.properties deleted file mode 100644 index e96108cf..00000000 --- a/flutter/android/gradle.properties +++ /dev/null @@ -1,6 +0,0 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError -android.useAndroidX=true -# This newDsl flag was added by the Flutter template -android.newDsl=false -# This builtInKotlin flag was added by the Flutter template -android.builtInKotlin=false diff --git a/flutter/android/settings.gradle.kts b/flutter/android/settings.gradle.kts deleted file mode 100644 index b28021a9..00000000 --- a/flutter/android/settings.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "9.1.0" apply false - id("org.jetbrains.kotlin.android") version "2.4.0" apply false -} - -include(":app") diff --git a/flutter/lib/android_app_entry.dart b/flutter/lib/android_app_entry.dart deleted file mode 100644 index 843bdde2..00000000 --- a/flutter/lib/android_app_entry.dart +++ /dev/null @@ -1,158 +0,0 @@ -import 'dart:async'; -import 'dart:collection'; -import 'dart:convert'; - -import 'package:flutter/services.dart'; - -import 'android_imported_asset.dart'; - -enum AndroidAppEntryKind { openCapture, openJournal, sharedText, sharedAsset } - -final class AndroidAppEntry { - const AndroidAppEntry._({required this.kind, this.text, this.asset}); - - factory AndroidAppEntry.fromMap(Map value) { - switch (value['kind']) { - case 'open-capture': - return const AndroidAppEntry._(kind: AndroidAppEntryKind.openCapture); - case 'open-journal': - return const AndroidAppEntry._(kind: AndroidAppEntryKind.openJournal); - case 'shared-text': - final text = value['text']; - if (text is! String || text.trim().isEmpty) { - throw const FormatException('A shared-text entry needs text'); - } - return AndroidAppEntry._( - kind: AndroidAppEntryKind.sharedText, - text: text, - ); - case 'shared-asset': - final asset = value['asset']; - if (asset is! Map) { - throw const FormatException('A shared-asset entry needs an asset'); - } - return AndroidAppEntry._( - kind: AndroidAppEntryKind.sharedAsset, - asset: AndroidImportedAsset.fromMap( - asset.map((key, value) => MapEntry(key.toString(), value)), - ), - ); - default: - throw FormatException( - 'Unsupported Android app entry: ${value['kind']}', - ); - } - } - - final AndroidAppEntryKind kind; - final String? text; - final AndroidImportedAsset? asset; - - Map coreRequest({ - required String uuid, - required int nowMilliseconds, - }) { - if (kind != AndroidAppEntryKind.sharedText) { - throw StateError('$kind is not a text capture'); - } - return { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'send', - 'payload': jsonEncode({ - 'text': text, - 'uuid': uuid, - 'now': nowMilliseconds, - }), - }, - }; - } -} - -abstract interface class AndroidAppEntrySource { - Stream> get entries; -} - -final class EventChannelAndroidAppEntrySource implements AndroidAppEntrySource { - const EventChannelAndroidAppEntrySource({EventChannel? channel}) - : _channel = channel ?? const EventChannel(_channelName); - - final EventChannel _channel; - - @override - Stream> get entries => - _channel.receiveBroadcastStream().map((value) { - if (value is! Map) { - throw const FormatException('Android app entry must be a map'); - } - return value.map((key, value) => MapEntry(key.toString(), value)); - }); - - static const _channelName = 'com.logseq.chat/app-entry'; -} - -typedef AndroidAppEntryHandler = Future Function(AndroidAppEntry entry); -typedef AndroidAppEntryErrorHandler = void Function( - Object error, - StackTrace stack, -); - -final class AndroidAppEntryCoordinator { - AndroidAppEntryCoordinator({ - required this.entries, - required this.handle, - this.onError, - }); - - final Stream> entries; - final AndroidAppEntryHandler handle; - final AndroidAppEntryErrorHandler? onError; - final Queue _pending = Queue(); - StreamSubscription>? _subscription; - Future _tail = Future.value(); - bool _ready = false; - - Future get settled => _tail; - - void start() { - if (_subscription != null) return; - _subscription = entries.listen( - (value) { - try { - _pending.add(AndroidAppEntry.fromMap(value)); - if (_ready) _scheduleDrain(); - } catch (error, stack) { - onError?.call(error, stack); - } - }, - onError: (Object error, StackTrace stack) => onError?.call(error, stack), - ); - } - - Future markReady() { - _ready = true; - return _scheduleDrain(); - } - - Future _scheduleDrain() { - _tail = _tail.then((_) async { - while (_ready && _pending.isNotEmpty) { - final entry = _pending.removeFirst(); - try { - await handle(entry); - } catch (error, stack) { - _pending.addFirst(entry); - onError?.call(error, stack); - break; - } - } - }); - return _tail; - } - - Future dispose() async { - await _subscription?.cancel(); - _subscription = null; - } -} diff --git a/flutter/lib/android_audio_playback.dart b/flutter/lib/android_audio_playback.dart deleted file mode 100644 index ee73bc8d..00000000 --- a/flutter/lib/android_audio_playback.dart +++ /dev/null @@ -1,294 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -const _audioExtensions = {'m4a', 'mp3', 'wav', 'aac', 'caf', 'ogg', 'opus'}; - -bool isAndroidAudioAsset(String assetType, String localPath) { - final normalizedType = assetType.toLowerCase(); - if (normalizedType.startsWith('audio/')) return true; - if (_audioExtensions.contains(normalizedType)) return true; - final dot = localPath.lastIndexOf('.'); - return dot >= 0 && - _audioExtensions.contains(localPath.substring(dot + 1).toLowerCase()); -} - -final class AndroidAudioPlaybackSession { - const AndroidAudioPlaybackSession({required this.id, required this.duration}); - - final int id; - final Duration duration; -} - -final class AndroidAudioPlaybackStatus { - const AndroidAudioPlaybackStatus({ - required this.isActive, - required this.isPlaying, - required this.position, - required this.duration, - }); - - final bool isActive; - final bool isPlaying; - final Duration position; - final Duration duration; -} - -abstract interface class AndroidAudioPlaybackBackend { - Future start(String path); - Future pause(int sessionId); - Future resume(int sessionId); - Future status(int sessionId); - Future stop(int sessionId); -} - -final class MethodChannelAndroidAudioPlaybackBackend - implements AndroidAudioPlaybackBackend { - const MethodChannelAndroidAudioPlaybackBackend({ - this.channel = const MethodChannel('com.logseq.chat/platform'), - }); - - final MethodChannel channel; - - @override - Future start(String path) async { - final response = await channel.invokeMapMethod( - 'startAudioPlayback', - {'path': path}, - ); - if (response == null) throw StateError('Audio playback did not start'); - return AndroidAudioPlaybackSession( - id: response['sessionId']! as int, - duration: Duration(milliseconds: response['durationMs']! as int), - ); - } - - @override - Future pause(int sessionId) => channel.invokeMethod( - 'pauseAudioPlayback', - {'sessionId': sessionId}, - ); - - @override - Future resume(int sessionId) => channel.invokeMethod( - 'resumeAudioPlayback', - {'sessionId': sessionId}, - ); - - @override - Future status(int sessionId) async { - final response = await channel.invokeMapMethod( - 'audioPlaybackStatus', - {'sessionId': sessionId}, - ); - if (response == null) throw StateError('Audio playback status is missing'); - return AndroidAudioPlaybackStatus( - isActive: response['isActive']! as bool, - isPlaying: response['isPlaying']! as bool, - position: Duration(milliseconds: response['positionMs']! as int), - duration: Duration(milliseconds: response['durationMs']! as int), - ); - } - - @override - Future stop(int sessionId) => - channel.invokeMethod('stopAudioPlayback', {'sessionId': sessionId}); -} - -final class AndroidAudioPlayer extends StatefulWidget { - const AndroidAudioPlayer({ - super.key, - required this.title, - required this.path, - this.backend = const MethodChannelAndroidAudioPlaybackBackend(), - }); - - final String title; - final String path; - final AndroidAudioPlaybackBackend backend; - - @override - State createState() => _AndroidAudioPlayerState(); -} - -final class _AndroidAudioPlayerState extends State { - AndroidAudioPlaybackSession? _session; - Timer? _statusTimer; - Duration _position = Duration.zero; - Duration _duration = Duration.zero; - bool _playing = false; - bool _busy = false; - String? _error; - - @override - void dispose() { - _statusTimer?.cancel(); - final session = _session; - if (session != null) unawaited(widget.backend.stop(session.id)); - super.dispose(); - } - - Future _togglePlayback() async { - if (_busy) return; - setState(() { - _busy = true; - _error = null; - }); - try { - final session = _session; - if (session == null) { - final started = await widget.backend.start(widget.path); - if (!mounted) { - unawaited(widget.backend.stop(started.id)); - return; - } - _session = started; - _duration = started.duration; - _playing = true; - _startStatusUpdates(); - } else if (_playing) { - await widget.backend.pause(session.id); - if (!mounted) return; - _playing = false; - _statusTimer?.cancel(); - } else { - await widget.backend.resume(session.id); - if (!mounted) return; - _playing = true; - _startStatusUpdates(); - } - } catch (_) { - if (!mounted) return; - _error = 'Could not play audio'; - _playing = false; - _statusTimer?.cancel(); - } finally { - if (mounted) setState(() => _busy = false); - } - } - - void _startStatusUpdates() { - _statusTimer?.cancel(); - _statusTimer = Timer.periodic( - const Duration(milliseconds: 400), - (_) => unawaited(_refreshStatus()), - ); - } - - Future _refreshStatus() async { - final session = _session; - if (session == null) return; - try { - final status = await widget.backend.status(session.id); - if (!mounted || _session?.id != session.id) return; - setState(() { - _position = status.position; - _duration = status.duration; - _playing = status.isPlaying; - if (!status.isActive) { - _session = null; - _position = Duration.zero; - _statusTimer?.cancel(); - } - }); - } catch (_) { - if (!mounted) return; - _statusTimer?.cancel(); - setState(() { - _session = null; - _playing = false; - _position = Duration.zero; - }); - } - } - - @override - Widget build(BuildContext context) { - final colorScheme = Theme.of(context).colorScheme; - final progress = _duration.inMilliseconds <= 0 - ? 0.0 - : (_position.inMilliseconds / _duration.inMilliseconds).clamp(0.0, 1.0); - return Semantics( - key: const ValueKey('player.asset.audio'), - identifier: 'player.asset.audio', - container: true, - label: _playing ? 'Pause audio' : 'Play audio', - child: DecoratedBox( - decoration: BoxDecoration( - color: colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.fromLTRB(8, 8, 16, 8), - child: Row( - children: [ - IconButton.filledTonal( - key: const ValueKey('button.audio.play-pause'), - tooltip: _playing ? 'Pause audio' : 'Play audio', - onPressed: _busy ? null : _togglePlayback, - icon: _busy - ? const SizedBox.square( - dimension: 20, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : Icon( - _playing - ? Icons.pause_rounded - : Icons.play_arrow_rounded, - ), - ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - widget.title.isEmpty ? 'Untitled audio' : widget.title, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodyMedium, - ), - const SizedBox(height: 6), - LinearProgressIndicator( - value: progress, - minHeight: 3, - borderRadius: BorderRadius.circular(2), - ), - const SizedBox(height: 4), - Text( - _playing ? 'Pause audio' : 'Play audio', - style: Theme.of(context).textTheme.labelSmall - ?.copyWith(color: colorScheme.onSurfaceVariant), - ), - if (_error case final error?) ...[ - const SizedBox(height: 4), - Text( - error, - style: Theme.of(context).textTheme.labelSmall - ?.copyWith(color: colorScheme.error), - ), - ], - ], - ), - ), - const SizedBox(width: 8), - Text( - _formatDuration(_position), - style: Theme.of(context).textTheme.labelSmall - ?.copyWith(color: colorScheme.onSurfaceVariant), - ), - ], - ), - ), - ), - ); - } -} - -String _formatDuration(Duration duration) { - final minutes = duration.inMinutes; - final seconds = duration.inSeconds.remainder(60); - return '$minutes:${seconds.toString().padLeft(2, '0')}'; -} diff --git a/flutter/lib/android_audio_recording.dart b/flutter/lib/android_audio_recording.dart deleted file mode 100644 index 0980a88c..00000000 --- a/flutter/lib/android_audio_recording.dart +++ /dev/null @@ -1,374 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -final class RecordedAudioAsset { - const RecordedAudioAsset({ - required this.uuid, - required this.title, - required this.assetType, - required this.size, - required this.checksum, - required this.localPath, - }); - - factory RecordedAudioAsset.fromMap(Map value) { - String requiredString(String key) { - final result = value[key]; - if (result is! String || result.isEmpty) { - throw FormatException('Recorded audio is missing $key'); - } - return result; - } - - final size = value['size']; - if (size is! int || size <= 0) { - throw const FormatException('Recorded audio has an invalid size'); - } - return RecordedAudioAsset( - uuid: requiredString('uuid'), - title: requiredString('title'), - assetType: requiredString('assetType'), - size: size, - checksum: requiredString('checksum'), - localPath: requiredString('localPath'), - ); - } - - final String uuid; - final String title; - final String assetType; - final int size; - final String checksum; - final String localPath; - - Map coreRequest({String? targetBlockId}) { - final payload = { - 'uuid': uuid, - 'title': title, - 'assetType': assetType, - 'assetSize': size, - 'assetChecksum': checksum, - 'localPath': localPath, - if (targetBlockId != null && targetBlockId.isNotEmpty) - 'targetBlockId': targetBlockId, - }; - return { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': {'action': 'addAsset', 'payload': jsonEncode(payload)}, - }; - } - - Map transcriptCoreRequest({ - required String transcriptUuid, - required String transcript, - }) => { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'addChildBlock', - 'payload': jsonEncode({ - 'uuid': transcriptUuid, - 'title': transcript, - 'parentId': uuid, - }), - }, - }; -} - -final class RecordedAudioRecordingResult { - const RecordedAudioRecordingResult({ - required this.asset, - required this.transcriptionEnabled, - }); - - final RecordedAudioAsset asset; - final bool transcriptionEnabled; -} - -abstract interface class AndroidAudioRecordingBackend { - Future supportsTranscription(); - - Future start(); - - Future stop(); - - Future cancel(); - - Future transcribe(String path); -} - -final class MethodChannelAndroidAudioRecordingBackend - implements AndroidAudioRecordingBackend { - const MethodChannelAndroidAudioRecordingBackend({ - this.channel = const MethodChannel('com.logseq.chat/platform'), - }); - - final MethodChannel channel; - - @override - Future supportsTranscription() async => - await channel.invokeMethod('supportsAudioTranscription') ?? false; - - @override - Future start() => channel.invokeMethod('startAudioRecording'); - - @override - Future stop() async { - final value = await channel.invokeMapMethod( - 'stopAudioRecording', - ); - if (value == null) { - throw const FormatException('Android did not return recorded audio'); - } - return RecordedAudioAsset.fromMap(value); - } - - @override - Future cancel() => channel.invokeMethod('cancelAudioRecording'); - - @override - Future transcribe(String path) async => - (await channel.invokeMethod('transcribeAudio', { - 'path': path, - }))?.trim() ?? - ''; -} - -Future showAndroidAudioRecordingSheet({ - required BuildContext context, - required AndroidAudioRecordingBackend backend, -}) => showModalBottomSheet( - context: context, - useSafeArea: true, - isScrollControlled: true, - isDismissible: false, - enableDrag: false, - builder: (_) => _AndroidAudioRecordingSheet(backend: backend), -); - -final class _AndroidAudioRecordingSheet extends StatefulWidget { - const _AndroidAudioRecordingSheet({required this.backend}); - - final AndroidAudioRecordingBackend backend; - - @override - State<_AndroidAudioRecordingSheet> createState() => - _AndroidAudioRecordingSheetState(); -} - -final class _AndroidAudioRecordingSheetState - extends State<_AndroidAudioRecordingSheet> { - Timer? _timer; - var _elapsedSeconds = 0; - var _recording = false; - var _saving = false; - var _transcriptionSupported = false; - var _transcriptionEnabled = true; - String? _error; - - @override - void initState() { - super.initState(); - unawaited(_start()); - unawaited(_loadTranscriptionSupport()); - } - - Future _loadTranscriptionSupport() async { - final supported = await widget.backend.supportsTranscription(); - if (mounted) setState(() => _transcriptionSupported = supported); - } - - Future _start() async { - try { - await widget.backend.start(); - if (!mounted) return; - setState(() => _recording = true); - _timer = Timer.periodic(const Duration(seconds: 1), (_) { - if (mounted) setState(() => _elapsedSeconds += 1); - }); - } catch (error) { - if (mounted) setState(() => _error = error.toString()); - } - } - - Future _stop() async { - if (!_recording || _saving) return; - setState(() { - _saving = true; - _error = null; - }); - try { - final asset = await widget.backend.stop(); - _recording = false; - _timer?.cancel(); - if (mounted) { - Navigator.pop( - context, - RecordedAudioRecordingResult( - asset: asset, - transcriptionEnabled: - _transcriptionSupported && _transcriptionEnabled, - ), - ); - } - } catch (error) { - if (mounted) { - setState(() { - _saving = false; - _error = error.toString(); - }); - } - } - } - - Future _cancel() async { - if (_saving) return; - _timer?.cancel(); - try { - await widget.backend.cancel(); - } finally { - _recording = false; - if (mounted) Navigator.pop(context); - } - } - - @override - void dispose() { - _timer?.cancel(); - super.dispose(); - } - - @override - Widget build(BuildContext context) { - final colors = Theme.of(context).colorScheme; - return PopScope( - canPop: false, - child: Semantics( - key: const ValueKey('sheet.audio-recording'), - container: true, - explicitChildNodes: true, - label: 'Audio recording', - child: Padding( - padding: const EdgeInsets.fromLTRB(24, 12, 24, 24), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 32, - height: 4, - decoration: BoxDecoration( - color: colors.onSurfaceVariant.withValues(alpha: 0.4), - borderRadius: BorderRadius.circular(2), - ), - ), - const SizedBox(height: 16), - Row( - children: [ - Text( - 'Audio recording', - style: Theme.of(context).textTheme.titleLarge, - ), - const Spacer(), - TextButton( - key: const ValueKey('button.audio.cancel'), - onPressed: _saving ? null : _cancel, - child: const Text('Cancel'), - ), - ], - ), - const SizedBox(height: 28), - Text( - _elapsedTitle, - style: Theme.of(context).textTheme.displaySmall?.copyWith( - fontFeatures: const [FontFeature.tabularFigures()], - ), - ), - const SizedBox(height: 20), - _Waveform(active: _recording), - const SizedBox(height: 20), - Text(_recording ? 'Recording…' : 'Preparing microphone…'), - if (_transcriptionSupported) ...[ - const SizedBox(height: 12), - SwitchListTile( - key: const ValueKey('toggle.audio.transcription'), - contentPadding: EdgeInsets.zero, - title: const Text('Transcribe recording'), - subtitle: const Text('Add an on-device transcript'), - value: _transcriptionEnabled, - onChanged: _saving - ? null - : (value) => - setState(() => _transcriptionEnabled = value), - ), - ], - if (_error case final error?) ...[ - const SizedBox(height: 16), - Text( - error, - textAlign: TextAlign.center, - style: TextStyle(color: colors.error), - ), - ], - const SizedBox(height: 28), - FilledButton.icon( - key: const ValueKey('button.audio.stop'), - onPressed: _recording && !_saving ? _stop : null, - style: FilledButton.styleFrom( - backgroundColor: colors.error, - foregroundColor: colors.onError, - minimumSize: const Size(200, 56), - ), - icon: _saving - ? const SizedBox.square( - dimension: 18, - child: CircularProgressIndicator(strokeWidth: 2), - ) - : const Icon(Icons.stop_rounded), - label: Text(_saving ? 'Saving…' : 'Stop recording'), - ), - const SizedBox(height: 8), - ], - ), - ), - ), - ); - } - - String get _elapsedTitle { - final minutes = (_elapsedSeconds ~/ 60).toString().padLeft(2, '0'); - final seconds = (_elapsedSeconds % 60).toString().padLeft(2, '0'); - return '$minutes:$seconds'; - } -} - -final class _Waveform extends StatelessWidget { - const _Waveform({required this.active}); - - final bool active; - - @override - Widget build(BuildContext context) => SizedBox( - height: 64, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: List.generate(17, (index) { - final height = active ? 12.0 + (index % 5) * 9 : 8.0; - return AnimatedContainer( - duration: const Duration(milliseconds: 180), - width: 4, - height: height, - margin: const EdgeInsets.symmetric(horizontal: 3), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.primary, - borderRadius: BorderRadius.circular(2), - ), - ); - }), - ), - ); -} diff --git a/flutter/lib/android_cloze.dart b/flutter/lib/android_cloze.dart deleted file mode 100644 index 22b4a115..00000000 --- a/flutter/lib/android_cloze.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter/material.dart'; - -final class AndroidCloze extends StatefulWidget { - const AndroidCloze({super.key, required this.text}); - - final String text; - - @override - State createState() => _AndroidClozeState(); -} - -final class _AndroidClozeState extends State { - var _revealed = false; - - @override - Widget build(BuildContext context) => Semantics( - identifier: 'block.rich.cloze.reveal', - label: _revealed ? widget.text : 'Reveal cloze', - button: true, - child: ActionChip( - key: const ValueKey('button.cloze.reveal'), - visualDensity: VisualDensity.compact, - avatar: Icon( - _revealed ? Icons.visibility_off_outlined : Icons.visibility_outlined, - size: 18, - ), - label: Text(_revealed ? widget.text : 'Tap to reveal'), - onPressed: () => setState(() => _revealed = !_revealed), - ), - ); -} diff --git a/flutter/lib/android_embedded_media.dart b/flutter/lib/android_embedded_media.dart deleted file mode 100644 index c3d0b855..00000000 --- a/flutter/lib/android_embedded_media.dart +++ /dev/null @@ -1,198 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:webview_flutter/webview_flutter.dart'; - -typedef AndroidWebViewBuilder = Widget Function(Uri uri); - -Uri? androidEmbeddedMediaUri(String value, {int? startSeconds}) { - final uri = Uri.tryParse(value.trim()); - if (uri == null || - !{'http', 'https'}.contains(uri.scheme) || - uri.host.isEmpty) { - return null; - } - final host = uri.host.toLowerCase(); - final isYouTube = - host == 'youtu.be' || - host == 'youtube.com' || - host.endsWith('.youtube.com') || - host == 'youtube-nocookie.com' || - host.endsWith('.youtube-nocookie.com'); - if (!isYouTube) return uri; - - String? videoId; - if (host == 'youtu.be') { - videoId = uri.pathSegments.firstOrNull; - } else if (uri.pathSegments.firstOrNull == 'embed') { - videoId = uri.pathSegments.elementAtOrNull(1); - } else if (uri.path == '/watch') { - videoId = uri.queryParameters['v']; - } - if (videoId == null || !RegExp(r'^[A-Za-z0-9_-]{6,}$').hasMatch(videoId)) { - return null; - } - return Uri( - scheme: 'https', - host: 'www.youtube-nocookie.com', - pathSegments: ['embed', videoId], - queryParameters: { - 'playsinline': '1', - if (startSeconds != null && startSeconds > 0) 'start': '$startSeconds', - }, - ); -} - -extension on List { - T? get firstOrNull => isEmpty ? null : first; - - T? elementAtOrNull(int index) => - index < 0 || index >= length ? null : this[index]; -} - -final class AndroidEmbeddedMedia extends StatefulWidget { - const AndroidEmbeddedMedia({ - super.key, - required this.url, - this.startSeconds, - this.isVideo = true, - this.webViewBuilder, - }); - - final String url; - final int? startSeconds; - final bool isVideo; - final AndroidWebViewBuilder? webViewBuilder; - - @override - State createState() => _AndroidEmbeddedMediaState(); -} - -final class _AndroidEmbeddedMediaState extends State { - var _loaded = false; - - Uri? get _uri => - androidEmbeddedMediaUri(widget.url, startSeconds: widget.startSeconds); - - @override - Widget build(BuildContext context) { - final uri = _uri; - if (uri == null) { - return Text( - widget.isVideo ? 'Invalid video URL' : 'Invalid embed URL', - style: TextStyle(color: Theme.of(context).colorScheme.onSurfaceVariant), - ); - } - if (_loaded) { - return Semantics( - key: const ValueKey('media.webview.loaded'), - identifier: 'media.webview.loaded', - container: true, - child: SizedBox( - height: 220, - width: double.infinity, - child: widget.webViewBuilder?.call(uri) ?? _AndroidWebView(uri: uri), - ), - ); - } - return Material( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(16), - clipBehavior: Clip.antiAlias, - child: InkWell( - key: const ValueKey('button.media.load'), - onTap: () => setState(() => _loaded = true), - child: ConstrainedBox( - constraints: const BoxConstraints(minHeight: 132), - child: Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon( - widget.isVideo - ? Icons.play_circle_outline_rounded - : Icons.web_asset_rounded, - size: 36, - ), - const SizedBox(width: 14), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.isVideo ? 'Video preview' : 'Embedded content', - style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 4), - Text( - uri.host, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.bodySmall?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, - ), - ), - const SizedBox(height: 8), - Text( - 'Tap to load', - style: Theme.of(context).textTheme.labelLarge?.copyWith( - color: Theme.of(context).colorScheme.primary, - ), - ), - ], - ), - ), - ], - ), - ), - ), - ), - ); - } -} - -final class _AndroidWebView extends StatefulWidget { - const _AndroidWebView({required this.uri}); - - final Uri uri; - - @override - State<_AndroidWebView> createState() => _AndroidWebViewState(); -} - -final class _AndroidWebViewState extends State<_AndroidWebView> { - late final WebViewController _controller; - - @override - void initState() { - super.initState(); - _controller = WebViewController() - ..setJavaScriptMode(JavaScriptMode.unrestricted) - ..setNavigationDelegate( - NavigationDelegate( - onNavigationRequest: (request) { - final uri = Uri.tryParse(request.url); - return uri != null && {'http', 'https'}.contains(uri.scheme) - ? NavigationDecision.navigate - : NavigationDecision.prevent; - }, - ), - ) - ..loadRequest(widget.uri, headers: _headers(widget.uri)); - } - - @override - void didUpdateWidget(covariant _AndroidWebView oldWidget) { - super.didUpdateWidget(oldWidget); - if (oldWidget.uri != widget.uri) { - _controller.loadRequest(widget.uri, headers: _headers(widget.uri)); - } - } - - @override - Widget build(BuildContext context) => WebViewWidget(controller: _controller); - - Map _headers(Uri uri) => - uri.host.endsWith('youtube-nocookie.com') - ? const {'Referer': 'https://logseq.com/'} - : const {}; -} diff --git a/flutter/lib/android_graph_lifecycle.dart b/flutter/lib/android_graph_lifecycle.dart deleted file mode 100644 index a381c3fe..00000000 --- a/flutter/lib/android_graph_lifecycle.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'dart:convert'; - -import 'android_platform_effects.dart'; -import 'core_effect_executor.dart'; -import 'native_effect_drain.dart'; - -typedef AccessTokenProvider = Future Function(); -typedef AndroidGraphLifecycleTrace = void Function(String message); - -void _ignoreGraphLifecycleTrace(String message) {} - -final class AndroidGraphLifecycle { - AndroidGraphLifecycle({ - required this.callCore, - required this.platform, - AccessTokenProvider? accessTokenProvider, - this.trace = _ignoreGraphLifecycleTrace, - }) : accessTokenProvider = accessTokenProvider ?? (() async => ''); - - final NativeCoreCall callCore; - final AndroidPlatformServices platform; - final AccessTokenProvider accessTokenProvider; - final AndroidGraphLifecycleTrace trace; - - Future execute(NativeEffect effect) async { - try { - switch (effect.kind) { - case 'create-graph': - final created = await _call( - 'createSyncGraph', - payload: jsonEncode({ - 'name': effect.text, - 'isEncrypted': effect.value == 1, - }), - ); - final failure = _failure(created); - if (failure != null) return failure; - final graphId = _selectedGraphId(created); - if (graphId.isEmpty) { - return const NativeEffectResolution.discard( - succeeded: false, - message: 'The created graph has no selected identifier', - ); - } - return await _openGraph(graphId); - case 'open-graph': - return await _openGraph(effect.text); - case 'unlock-graph': - return _resolution(await _call('unlockGraph', payload: effect.text)); - default: - return NativeEffectResolution.discard( - succeeded: false, - message: 'Unsupported Android graph effect: ${effect.kind}', - ); - } - } catch (error) { - final message = '${_failureCode(effect.kind)}\n$error'; - trace( - 'effect.failed kind=${effect.kind} message=${message.replaceAll('\n', r'\n')}', - ); - return NativeEffectResolution.discard(succeeded: false, message: message); - } - } - - String _failureCode(String kind) => switch (kind) { - 'create-graph' => 'graph_create_failed', - 'open-graph' => 'graph_open_failed', - 'unlock-graph' => 'graph_unlock_failed', - _ => 'graph_operation_failed', - }; - - Future _openGraph(String graphId) async { - trace('open.start graphId=$graphId'); - final selected = await _call('selectGraph', payload: graphId); - final selectionFailure = _failure(selected); - if (selectionFailure != null) return selectionFailure; - trace('select.complete graphId=$graphId'); - - final state = await platform.loadStorageState(); - final directory = '${state.graphsDirectory}/$graphId'; - final isEncrypted = _graphIsEncrypted(selected, graphId); - final isLocal = state.localGraphIds.contains(graphId); - trace('storage.loaded graphId=$graphId local=$isLocal'); - late final String opened; - if (isLocal) { - opened = await _call( - 'openGraph', - payload: jsonEncode({ - 'graphId': graphId, - 'activePath': '$directory/graph.sqlite', - 'checkpointPath': '$directory/sync.checkpoint', - 'isEncrypted': isEncrypted, - }), - ); - } else { - final token = await accessTokenProvider() ?? ''; - trace( - 'snapshot.download.start graphId=$graphId baseUrl=${state.baseUrl}', - ); - final artifact = await platform.downloadGraphSnapshot( - baseUrl: state.baseUrl, - graphId: graphId, - accessToken: token, - workingDirectory: directory, - ); - trace( - 'snapshot.download.complete graphId=$graphId path=${artifact.filePath}', - ); - try { - trace('snapshot.import.start graphId=$graphId'); - opened = await _call( - 'importSnapshot', - payload: jsonEncode({ - 'graphId': graphId, - 'activePath': '$directory/graph.sqlite', - 'checkpointPath': '$directory/sync.checkpoint', - 'metadataBody': artifact.metadataBody, - 'downloadPath': artifact.filePath, - 'isEncrypted': isEncrypted, - }), - ); - trace('snapshot.import.complete graphId=$graphId'); - } finally { - await platform.deleteTemporaryFile(artifact.filePath); - } - } - - final openFailure = _failure(opened); - if (openFailure != null) return openFailure; - await platform.persistSelectedGraphId(graphId); - trace('selection.persist.complete graphId=$graphId'); - trace('open.complete graphId=$graphId'); - return NativeEffectResolution.coreResponse(opened); - } - - Future _call(String action, {String? payload}) { - final params = {'action': action}; - if (payload != null) params['payload'] = payload; - return callCore( - jsonEncode({'apiVersion': 1, 'method': 'dispatch', 'params': params}), - ); - } - - NativeEffectResolution _resolution(String response) => - _failure(response) ?? NativeEffectResolution.coreResponse(response); - - NativeEffectResolution? _failure(String response) { - final decoded = _decodedResponse(response); - if (decoded['ok'] == true) return null; - final error = decoded['error']; - final code = error is Map && error['code'] is String - ? error['code']! as String - : 'core_error'; - final message = error is Map && error['message'] is String - ? error['message']! as String - : 'The OCaml core rejected the graph operation'; - return NativeEffectResolution.discard( - succeeded: false, - message: '$code\n$message', - ); - } - - String _selectedGraphId(String response) { - final result = _decodedResponse(response)['result']; - if (result is! Map) return ''; - return result['selectedGraphId'] is String - ? result['selectedGraphId']! as String - : ''; - } - - bool _graphIsEncrypted(String response, String graphId) { - final result = _decodedResponse(response)['result']; - if (result is! Map) return false; - final graphs = result['graphs']; - if (graphs is! List) return false; - for (final graph in graphs) { - if (graph is Map && graph['id'] == graphId) { - return graph['isEncrypted'] == true; - } - } - return false; - } - - Map _decodedResponse(String response) { - final decoded = jsonDecode(response); - if (decoded is! Map) { - throw const FormatException('The native core response must be an object'); - } - return decoded; - } -} diff --git a/flutter/lib/android_imported_asset.dart b/flutter/lib/android_imported_asset.dart deleted file mode 100644 index 1b67a011..00000000 --- a/flutter/lib/android_imported_asset.dart +++ /dev/null @@ -1,60 +0,0 @@ -import 'dart:convert'; - -final class AndroidImportedAsset { - const AndroidImportedAsset({ - required this.uuid, - required this.title, - required this.assetType, - required this.size, - required this.checksum, - required this.localPath, - }); - - factory AndroidImportedAsset.fromMap(Map value) { - String requiredString(String key) { - final result = value[key]; - if (result is! String || result.isEmpty) { - throw FormatException('Imported asset is missing $key'); - } - return result; - } - - final size = value['size']; - if (size is! int || size <= 0) { - throw const FormatException('Imported asset has an invalid size'); - } - return AndroidImportedAsset( - uuid: requiredString('uuid'), - title: requiredString('title'), - assetType: requiredString('assetType'), - size: size, - checksum: requiredString('checksum'), - localPath: requiredString('localPath'), - ); - } - - final String uuid; - final String title; - final String assetType; - final int size; - final String checksum; - final String localPath; - - Map coreRequest({String? targetBlockId}) { - final payload = { - 'uuid': uuid, - 'title': title, - 'assetType': assetType, - 'assetSize': size, - 'assetChecksum': checksum, - 'localPath': localPath, - if (targetBlockId != null && targetBlockId.isNotEmpty) - 'targetBlockId': targetBlockId, - }; - return { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': {'action': 'addAsset', 'payload': jsonEncode(payload)}, - }; - } -} diff --git a/flutter/lib/android_math.dart b/flutter/lib/android_math.dart deleted file mode 100644 index ec1700f3..00000000 --- a/flutter/lib/android_math.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_math_fork/flutter_math.dart'; - -final class AndroidMath extends StatelessWidget { - const AndroidMath({super.key, required this.expression}); - - final String expression; - - @override - Widget build(BuildContext context) => Semantics( - key: const ValueKey('math.rendered'), - identifier: 'block.rich.math.rendered', - container: true, - label: 'Math: $expression', - child: ExcludeSemantics( - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Math.tex( - expression, - mathStyle: MathStyle.display, - textStyle: Theme.of(context).textTheme.bodyLarge, - onErrorFallback: (_) => Text( - expression, - style: Theme.of(context).textTheme.bodyMedium - ?.copyWith(color: Theme.of(context).colorScheme.error), - ), - ), - ), - ), - ), - ); -} diff --git a/flutter/lib/android_outliner_commands.dart b/flutter/lib/android_outliner_commands.dart deleted file mode 100644 index 1dd09c9a..00000000 --- a/flutter/lib/android_outliner_commands.dart +++ /dev/null @@ -1,221 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; - -import 'android_platform_effects.dart'; - -final class OutlinerPlatformCommand { - const OutlinerPlatformCommand({ - required this.type, - this.style, - this.text, - this.uuid, - this.uuids = const [], - }); - - factory OutlinerPlatformCommand.fromJson(Map value) { - final uuids = value['uuids']; - return OutlinerPlatformCommand( - type: value['type'] as String? ?? '', - style: value['style'] as String?, - text: value['text'] as String?, - uuid: value['uuid'] as String?, - uuids: uuids is List - ? uuids.whereType().toList(growable: false) - : const [], - ); - } - - final String type; - final String? style; - final String? text; - final String? uuid; - final List uuids; -} - -final class OutlinerPlatformCommandBatch { - const OutlinerPlatformCommandBatch({ - required this.revision, - required this.graphName, - required this.commands, - this.selectedBlockIds = const [], - }); - - final int revision; - final String graphName; - final List commands; - final List selectedBlockIds; -} - -typedef OutlinerPlatformCommandBatchHandler = FutureOr Function( - OutlinerPlatformCommandBatch batch, -); - -final class OutlinerPlatformCommandDispatcher { - OutlinerPlatformCommandDispatcher(this.onBatch); - - final OutlinerPlatformCommandBatchHandler onBatch; - var _lastRevision = 0; - - Future deliver(String response) async { - final batch = _decode(response); - if (batch == null) { - debugPrint('[OutlinerCommands] response did not contain a command batch'); - return; - } - debugPrint( - '[OutlinerCommands] revision=${batch.revision} ' - 'last=$_lastRevision selected=${batch.selectedBlockIds.join(',')} ' - 'commands=${batch.commands.map((value) => value.type).join(',')}', - ); - if (batch.revision <= _lastRevision) return; - _lastRevision = batch.revision; - if (batch.commands.isNotEmpty) await onBatch(batch); - } - - static OutlinerPlatformCommandBatch? _decode(String response) { - final Object? decoded; - try { - decoded = jsonDecode(response); - } on FormatException { - return null; - } - if (decoded is! Map || decoded['ok'] != true) return null; - final result = decoded['result']; - if (result is! Map) return null; - final revision = result['outlinerCommandRevision']; - final values = result['outlinerCommands']; - if (revision is! int || values is! List) return null; - final outlinerState = result['outlinerState']; - final selected = outlinerState is Map - ? outlinerState['selectedBlockIds'] - : null; - return OutlinerPlatformCommandBatch( - revision: revision, - graphName: result['graphName'] as String? ?? '', - commands: values - .whereType>() - .map(OutlinerPlatformCommand.fromJson) - .where((command) => command.type.isNotEmpty) - .toList(growable: false), - selectedBlockIds: selected is List - ? selected.whereType().toList(growable: false) - : const [], - ); - } -} - -typedef SendOutlinerEvent = Future Function(Map event); -typedef PerformOutlinerHaptic = Future Function(String? style); -typedef PresentAudioRecording = Future Function(String? targetBlockId); -typedef PresentAttachment = Future Function( - String kind, - String? targetBlockId, -); - -final class AndroidOutlinerPlatformCommandHandler { - AndroidOutlinerPlatformCommandHandler({ - required this.navigatorKey, - required this.platform, - required this.sendOutlinerEvent, - required this.presentAttachment, - required this.presentAudioRecording, - PerformOutlinerHaptic? performHaptic, - }) : performHaptic = performHaptic ?? _performHaptic; - - final GlobalKey navigatorKey; - final AndroidPlatformServices platform; - final SendOutlinerEvent sendOutlinerEvent; - final PresentAttachment presentAttachment; - final PresentAudioRecording presentAudioRecording; - final PerformOutlinerHaptic performHaptic; - - Future handle(OutlinerPlatformCommandBatch batch) async { - for (final command in batch.commands) { - switch (command.type) { - case 'haptic': - await performHaptic(command.style); - case 'confirmDelete': - await _confirmDeletion(command.uuids); - case 'setClipboardText': - await platform.copyText(command.text ?? ''); - case 'setClipboardReferences': - await platform.copyText( - command.uuids.map((uuid) => '[[$uuid]]').join('\n'), - ); - case 'setClipboardURLs': - await platform.copyText( - command.uuids - .map( - (uuid) => 'logseq://graph/${batch.graphName}?block-id=$uuid', - ) - .join('\n'), - ); - case 'pickAttachment': - await presentAttachment('files', command.uuid); - case 'takePhoto': - await presentAttachment('camera', command.uuid); - case 'recordAudio': - await presentAudioRecording(command.uuid); - case 'focusBlock': - // The retained Android editor owns focus and uses autofocus when - // the corresponding block editor is inserted into the tree. - break; - } - } - } - - Future _confirmDeletion(List blockIds) async { - final context = navigatorKey.currentContext; - debugPrint( - '[OutlinerCommands] confirmDelete blocks=${blockIds.length} ' - 'context=${context != null}', - ); - if (context == null || blockIds.isEmpty) return; - final plural = blockIds.length > 1; - final confirmed = await showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(plural ? 'Delete blocks?' : 'Delete block?'), - content: Text( - plural - ? 'This deletes the blocks and all of their children.' - : 'This deletes the block and all of its children.', - ), - actions: [ - Semantics( - key: const ValueKey('button.outliner-delete.cancel'), - identifier: 'button.outliner-delete.cancel', - button: true, - child: TextButton( - onPressed: () => Navigator.pop(context, false), - child: const Text('Cancel'), - ), - ), - Semantics( - key: const ValueKey('button.outliner-delete.confirm'), - identifier: 'button.outliner-delete.confirm', - button: true, - child: TextButton( - style: TextButton.styleFrom( - foregroundColor: Theme.of(context).colorScheme.error, - ), - onPressed: () => Navigator.pop(context, true), - child: const Text('Delete'), - ), - ), - ], - ), - ); - if (confirmed == true) { - await sendOutlinerEvent(const {'type': 'confirmDelete'}); - } - } - - static Future _performHaptic(String? style) => switch (style) { - 'selection' => HapticFeedback.selectionClick(), - _ => HapticFeedback.mediumImpact(), - }; -} diff --git a/flutter/lib/android_platform_effects.dart b/flutter/lib/android_platform_effects.dart deleted file mode 100644 index 767d5a67..00000000 --- a/flutter/lib/android_platform_effects.dart +++ /dev/null @@ -1,531 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/services.dart'; - -import 'core_bootstrap.dart'; -import 'android_imported_asset.dart'; -import 'native_effect_drain.dart'; - -abstract interface class AndroidAuthentication { - Future hasStoredSession(); - - Future restoreAccessToken(); - - Future signIn(); - - Future signOut(); -} - -final class MethodChannelAndroidAuthentication - implements AndroidAuthentication { - const MethodChannelAndroidAuthentication({ - this._channel = const MethodChannel('com.logseq.chat/authentication'), - }); - - final MethodChannel _channel; - - @override - Future hasStoredSession() async => - await _channel.invokeMethod('hasStoredSession') ?? false; - - @override - Future restoreAccessToken() => - _channel.invokeMethod('restoreAccessToken'); - - @override - Future signIn() async => - (await _channel.invokeMethod('signIn')) ?? ''; - - @override - Future signOut() => _channel.invokeMethod('signOut'); -} - -abstract class AndroidPlatformServices { - Future loadStorageState() async => - const AndroidStorageState( - databasePath: '', - graphsDirectory: '', - baseUrl: 'http://127.0.0.1:8787', - selectedGraphId: '', - localGraphIds: [], - settings: AndroidHostSettings.defaults, - composerDraft: '', - ); - - Future persistComposerDraft(String draft) async {} - - Future saveSettings(String settings) async {} - - Future openExternalUrl(String url) async => false; - - Future copyText(String text) async {} - - Future refreshRuntimeLog({ - required String source, - required int flags, - }) async => '[]'; - - Future appendRuntimeLog({ - required String level, - required String source, - required String message, - }) async {} - - Future presentAttachment(String kind) async => false; - - Future> importAttachments(String kind) async => - const []; - - Future presentAsset(String metadata) async => false; - - Future presentPageShare({ - required String text, - required String metadata, - }) async => false; - - Future syncNow() async => false; - - Future deleteLocalGraph(String graphId) async => false; - - Future exportGraphDatabase() async => false; - - Future downloadGraphSnapshot({ - required String baseUrl, - required String graphId, - required String accessToken, - required String workingDirectory, - }) async => throw UnsupportedError('Graph snapshot download is unavailable'); - - Future persistSelectedGraphId(String graphId) async {} - - Future deleteTemporaryFile(String path) async {} - - String resolveAssetPath(String path) => path; -} - -final class MethodChannelAndroidPlatformServices - extends AndroidPlatformServices { - MethodChannelAndroidPlatformServices({ - this.channel = const MethodChannel('com.logseq.chat/platform'), - }); - - final MethodChannel channel; - String? _filesDirectory; - - @override - Future loadStorageState() async { - final value = await channel.invokeMapMethod( - 'loadStorageState', - ); - if (value == null) { - throw PlatformException( - code: 'storage_state_missing', - message: 'Android did not return storage state', - ); - } - final localGraphIds = value['localGraphIds']; - final encodedSettings = value['settings']; - final databasePath = value['databasePath']! as String; - _filesDirectory = File(databasePath).parent.path; - return AndroidStorageState( - databasePath: databasePath, - graphsDirectory: value['graphsDirectory']! as String, - baseUrl: value['baseUrl']! as String, - selectedGraphId: value['selectedGraphId']! as String, - localGraphIds: localGraphIds is List - ? localGraphIds.whereType().toList(growable: false) - : const [], - settings: AndroidHostSettings.fromPlatformValue(encodedSettings), - composerDraft: value['composerDraft'] as String? ?? '', - ); - } - - @override - Future persistComposerDraft(String draft) => - channel.invokeMethod('persistComposerDraft', {'draft': draft}); - - @override - Future saveSettings(String settings) => - channel.invokeMethod('saveSettings', {'settings': settings}); - - @override - Future openExternalUrl(String url) async => - await channel.invokeMethod('openExternalUrl', {'url': url}) ?? - false; - - @override - Future copyText(String text) => - channel.invokeMethod('copyText', {'text': text}); - - @override - Future refreshRuntimeLog({ - required String source, - required int flags, - }) async => - await channel.invokeMethod('refreshRuntimeLog', { - 'source': source, - 'flags': flags, - }) ?? - '[]'; - - @override - Future appendRuntimeLog({ - required String level, - required String source, - required String message, - }) => channel.invokeMethod('appendRuntimeLog', { - 'level': level, - 'source': source, - 'message': message, - }); - - @override - Future presentAttachment(String kind) async => - await channel.invokeMethod('presentAttachment', {'kind': kind}) ?? - false; - - @override - Future> importAttachments(String kind) async { - final values = await channel.invokeListMethod( - 'importAttachments', - {'kind': kind}, - ); - if (values == null) return const []; - return values - .whereType>() - .map( - (value) => AndroidImportedAsset.fromMap( - value.map((key, value) => MapEntry(key.toString(), value)), - ), - ) - .toList(growable: false); - } - - @override - Future presentAsset(String metadata) async => - await channel.invokeMethod('presentAsset', { - 'metadata': metadata, - }) ?? - false; - - @override - Future presentPageShare({ - required String text, - required String metadata, - }) async => - await channel.invokeMethod('presentPageShare', { - 'text': text, - 'metadata': metadata, - }) ?? - false; - - @override - Future syncNow() async => - await channel.invokeMethod('syncNow') ?? false; - - @override - Future deleteLocalGraph(String graphId) async => - await channel.invokeMethod('deleteLocalGraph', { - 'graphId': graphId, - }) ?? - false; - - @override - Future exportGraphDatabase() async => - await channel.invokeMethod('exportGraphDatabase') ?? false; - - @override - Future downloadGraphSnapshot({ - required String baseUrl, - required String graphId, - required String accessToken, - required String workingDirectory, - }) async { - final value = await channel.invokeMapMethod( - 'downloadGraphSnapshot', - { - 'baseUrl': baseUrl, - 'graphId': graphId, - 'accessToken': accessToken, - 'workingDirectory': workingDirectory, - }, - ); - if (value == null) { - throw const FormatException('Android did not return a graph snapshot'); - } - return AndroidDownloadedSnapshot( - metadataBody: value['metadataBody']! as String, - filePath: value['filePath']! as String, - ); - } - - @override - Future persistSelectedGraphId(String graphId) => channel - .invokeMethod('persistSelectedGraphId', {'graphId': graphId}); - - @override - Future deleteTemporaryFile(String path) => - channel.invokeMethod('deleteTemporaryFile', {'path': path}); - - @override - String resolveAssetPath(String path) { - if (path.isEmpty || File(path).isAbsolute) return path; - final filesDirectory = _filesDirectory; - return filesDirectory == null - ? path - : File('$filesDirectory${Platform.pathSeparator}$path').path; - } -} - -final class AndroidPlatformEffects { - AndroidPlatformEffects({ - required this.authentication, - AndroidPlatformServices? platform, - }) : platform = platform ?? MethodChannelAndroidPlatformServices(); - - final AndroidAuthentication authentication; - final AndroidPlatformServices platform; - - Future initialAuthenticationCode() async { - try { - return await authentication.hasStoredSession() ? 3 : 1; - } catch (_) { - return 1; - } - } - - Future restoreAccessToken() => authentication.restoreAccessToken(); - - Future coreStartupState({ - required String accessToken, - AndroidStorageState? storage, - }) async { - final resolvedStorage = storage ?? await platform.loadStorageState(); - return CoreStartupState( - databasePath: resolvedStorage.databasePath, - graphsDirectory: resolvedStorage.graphsDirectory, - baseUrl: resolvedStorage.baseUrl, - selectedGraphId: resolvedStorage.selectedGraphId, - localGraphIds: resolvedStorage.localGraphIds, - accessToken: accessToken, - ); - } - - Future execute(NativeEffect effect) async { - try { - switch (effect.kind) { - case 'persist-composer-draft': - await platform.persistComposerDraft(effect.text); - return const NativeEffectResolution.discard(); - case 'save-settings': - await platform.saveSettings(effect.text); - return const NativeEffectResolution.discard(); - case 'open-external-url': - return NativeEffectResolution.discard( - succeeded: await platform.openExternalUrl(effect.text), - message: '', - ); - case 'copy-runtime-log': - await platform.copyText(_runtimeLogText(effect.text)); - return const NativeEffectResolution.discard(); - case 'refresh-runtime-log': - final records = await platform.refreshRuntimeLog( - source: effect.text, - flags: effect.value ?? 0, - ); - return NativeEffectResolution.hostUpdate( - kind: 'runtime-log', - payload: records, - ); - case 'present-attachment': - return NativeEffectResolution.discard( - succeeded: await platform.presentAttachment(effect.text), - message: '', - ); - case 'present-asset': - return NativeEffectResolution.discard( - succeeded: await platform.presentAsset(effect.metadata ?? ''), - message: '', - ); - case 'present-page-share': - return NativeEffectResolution.discard( - succeeded: await platform.presentPageShare( - text: effect.text, - metadata: effect.metadata ?? '[]', - ), - message: '', - ); - case 'sync-now': - final succeeded = await platform.syncNow(); - return NativeEffectResolution.discard( - succeeded: succeeded, - message: succeeded ? '' : 'Sync is unavailable while the WebSocket transport is being migrated', - ); - case 'delete-local-graph': - return NativeEffectResolution.discard( - succeeded: await platform.deleteLocalGraph(effect.text), - message: '', - ); - case 'export-graph-database': - return NativeEffectResolution.discard( - succeeded: await platform.exportGraphDatabase(), - message: '', - ); - case 'sign-in': - final token = await authentication.signIn(); - if (token.trim().isEmpty) { - return const NativeEffectResolution.discard( - succeeded: false, - message: 'Hosted sign-in did not return an access token', - ); - } - return const NativeEffectResolution.discard(); - case 'sign-out': - await authentication.signOut(); - return const NativeEffectResolution.discard(); - default: - return NativeEffectResolution.discard( - succeeded: false, - message: 'Unsupported Android platform effect: ${effect.kind}', - ); - } - } catch (error) { - return NativeEffectResolution.discard( - succeeded: false, - message: error.toString(), - ); - } - } -} - -final class AndroidStorageState { - const AndroidStorageState({ - required this.databasePath, - required this.graphsDirectory, - required this.baseUrl, - required this.selectedGraphId, - required this.localGraphIds, - this.settings = AndroidHostSettings.defaults, - this.composerDraft = '', - }); - - final String databasePath; - final String graphsDirectory; - final String baseUrl; - final String selectedGraphId; - final List localGraphIds; - final AndroidHostSettings settings; - final String composerDraft; - - List get startupHostUpdates => [ - const AndroidHostUpdate(kind: 'graph-loading', payload: 'true'), - AndroidHostUpdate( - kind: 'settings', - payload: jsonEncode(settings.hostPayload), - ), - AndroidHostUpdate( - kind: 'composer-draft', - payload: jsonEncode(composerDraft), - ), - ]; -} - -final class AndroidHostUpdate { - const AndroidHostUpdate({required this.kind, required this.payload}); - - final String kind; - final String payload; -} - -final class AndroidHostSettings { - const AndroidHostSettings({ - required this.appearance, - required this.language, - required this.spellCheck, - required this.autoCorrection, - required this.sidebarTabs, - required this.baseUrl, - required this.version, - required this.revision, - }); - - static const defaults = AndroidHostSettings( - appearance: 'system', - language: 'system', - spellCheck: true, - autoCorrection: true, - sidebarTabs: [], - baseUrl: 'http://127.0.0.1:8787', - version: 'Development', - revision: 'Development', - ); - - factory AndroidHostSettings.fromPlatformValue(Object? value) { - if (value is! Map) return defaults; - final tabs = value['sidebarTabs']; - return AndroidHostSettings( - appearance: value['appearance'] as String? ?? defaults.appearance, - language: value['language'] as String? ?? defaults.language, - spellCheck: value['spellCheck'] as bool? ?? defaults.spellCheck, - autoCorrection: - value['autoCorrection'] as bool? ?? defaults.autoCorrection, - sidebarTabs: tabs is List - ? tabs.whereType().toList(growable: false) - : defaults.sidebarTabs, - baseUrl: value['baseURL'] as String? ?? defaults.baseUrl, - version: value['version'] as String? ?? defaults.version, - revision: value['revision'] as String? ?? defaults.revision, - ); - } - - final String appearance; - final String language; - final bool spellCheck; - final bool autoCorrection; - final List sidebarTabs; - final String baseUrl; - final String version; - final String revision; - - Map get hostPayload => { - 'appearance': appearance, - 'language': language, - 'spellCheck': spellCheck, - 'autoCorrection': autoCorrection, - 'sidebarTabs': sidebarTabs, - 'baseURL': baseUrl, - 'version': version, - 'revision': revision, - }; -} - -final class AndroidDownloadedSnapshot { - const AndroidDownloadedSnapshot({ - required this.metadataBody, - required this.filePath, - }); - - final String metadataBody; - final String filePath; -} - -String _runtimeLogText(String encoded) { - final decoded = jsonDecode(encoded); - if (decoded is! List) { - throw const FormatException('Runtime log records must be a list'); - } - return decoded - .map((entry) { - if (entry is! Map) { - throw const FormatException('Runtime log record must be an object'); - } - return [ - entry['timestamp'], - entry['level'], - entry['source'], - entry['message'], - ].whereType().join(' '); - }) - .join('\n'); -} diff --git a/flutter/lib/core_bootstrap.dart b/flutter/lib/core_bootstrap.dart deleted file mode 100644 index 52a2bf11..00000000 --- a/flutter/lib/core_bootstrap.dart +++ /dev/null @@ -1,155 +0,0 @@ -import 'dart:convert'; - -import 'core_effect_executor.dart'; - -typedef CoreBootstrapTrace = void Function(String message); - -final class CoreStartupState { - const CoreStartupState({ - required this.databasePath, - required this.graphsDirectory, - required this.baseUrl, - required this.selectedGraphId, - required this.localGraphIds, - required this.accessToken, - }); - - final String databasePath; - final String graphsDirectory; - final String baseUrl; - final String selectedGraphId; - final List localGraphIds; - final String accessToken; -} - -final class CoreBootstrapResult { - const CoreBootstrapResult({ - required this.catalogResponse, - required this.graphResponse, - required this.localGraphIds, - }); - - final String catalogResponse; - final String? graphResponse; - final List localGraphIds; -} - -final class CoreBootstrap { - const CoreBootstrap({required this.callCore, this.trace}); - - final NativeCoreCall callCore; - final CoreBootstrapTrace? trace; - - Future restore(CoreStartupState state) async { - final catalogResponse = await _call( - operation: 'open catalog', - request: _request(method: 'open', path: state.databasePath), - ); - final catalog = _successfulResult( - catalogResponse, - operation: 'open catalog', - ); - final configureResponse = await _call( - operation: 'configure graph', - request: _request( - method: 'dispatch', - action: 'configure', - payload: jsonEncode({ - 'baseUrl': state.baseUrl, - 'graphId': state.selectedGraphId, - 'token': state.accessToken, - }), - ), - ); - _successfulResult(configureResponse, operation: 'configure graph'); - - String? graphResponse; - if (state.selectedGraphId.isNotEmpty && - state.localGraphIds.contains(state.selectedGraphId) && - !_graphIsEncrypted(catalog, state.selectedGraphId)) { - final directory = '${state.graphsDirectory}/${state.selectedGraphId}'; - graphResponse = await _call( - operation: 'open local graph', - request: _request( - method: 'dispatch', - action: 'openGraph', - payload: jsonEncode({ - 'graphId': state.selectedGraphId, - 'activePath': '$directory/graph.sqlite', - 'checkpointPath': '$directory/sync.checkpoint', - 'isEncrypted': false, - }), - ), - ); - _successfulResult(graphResponse, operation: 'open local graph'); - } - - return CoreBootstrapResult( - catalogResponse: catalogResponse, - graphResponse: graphResponse, - localGraphIds: state.localGraphIds, - ); - } - - Future _call({ - required String operation, - required String request, - }) async { - trace?.call('$operation started'); - final stopwatch = Stopwatch()..start(); - try { - return await callCore(request); - } finally { - trace?.call( - '$operation completed durationMs=${stopwatch.elapsedMilliseconds}', - ); - } - } - - bool _graphIsEncrypted(Map catalog, String graphId) { - final graphs = catalog['graphs']; - if (graphs is! List) return false; - for (final graph in graphs) { - if (graph is Map && graph['id'] == graphId) { - return graph['isEncrypted'] == true; - } - } - return false; - } - - Map _successfulResult( - String encoded, { - required String operation, - }) { - final response = jsonDecode(encoded); - if (response is! Map) { - throw FormatException( - 'Could not $operation: core response is not an object', - ); - } - if (response['ok'] != true) { - final error = response['error']; - final message = error is Map - ? error['message'] as String? - : null; - throw StateError( - 'Could not $operation: ${message ?? 'unknown core error'}', - ); - } - final result = response['result']; - return result is Map ? result : const {}; - } - - String _request({ - required String method, - String? action, - String? payload, - String? path, - }) { - final params = {}; - if (action != null) params['action'] = action; - if (payload != null) params['payload'] = payload; - if (path != null) params['path'] = path; - return jsonEncode({'apiVersion': 1, 'method': method, 'params': params}); - } -} diff --git a/flutter/lib/core_effect_executor.dart b/flutter/lib/core_effect_executor.dart deleted file mode 100644 index 01238f59..00000000 --- a/flutter/lib/core_effect_executor.dart +++ /dev/null @@ -1,283 +0,0 @@ -import 'dart:convert'; - -import 'native_effect_drain.dart'; - -typedef NativeCoreCall = Future Function(String request); -typedef MillisecondsClock = int Function(); -typedef UuidFactory = String Function(); -typedef NativeGraphExecutor = Future Function( - NativeEffect effect, -); - -final class CoreEffectExecutor { - CoreEffectExecutor({ - required this.callCore, - required this.executePlatformEffect, - required this.executeGraphEffect, - MillisecondsClock? nowMilliseconds, - UuidFactory? newUuid, - }) : nowMilliseconds = - nowMilliseconds ?? (() => DateTime.now().millisecondsSinceEpoch), - newUuid = newUuid ?? newCoreUuid; - - final NativeCoreCall callCore; - final NativeEffectExecutor executePlatformEffect; - final NativeGraphExecutor executeGraphEffect; - final MillisecondsClock nowMilliseconds; - final UuidFactory newUuid; - - static const _platformEffectKinds = { - 'persist-composer-draft', - 'present-attachment', - 'present-asset', - 'present-page-share', - 'sync-now', - 'delete-local-graph', - 'save-settings', - 'export-graph-database', - 'open-external-url', - 'refresh-runtime-log', - 'copy-runtime-log', - 'sign-in', - 'sign-out', - }; - - static const _graphEffectKinds = { - 'open-graph', - 'unlock-graph', - 'create-graph', - }; - - Future execute(NativeEffect effect) async { - if (_platformEffectKinds.contains(effect.kind)) { - return executePlatformEffect(effect); - } - if (_graphEffectKinds.contains(effect.kind)) { - return executeGraphEffect(effect); - } - - try { - final request = _request(effect); - if (request == null) { - return NativeEffectResolution.discard( - succeeded: false, - message: 'Unsupported LG effect: ${effect.kind}', - ); - } - final response = await callCore(jsonEncode(request)); - return _resolution(response); - } catch (error) { - return NativeEffectResolution.discard( - succeeded: false, - message: error.toString(), - ); - } - } - - Map? _request(NativeEffect effect) { - String action; - String? payload; - switch (effect.kind) { - case 'send-capture': - action = 'send'; - payload = _payload({ - 'text': effect.text, - 'uuid': newUuid(), - 'now': nowMilliseconds(), - }); - case 'send-task': - action = 'sendTask'; - payload = _payload({ - 'text': effect.text, - 'uuid': newUuid(), - 'now': nowMilliseconds(), - 'status': _metadataObject(effect, 'task status'), - }); - case 'search-nodes': - action = 'searchNodes'; - payload = effect.text; - case 'open-node': - action = 'openNode'; - payload = _payload({'uuid': effect.text}); - case 'close-node': - action = 'closeNode'; - case 'select-sidebar-page': - action = 'selectPage'; - payload = effect.text; - case 'clear-selected-page': - action = 'clearSelectedPage'; - case 'load-older-journals': - action = 'loadOlderJournals'; - case 'set-page-favorite': - action = 'setPageFavorite'; - payload = _payload({ - 'pageUuid': effect.text, - 'favorite': effect.value == 1, - 'operationId': newUuid(), - 'now': nowMilliseconds(), - }); - case 'delete-page': - action = 'deletePage'; - payload = _payload({ - 'pageUuid': effect.text, - 'operationId': newUuid(), - 'now': nowMilliseconds(), - }); - case 'load-flashcards': - action = 'loadFlashcards'; - payload = nowMilliseconds().toString(); - case 'review-flashcard': - action = 'reviewFlashcard'; - payload = _payload({ - 'uuid': _requiredUuid(effect), - 'rating': effect.text, - 'now': nowMilliseconds(), - 'operationId': newUuid(), - }); - case 'refresh-graphs': - action = 'refresh'; - case 'tap-outliner-block': - return _outlinerRequest({'type': 'tapBlock', 'uuid': effect.text}); - case 'toggle-outliner-collapsed': - return _outlinerRequest({ - 'type': 'toggleCollapsed', - 'uuid': effect.text, - }); - case 'long-press-outliner-block': - return _outlinerRequest({ - 'type': 'longPressBlock', - 'uuid': effect.text, - }); - case 'add-root-block': - return _outlinerRequest({'type': 'addRootBlock', 'uuid': effect.text}); - case 'drop-outliner-blocks': - final placement = effect.metadata; - if (placement == null) { - throw const FormatException( - 'The outliner drop effect is missing its placement', - ); - } - return _outlinerRequest({ - 'type': 'dropBlocks', - 'targetUuid': effect.text, - 'placement': placement, - }); - case 'set-outliner-task-status': - final status = _metadataObject(effect, 'task status'); - return _outlinerRequest({ - 'type': 'setTaskStatus', - 'uuid': effect.text, - 'statusIdent': status['ident'], - 'statusUuid': status['uuid'], - }); - case 'outliner-toolbar': - return _outlinerRequest({'type': 'toolbar', 'action': effect.text}); - case 'choose-outliner-autocomplete': - return _outlinerRequest({ - 'type': 'chooseAutocomplete', - 'value': effect.text, - }); - case 'save-outliner-editing': - return _outlinerRequest({'type': 'saveEditing'}); - case 'cancel-outliner-editing': - return _outlinerRequest({'type': 'cancelEditing'}); - case 'change-outliner-text': - return _outlinerRequest({ - 'type': 'textChanged', - 'uuid': _requiredUuid(effect), - 'title': effect.text, - 'caretUTF16Offset': _requiredValue(effect), - }); - case 'return-outliner-editor': - return _outlinerRequest({ - 'type': 'returnPressed', - 'uuid': _requiredUuid(effect), - 'title': effect.text, - 'caretUTF16Offset': _requiredValue(effect), - }); - case 'backspace-outliner-editor': - return _outlinerRequest({ - 'type': 'backspacePressed', - 'uuid': _requiredUuid(effect), - 'title': effect.text, - 'selectionLength': _requiredValue(effect), - }); - case 'move-outliner-caret': - return _outlinerRequest({ - 'type': 'caretMoved', - 'uuid': _requiredUuid(effect), - 'caretUTF16Offset': _requiredValue(effect), - }); - default: - return null; - } - return _rpcRequest(action: action, payload: payload); - } - - Map _outlinerRequest(Map event) => - _rpcRequest(action: 'outlinerEvent', payload: _payload(event)); - - Map _rpcRequest({required String action, String? payload}) { - final params = {'action': action}; - if (payload != null) params['payload'] = payload; - return {'apiVersion': 1, 'method': 'dispatch', 'params': params}; - } - - Map _metadataObject(NativeEffect effect, String label) { - final metadata = effect.metadata; - if (metadata == null) { - throw FormatException('The ${effect.kind} effect is missing its $label'); - } - final decoded = jsonDecode(metadata); - if (decoded is! Map) { - throw FormatException('The ${effect.kind} $label must be an object'); - } - return decoded; - } - - String _requiredUuid(NativeEffect effect) { - final uuid = effect.uuid; - if (uuid == null) { - throw FormatException('The ${effect.kind} effect is missing its UUID'); - } - return uuid; - } - - int _requiredValue(NativeEffect effect) { - final value = effect.value; - if (value == null) { - throw FormatException( - 'The ${effect.kind} effect is missing its integer value', - ); - } - return value; - } - - NativeEffectResolution _resolution(String response) { - final decoded = jsonDecode(response); - if (decoded is! Map) { - throw const FormatException('The native core response must be an object'); - } - if (decoded['ok'] == true) { - return NativeEffectResolution.coreResponse(response); - } - final error = decoded['error']; - final code = error is Map && error['code'] is String - ? error['code']! as String - : 'core_error'; - final message = error is Map && error['message'] is String - ? error['message']! as String - : 'The OCaml core rejected the effect'; - return NativeEffectResolution.discard( - succeeded: false, - message: '$code\n$message', - ); - } -} - -String _payload(Map value) => jsonEncode(value); - -String newCoreUuid() { - final timestamp = DateTime.now().microsecondsSinceEpoch.toRadixString(16); - return '$timestamp-${timestamp.padLeft(32, '0').substring(0, 32)}'; -} diff --git a/flutter/lib/flutter_patch_applier.dart b/flutter/lib/flutter_patch_applier.dart deleted file mode 100644 index e5696f8e..00000000 --- a/flutter/lib/flutter_patch_applier.dart +++ /dev/null @@ -1,110 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/foundation.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -final class FlutterPatchApplier extends ChangeNotifier { - FlutterPatchApplier(this._backend); - - final LUIFlutterBackend _backend; - Map _nodeKinds = {}; - Set _ignoredProperties = {}; - - void applyJson(String patch) { - final document = jsonDecode(patch) as Map; - final operations = document['ops'] as List; - final nextNodeKinds = Map.of(_nodeKinds); - final nextIgnoredProperties = Set.of(_ignoredProperties); - final compatibleOperations = []; - var structureChanged = false; - - for (final value in operations) { - final operation = value as Map; - final name = operation['op']; - if (name == 'insert-child' || - name == 'remove-child' || - name == 'move-child') { - structureChanged = true; - } - final id = operation['id']; - if (name == 'create-node' && id is int) { - nextNodeKinds[id] = operation['kind'] as String; - } else if (name == 'drop-node' && id is int) { - nextNodeKinds.remove(id); - nextIgnoredProperties.removeWhere( - (property) => property.startsWith('$id:'), - ); - } else if (name == 'set-prop' && id is int) { - final property = operation['property'] as String; - final key = _propertyKey(id, property); - if (_isUnsupportedPresentationHint( - kind: nextNodeKinds[id], - property: property, - value: operation['value'], - )) { - nextIgnoredProperties.add(key); - continue; - } - nextIgnoredProperties.remove(key); - if (property == 'size' && - operation['value'] == 'icon' && - const {'button', 'toggle-button'}.contains(nextNodeKinds[id])) { - // Icon controls center their glyph inside the full touch target. - // The Flutter backend otherwise inherits leading text alignment. - compatibleOperations.add(operation); - compatibleOperations.add({ - 'op': 'set-prop', - 'id': id, - 'property': 'text-alignment', - 'value': 'center', - }); - continue; - } - } else if (name == 'remove-prop' && id is int) { - final property = operation['property'] as String; - final key = _propertyKey(id, property); - if (nextIgnoredProperties.remove(key)) continue; - } - compatibleOperations.add(operation); - } - - _backend.applyJson(jsonEncode({...document, 'ops': compatibleOperations})); - _nodeKinds = nextNodeKinds; - _ignoredProperties = nextIgnoredProperties; - if (structureChanged) { - notifyListeners(); - } - } - - static bool _isUnsupportedPresentationHint({ - required String? kind, - required String property, - required Object? value, - }) => switch (property) { - 'container-relative-frame' || 'container-relative-frame-inset' => true, - 'selected' => kind == 'virtual-list', - 'padding-horizontal' || 'padding-vertical' => !const { - 'row', - 'column', - 'grid', - 'box', - }.contains(kind), - 'style-class' => kind == 'dialog' || kind == 'sheet', - 'icon-placement' => - (kind != 'button' && kind != 'toggle-button') || - (value != 'leading' && value != 'trailing'), - 'role' => - value != 'treeitem' || - !const { - 'row', - 'column', - 'panel', - 'card', - 'box', - 'list-item', - }.contains(kind), - _ => false, - }; - - static String _propertyKey(int id, String property) => '$id:$property'; -} diff --git a/flutter/lib/graph_catalog_auto_refresh.dart b/flutter/lib/graph_catalog_auto_refresh.dart deleted file mode 100644 index b98d8242..00000000 --- a/flutter/lib/graph_catalog_auto_refresh.dart +++ /dev/null @@ -1,120 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'core_effect_executor.dart'; - -typedef ApplyCoreResponse = Future Function(String response); -typedef GraphCatalogRefreshTrace = void Function(String message); -typedef GraphCatalogPeriodicScheduler = Timer Function( - Duration interval, - void Function() tick, -); - -void _ignoreGraphCatalogRefreshTrace(String message) {} - -Timer _scheduleGraphCatalogRefresh(Duration interval, void Function() tick) => - Timer.periodic(interval, (_) => tick()); - -final class GraphCatalogAutoRefresh { - GraphCatalogAutoRefresh({ - required this.callCore, - required this.applyCoreResponse, - this.trace = _ignoreGraphCatalogRefreshTrace, - this.schedulePeriodic = _scheduleGraphCatalogRefresh, - }); - - final NativeCoreCall callCore; - final ApplyCoreResponse applyCoreResponse; - final GraphCatalogRefreshTrace trace; - final GraphCatalogPeriodicScheduler schedulePeriodic; - Future? _activeRefresh; - Timer? _periodicTimer; - String? _catalogFingerprint; - - void rememberCatalog(String response) { - _catalogFingerprint = _fingerprint(response); - } - - void startPeriodic({Duration interval = const Duration(seconds: 15)}) { - if (_periodicTimer != null) return; - trace('periodic.start intervalMs=${interval.inMilliseconds}'); - _periodicTimer = schedulePeriodic(interval, _periodicTick); - } - - void stopPeriodic() { - final timer = _periodicTimer; - if (timer == null) return; - timer.cancel(); - _periodicTimer = null; - trace('periodic.stop'); - } - - void _periodicTick() { - unawaited( - refresh().onError((error, stackTrace) { - trace('periodic.failed error=$error'); - return false; - }), - ); - } - - Future refresh() { - final active = _activeRefresh; - if (active != null) return active; - late final Future operation; - operation = _run().whenComplete(() { - if (identical(_activeRefresh, operation)) _activeRefresh = null; - }); - _activeRefresh = operation; - return operation; - } - - Future _run() async { - trace('refresh.start'); - final response = await callCore( - jsonEncode({ - 'apiVersion': 1, - 'method': 'dispatch', - 'params': {'action': 'refreshGraphCatalog'}, - }), - ); - final decoded = jsonDecode(response); - if (decoded is! Map || decoded['ok'] != true) { - final error = decoded is Map ? decoded['error'] : null; - final code = error is Map ? error['code'] : null; - final message = error is Map ? error['message'] : null; - trace( - 'refresh.rejected code=${code ?? 'unknown'} ' - 'message=${message ?? 'Unknown core response'}', - ); - return false; - } - final fingerprint = _fingerprintFromEnvelope(decoded); - if (fingerprint != null && fingerprint == _catalogFingerprint) { - trace('refresh.unchanged'); - return true; - } - await applyCoreResponse(response); - _catalogFingerprint = fingerprint; - trace('refresh.complete'); - return true; - } - - String? _fingerprint(String response) { - try { - final decoded = jsonDecode(response); - return decoded is Map - ? _fingerprintFromEnvelope(decoded) - : null; - } on FormatException { - return null; - } - } - - String? _fingerprintFromEnvelope(Map envelope) { - final result = envelope['result']; - if (result is! Map) return null; - final graphs = result['graphs']; - return graphs is List ? jsonEncode(graphs) : null; - } -} diff --git a/flutter/lib/graph_catalog_polling_policy.dart b/flutter/lib/graph_catalog_polling_policy.dart deleted file mode 100644 index 61d01402..00000000 --- a/flutter/lib/graph_catalog_polling_policy.dart +++ /dev/null @@ -1,6 +0,0 @@ -bool shouldPollGraphCatalog({ - required bool authenticated, - required bool hasOpenGraph, - required bool foreground, -}) => - authenticated && !hasOpenGraph && foreground; diff --git a/flutter/lib/logseq_chat_app_frame.dart b/flutter/lib/logseq_chat_app_frame.dart deleted file mode 100644 index 5f659e2e..00000000 --- a/flutter/lib/logseq_chat_app_frame.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; - -final class LogseqChatAppFrame extends StatelessWidget { - const LogseqChatAppFrame({required this.child, super.key}); - - final Widget child; - - @override - Widget build(BuildContext context) => Scaffold(body: SafeArea(child: child)); -} diff --git a/flutter/lib/logseq_chat_extensions.dart b/flutter/lib/logseq_chat_extensions.dart deleted file mode 100644 index 16c83a76..00000000 --- a/flutter/lib/logseq_chat_extensions.dart +++ /dev/null @@ -1,1244 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:highlighter/highlighter.dart' as syntax; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -import 'android_audio_playback.dart'; -import 'android_cloze.dart'; -import 'android_embedded_media.dart'; -import 'android_math.dart'; - -final _syntaxNodeCache = >{}; -const _syntaxNodeCacheLimit = 64; - -const _editorFingerprint = - 'lui-extension-v1|15:outliner-editor|profiles:android/flutter,' - 'ios/swiftui|standard-children:0|children:|' - 'properties:18:caret-utf16-offset:int:required:none,5:title:string:' - 'required:none,8:block-id:string:required:none|events:11:text-change[' - '18:caret-utf16-offset:int:required,5:title:string:required],12:caret-change[' - '18:caret-utf16-offset:int:required],6:return[18:caret-utf16-offset:int:' - 'required,5:title:string:required],9:backspace[16:selection-length:int:' - 'required,5:title:string:required]'; -const _richFingerprint = - 'lui-extension-v1|22:outliner-block-content|profiles:android/flutter,' - 'ios/swiftui|standard-children:0|children:|' - 'properties:10:asset-type:string:required:none,10:local-path:string:' - 'required:none,11:markup-json:string:required:none,12:is-completed:bool:' - 'required:none,18:youtube-target-url:string:required:none,5:title:string:' - 'required:none,8:block-id:string:required:none,8:is-asset:bool:required:none|' - 'events:10:drag-start[4:uuid:string:required],4:drop[4:uuid:string:required,' - '9:placement:string:required],4:edit[4:uuid:string:required],9:open-node[' - '4:uuid:string:required]'; -const _navigationFingerprint = - 'lui-extension-v1|23:native-navigation-stack|profiles:android/flutter,' - 'ios/swiftui|standard-children:1|children:|' - 'properties:26:composer-dismissal-enabled:bool:required:none,' - '28:bottom-occupies-layout-space:bool:required:none,5:depth:int:required:none,' - '5:title:string:required:none|events:16:dismiss-composer[],4:back[' - '5:count:int:required]'; -const _searchFingerprint = - 'lui-extension-v1|26:native-search-presentation|profiles:android/flutter,' - 'ios/swiftui|standard-children:1|children:|' - 'properties:5:depth:int:required:none,5:query:string:required:none,' - '5:title:string:required:none,9:presented:bool:required:none|events:' - '13:query-changed[5:query:string:required],4:back[5:count:int:required],' - '7:dismiss[]'; - -String _identityAssetPath(String path) => path; - -LUIFlutterExtensionRegistry logseqChatExtensionRegistry({ - String Function(String) resolveAssetPath = _identityAssetPath, -}) { - final youtubePlayback = _YoutubePlaybackCoordinator(); - return LUIFlutterExtensionRegistry() - ..register( - LUIFlutterExtension( - identifier: 'outliner-editor', - fingerprint: _editorFingerprint, - properties: [ - _requiredStringProperty('block-id'), - _requiredStringProperty('title'), - _requiredIntProperty('caret-utf16-offset'), - ], - events: [ - LUIExtensionEventSchema( - name: 'text-change', - fields: [ - _requiredStringField('title'), - _requiredIntField('caret-utf16-offset'), - ], - ), - LUIExtensionEventSchema( - name: 'return', - fields: [ - _requiredStringField('title'), - _requiredIntField('caret-utf16-offset'), - ], - ), - LUIExtensionEventSchema( - name: 'backspace', - fields: [ - _requiredStringField('title'), - _requiredIntField('selection-length'), - ], - ), - LUIExtensionEventSchema( - name: 'caret-change', - fields: [_requiredIntField('caret-utf16-offset')], - ), - ], - builder: (context) => _OutlinerEditor(context: context), - ), - ) - ..register( - LUIFlutterExtension( - identifier: 'outliner-block-content', - fingerprint: _richFingerprint, - properties: [ - _requiredStringProperty('title'), - _requiredStringProperty('block-id'), - _requiredStringProperty('markup-json'), - _requiredStringProperty('youtube-target-url'), - _requiredBoolProperty('is-asset'), - _requiredBoolProperty('is-completed'), - _requiredStringProperty('asset-type'), - _requiredStringProperty('local-path'), - ], - events: [ - LUIExtensionEventSchema( - name: 'drag-start', - fields: [_requiredStringField('uuid')], - ), - LUIExtensionEventSchema( - name: 'drop', - fields: [ - _requiredStringField('uuid'), - _requiredStringField('placement'), - ], - ), - LUIExtensionEventSchema( - name: 'edit', - fields: [_requiredStringField('uuid')], - ), - LUIExtensionEventSchema( - name: 'open-node', - fields: [_requiredStringField('uuid')], - ), - ], - builder: (context) => _OutlinerBlockContent( - context: context, - youtubePlayback: youtubePlayback, - resolveAssetPath: resolveAssetPath, - ), - ), - ) - ..register( - LUIFlutterExtension( - identifier: 'native-navigation-stack', - fingerprint: _navigationFingerprint, - acceptsStandardChildren: true, - properties: [ - _requiredIntProperty('depth'), - _requiredBoolProperty('bottom-occupies-layout-space'), - _requiredBoolProperty('composer-dismissal-enabled'), - _requiredStringProperty('title'), - ], - events: [ - LUIExtensionEventSchema( - name: 'back', - fields: [_requiredIntField('count')], - ), - LUIExtensionEventSchema(name: 'dismiss-composer'), - ], - builder: (context) => _NavigationBoundary(context: context), - ), - ) - ..register( - LUIFlutterExtension( - identifier: 'native-search-presentation', - fingerprint: _searchFingerprint, - acceptsStandardChildren: true, - properties: [ - _requiredBoolProperty('presented'), - _requiredIntProperty('depth'), - _requiredStringProperty('query'), - _requiredStringProperty('title'), - ], - events: [ - LUIExtensionEventSchema( - name: 'back', - fields: [_requiredIntField('count')], - ), - LUIExtensionEventSchema(name: 'dismiss'), - LUIExtensionEventSchema( - name: 'query-changed', - fields: [_requiredStringField('query')], - ), - ], - builder: (context) => _SearchPresentation(context: context), - ), - ); -} - -LUIExtensionEventField _requiredStringField(String name) => - LUIExtensionEventField( - name: name, - kind: LUIExtensionValueKind.string, - isRequired: true, - ); - -LUIExtensionEventField _requiredIntField(String name) => LUIExtensionEventField( - name: name, - kind: LUIExtensionValueKind.integer, - isRequired: true, -); - -LUIExtensionProperty _requiredStringProperty(String name) => - LUIExtensionProperty( - name: name, - kind: LUIExtensionValueKind.string, - isRequired: true, - ); - -LUIExtensionProperty _requiredBoolProperty(String name) => LUIExtensionProperty( - name: name, - kind: LUIExtensionValueKind.boolean, - isRequired: true, -); - -LUIExtensionProperty _requiredIntProperty(String name) => LUIExtensionProperty( - name: name, - kind: LUIExtensionValueKind.integer, - isRequired: true, -); - -final class _NavigationBoundary extends StatelessWidget { - const _NavigationBoundary({required this.context}); - - final LUIFlutterExtensionContext context; - - @override - Widget build(BuildContext buildContext) { - final depth = context.property('depth')! as int; - final dismissesComposer = - context.property('composer-dismissal-enabled')! as bool; - return PopScope( - canPop: depth == 0 && !dismissesComposer, - onPopInvokedWithResult: (didPop, _) { - if (didPop) return; - if (dismissesComposer) { - context.emit(name: 'dismiss-composer'); - } else if (depth > 0) { - context.emit(name: 'back', values: const {'count': 1}); - } - }, - child: context.content, - ); - } -} - -final class _SearchPresentation extends StatefulWidget { - const _SearchPresentation({required this.context}); - - final LUIFlutterExtensionContext context; - - @override - State<_SearchPresentation> createState() => _SearchPresentationState(); -} - -final class _SearchPresentationState extends State<_SearchPresentation> - with SingleTickerProviderStateMixin { - late final SearchController _controller; - late final FocusNode _focusNode; - late final AnimationController _transition; - late String _modelQuery; - late bool _presented; - var _closing = false; - - @override - void initState() { - super.initState(); - _controller = SearchController(); - _focusNode = FocusNode(); - _modelQuery = widget.context.property('query')! as String; - _controller.text = _modelQuery; - _presented = widget.context.property('presented')! as bool; - _transition = AnimationController( - vsync: this, - duration: const Duration(milliseconds: 160), - ); - if (_presented) _transition.forward(); - } - - @override - void didUpdateWidget(covariant _SearchPresentation oldWidget) { - super.didUpdateWidget(oldWidget); - final query = widget.context.property('query')! as String; - if (query != _modelQuery) { - _modelQuery = query; - if (_controller.text != query) { - _controller.value = TextEditingValue( - text: query, - selection: TextSelection.collapsed(offset: query.length), - ); - } - } - final presented = widget.context.property('presented')! as bool; - if (presented != _presented) { - _presented = presented; - _closing = false; - if (presented) { - _transition.forward(from: 0); - } else { - _transition.value = 0; - _focusNode.unfocus(); - } - } - if ((widget.context.property('depth')! as int) > 0) { - _focusNode.unfocus(); - } - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _transition.duration = MediaQuery.disableAnimationsOf(context) - ? Duration.zero - : const Duration(milliseconds: 160); - } - - Future _dismiss() async { - if (_closing) return; - _closing = true; - _focusNode.unfocus(); - try { - await _transition.reverse().orCancel; - if (mounted && _presented) widget.context.emit(name: 'dismiss'); - } on TickerCanceled { - // The host may close or replace search while its transition is running. - } - } - - @override - Widget build(BuildContext context) { - final extension = widget.context; - if (!(extension.property('presented')! as bool)) return extension.content; - final depth = extension.property('depth')! as int; - final query = extension.property('query')! as String; - return PopScope( - canPop: false, - onPopInvokedWithResult: (didPop, _) { - if (didPop) return; - if (depth > 0) { - extension.emit(name: 'back', values: const {'count': 1}); - } else { - unawaited(_dismiss()); - } - }, - child: FadeTransition( - opacity: _transition, - alwaysIncludeSemantics: true, - child: Column( - children: [ - SafeArea( - bottom: false, - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 8, 16, 8), - child: Semantics( - key: const ValueKey('search-field'), - identifier: 'field.search', - child: SearchBar( - controller: _controller, - focusNode: _focusNode, - autoFocus: query.isEmpty, - textInputAction: TextInputAction.search, - hintText: 'Search pages and blocks', - leading: IconButton( - tooltip: depth > 0 ? 'Back' : 'Close search', - icon: const Icon(Icons.arrow_back_rounded), - onPressed: () { - if (depth > 0) { - extension.emit( - name: 'back', - values: const {'count': 1}, - ); - } else { - unawaited(_dismiss()); - } - }, - ), - trailing: [ - ValueListenableBuilder( - valueListenable: _controller, - builder: (context, value, _) => value.text.isEmpty - ? const SizedBox.shrink() - : IconButton( - tooltip: 'Clear search', - icon: const Icon(Icons.close_rounded), - onPressed: () { - _controller.clear(); - extension.emit( - name: 'query-changed', - values: const {'query': ''}, - ); - _focusNode.requestFocus(); - }, - ), - ), - ], - onChanged: (query) => extension.emit( - name: 'query-changed', - values: {'query': query}, - ), - ), - ), - ), - ), - Expanded( - child: NotificationListener( - onNotification: (notification) { - if (notification.dragDetails != null) _focusNode.unfocus(); - return false; - }, - child: extension.content, - ), - ), - ], - ), - ), - ); - } - - @override - void dispose() { - _transition.dispose(); - _focusNode.dispose(); - _controller.dispose(); - super.dispose(); - } -} - -final class _YoutubePlaybackCoordinator - extends ValueNotifier> { - _YoutubePlaybackCoordinator() : super(const {}); - - void seek(String url, int seconds) { - if (url.isEmpty) return; - value = {...value, url: seconds}; - } -} - -final class _OutlinerBlockContent extends StatelessWidget { - const _OutlinerBlockContent({ - required this.context, - required this.youtubePlayback, - required this.resolveAssetPath, - }); - - final LUIFlutterExtensionContext context; - final _YoutubePlaybackCoordinator youtubePlayback; - final String Function(String) resolveAssetPath; - - @override - Widget build(BuildContext buildContext) { - final uuid = context.property('block-id')! as String; - final title = context.property('title')! as String; - final completed = context.property('is-completed')! as bool; - final isAsset = context.property('is-asset')! as bool; - final row = GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: () => context.emit(name: 'edit', values: {'uuid': uuid}), - child: DefaultTextStyle.merge( - style: completed - ? const TextStyle(decoration: TextDecoration.lineThrough) - : null, - child: isAsset - ? _ProjectedAsset( - title: title, - assetType: context.property('asset-type')! as String, - localPath: resolveAssetPath( - context.property('local-path')! as String, - ), - ) - : _ProjectedMarkup( - encoded: context.property('markup-json')! as String, - fallback: title, - youtubeTargetUrl: - context.property('youtube-target-url')! as String, - youtubePlayback: youtubePlayback, - onOpenNode: (nodeUuid) => - context.emit(name: 'open-node', values: {'uuid': nodeUuid}), - ), - ), - ); - return Builder( - builder: (targetContext) => DragTarget( - onWillAcceptWithDetails: (details) => details.data != uuid, - onAcceptWithDetails: (details) { - final box = targetContext.findRenderObject()! as RenderBox; - final localY = box.globalToLocal(details.offset).dy; - context.emit( - name: 'drop', - values: { - 'uuid': uuid, - 'placement': androidOutlinerDropPlacement( - localY, - box.size.height, - ), - }, - ); - }, - builder: (_, candidates, _) => AnimatedContainer( - duration: const Duration(milliseconds: 120), - decoration: BoxDecoration( - color: candidates.isEmpty - ? Colors.transparent - : Theme.of(buildContext).colorScheme.primaryContainer, - borderRadius: BorderRadius.circular(8), - ), - child: Semantics( - key: ValueKey('outliner-block-content-$uuid'), - container: true, - explicitChildNodes: true, - label: 'Edit block ${title.isEmpty ? 'Untitled block' : title}', - button: true, - child: LongPressDraggable( - data: uuid, - dragAnchorStrategy: pointerDragAnchorStrategy, - onDragStarted: () => - context.emit(name: 'drag-start', values: {'uuid': uuid}), - feedback: Material( - elevation: 6, - color: Theme.of(buildContext).colorScheme.surfaceContainerHigh, - borderRadius: BorderRadius.circular(12), - child: ConstrainedBox( - constraints: const BoxConstraints(maxWidth: 320), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 12, - ), - child: Text(title.isEmpty ? 'Untitled block' : title), - ), - ), - ), - childWhenDragging: Opacity(opacity: 0.35, child: row), - child: row, - ), - ), - ), - ), - ); - } -} - -String androidOutlinerDropPlacement(double localY, double rowHeight) { - final height = rowHeight <= 0 ? 1.0 : rowHeight; - if (localY < height * 0.25) return 'before'; - if (localY > height * 0.75) return 'after'; - return 'inside'; -} - -final class _ProjectedAsset extends StatelessWidget { - const _ProjectedAsset({ - required this.title, - required this.assetType, - required this.localPath, - }); - - final String title; - final String assetType; - final String localPath; - - @override - Widget build(BuildContext context) { - if (isAndroidImageAsset(assetType, localPath) && localPath.isNotEmpty) { - return Semantics( - key: const ValueKey('asset.preview.image'), - identifier: 'asset.preview.image', - label: title, - image: true, - child: ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.file( - File(localPath), - fit: BoxFit.cover, - errorBuilder: (_, _, _) => _fallback(), - ), - ), - ); - } - if (localPath.isNotEmpty && isAndroidAudioAsset(assetType, localPath)) { - return AndroidAudioPlayer(title: title, path: localPath); - } - return _fallback(); - } - - Widget _fallback() => Row( - mainAxisSize: MainAxisSize.min, - children: [ - const Icon(Icons.attach_file_rounded), - const SizedBox(width: 8), - Flexible(child: Text(title)), - ], - ); -} - -bool isAndroidImageAsset(String assetType, String localPath) { - final normalizedType = assetType.toLowerCase().split(';').first.trim(); - if (normalizedType.startsWith('image/')) return true; - const imageExtensions = { - 'png', - 'jpg', - 'jpeg', - 'gif', - 'webp', - 'bmp', - 'wbmp', - 'heic', - 'heif', - 'avif', - }; - if (imageExtensions.contains(normalizedType)) return true; - final dot = localPath.lastIndexOf('.'); - if (dot < 0 || dot == localPath.length - 1) return false; - return imageExtensions.contains(localPath.substring(dot + 1).toLowerCase()); -} - -final class _ProjectedMarkup extends StatelessWidget { - const _ProjectedMarkup({ - required this.encoded, - required this.fallback, - required this.youtubeTargetUrl, - required this.youtubePlayback, - required this.onOpenNode, - }); - - final String encoded; - final String fallback; - final String youtubeTargetUrl; - final _YoutubePlaybackCoordinator youtubePlayback; - final ValueChanged onOpenNode; - - @override - Widget build(BuildContext context) { - final nodes = _decode(); - if (nodes.isEmpty) return Text(fallback); - return ValueListenableBuilder>( - valueListenable: youtubePlayback, - builder: (context, playbackStarts, _) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - for (final (index, chunk) in _chunks(nodes).indexed) - _chunk(context, chunk, index, playbackStarts), - ], - ), - ); - } - - Widget _chunk( - BuildContext context, - List> chunk, - int index, - Map playbackStarts, - ) { - if (chunk.length == 1 && _isRich(chunk.first)) { - final node = chunk.first; - final identifier = _richIdentifier(node, playbackStarts); - return Semantics( - key: ValueKey(identifier), - identifier: identifier, - container: true, - child: _node(context, node), - ); - } - final identifier = 'block.rich.inline.$index'; - return Semantics( - key: ValueKey(identifier), - identifier: identifier, - container: true, - explicitChildNodes: true, - label: _plainText(chunk), - child: Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - children: [for (final node in chunk) _node(context, node)], - ), - ); - } - - List>> _chunks(List> nodes) { - final result = >>[]; - var inline = >[]; - for (final node in nodes) { - if (_isRich(node)) { - if (inline.isNotEmpty) result.add(inline); - inline = >[]; - result.add([node]); - } else { - inline.add(node); - } - } - if (inline.isNotEmpty) result.add(inline); - return result; - } - - bool _isRich(Map node) => const { - 'quote', - 'math', - 'codeBlock', - 'video', - 'iframe', - 'youtubeTimestamp', - 'cloze', - }.contains(node['type']); - - String _richIdentifier( - Map node, - Map playbackStarts, - ) { - final type = node['type'] as String? ?? 'text'; - if (type == 'video') { - final start = playbackStarts[node['url'] as String? ?? '']; - if (start != null) return 'block.rich.video.start.$start'; - } else if (type == 'youtubeTimestamp') { - final seconds = int.tryParse(node['style'] as String? ?? ''); - if (seconds != null && playbackStarts[youtubeTargetUrl] == seconds) { - return 'block.rich.youtubeTimestamp.start.$seconds'; - } - } - return 'block.rich.$type'; - } - - List> _decode() { - try { - final decoded = jsonDecode(encoded); - if (decoded is! List) return const []; - return [ - for (final node in decoded) - if (node is Map) node, - ]; - } catch (_) { - return const []; - } - } - - Widget _node(BuildContext context, Map node) { - final type = node['type'] as String? ?? 'text'; - final text = node['text'] as String? ?? ''; - final title = node['title'] as String? ?? ''; - final url = node['url'] as String? ?? ''; - final children = _children(node); - switch (type) { - case 'emphasis': - return DefaultTextStyle.merge( - style: _emphasisStyle(node['style'] as String?), - child: Wrap( - crossAxisAlignment: WrapCrossAlignment.center, - children: [for (final child in children) _node(context, child)], - ), - ); - case 'code': - return Container( - padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHighest, - borderRadius: BorderRadius.circular(4), - ), - child: Text(text, style: const TextStyle(fontFamily: 'monospace')), - ); - case 'codeBlock': - final language = node['style'] as String? ?? ''; - return Container( - width: double.infinity, - margin: const EdgeInsets.symmetric(vertical: 6), - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.surfaceContainerHighest, - borderRadius: BorderRadius.circular(10), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (language.isNotEmpty) ...[ - Text( - language, - style: Theme.of(context).textTheme.labelSmall?.copyWith( - color: Theme.of(context).colorScheme.onSurfaceVariant, - fontFamily: 'monospace', - ), - ), - const SizedBox(height: 6), - ], - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: SelectableText.rich( - _highlightedCodeSpan(context, text, language), - ), - ), - ], - ), - ); - case 'quote': - return Container( - width: double.infinity, - margin: const EdgeInsets.symmetric(vertical: 4), - padding: const EdgeInsets.only(left: 12), - decoration: BoxDecoration( - border: Border( - left: BorderSide( - width: 3, - color: Theme.of(context).colorScheme.outlineVariant, - ), - ), - ), - child: DefaultTextStyle.merge( - style: const TextStyle(fontStyle: FontStyle.italic), - child: Wrap( - children: [for (final child in children) _node(context, child)], - ), - ), - ); - case 'nodeReference': - case 'tagReference': - final nodeUuid = node['uuid'] as String? ?? ''; - final label = type == 'tagReference' ? '#$title' : title; - final identifier = - 'link.${type == 'tagReference' ? 'tag' : 'node'}.$nodeUuid'; - final openNode = nodeUuid.isEmpty ? null : () => onOpenNode(nodeUuid); - return Semantics( - key: ValueKey(identifier), - identifier: identifier, - container: true, - link: true, - label: label, - onTap: openNode, - child: ExcludeSemantics( - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onTap: openNode, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 2), - child: Text( - label, - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - ), - ), - ), - ), - ), - ); - case 'link': - return Text( - children.isEmpty ? url : _plainText(children), - style: TextStyle( - color: Theme.of(context).colorScheme.primary, - decoration: TextDecoration.underline, - ), - ); - case 'youtubeTimestamp': - final seconds = int.tryParse(node['style'] as String? ?? ''); - return InkWell( - onTap: seconds == null || youtubeTargetUrl.isEmpty - ? null - : () => youtubePlayback.seek(youtubeTargetUrl, seconds), - child: SizedBox(width: double.infinity, child: Text('â—· $text')), - ); - case 'video': - return AndroidEmbeddedMedia( - url: url, - startSeconds: youtubePlayback.value[url], - ); - case 'iframe': - return AndroidEmbeddedMedia(url: url, isVideo: false); - case 'cloze': - return AndroidCloze(text: text); - case 'math': - return AndroidMath(expression: text); - default: - return Text(text); - } - } - - TextSpan _highlightedCodeSpan( - BuildContext context, - String code, - String language, - ) { - final brightness = Theme.of(context).brightness; - final baseStyle = Theme.of(context).textTheme.bodyMedium?.copyWith( - fontFamily: 'monospace', - color: Theme.of(context).colorScheme.onSurface, - height: 1.45, - ); - final normalizedLanguage = _normalizedCodeLanguage(language); - final cacheKey = '$normalizedLanguage\u0000$code'; - final nodes = - _syntaxNodeCache[cacheKey] ?? - () { - final parsed = - syntax.highlight - .parse(code, language: normalizedLanguage) - .nodes ?? - const []; - if (_syntaxNodeCache.length >= _syntaxNodeCacheLimit) { - _syntaxNodeCache.remove(_syntaxNodeCache.keys.first); - } - _syntaxNodeCache[cacheKey] = parsed; - return parsed; - }(); - - TextSpan span(syntax.Node node) { - final children = node.children; - return TextSpan( - text: node.value, - style: _syntaxStyle(node.className, brightness), - children: children == null - ? null - : [for (final child in children) span(child)], - ); - } - - return TextSpan( - style: baseStyle, - children: [for (final node in nodes) span(node)], - ); - } - - String _normalizedCodeLanguage(String language) => - switch (language.trim().toLowerCase()) { - 'clj' || 'cljs' || 'cljc' => 'clojure', - 'js' => 'javascript', - 'ts' => 'typescript', - 'sh' || 'zsh' => 'shell', - 'py' => 'python', - 'rb' => 'ruby', - 'yml' => 'yaml', - 'c#' => 'cs', - 'objective-c' || 'objc' => 'objectivec', - '' => 'plaintext', - final value => value, - }; - - TextStyle? _syntaxStyle(String? token, Brightness brightness) { - if (token == null) return null; - final dark = brightness == Brightness.dark; - final color = switch (token) { - 'comment' || - 'quote' => dark ? const Color(0xff8b949e) : const Color(0xff6e7781), - 'keyword' || - 'selector-tag' || - 'addition' => dark ? const Color(0xffff7b72) : const Color(0xffcf222e), - 'number' || 'literal' || 'variable' || 'template-variable' => - dark ? const Color(0xff79c0ff) : const Color(0xff0550ae), - 'string' || - 'doctag' || - 'regexp' => dark ? const Color(0xffa5d6ff) : const Color(0xff0a3069), - 'title' || 'section' || 'name' || 'selector-id' || 'selector-class' => - dark ? const Color(0xffd2a8ff) : const Color(0xff8250df), - 'type' || - 'class' || - 'built_in' || - 'builtin-name' || - 'attribute' => dark ? const Color(0xff7ee787) : const Color(0xff116329), - 'meta' || - 'symbol' || - 'bullet' || - 'link' => dark ? const Color(0xffffa657) : const Color(0xff953800), - 'deletion' => dark ? const Color(0xffff7b72) : const Color(0xffcf222e), - _ => null, - }; - if (color == null) return null; - return TextStyle( - color: color, - fontStyle: token == 'comment' ? FontStyle.italic : null, - fontWeight: token == 'keyword' ? FontWeight.w600 : null, - ); - } - - List> _children(Map node) { - final children = node['children']; - if (children is! List) return const []; - return [ - for (final child in children) - if (child is Map) child, - ]; - } - - String _plainText(List> nodes) => nodes.map((node) { - final type = node['type']; - if (type == 'nodeReference') return node['title'] as String? ?? ''; - if (type == 'tagReference') return '#${node['title'] as String? ?? ''}'; - final children = _children(node); - return children.isEmpty - ? (node['text'] as String? ?? node['url'] as String? ?? '') - : _plainText(children); - }).join(); - - TextStyle? _emphasisStyle(String? style) => switch (style) { - 'bold' => const TextStyle(fontWeight: FontWeight.bold), - 'italic' => const TextStyle(fontStyle: FontStyle.italic), - 'underline' => const TextStyle(decoration: TextDecoration.underline), - 'strikeThrough' => const TextStyle(decoration: TextDecoration.lineThrough), - _ => null, - }; -} - -final class _OutlinerEditor extends StatefulWidget { - const _OutlinerEditor({required this.context}); - - final LUIFlutterExtensionContext context; - - @override - State<_OutlinerEditor> createState() => _OutlinerEditorState(); -} - -final class _OutlinerEditorState extends State<_OutlinerEditor> { - static const _textChangeDelay = Duration(milliseconds: 80); - - late final TextEditingController _controller; - late String _observedText; - late String _previousText; - late String _modelTitle; - final _publishedTitles = []; - late int _modelCaret; - late TextSelection _observedSelection; - late TextSelection _previousSelection; - var _wasComposing = false; - var _applyingModel = false; - Timer? _textChangeTimer; - - @override - void initState() { - super.initState(); - _controller = TextEditingController( - text: widget.context.property('title')! as String, - ); - _restoreSelection(); - _observedText = _controller.text; - _previousText = _modelTitle = _controller.text; - _modelCaret = widget.context.property('caret-utf16-offset')! as int; - _previousSelection = _observedSelection = _controller.selection; - _controller.addListener(_observeController); - } - - @override - void didUpdateWidget(covariant _OutlinerEditor oldWidget) { - super.didUpdateWidget(oldWidget); - final title = widget.context.property('title')! as String; - final caret = widget.context.property('caret-utf16-offset')! as int; - final titleChanged = title != _modelTitle; - final caretChanged = caret != _modelCaret; - _modelTitle = title; - _modelCaret = caret; - // Model acknowledgements can arrive after another edit or caret movement. - final acknowledged = _publishedTitles.indexOf(title); - if (acknowledged >= 0) { - _publishedTitles.removeRange(0, acknowledged + 1); - return; - } - if (titleChanged || (caretChanged && _controller.text == title)) { - if (titleChanged) _publishedTitles.clear(); - _applyingModel = true; - try { - if (_controller.text != title) { - _textChangeTimer?.cancel(); - _controller.text = title; - } - _restoreSelection(); - _rememberControllerValue(); - } finally { - _applyingModel = false; - } - } - } - - void _restoreSelection() { - final requested = widget.context.property('caret-utf16-offset')! as int; - final offset = requested.clamp(0, _controller.text.length); - _controller.selection = TextSelection.collapsed(offset: offset); - } - - int get _caret { - final offset = _controller.selection.baseOffset; - return offset < 0 ? _controller.text.length : offset; - } - - void _observeController() { - if (_applyingModel) return; - final selection = _controller.selection; - final textChanged = _controller.text != _observedText; - final selectionChanged = selection != _observedSelection; - final composing = - _controller.value.isComposingRangeValid && - !_controller.value.composing.isCollapsed; - final committed = _wasComposing && !composing; - _wasComposing = composing; - if (textChanged) { - _previousText = _observedText; - _previousSelection = _observedSelection; - } - _rememberControllerValue(); - if (committed && !textChanged) _handleTextChanged(_controller.text); - if (!textChanged && selectionChanged && selection.baseOffset >= 0) { - widget.context.emit( - name: 'caret-change', - values: {'caret-utf16-offset': selection.baseOffset}, - ); - } - } - - void _rememberControllerValue() { - _observedText = _controller.text; - _observedSelection = _controller.selection; - } - - void _handleTextChanged(String title) { - if (_controller.value.isComposingRangeValid && - !_controller.value.composing.isCollapsed) { - _textChangeTimer?.cancel(); - return; - } - final newline = _caret - 1; - final singleInsertion = - title.length == _previousText.length + 1 && - newline >= 0 && - newline < title.length && - title[newline] == '\n' && - title.replaceRange(newline, newline + 1, '') == _previousText; - final replacedSelection = - _previousSelection.isValid && - !_previousSelection.isCollapsed && - _previousText.replaceRange( - _previousSelection.start, - _previousSelection.end, - '\n', - ) == - title; - if ((singleInsertion || replacedSelection) && - !HardwareKeyboard.instance.isShiftPressed) { - _textChangeTimer?.cancel(); - final submitted = title.replaceRange(newline, newline + 1, ''); - final caret = newline.clamp(0, submitted.length); - _applyingModel = true; - try { - _controller.value = TextEditingValue( - text: submitted, - selection: TextSelection.collapsed(offset: caret), - ); - _rememberControllerValue(); - } finally { - _applyingModel = false; - } - _publishedTitles.add(submitted); - widget.context.emit( - name: 'return', - values: {'title': submitted, 'caret-utf16-offset': caret}, - ); - return; - } - final caret = _caret; - _textChangeTimer?.cancel(); - _textChangeTimer = Timer(_textChangeDelay, () { - if (!mounted) return; - _publishedTitles.add(title); - widget.context.emit( - name: 'text-change', - values: {'title': title, 'caret-utf16-offset': caret}, - ); - }); - } - - KeyEventResult _handleKeyEvent(FocusNode _, KeyEvent event) { - if (event is! KeyDownEvent || - event.logicalKey != LogicalKeyboardKey.backspace) { - return KeyEventResult.ignored; - } - final selection = _controller.selection; - if (!selection.isValid || !selection.isCollapsed || selection.start != 0) { - return KeyEventResult.ignored; - } - _emitStructuralBackspace(); - return KeyEventResult.handled; - } - - void _emitStructuralBackspace() { - widget.context.emit( - name: 'backspace', - values: {'title': _controller.text, 'selection-length': 0}, - ); - } - - @override - Widget build(BuildContext context) { - final extension = widget.context; - final blockId = extension.property('block-id')! as String; - return Focus( - onKeyEvent: _handleKeyEvent, - child: Semantics( - key: ValueKey('outliner-editor-$blockId'), - identifier: 'field.outliner.block.$blockId', - child: TextField( - controller: _controller, - autofocus: true, - maxLines: null, - style: Theme.of(context).textTheme.bodyMedium, - textInputAction: TextInputAction.newline, - inputFormatters: [ - _StructuralBackspaceFormatter(_emitStructuralBackspace), - ], - decoration: const InputDecoration( - filled: false, - border: InputBorder.none, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - disabledBorder: InputBorder.none, - errorBorder: InputBorder.none, - focusedErrorBorder: InputBorder.none, - isDense: true, - isCollapsed: true, - contentPadding: EdgeInsets.zero, - ), - onChanged: _handleTextChanged, - onSubmitted: (title) => extension.emit( - name: 'return', - values: {'title': title, 'caret-utf16-offset': _caret}, - ), - ), - ), - ); - } - - @override - void dispose() { - _textChangeTimer?.cancel(); - _controller.dispose(); - super.dispose(); - } -} - -final class _StructuralBackspaceFormatter extends TextInputFormatter { - _StructuralBackspaceFormatter(this.onStructuralBackspace); - - final VoidCallback onStructuralBackspace; - - @override - TextEditingValue formatEditUpdate( - TextEditingValue oldValue, - TextEditingValue newValue, - ) { - if (oldValue.text == newValue.text && - oldValue.selection.isValid && - oldValue.selection.isCollapsed && - oldValue.selection.start == 0 && - newValue.selection == oldValue.selection) { - onStructuralBackspace(); - } - return newValue; - } -} diff --git a/flutter/lib/logseq_chat_icons.dart b/flutter/lib/logseq_chat_icons.dart deleted file mode 100644 index ae5e6513..00000000 --- a/flutter/lib/logseq_chat_icons.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:flutter/material.dart'; - -const logseqChatAppIcons = { - 'outliner-bullet': Icons.circle, - 'add': Icons.add_rounded, - 'arrow-up': Icons.arrow_upward_rounded, - 'arrow-down': Icons.arrow_downward_rounded, - 'calendar': Icons.calendar_month_outlined, - 'chevron-down': Icons.expand_more_rounded, - 'chevron-right': Icons.chevron_right_rounded, - 'close': Icons.close_rounded, - 'composer-add': Icons.add_circle_outline_rounded, - 'composer-file': Icons.attach_file_rounded, - 'composer-photo': Icons.photo_library_outlined, - 'disclosure-down': Icons.expand_more_rounded, - 'disclosure-right': Icons.chevron_right_rounded, - 'graph-locked': Icons.lock_outline_rounded, - 'document': Icons.article_outlined, - 'download': Icons.download_outlined, - 'flashcards': Icons.style_outlined, - 'folder': Icons.hub_outlined, - 'graph-local': Icons.storage_rounded, - 'graph-remote': Icons.cloud_outlined, - 'history': Icons.history_rounded, - 'logo': Icons.hub_rounded, - 'more-horiz': Icons.more_horiz_rounded, - 'more-vert': Icons.more_vert_rounded, - 'navigation-back': Icons.arrow_back_rounded, - 'open-external': Icons.open_in_new_rounded, - 'refresh': Icons.refresh_rounded, - 'search': Icons.search_rounded, - 'send': Icons.send_rounded, - 'selected': Icons.check_circle_rounded, - 'settings': Icons.settings_outlined, - 'share': Icons.share_outlined, - 'sidebar-toggle': Icons.menu_rounded, - 'sign-out': Icons.logout_rounded, - 'star': Icons.star_outline_rounded, - 'star-filled': Icons.star_rounded, - 'status-dot': Icons.circle, - 'sync-status': Icons.sync_rounded, - 'task-backlog': Icons.circle_outlined, - 'task-canceled': Icons.cancel_outlined, - 'task-doing': Icons.donut_large_rounded, - 'task-done': Icons.check_circle_outline_rounded, - 'task-review': Icons.mark_chat_read_outlined, - 'task-todo': Icons.radio_button_unchecked, - 'terminal': Icons.terminal_rounded, - 'toolbar-attachment': Icons.attach_file_rounded, - 'toolbar-audio': Icons.mic_none_rounded, - 'toolbar-camera': Icons.photo_camera_outlined, - 'toolbar-copy': Icons.content_copy_rounded, - 'toolbar-copy-reference': Icons.data_object_rounded, - 'toolbar-copy-url': Icons.link_rounded, - 'toolbar-delete': Icons.delete_outline_rounded, - 'toolbar-hide-keyboard': Icons.keyboard_hide_rounded, - 'toolbar-indent': Icons.format_indent_increase, - 'toolbar-move-down': Icons.arrow_downward_rounded, - 'toolbar-move-up': Icons.arrow_upward_rounded, - 'toolbar-outdent': Icons.format_indent_decrease, - 'toolbar-tag': Icons.tag_rounded, - 'toolbar-task': Icons.check_box_outlined, - 'toolbar-unselect': Icons.deselect_rounded, - 'trash': Icons.delete_outline_rounded, - 'unselected': Icons.radio_button_unchecked_rounded, - 'warning': Icons.warning_amber_rounded, -}; diff --git a/flutter/lib/logseq_chat_native_bridge.dart b/flutter/lib/logseq_chat_native_bridge.dart deleted file mode 100644 index 093a61b4..00000000 --- a/flutter/lib/logseq_chat_native_bridge.dart +++ /dev/null @@ -1,403 +0,0 @@ -import 'dart:ffi'; -import 'dart:isolate'; - -import 'package:ffi/ffi.dart'; -import 'package:flutter/foundation.dart'; - -import 'lui_dispatch.dart'; -import 'native_effect_drain.dart'; -import 'native_runtime_scheduler.dart'; - -typedef _NativeInitialize = Pointer Function(Int32, Int32, Int32); -typedef _DartInitialize = Pointer Function(int, int, int); -typedef _NativeNodeEvent = Pointer Function(Int64); -typedef _DartNodeEvent = Pointer Function(int); -typedef _NativeTextEvent = Pointer Function(Int64, Pointer); -typedef _DartTextEvent = Pointer Function(int, Pointer); -typedef _NativeToggleEvent = Pointer Function(Int64, Int32); -typedef _DartToggleEvent = Pointer Function(int, int); -typedef _NativeRangeEvent = Pointer Function(Int64, Int32, Int32); -typedef _DartRangeEvent = Pointer Function(int, int, int); -typedef _NativeScrollCompletedEvent = Pointer Function( - Int64, - Int32, - Pointer, -); -typedef _DartScrollCompletedEvent = Pointer Function( - int, - int, - Pointer, -); -typedef _NativeValueEvent = Pointer Function(Int64, Double); -typedef _DartValueEvent = Pointer Function(int, double); -typedef _NativeExtensionEvent = Pointer Function( - Int64, - Pointer, - Pointer, - Pointer, - Int64, -); -typedef _DartExtensionEvent = Pointer Function( - int, - Pointer, - Pointer, - Pointer, - int, -); -typedef _NativeRootNode = Int64 Function(); -typedef _DartRootNode = int Function(); -typedef _NativeNoArgument = Pointer Function(); -typedef _DartNoArgument = Pointer Function(); -typedef _NativeResolveEffect = Pointer Function( - Int64, - Int32, - Pointer, -); -typedef _DartResolveEffect = Pointer Function(int, int, Pointer); -typedef _NativeStringArgument = Pointer Function(Pointer); -typedef _DartStringArgument = Pointer Function(Pointer); -typedef _NativeTwoStringArguments = Pointer Function( - Pointer, - Pointer, -); -typedef _DartTwoStringArguments = Pointer Function( - Pointer, - Pointer, -); -typedef _NativeCoreCall = Pointer Function(Pointer); -typedef _DartCoreCall = Pointer Function(Pointer); - -final class LogseqChatNativeBridge - implements LogseqChatNativeDispatch, NativeEffectRuntime { - LogseqChatNativeBridge({required this.onPatch, DynamicLibrary? library}) - : _library = library ?? DynamicLibrary.open('liblogseq_chat_core.so'), - _runtimeScheduler = NativeRuntimeScheduler() { - _initialize = _library.lookupFunction<_NativeInitialize, _DartInitialize>( - 'logseq_chat_lui_initialize', - ); - _rootNode = _library.lookupFunction<_NativeRootNode, _DartRootNode>( - 'logseq_chat_lui_root_node', - ); - _appear = _nodeEvent('logseq_chat_lui_appear'); - _press = _nodeEvent('logseq_chat_lui_press'); - _longPress = _nodeEvent('logseq_chat_lui_long_press'); - _textChanged = _library.lookupFunction<_NativeTextEvent, _DartTextEvent>( - 'logseq_chat_lui_text_changed', - ); - _submit = _nodeEvent('logseq_chat_lui_submit'); - _toggleChanged = _library - .lookupFunction<_NativeToggleEvent, _DartToggleEvent>( - 'logseq_chat_lui_toggle_changed', - ); - _change = _nodeEvent('logseq_chat_lui_change'); - _valueChanged = _library.lookupFunction<_NativeValueEvent, _DartValueEvent>( - 'logseq_chat_lui_value_changed', - ); - _dismiss = _nodeEvent('logseq_chat_lui_dismiss'); - _doublePress = _nodeEvent('logseq_chat_lui_double_press'); - _picked = _library.lookupFunction<_NativeTextEvent, _DartTextEvent>( - 'logseq_chat_lui_picked', - ); - _visibleRange = _library.lookupFunction<_NativeRangeEvent, _DartRangeEvent>( - 'logseq_chat_lui_visible_range', - ); - _scrollCompleted = _library - .lookupFunction<_NativeScrollCompletedEvent, _DartScrollCompletedEvent>( - 'logseq_chat_lui_scroll_completed', - ); - _extensionEvent = _library - .lookupFunction<_NativeExtensionEvent, _DartExtensionEvent>( - 'logseq_chat_lui_extension_event', - ); - _dispose = _library.lookupFunction<_NativeNoArgument, _DartNoArgument>( - 'logseq_chat_lui_dispose', - ); - _takeEffect = _library.lookupFunction<_NativeNoArgument, _DartNoArgument>( - 'logseq_chat_lui_take_effect', - ); - _resolveEffect = _library - .lookupFunction<_NativeResolveEffect, _DartResolveEffect>( - 'logseq_chat_lui_resolve_effect', - ); - _applySnapshot = _library - .lookupFunction<_NativeStringArgument, _DartStringArgument>( - 'logseq_chat_lui_apply_snapshot', - ); - _applyHostUpdate = _library - .lookupFunction<_NativeTwoStringArguments, _DartTwoStringArguments>( - 'logseq_chat_lui_apply_host_update', - ); - } - - final void Function(String json) onPatch; - final DynamicLibrary _library; - final NativeRuntimeScheduler _runtimeScheduler; - late final _DartInitialize _initialize; - late final _DartRootNode _rootNode; - late final _DartNodeEvent _appear; - late final _DartNodeEvent _press; - late final _DartNodeEvent _longPress; - late final _DartTextEvent _textChanged; - late final _DartNodeEvent _submit; - late final _DartToggleEvent _toggleChanged; - late final _DartNodeEvent _change; - late final _DartValueEvent _valueChanged; - late final _DartNodeEvent _dismiss; - late final _DartNodeEvent _doublePress; - late final _DartTextEvent _picked; - late final _DartRangeEvent _visibleRange; - late final _DartScrollCompletedEvent _scrollCompleted; - late final _DartExtensionEvent _extensionEvent; - late final _DartNoArgument _dispose; - late final _DartNoArgument _takeEffect; - late final _DartResolveEffect _resolveEffect; - late final _DartStringArgument _applySnapshot; - late final _DartTwoStringArguments _applyHostUpdate; - - set onCoreIdle(void Function()? callback) { - _runtimeScheduler.onIdle = callback; - } - - _DartNodeEvent _nodeEvent(String symbol) => - _library.lookupFunction<_NativeNodeEvent, _DartNodeEvent>(symbol); - - int initialize({int authenticationCode = 1}) { - _apply(_initialize(3, 3, authenticationCode)); - return _rootNode(); - } - - @override - void appear(int node) => _runtimeScheduler.runUi(() => _apply(_appear(node))); - - @override - void press(int node) => _runtimeScheduler.runUi(() => _apply(_press(node))); - - @override - void longPress(int node) => - _runtimeScheduler.runUi(() => _apply(_longPress(node))); - - @override - void textChanged(int node, String text) { - _runtimeScheduler.runUi(() { - final nativeText = text.toNativeUtf8(); - try { - _apply(_textChanged(node, nativeText)); - } finally { - malloc.free(nativeText); - } - }); - } - - @override - void submit(int node) => _runtimeScheduler.runUi(() => _apply(_submit(node))); - - @override - void toggleChanged(int node, bool checked) => _runtimeScheduler.runUi( - () => _apply(_toggleChanged(node, checked ? 1 : 0)), - ); - - @override - void change(int node) => _runtimeScheduler.runUi(() => _apply(_change(node))); - - @override - void valueChanged(int node, double value) => - _runtimeScheduler.runUi(() => _apply(_valueChanged(node, value))); - - @override - void dismiss(int node) => - _runtimeScheduler.runUi(() => _apply(_dismiss(node))); - - @override - void doublePress(int node) => - _runtimeScheduler.runUi(() => _apply(_doublePress(node))); - - @override - void picked(int node, String payload) { - _runtimeScheduler.runUi(() { - final nativePayload = payload.toNativeUtf8(); - try { - _apply(_picked(node, nativePayload)); - } finally { - malloc.free(nativePayload); - } - }); - } - - @override - void visibleRange(int node, int first, int last) => - _runtimeScheduler.runUi(() => _apply(_visibleRange(node, first, last))); - - @override - void scrollCompleted(int node, int token, String outcome) { - _runtimeScheduler.runUi(() { - final nativeOutcome = outcome.toNativeUtf8(); - try { - _apply(_scrollCompleted(node, token, nativeOutcome)); - } finally { - malloc.free(nativeOutcome); - } - }); - } - - @override - void extensionEvent( - int node, - String identifier, - String name, - String text, - int value, - ) { - _runtimeScheduler.runUi(() { - final nativeIdentifier = identifier.toNativeUtf8(); - final nativeName = name.toNativeUtf8(); - final nativeText = text.toNativeUtf8(); - try { - _apply( - _extensionEvent( - node, - nativeIdentifier, - nativeName, - nativeText, - value, - ), - ); - } finally { - malloc.free(nativeIdentifier); - malloc.free(nativeName); - malloc.free(nativeText); - } - }); - } - - void close() => _runtimeScheduler.runUi(() => _apply(_dispose())); - - @override - String takeEffect() => - _runtimeScheduler.isCoreBusy ? '' : _read(_takeEffect()); - - @override - String resolveEffect({ - required int id, - required bool succeeded, - required String message, - }) { - if (_runtimeScheduler.isCoreBusy) { - debugPrint('[NativeBridge] resolveEffect id=$id queued (core busy)'); - _runtimeScheduler.runUi( - () => _apply( - _resolveEffectWithMessage( - id: id, - succeeded: succeeded, - message: message, - ), - ), - ); - return ''; - } - debugPrint('[NativeBridge] resolveEffect id=$id call'); - final result = _read( - _resolveEffectWithMessage(id: id, succeeded: succeeded, message: message), - ); - debugPrint( - '[NativeBridge] resolveEffect id=$id returned chars=${result.length}', - ); - return result; - } - - Pointer _resolveEffectWithMessage({ - required int id, - required bool succeeded, - required String message, - }) { - final nativeMessage = message.toNativeUtf8(); - try { - return _resolveEffect(id, succeeded ? 1 : 0, nativeMessage); - } finally { - malloc.free(nativeMessage); - } - } - - @override - String applySnapshot(String response) { - if (_runtimeScheduler.isCoreBusy) { - debugPrint( - '[NativeBridge] applySnapshot queued (core busy) ' - 'chars=${response.length}', - ); - _runtimeScheduler.runUi( - () => _apply(_applySnapshotWithResponse(response)), - ); - return ''; - } - debugPrint('[NativeBridge] applySnapshot call chars=${response.length}'); - final result = _read(_applySnapshotWithResponse(response)); - debugPrint('[NativeBridge] applySnapshot returned chars=${result.length}'); - return result; - } - - Pointer _applySnapshotWithResponse(String response) { - final nativeResponse = response.toNativeUtf8(); - try { - return _applySnapshot(nativeResponse); - } finally { - malloc.free(nativeResponse); - } - } - - @override - String applyHostUpdate({required String kind, required String payload}) { - if (_runtimeScheduler.isCoreBusy) { - debugPrint( - '[NativeBridge] applyHostUpdate kind=$kind queued (core busy)', - ); - _runtimeScheduler.runUi( - () => _apply(_applyHostUpdateWithPayload(kind, payload)), - ); - return ''; - } - debugPrint('[NativeBridge] applyHostUpdate kind=$kind call'); - final result = _read(_applyHostUpdateWithPayload(kind, payload)); - debugPrint( - '[NativeBridge] applyHostUpdate kind=$kind returned ' - 'chars=${result.length}', - ); - return result; - } - - Pointer _applyHostUpdateWithPayload(String kind, String payload) { - final nativeKind = kind.toNativeUtf8(); - final nativePayload = payload.toNativeUtf8(); - try { - return _applyHostUpdate(nativeKind, nativePayload); - } finally { - malloc.free(nativeKind); - malloc.free(nativePayload); - } - } - - Future callCore(String request) => _runtimeScheduler.runCore( - () => Isolate.run(() => _callCoreInWorker(request)), - ); - - void _apply(Pointer pointer) { - final patch = _read(pointer); - if (patch.isNotEmpty) onPatch(patch); - } - - String _read(Pointer pointer) => - pointer == nullptr ? '' : pointer.toDartString(); -} - -String _callCoreInWorker(String request) { - final library = DynamicLibrary.open('liblogseq_chat_core.so'); - final call = library.lookupFunction<_NativeCoreCall, _DartCoreCall>( - 'logseq_chat_call', - ); - final nativeRequest = request.toNativeUtf8(); - try { - final response = call(nativeRequest); - return response == nullptr ? '' : response.toDartString(); - } finally { - malloc.free(nativeRequest); - } -} diff --git a/flutter/lib/logseq_chat_theme.dart b/flutter/lib/logseq_chat_theme.dart deleted file mode 100644 index 6f62f87c..00000000 --- a/flutter/lib/logseq_chat_theme.dart +++ /dev/null @@ -1,223 +0,0 @@ -import 'package:flutter/material.dart'; - -ThemeMode logseqChatThemeMode(String appearance) => switch (appearance) { - 'light' => ThemeMode.light, - 'dark' => ThemeMode.dark, - _ => ThemeMode.system, -}; - -abstract final class LogseqChatTheme { - static const accent = Color(0xff2d6cdf); - static const _lightSurface = Color(0xfff8f9ff); - static const _darkSurface = Color(0xff101318); - - static ThemeData light() => _theme(Brightness.light); - - static ThemeData dark() => _theme(Brightness.dark); - - static ThemeData _theme(Brightness brightness) { - final dark = brightness == Brightness.dark; - final seededScheme = ColorScheme.fromSeed( - seedColor: accent, - brightness: brightness, - surface: dark ? _darkSurface : _lightSurface, - dynamicSchemeVariant: DynamicSchemeVariant.fidelity, - contrastLevel: 0.05, - ); - final scheme = seededScheme.copyWith( - secondaryContainer: seededScheme.surfaceContainerHighest, - onSecondaryContainer: seededScheme.onSurface, - ); - final baseTypography = Typography.material2021( - platform: TargetPlatform.android, - colorScheme: scheme, - ); - final baseTextTheme = dark ? baseTypography.white : baseTypography.black; - final textTheme = baseTextTheme.copyWith( - displayLarge: baseTextTheme.displayLarge?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: -1.5, - ), - headlineLarge: baseTextTheme.headlineLarge?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: -0.6, - ), - headlineMedium: baseTextTheme.headlineMedium?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: -0.35, - ), - titleLarge: baseTextTheme.titleLarge?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: -0.2, - ), - titleMedium: baseTextTheme.titleMedium?.copyWith( - fontWeight: FontWeight.w600, - ), - bodyLarge: baseTextTheme.bodyLarge?.copyWith(height: 1.45), - bodyMedium: baseTextTheme.bodyMedium?.copyWith(height: 1.42), - labelLarge: baseTextTheme.labelLarge?.copyWith( - fontWeight: FontWeight.w600, - letterSpacing: 0.1, - ), - ); - const pill = StadiumBorder(); - const controlPadding = EdgeInsets.symmetric(horizontal: 20, vertical: 12); - final fieldBorder = OutlineInputBorder( - borderRadius: BorderRadius.circular(20), - borderSide: BorderSide.none, - ); - return ThemeData( - useMaterial3: true, - brightness: brightness, - colorScheme: scheme, - textTheme: textTheme, - scaffoldBackgroundColor: scheme.surface, - materialTapTargetSize: MaterialTapTargetSize.padded, - visualDensity: VisualDensity.standard, - splashFactory: InkSparkle.splashFactory, - appBarTheme: AppBarTheme( - elevation: 0, - scrolledUnderElevation: 0, - centerTitle: false, - backgroundColor: scheme.surface, - foregroundColor: scheme.onSurface, - surfaceTintColor: Colors.transparent, - titleTextStyle: textTheme.titleLarge?.copyWith(color: scheme.onSurface), - ), - filledButtonTheme: FilledButtonThemeData( - style: FilledButton.styleFrom( - minimumSize: const Size(64, 48), - padding: controlPadding, - shape: pill, - textStyle: textTheme.labelLarge, - ), - ), - outlinedButtonTheme: OutlinedButtonThemeData( - style: OutlinedButton.styleFrom( - minimumSize: const Size(64, 48), - padding: controlPadding, - shape: pill, - side: BorderSide(color: scheme.outlineVariant), - textStyle: textTheme.labelLarge, - ), - ), - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - foregroundColor: scheme.onSurface, - disabledForegroundColor: scheme.onSurface.withValues(alpha: 0.38), - minimumSize: const Size(48, 48), - padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), - shape: pill, - textStyle: textTheme.labelLarge, - ), - ), - iconButtonTheme: IconButtonThemeData( - style: IconButton.styleFrom( - minimumSize: const Size.square(48), - maximumSize: const Size.square(48), - iconSize: 22, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16), - ), - ), - ), - inputDecorationTheme: InputDecorationTheme( - filled: true, - fillColor: scheme.surfaceContainerHighest, - border: fieldBorder, - enabledBorder: fieldBorder, - focusedBorder: fieldBorder.copyWith( - borderSide: BorderSide(color: scheme.primary, width: 2), - ), - errorBorder: fieldBorder.copyWith( - borderSide: BorderSide(color: scheme.error, width: 1.5), - ), - focusedErrorBorder: fieldBorder.copyWith( - borderSide: BorderSide(color: scheme.error, width: 2), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 18, - vertical: 16, - ), - ), - drawerTheme: DrawerThemeData( - width: 320, - elevation: 0, - backgroundColor: scheme.surfaceContainerLow, - surfaceTintColor: Colors.transparent, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.horizontal(right: Radius.circular(28)), - ), - ), - navigationDrawerTheme: NavigationDrawerThemeData( - backgroundColor: scheme.surfaceContainerLow, - surfaceTintColor: Colors.transparent, - elevation: 0, - indicatorColor: scheme.secondaryContainer, - indicatorShape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(18), - ), - labelTextStyle: WidgetStateProperty.resolveWith( - (states) => textTheme.labelLarge?.copyWith( - color: states.contains(WidgetState.selected) - ? scheme.onSecondaryContainer - : scheme.onSurfaceVariant, - ), - ), - ), - bottomSheetTheme: BottomSheetThemeData( - elevation: 0, - modalElevation: 1, - backgroundColor: scheme.surfaceContainerLow, - modalBackgroundColor: scheme.surfaceContainerLow, - surfaceTintColor: Colors.transparent, - showDragHandle: true, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(28)), - ), - ), - cardTheme: CardThemeData( - elevation: 0, - color: scheme.surfaceContainerLow, - surfaceTintColor: Colors.transparent, - margin: EdgeInsets.zero, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), - ), - dialogTheme: DialogThemeData( - elevation: 0, - backgroundColor: scheme.surfaceContainerHigh, - surfaceTintColor: Colors.transparent, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(28)), - ), - popupMenuTheme: PopupMenuThemeData( - elevation: 2, - color: scheme.surfaceContainer, - surfaceTintColor: Colors.transparent, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - ), - listTileTheme: ListTileThemeData( - minTileHeight: 52, - minVerticalPadding: 8, - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)), - iconColor: scheme.onSurfaceVariant, - textColor: scheme.onSurface, - selectedColor: scheme.onSecondaryContainer, - selectedTileColor: scheme.secondaryContainer, - ), - dividerTheme: DividerThemeData( - color: scheme.outlineVariant, - thickness: 1, - space: 1, - ), - snackBarTheme: SnackBarThemeData( - behavior: SnackBarBehavior.floating, - backgroundColor: scheme.inverseSurface, - contentTextStyle: textTheme.bodyMedium?.copyWith( - color: scheme.onInverseSurface, - ), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)), - ), - ); - } -} diff --git a/flutter/lib/lui_dispatch.dart b/flutter/lib/lui_dispatch.dart deleted file mode 100644 index ab06762b..00000000 --- a/flutter/lib/lui_dispatch.dart +++ /dev/null @@ -1,89 +0,0 @@ -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -abstract interface class LogseqChatNativeDispatch { - void appear(int node); - void press(int node); - void longPress(int node); - void textChanged(int node, String text); - void submit(int node); - void toggleChanged(int node, bool checked); - void change(int node); - void valueChanged(int node, double value); - void dismiss(int node); - void picked(int node, String payload); - void scrollCompleted(int node, int token, String outcome); - void visibleRange(int node, int first, int last); - void doublePress(int node); - void extensionEvent( - int node, - String identifier, - String name, - String text, - int value, - ); -} - -void dispatchLUIEvent(LUIEvent event, LogseqChatNativeDispatch native) { - switch (event) { - case LUIAppearEvent(:final node): - native.appear(node); - case LUIPressEvent(:final node): - native.press(node); - case LUILongPressEvent(:final node): - native.longPress(node); - case LUITextChangedEvent(:final node, :final text): - native.textChanged(node, text); - case LUISubmitEvent(:final node): - native.submit(node); - case LUIToggleChangedEvent(:final node, :final checked): - native.toggleChanged(node, checked); - case LUIChangeEvent(:final node): - native.change(node); - case LUIValueChangedEvent(:final node, :final value): - native.valueChanged(node, value); - case LUIDismissEvent(:final node): - native.dismiss(node); - case LUIPickedEvent(:final node, :final payload): - native.picked(node, payload); - case LUIScrollCompletedEvent(:final node, :final token, :final outcome): - native.scrollCompleted(node, token, outcome); - case LUIVisibleRangeEvent(:final node, :final first, :final last): - native.visibleRange(node, first, last); - case LUIDoublePressEvent(:final node): - native.doublePress(node); - case LUIExtensionComponentEvent( - :final node, - :final identifier, - :final name, - :final values, - ): - native.extensionEvent( - node, - identifier, - name, - _extensionText(values), - _extensionValue(values), - ); - } -} - -String _extensionText(Map values) { - for (final key in const ['uuid', 'title', 'query', 'value']) { - final value = values[key]; - if (value is String) return value; - } - return ''; -} - -int _extensionValue(Map values) { - for (final key in const ['caret-utf16-offset', 'selection-length', 'count']) { - final value = values[key]; - if (value is int) return value; - } - return switch (values['placement']) { - 'before' => 0, - 'inside' => 1, - 'after' => 2, - _ => 0, - }; -} diff --git a/flutter/lib/main.dart b/flutter/lib/main.dart deleted file mode 100644 index cd1c0217..00000000 --- a/flutter/lib/main.dart +++ /dev/null @@ -1,752 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -import 'android_platform_effects.dart'; -import 'android_imported_asset.dart'; -import 'android_app_entry.dart'; -import 'android_audio_recording.dart'; -import 'android_outliner_commands.dart'; -import 'android_graph_lifecycle.dart'; -import 'core_bootstrap.dart'; -import 'core_effect_executor.dart'; -import 'flutter_patch_applier.dart'; -import 'graph_catalog_auto_refresh.dart'; -import 'graph_catalog_polling_policy.dart'; -import 'logseq_chat_extensions.dart'; -import 'logseq_chat_icons.dart'; -import 'logseq_chat_app_frame.dart'; -import 'logseq_chat_native_bridge.dart'; -import 'logseq_chat_theme.dart'; -import 'lui_dispatch.dart'; -import 'native_effect_drain.dart'; - -final Stopwatch _startupClock = Stopwatch()..start(); - -void _traceStartup(String message) { - debugPrint('[Startup] +${_startupClock.elapsedMilliseconds}ms $message'); -} - -void main() { - _traceStartup('main entered'); - WidgetsFlutterBinding.ensureInitialized(); - unawaited( - SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge).then((_) { - SystemChrome.setSystemUIOverlayStyle( - const SystemUiOverlayStyle( - statusBarColor: Colors.transparent, - systemNavigationBarColor: Colors.transparent, - systemNavigationBarDividerColor: Colors.transparent, - systemNavigationBarContrastEnforced: false, - statusBarBrightness: Brightness.dark, - statusBarIconBrightness: Brightness.dark, - ), - ); - }), - ); - _traceStartup('Flutter binding initialized'); - runApp(const LogseqChatFlutterApp()); - _traceStartup('runApp returned'); -} - -class LogseqChatFlutterApp extends StatefulWidget { - const LogseqChatFlutterApp({super.key}); - - @override - State createState() => _LogseqChatFlutterAppState(); -} - -class _LogseqChatFlutterAppState extends State - with WidgetsBindingObserver { - final _navigatorKey = GlobalKey(); - final _messengerKey = GlobalKey(); - late final LUIFlutterBackend _backend; - late final FlutterPatchApplier _patchApplier; - LogseqChatNativeBridge? _bridge; - NativeEffectDrain? _effectDrain; - CoreEffectExecutor? _coreEffects; - GraphCatalogAutoRefresh? _graphCatalogAutoRefresh; - Future? _activeBootstrap; - var _activeBootstrapHasStoredSession = false; - var _hasAuthenticatedSession = false; - var _hasOpenGraph = false; - var _appIsForeground = true; - late final AndroidPlatformEffects _platformEffects; - late final AndroidAppEntryCoordinator _appEntries; - final _audioRecording = const MethodChannelAndroidAudioRecordingBackend(); - late final OutlinerPlatformCommandDispatcher _outlinerCommands; - int? _rootNode; - Object? _startupError; - ThemeMode _themeMode = ThemeMode.system; - - @override - void initState() { - super.initState(); - _traceStartup('app state init started'); - WidgetsBinding.instance.addObserver(this); - _platformEffects = AndroidPlatformEffects( - authentication: MethodChannelAndroidAuthentication(), - ); - _appEntries = AndroidAppEntryCoordinator( - entries: const EventChannelAndroidAppEntrySource().entries, - handle: _handleAppEntry, - onError: _reportEffectError, - )..start(); - _logRuntime( - level: 'info', - source: 'ui', - message: 'Flutter host initialized', - ); - _backend = LUIFlutterBackend( - onEvent: _dispatch, - extensionRegistry: logseqChatExtensionRegistry( - resolveAssetPath: _platformEffects.platform.resolveAssetPath, - ), - appIcons: logseqChatAppIcons, - filePathResolver: _platformEffects.platform.resolveAssetPath, - ); - _patchApplier = FlutterPatchApplier(_backend); - final commandHandler = AndroidOutlinerPlatformCommandHandler( - navigatorKey: _navigatorKey, - platform: _platformEffects.platform, - sendOutlinerEvent: _sendOutlinerEvent, - presentAttachment: _presentAttachment, - presentAudioRecording: _presentAudioRecording, - ); - _outlinerCommands = OutlinerPlatformCommandDispatcher( - commandHandler.handle, - ); - WidgetsBinding.instance.addPostFrameCallback((_) { - _traceStartup('first Flutter frame completed'); - }); - _traceStartup('app state init completed; starting host bootstrap'); - unawaited(_start()); - } - - Future _start() async { - try { - _traceStartup('platform startup state requested'); - final authenticationFuture = _platformEffects.initialAuthenticationCode(); - final storageFuture = _platformEffects.platform.loadStorageState(); - final authenticationCode = await authenticationFuture; - final storage = await storageFuture; - _traceStartup('platform startup state loaded'); - if (!mounted) return; - _themeMode = logseqChatThemeMode(storage.settings.appearance); - _traceStartup('native bridge loading started'); - final bridge = LogseqChatNativeBridge(onPatch: _applyPatch); - _traceStartup('native bridge loaded'); - _bridge = bridge; - final graphLifecycle = AndroidGraphLifecycle( - callCore: bridge.callCore, - platform: _platformEffects.platform, - accessTokenProvider: _platformEffects.restoreAccessToken, - trace: _traceGraphLifecycle, - ); - _coreEffects = CoreEffectExecutor( - callCore: bridge.callCore, - executePlatformEffect: _platformEffects.execute, - executeGraphEffect: graphLifecycle.execute, - ); - _graphCatalogAutoRefresh = GraphCatalogAutoRefresh( - callCore: bridge.callCore, - applyCoreResponse: _applyCoreResponse, - trace: (message) => _traceGraphCatalogRefresh('automatic $message'), - ); - final effectDrain = NativeEffectDrain( - runtime: bridge, - execute: _executeEffect, - applyPatch: _applyPatch, - afterCoreResponseApplied: _outlinerCommands.deliver, - onError: _reportEffectError, - trace: _traceNativeEffect, - ); - _effectDrain = effectDrain; - bridge.onCoreIdle = () { - final drain = _effectDrain; - if (drain != null) unawaited(drain.drain()); - }; - _traceStartup('LUI initialization started'); - final rootNode = bridge.initialize( - authenticationCode: authenticationCode, - ); - _traceStartup('LUI initialization completed'); - for (final update in storage.startupHostUpdates) { - _applyPatch( - bridge.applyHostUpdate(kind: update.kind, payload: update.payload), - ); - } - setState(() => _rootNode = rootNode); - _traceStartup('LUI root mounted'); - unawaited(effectDrain.drain()); - unawaited( - _restoreCore( - hasStoredSession: authenticationCode == 3, - storage: storage, - ), - ); - } catch (error, stack) { - if (mounted) setState(() => _startupError = error); - FlutterError.reportError( - FlutterErrorDetails( - exception: error, - stack: stack, - library: 'Logseq Chat Flutter host', - context: ErrorDescription('while starting the native LG runtime'), - ), - ); - } - } - - void _dispatch(LUIEvent event) { - final bridge = _bridge; - if (bridge == null) return; - switch (event) { - case LUIPressEvent(:final node): - debugPrint('[LUIEvent] press node=$node'); - case LUISubmitEvent(:final node): - debugPrint('[LUIEvent] submit node=$node'); - case LUIToggleChangedEvent(:final node, :final checked): - debugPrint('[LUIEvent] toggle node=$node checked=$checked'); - case LUIDismissEvent(:final node): - debugPrint('[LUIEvent] dismiss node=$node'); - case LUIExtensionComponentEvent( - :final node, - :final identifier, - :final name, - ): - debugPrint( - '[LUIEvent] extension node=$node component=$identifier name=$name', - ); - default: - break; - } - dispatchLUIEvent(event, bridge); - final effectDrain = _effectDrain; - if (effectDrain != null) unawaited(effectDrain.drain()); - } - - Future _executeEffect(NativeEffect effect) async { - if (effect.kind == 'present-attachment') { - try { - if (effect.text == 'audio') { - await _presentAudioRecording(null); - } else { - await _presentAttachment(effect.text, null); - } - return const NativeEffectResolution.discard(); - } catch (error, stack) { - _reportEffectError(error, stack); - return NativeEffectResolution.discard( - succeeded: false, - message: error.toString(), - ); - } - } - final coreEffects = _coreEffects; - if (coreEffects == null) { - return const NativeEffectResolution.discard( - succeeded: false, - message: 'The native core effect executor is unavailable', - ); - } - final resolution = await coreEffects.execute(effect); - if (effect.kind == 'save-settings' && resolution.succeeded) { - final settings = jsonDecode(effect.text); - if (settings is Map) { - final nextThemeMode = logseqChatThemeMode( - settings['appearance'] as String? ?? 'system', - ); - if (mounted && nextThemeMode != _themeMode) { - setState(() => _themeMode = nextThemeMode); - } - } - } - if (effect.kind == 'sign-in' && resolution.succeeded) { - await _restoreCore(hasStoredSession: true); - } - if (effect.kind == 'sign-out' && resolution.succeeded) { - _hasAuthenticatedSession = false; - _hasOpenGraph = false; - _graphCatalogAutoRefresh?.stopPeriodic(); - } - if (resolution.succeeded && - (effect.kind == 'open-graph' || - effect.kind == 'unlock-graph' || - effect.kind == 'create-graph')) { - _hasOpenGraph = true; - _graphCatalogAutoRefresh?.stopPeriodic(); - } - return resolution; - } - - Future _restoreCore({ - required bool hasStoredSession, - AndroidStorageState? storage, - }) { - final active = _activeBootstrap; - if (active != null) { - if (hasStoredSession && !_activeBootstrapHasStoredSession) { - return active.then((_) => _restoreCore(hasStoredSession: true)); - } - return active; - } - late final Future operation; - operation = - _runCoreRestore( - hasStoredSession: hasStoredSession, - storage: storage, - ).whenComplete(() { - if (identical(_activeBootstrap, operation)) _activeBootstrap = null; - }); - _activeBootstrap = operation; - _activeBootstrapHasStoredSession = hasStoredSession; - return operation; - } - - Future _runCoreRestore({ - required bool hasStoredSession, - AndroidStorageState? storage, - }) async { - final bridge = _bridge; - if (bridge == null) return; - var accessToken = ''; - if (hasStoredSession) { - try { - accessToken = (await _platformEffects.restoreAccessToken()) ?? ''; - if (accessToken.trim().isEmpty) { - throw StateError('The stored session did not return an access token'); - } - } catch (error, stack) { - _hasAuthenticatedSession = false; - _applyPatch( - bridge.applyHostUpdate( - kind: 'authentication', - payload: jsonEncode({ - 'state': 'signedOut', - 'errorMessage': error.toString(), - }), - ), - ); - _reportEffectError(error, stack); - } - } - _hasAuthenticatedSession = accessToken.trim().isNotEmpty; - try { - _logRuntime( - level: 'info', - source: 'core', - message: 'Restoring core state', - ); - final state = await _platformEffects.coreStartupState( - accessToken: accessToken, - storage: storage, - ); - final restored = await CoreBootstrap( - callCore: bridge.callCore, - trace: (message) => _traceGraphLifecycle('bootstrap $message'), - ).restore(state); - await _applyCoreResponse(restored.catalogResponse); - _graphCatalogAutoRefresh?.rememberCatalog(restored.catalogResponse); - _applyPatch( - bridge.applyHostUpdate( - kind: 'local-graph-ids', - payload: jsonEncode(restored.localGraphIds), - ), - ); - final graphResponse = restored.graphResponse; - _hasOpenGraph = graphResponse != null; - if (graphResponse != null) { - await _applyCoreResponse(graphResponse); - } - _applyPatch( - bridge.applyHostUpdate(kind: 'graph-loading', payload: 'false'), - ); - _logRuntime( - level: 'info', - source: 'core', - message: 'Core state restored', - ); - await _appEntries.markReady(); - if (shouldPollGraphCatalog( - authenticated: _hasAuthenticatedSession, - hasOpenGraph: _hasOpenGraph, - foreground: _appIsForeground, - )) { - _graphCatalogAutoRefresh?.startPeriodic(); - unawaited(_refreshGraphCatalog(reason: 'restore')); - } else { - _graphCatalogAutoRefresh?.stopPeriodic(); - } - } catch (error, stack) { - _logRuntime(level: 'error', source: 'core', message: error.toString()); - _reportEffectError(error, stack); - _applyPatch( - bridge.applyHostUpdate(kind: 'graph-loading', payload: 'false'), - ); - } - } - - Future _refreshGraphCatalog({required String reason}) async { - final refresher = _graphCatalogAutoRefresh; - if (refresher == null || - !shouldPollGraphCatalog( - authenticated: _hasAuthenticatedSession, - hasOpenGraph: _hasOpenGraph, - foreground: _appIsForeground, - )) { - return; - } - try { - _traceGraphCatalogRefresh('$reason requested'); - final refreshed = await refresher.refresh(); - if (!refreshed) { - _traceGraphCatalogRefresh('$reason rejected'); - } - } catch (error, stack) { - _traceGraphCatalogRefresh('$reason failed error=$error'); - _reportEffectError(error, stack); - } - } - - @override - void didChangeAppLifecycleState(AppLifecycleState state) { - _appIsForeground = state == AppLifecycleState.resumed; - if (shouldPollGraphCatalog( - authenticated: _hasAuthenticatedSession, - hasOpenGraph: _hasOpenGraph, - foreground: _appIsForeground, - )) { - _graphCatalogAutoRefresh?.startPeriodic(); - unawaited(_refreshGraphCatalog(reason: 'resume')); - } else { - _graphCatalogAutoRefresh?.stopPeriodic(); - } - } - - void _applyPatch(String patch) { - if (patch.isEmpty) return; - try { - _patchApplier.applyJson(patch); - } catch (error, stack) { - _reportEffectError(error, stack); - if (mounted) setState(() => _startupError = error); - } - } - - Future _applyCoreResponse(String response) async { - final bridge = _bridge; - if (bridge == null) return; - _applyPatch(bridge.applySnapshot(response)); - await _outlinerCommands.deliver(response); - } - - Future _sendOutlinerEvent(Map event) async { - final bridge = _bridge; - if (bridge == null) return; - final response = await bridge.callCore( - jsonEncode({ - 'apiVersion': 1, - 'method': 'dispatch', - 'params': {'action': 'outlinerEvent', 'payload': jsonEncode(event)}, - }), - ); - await _applyCoreResponse(response); - } - - Future _presentAudioRecording(String? targetBlockId) async { - final context = _navigatorKey.currentContext; - if (context == null) { - throw StateError('Audio recording requires an active Android screen'); - } - final recording = await showAndroidAudioRecordingSheet( - context: context, - backend: _audioRecording, - ); - if (recording == null) return; - final asset = recording.asset; - final bridge = _bridge; - if (bridge == null) { - throw StateError('The native core is unavailable for recorded audio'); - } - final response = await bridge.callCore( - jsonEncode(asset.coreRequest(targetBlockId: targetBlockId)), - ); - final decoded = jsonDecode(response); - if (decoded is! Map || decoded['ok'] != true) { - throw StateError('The native core rejected the recorded audio asset'); - } - await _applyCoreResponse(response); - if (recording.transcriptionEnabled) { - unawaited(_transcribeRecording(asset)); - } - } - - Future _transcribeRecording(RecordedAudioAsset asset) async { - try { - _logRuntime( - level: 'info', - source: 'ui', - message: 'Audio transcription started', - ); - final transcript = (await _audioRecording.transcribe(asset.localPath)) - .trim(); - if (transcript.isEmpty) return; - final bridge = _bridge; - if (bridge == null) return; - final response = await bridge.callCore( - jsonEncode( - asset.transcriptCoreRequest( - transcriptUuid: '${asset.uuid}-transcript', - transcript: transcript, - ), - ), - ); - await _applyCoreResponse(response); - _logRuntime( - level: 'info', - source: 'ui', - message: 'Audio transcription completed', - ); - } catch (error, stack) { - _reportEffectError(error, stack); - } - } - - Future _presentAttachment(String kind, String? targetBlockId) async { - debugPrint( - '[AttachmentImport] requesting kind=$kind target=${targetBlockId ?? "composer"}', - ); - _logRuntime( - level: 'info', - source: 'ui', - message: 'Requesting $kind attachment', - ); - final assets = await _platformEffects.platform.importAttachments(kind); - debugPrint('[AttachmentImport] received count=${assets.length} kind=$kind'); - _logRuntime( - level: 'info', - source: 'ui', - message: 'Imported ${assets.length} $kind attachment(s)', - ); - for (final asset in assets) { - await _addImportedAsset(asset, targetBlockId: targetBlockId); - } - } - - Future _addImportedAsset( - AndroidImportedAsset asset, { - required String? targetBlockId, - }) async { - final bridge = _bridge; - if (bridge == null) { - throw StateError('The native core is unavailable for imported assets'); - } - final response = await bridge.callCore( - jsonEncode(asset.coreRequest(targetBlockId: targetBlockId)), - ); - final decoded = jsonDecode(response); - if (decoded is! Map || decoded['ok'] != true) { - throw StateError('The native core rejected ${asset.title}'); - } - debugPrint( - '[AttachmentImport] added title=${asset.title} ' - 'target=${targetBlockId ?? "composer"} responseBytes=${response.length} ' - 'containsAsset=${response.contains(asset.uuid)}', - ); - _logRuntime( - level: 'info', - source: 'core', - message: 'Added attachment ${asset.title}', - ); - await _applyCoreResponse(response); - } - - Future _handleAppEntry(AndroidAppEntry entry) async { - final bridge = _bridge; - if (bridge == null) { - throw StateError( - 'The native core is unavailable for an Android app entry', - ); - } - debugPrint('[AppEntry] handling kind=${entry.kind.name}'); - _logRuntime( - level: 'info', - source: 'ui', - message: 'Handling Android app entry ${entry.kind.name}', - ); - switch (entry.kind) { - case AndroidAppEntryKind.openCapture: - _applyPatch( - bridge.applyHostUpdate(kind: 'open-capture', payload: '{}'), - ); - case AndroidAppEntryKind.openJournal: - await _applyAppEntryCoreRequest({ - 'apiVersion': 1, - 'method': 'dispatch', - 'params': {'action': 'clearSelectedPage'}, - }); - case AndroidAppEntryKind.sharedText: - await _applyAppEntryCoreRequest( - entry.coreRequest( - uuid: newCoreUuid(), - nowMilliseconds: DateTime.now().millisecondsSinceEpoch, - ), - ); - case AndroidAppEntryKind.sharedAsset: - await _addImportedAsset(entry.asset!, targetBlockId: null); - } - debugPrint('[AppEntry] completed kind=${entry.kind.name}'); - } - - Future _applyAppEntryCoreRequest(Map request) async { - final bridge = _bridge; - if (bridge == null) { - throw StateError( - 'The native core is unavailable for an Android app entry', - ); - } - final response = await bridge.callCore(jsonEncode(request)); - final decoded = jsonDecode(response); - if (decoded is! Map || decoded['ok'] != true) { - throw StateError('The native core rejected the Android app entry'); - } - await _applyCoreResponse(response); - } - - void _reportEffectError(Object error, StackTrace stack) { - _logRuntime(level: 'error', source: 'ui', message: error.toString()); - _messengerKey.currentState - ?..hideCurrentSnackBar() - ..showSnackBar( - SnackBar( - behavior: SnackBarBehavior.floating, - content: Text('Something went wrong: $error'), - ), - ); - FlutterError.reportError( - FlutterErrorDetails( - exception: error, - stack: stack, - library: 'Logseq Chat Flutter host', - context: ErrorDescription('while executing a native LG effect'), - ), - ); - } - - void _traceNativeEffect(String message) { - if (!message.contains('kind=open-graph') && - !message.contains('kind=create-graph') && - !message.contains('kind=unlock-graph') && - !message.contains('kind=refresh-graphs') && - !message.contains('kind=send-capture') && - !message.contains('kind=send-task') && - !message.contains('kind=search-nodes') && - !message.contains('patch')) { - return; - } - debugPrint('[NativeEffect] $message'); - _logRuntime(level: 'info', source: 'ui', message: message); - } - - void _traceGraphLifecycle(String message) { - debugPrint('[GraphLifecycle] $message'); - _logRuntime(level: 'info', source: 'core', message: message); - } - - void _traceGraphCatalogRefresh(String message) { - debugPrint('[GraphCatalog] $message'); - _logRuntime(level: 'info', source: 'core', message: message); - } - - void _logRuntime({ - required String level, - required String source, - required String message, - }) { - unawaited( - _platformEffects.platform.appendRuntimeLog( - level: level, - source: source, - message: message, - ), - ); - } - - @override - Widget build(BuildContext context) { - return MaterialApp( - navigatorKey: _navigatorKey, - scaffoldMessengerKey: _messengerKey, - debugShowCheckedModeBanner: false, - title: 'Logseq Chat', - theme: LogseqChatTheme.light(), - darkTheme: LogseqChatTheme.dark(), - themeMode: _themeMode, - home: LogseqChatAppFrame(child: _content()), - ); - } - - Widget _content() { - if (_startupError != null) { - return SafeArea( - child: Center( - child: Padding( - padding: const EdgeInsets.all(24), - child: Column( - mainAxisSize: MainAxisSize.min, - spacing: 16, - children: [ - Icon( - Icons.error_outline_rounded, - size: 48, - color: Theme.of(context).colorScheme.error, - ), - Text( - 'Could not start Logseq Chat', - style: Theme.of(context).textTheme.titleMedium, - ), - Text( - '$_startupError', - style: Theme.of(context).textTheme.bodySmall, - ), - FilledButton( - onPressed: () { - setState(() => _startupError = null); - unawaited(_start()); - }, - child: const Text('Retry'), - ), - ], - ), - ), - ), - ); - } - final rootNode = _rootNode; - if (rootNode != null && rootNode >= 0) { - return ListenableBuilder( - listenable: _patchApplier, - builder: (context, child) => - SizedBox.expand(child: _backend.widget(node: rootNode)), - ); - } - return const SizedBox.expand(); - } - - @override - void dispose() { - _graphCatalogAutoRefresh?.stopPeriodic(); - WidgetsBinding.instance.removeObserver(this); - unawaited(_appEntries.dispose()); - _effectDrain?.dispose(); - _bridge?.onCoreIdle = null; - _bridge?.close(); - _patchApplier.dispose(); - _backend.dispose(); - super.dispose(); - } -} diff --git a/flutter/lib/native_effect_drain.dart b/flutter/lib/native_effect_drain.dart deleted file mode 100644 index 5bdc83ab..00000000 --- a/flutter/lib/native_effect_drain.dart +++ /dev/null @@ -1,339 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -abstract interface class NativeEffectRuntime { - String takeEffect(); - - String resolveEffect({ - required int id, - required bool succeeded, - required String message, - }); - - String applySnapshot(String response); - - String applyHostUpdate({required String kind, required String payload}); -} - -final class NativeEffect { - const NativeEffect({ - required this.id, - required this.kind, - required this.text, - this.uuid, - this.value, - this.metadata, - }); - - final int id; - final String kind; - final String text; - final String? uuid; - final int? value; - final String? metadata; -} - -enum NativeEffectOutputKind { coreResponse, hostUpdate, discard } - -final class NativeEffectResolution { - const NativeEffectResolution({ - required this.succeeded, - required this.message, - required this.output, - this.hostUpdateKind, - }); - - const NativeEffectResolution.coreResponse(String response) - : succeeded = true, - message = response, - output = NativeEffectOutputKind.coreResponse, - hostUpdateKind = null; - - const NativeEffectResolution.hostUpdate({ - required String kind, - required String payload, - }) : succeeded = true, - message = payload, - output = NativeEffectOutputKind.hostUpdate, - hostUpdateKind = kind; - - const NativeEffectResolution.discard({ - this.succeeded = true, - this.message = '', - }) : output = NativeEffectOutputKind.discard, - hostUpdateKind = null; - - final bool succeeded; - final String message; - final NativeEffectOutputKind output; - final String? hostUpdateKind; -} - -typedef NativeEffectExecutor = Future Function( - NativeEffect effect, -); -typedef CoreResponseApplied = Future Function(String response); -typedef NativeEffectTrace = void Function(String message); - -void _ignoreNativeEffectTrace(String message) {} - -final class NativeEffectDrain { - NativeEffectDrain({ - required this.runtime, - required this.execute, - required this.applyPatch, - required this.onError, - this.trace = _ignoreNativeEffectTrace, - this.afterCoreResponseApplied, - this.outlinerAutosaveDelay = const Duration(seconds: 1), - }); - - final NativeEffectRuntime runtime; - final NativeEffectExecutor execute; - final void Function(String patch) applyPatch; - final void Function(Object error, StackTrace stackTrace) onError; - final NativeEffectTrace trace; - final CoreResponseApplied? afterCoreResponseApplied; - final Duration outlinerAutosaveDelay; - Future? _activeDrain; - Timer? _outlinerAutosaveTimer; - var _outlinerAutosavePending = false; - var _disposed = false; - - Future drain() { - if (_disposed) return Future.value(); - final active = _activeDrain; - if (active != null) return active; - - late final Future operation; - operation = _run().whenComplete(() { - if (identical(_activeDrain, operation)) _activeDrain = null; - }); - _activeDrain = operation; - return operation; - } - - Future _run() async { - while (true) { - final encoded = runtime.takeEffect(); - if (encoded.isEmpty) { - if (_outlinerAutosavePending) { - _outlinerAutosavePending = false; - await _executeOutlinerAutosave(); - continue; - } - return; - } - - final _EffectDispatch dispatch; - try { - dispatch = _EffectDispatch.decode(encoded); - } catch (error, stackTrace) { - onError(error, stackTrace); - return; - } - - _apply(dispatch.patch, 'dispatch kind=${dispatch.effect.kind}'); - _cancelOutlinerAutosaveBeforeExecuting(dispatch.effect); - final stopwatch = Stopwatch()..start(); - trace('start id=${dispatch.effect.id} kind=${dispatch.effect.kind}'); - final resolution = await execute(dispatch.effect); - stopwatch.stop(); - trace( - 'finish id=${dispatch.effect.id} kind=${dispatch.effect.kind} ' - 'succeeded=${resolution.succeeded} output=${resolution.output.name} ' - 'elapsedMs=${stopwatch.elapsedMilliseconds} ' - '${_resolutionSummary(dispatch.effect, resolution)}', - ); - if (resolution.succeeded) { - switch (resolution.output) { - case NativeEffectOutputKind.coreResponse: - _apply(runtime.applySnapshot(resolution.message), 'applySnapshot'); - await afterCoreResponseApplied?.call(resolution.message); - _scheduleOutlinerAutosaveIfNeeded( - dispatch.effect, - resolution.message, - ); - break; - case NativeEffectOutputKind.hostUpdate: - _apply( - runtime.applyHostUpdate( - kind: resolution.hostUpdateKind!, - payload: resolution.message, - ), - 'applyHostUpdate kind=${resolution.hostUpdateKind}', - ); - break; - case NativeEffectOutputKind.discard: - break; - } - } - _apply( - runtime.resolveEffect( - id: dispatch.effect.id, - succeeded: resolution.succeeded, - message: resolution.message, - ), - 'resolveEffect id=${dispatch.effect.id} ' - 'succeeded=${resolution.succeeded}', - ); - } - } - - void dispose() { - _disposed = true; - _outlinerAutosaveTimer?.cancel(); - _outlinerAutosaveTimer = null; - _outlinerAutosavePending = false; - } - - void _cancelOutlinerAutosaveBeforeExecuting(NativeEffect effect) { - if (!effect.kind.contains('outliner') || - effect.kind == 'move-outliner-caret') { - return; - } - _outlinerAutosaveTimer?.cancel(); - _outlinerAutosaveTimer = null; - _outlinerAutosavePending = false; - } - - void _scheduleOutlinerAutosaveIfNeeded(NativeEffect effect, String response) { - final shouldSchedule = switch (effect.kind) { - 'choose-outliner-autocomplete' => true, - 'change-outliner-text' => !_responseHasOutlinerAutocomplete(response), - _ => false, - }; - if (!shouldSchedule || _disposed) return; - _outlinerAutosaveTimer?.cancel(); - _outlinerAutosaveTimer = Timer(outlinerAutosaveDelay, () { - _outlinerAutosaveTimer = null; - if (_disposed) return; - _outlinerAutosavePending = true; - unawaited(drain()); - }); - } - - bool _responseHasOutlinerAutocomplete(String response) { - try { - final envelope = jsonDecode(response); - if (envelope is! Map) return false; - final result = envelope['result']; - if (result is! Map) return false; - final state = result['outlinerState']; - return state is Map && state['autocomplete'] != null; - } on FormatException { - return false; - } - } - - Future _executeOutlinerAutosave() async { - try { - final resolution = await execute( - const NativeEffect(id: 0, kind: 'save-outliner-editing', text: ''), - ); - if (!resolution.succeeded) { - throw StateError('Outliner autosave failed: ${resolution.message}'); - } - if (resolution.output != NativeEffectOutputKind.coreResponse) { - throw StateError('Outliner autosave did not return a core response'); - } - _apply( - runtime.applySnapshot(resolution.message), - 'applySnapshot(outliner-autosave)', - ); - await afterCoreResponseApplied?.call(resolution.message); - } catch (error, stackTrace) { - onError(error, stackTrace); - } - } - - void _apply(String patch, String source) { - if (patch.isNotEmpty) { - trace('applying patch from $source chars=${patch.length}'); - applyPatch(patch); - trace('applied patch from $source'); - } else { - // An OCaml exception in a lui_* FFI call surfaces as an empty patch — - // log the producer so a wedged pipeline is visible in the drain trace. - trace('empty patch from $source'); - } - } - - String _singleLine(String message) => message.replaceAll('\n', r'\n'); - - String _resolutionSummary( - NativeEffect effect, - NativeEffectResolution resolution, - ) { - if (resolution.succeeded) { - if (effect.kind == 'search-nodes' && - resolution.output == NativeEffectOutputKind.coreResponse) { - try { - final envelope = jsonDecode(resolution.message); - final result = envelope is Map - ? envelope['result'] - : null; - if (result is Map) { - final query = result['searchQuery']; - final results = result['searchResults']; - return 'messageChars=${resolution.message.length} ' - 'searchQueryChars=${query is String ? query.length : -1} ' - 'searchResults=${results is List ? results.length : -1}'; - } - } on FormatException { - // The normal response validation reports malformed JSON elsewhere. - } - } - return 'messageChars=${resolution.message.length}'; - } - final message = _singleLine(resolution.message); - const limit = 240; - return 'message=${message.length <= limit ? message : '${message.substring(0, limit)}…'}'; - } -} - -final class _EffectDispatch { - const _EffectDispatch({required this.effect, required this.patch}); - - factory _EffectDispatch.decode(String encoded) { - final decoded = jsonDecode(encoded); - if (decoded is! Map) { - throw const FormatException('Effect dispatch must be an object'); - } - final effectValue = decoded['effect']; - final patch = decoded['patch']; - if (effectValue is! Map || patch is! String) { - throw const FormatException('Effect dispatch is missing effect or patch'); - } - - final id = effectValue['id']; - final kind = effectValue['kind']; - final text = effectValue['text']; - final uuid = effectValue['uuid']; - final value = effectValue['value']; - final metadata = effectValue['metadata']; - if (id is! int || kind is! String || text is! String) { - throw const FormatException('Effect contains invalid required values'); - } - if (uuid != null && uuid is! String || - value != null && value is! int || - metadata != null && metadata is! String) { - throw const FormatException('Effect contains invalid optional values'); - } - - return _EffectDispatch( - effect: NativeEffect( - id: id, - kind: kind, - text: text, - uuid: uuid as String?, - value: value as int?, - metadata: metadata as String?, - ), - patch: patch, - ); - } - - final NativeEffect effect; - final String patch; -} diff --git a/flutter/lib/native_runtime_scheduler.dart b/flutter/lib/native_runtime_scheduler.dart deleted file mode 100644 index cf776f63..00000000 --- a/flutter/lib/native_runtime_scheduler.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:async'; -import 'dart:collection'; - -typedef NativeRuntimeIdleCallback = void Function(); - -final class NativeRuntimeScheduler { - NativeRuntimeScheduler({this.onIdle}); - - NativeRuntimeIdleCallback? onIdle; - - final Queue _deferredUiCalls = Queue(); - Future _coreTail = Future.value(); - var _pendingCoreCalls = 0; - - bool get isCoreBusy => _pendingCoreCalls > 0; - - Future runCore(Future Function() operation) { - final result = Completer(); - _pendingCoreCalls += 1; - _coreTail = _coreTail.then((_) async { - try { - result.complete(await operation()); - } catch (error, stackTrace) { - result.completeError(error, stackTrace); - } finally { - _pendingCoreCalls -= 1; - if (_pendingCoreCalls == 0) { - _flushUiCalls(); - onIdle?.call(); - } - } - }); - return result.future; - } - - void runUi(void Function() operation) { - if (isCoreBusy) { - _deferredUiCalls.addLast(operation); - return; - } - operation(); - } - - void _flushUiCalls() { - while (_deferredUiCalls.isNotEmpty) { - _deferredUiCalls.removeFirst()(); - } - } -} diff --git a/flutter/pubspec.lock b/flutter/pubspec.lock deleted file mode 100644 index 3fae3b19..00000000 --- a/flutter/pubspec.lock +++ /dev/null @@ -1,398 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - args: - dependency: transitive - description: - name: args - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" - source: hosted - version: "2.7.0" - async: - dependency: transitive - description: - name: async - sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 - url: "https://pub.dev" - source: hosted - version: "2.13.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" - source: hosted - version: "2.1.2" - characters: - dependency: transitive - description: - name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b - url: "https://pub.dev" - source: hosted - version: "1.4.1" - clock: - dependency: transitive - description: - name: clock - sha256: e51d50bca3217c9a9fa2b41a30e4a38971133f5f9ec7a3d57bae095007f1d28e - url: "https://pub.dev" - source: hosted - version: "1.1.3" - collection: - dependency: transitive - description: - name: collection - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" - source: hosted - version: "1.19.1" - fake_async: - dependency: transitive - description: - name: fake_async - sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" - url: "https://pub.dev" - source: hosted - version: "1.3.3" - ffi: - dependency: "direct main" - description: - name: ffi - sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" - url: "https://pub.dev" - source: hosted - version: "2.2.0" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_lints: - dependency: "direct dev" - description: - name: flutter_lints - sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" - url: "https://pub.dev" - source: hosted - version: "6.0.0" - flutter_math_fork: - dependency: "direct main" - description: - name: flutter_math_fork - sha256: "6d5f2f1aa57ae539ffb0a04bb39d2da67af74601d685a161aff7ce5bda5fa407" - url: "https://pub.dev" - source: hosted - version: "0.7.4" - flutter_svg: - dependency: transitive - description: - name: flutter_svg - sha256: "35882981abcbfb8c15b286f0cd690ff25bac12d95eff3e25ee207f37d4c42e7f" - url: "https://pub.dev" - source: hosted - version: "2.3.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - highlighter: - dependency: "direct main" - description: - name: highlighter - sha256: "92180c72b9da8758e1acf39a45aa305a97dcfe2fdc8f3d1d2947c23f2772bfbc" - url: "https://pub.dev" - source: hosted - version: "0.1.1" - http: - dependency: transitive - description: - name: http - sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" - url: "https://pub.dev" - source: hosted - version: "1.6.0" - http_parser: - dependency: transitive - description: - name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" - url: "https://pub.dev" - source: hosted - version: "4.1.2" - leak_tracker: - dependency: transitive - description: - name: leak_tracker - sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" - url: "https://pub.dev" - source: hosted - version: "11.0.2" - leak_tracker_flutter_testing: - dependency: transitive - description: - name: leak_tracker_flutter_testing - sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" - url: "https://pub.dev" - source: hosted - version: "3.0.10" - leak_tracker_testing: - dependency: transitive - description: - name: leak_tracker_testing - sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" - url: "https://pub.dev" - source: hosted - version: "3.0.2" - lints: - dependency: transitive - description: - name: lints - sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" - url: "https://pub.dev" - source: hosted - version: "6.1.0" - lui_flutter_backend: - dependency: "direct main" - description: - path: "platform/flutter" - ref: "1db993d4e2eaa2ec844620e374c736829798a2d0" - resolved-ref: "1db993d4e2eaa2ec844620e374c736829798a2d0" - url: "ssh://git@github.com/logseq/lui.git" - source: git - version: "0.1.0" - matcher: - dependency: transitive - description: - name: matcher - sha256: "31bd099b47c10cd1aeb55146a2d46ce0277630ecef3f7dae54ad7873f36696cd" - url: "https://pub.dev" - source: hosted - version: "0.12.20" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" - url: "https://pub.dev" - source: hosted - version: "0.13.0" - meta: - dependency: transitive - description: - name: meta - sha256: c82594181e3312f3d0695fc95aaaf7758d75b8d4ae2bbecf223b9fd5109a059d - url: "https://pub.dev" - source: hosted - version: "1.18.3" - nested: - dependency: transitive - description: - name: nested - sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" - source: hosted - version: "1.0.0" - path: - dependency: transitive - description: - name: path - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" - source: hosted - version: "1.9.1" - path_parsing: - dependency: transitive - description: - name: path_parsing - sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" - url: "https://pub.dev" - source: hosted - version: "1.1.0" - petitparser: - dependency: transitive - description: - name: petitparser - sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" - url: "https://pub.dev" - source: hosted - version: "7.0.2" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" - source: hosted - version: "2.1.8" - provider: - dependency: transitive - description: - name: provider - sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" - url: "https://pub.dev" - source: hosted - version: "6.1.5+1" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.0" - source_span: - dependency: transitive - description: - name: source_span - sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" - url: "https://pub.dev" - source: hosted - version: "1.10.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - sha256: "277654b3034d17ac6f9f1cb5595db011b1d5d41e8806866db28e0abaa101c490" - url: "https://pub.dev" - source: hosted - version: "1.12.2" - stream_channel: - dependency: transitive - description: - name: stream_channel - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" - source: hosted - version: "2.1.4" - string_scanner: - dependency: transitive - description: - name: string_scanner - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" - source: hosted - version: "1.4.1" - term_glyph: - dependency: transitive - description: - name: term_glyph - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" - source: hosted - version: "1.2.2" - test_api: - dependency: transitive - description: - name: test_api - sha256: "2a122cbe059f8b610d3a5415f42e255b6c17b1f21eee1d960f31080237fb4f11" - url: "https://pub.dev" - source: hosted - version: "0.7.12" - tuple: - dependency: transitive - description: - name: tuple - sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 - url: "https://pub.dev" - source: hosted - version: "2.0.2" - typed_data: - dependency: transitive - description: - name: typed_data - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" - source: hosted - version: "1.4.0" - vector_graphics: - dependency: transitive - description: - name: vector_graphics - sha256: "9d0e3b9cb16542ad660daee871e726a10d13a93b7b5391677c3160e8f5e83935" - url: "https://pub.dev" - source: hosted - version: "1.2.3" - vector_graphics_codec: - dependency: transitive - description: - name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" - url: "https://pub.dev" - source: hosted - version: "1.1.13" - vector_graphics_compiler: - dependency: transitive - description: - name: vector_graphics_compiler - sha256: "4dca4feb77dc3ec7f6e27e49c53241eb8217f55e4f9b12599a27f8903bca5682" - url: "https://pub.dev" - source: hosted - version: "1.3.0" - vector_math: - dependency: transitive - description: - name: vector_math - sha256: "1d774bbdf6b72a0b12122fc1560c9c2d2a67db5a4a4cc2bd8a5c990ab20e3188" - url: "https://pub.dev" - source: hosted - version: "2.4.0" - vm_service: - dependency: transitive - description: - name: vm_service - sha256: "5f37239c4851efcef929cea7824e76df7f2f0970aef85d66bbc430afa40e72f0" - url: "https://pub.dev" - source: hosted - version: "15.3.0" - web: - dependency: transitive - description: - name: web - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" - source: hosted - version: "1.1.1" - webview_flutter: - dependency: "direct main" - description: - name: webview_flutter - sha256: d53e1ccf5516f25017e3c9d44c39034db352d20fa34fe200674270242c2c5111 - url: "https://pub.dev" - source: hosted - version: "4.14.1" - webview_flutter_android: - dependency: transitive - description: - name: webview_flutter_android - sha256: "4de8b3d1ff4ebe1bdb42e68a5e4f809194a3cb0117a8f495f590004f00da3964" - url: "https://pub.dev" - source: hosted - version: "4.14.1" - webview_flutter_platform_interface: - dependency: transitive - description: - name: webview_flutter_platform_interface - sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04" - url: "https://pub.dev" - source: hosted - version: "2.15.1" - webview_flutter_wkwebview: - dependency: transitive - description: - name: webview_flutter_wkwebview - sha256: fe359c7fac1002124b5b9e2ba3a41906bbb9b2d029ccb4a0067404d8f3704730 - url: "https://pub.dev" - source: hosted - version: "3.26.1" - xml: - dependency: transitive - description: - name: xml - sha256: "67f0aff7be013d107995e9b75bf4e7f2c3ef2dfdb2c8e68024bba0a7fd5756a4" - url: "https://pub.dev" - source: hosted - version: "7.0.1" -sdks: - dart: ">=3.13.1 <4.0.0" - flutter: ">=3.44.0" diff --git a/flutter/pubspec.yaml b/flutter/pubspec.yaml deleted file mode 100644 index bc6e84fc..00000000 --- a/flutter/pubspec.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: logseq_chat_flutter -description: Native Material Android host for the shared Logseq Chat LG runtime. -publish_to: none -version: 1.0.0+1 - -environment: - sdk: ^3.13.1 - -dependencies: - ffi: ^2.1.4 - flutter: - sdk: flutter - flutter_math_fork: ^0.7.4 - highlighter: ^0.1.1 - lui_flutter_backend: - git: - url: ssh://git@github.com/logseq/lui.git - ref: 1db993d4e2eaa2ec844620e374c736829798a2d0 - path: platform/flutter - webview_flutter: ^4.14.1 - -dev_dependencies: - flutter_lints: ^6.0.0 - flutter_test: - sdk: flutter - -flutter: - uses-material-design: true diff --git a/flutter/test/android_app_entry_test.dart b/flutter/test/android_app_entry_test.dart deleted file mode 100644 index 41973d6e..00000000 --- a/flutter/test/android_app_entry_test.dart +++ /dev/null @@ -1,92 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_app_entry.dart'; - -void main() { - test('parses supported Android app entries', () { - expect( - AndroidAppEntry.fromMap(const {'kind': 'open-capture'}).kind, - AndroidAppEntryKind.openCapture, - ); - expect( - AndroidAppEntry.fromMap(const {'kind': 'open-journal'}).kind, - AndroidAppEntryKind.openJournal, - ); - final shared = AndroidAppEntry.fromMap(const { - 'kind': 'shared-text', - 'text': 'A shared note', - }); - expect(shared.kind, AndroidAppEntryKind.sharedText); - expect(shared.text, 'A shared note'); - expect(shared.coreRequest(uuid: 'capture-id', nowMilliseconds: 42), { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'send', - 'payload': '{"text":"A shared note","uuid":"capture-id","now":42}', - }, - }); - }); - - test('rejects malformed app entries', () { - expect( - () => AndroidAppEntry.fromMap(const {'kind': 'shared-text', 'text': ''}), - throwsFormatException, - ); - expect( - () => AndroidAppEntry.fromMap(const {'kind': 'unknown'}), - throwsFormatException, - ); - }); - - test('queues cold-start entries until core restore is ready', () async { - final stream = StreamController>(sync: true); - addTearDown(stream.close); - final handled = []; - final coordinator = AndroidAppEntryCoordinator( - entries: stream.stream, - handle: (entry) async => handled.add(entry.kind), - )..start(); - addTearDown(coordinator.dispose); - - stream.add(const {'kind': 'open-capture'}); - stream.add(const {'kind': 'open-journal'}); - await Future.delayed(Duration.zero); - expect(handled, isEmpty); - - await coordinator.markReady(); - expect(handled, [ - AndroidAppEntryKind.openCapture, - AndroidAppEntryKind.openJournal, - ]); - - stream.add(const {'kind': 'shared-text', 'text': 'Warm share'}); - await coordinator.settled; - expect(handled.last, AndroidAppEntryKind.sharedText); - }); - - test('retains a failed entry for a later retry', () async { - final stream = StreamController>(sync: true); - addTearDown(stream.close); - var attempts = 0; - final errors = []; - final coordinator = AndroidAppEntryCoordinator( - entries: stream.stream, - handle: (_) async { - attempts += 1; - if (attempts == 1) throw StateError('core is restoring'); - }, - onError: (error, _) => errors.add(error), - )..start(); - addTearDown(coordinator.dispose); - - stream.add(const {'kind': 'shared-text', 'text': 'Retain me'}); - await coordinator.markReady(); - expect(attempts, 1); - expect(errors, hasLength(1)); - - await coordinator.markReady(); - expect(attempts, 2); - }); -} diff --git a/flutter/test/android_audio_playback_native_contract_test.dart b/flutter/test/android_audio_playback_native_contract_test.dart deleted file mode 100644 index 0b15ae5a..00000000 --- a/flutter/test/android_audio_playback_native_contract_test.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('Android host provides native MediaPlayer playback methods', () { - final player = File( - 'android/app/src/main/kotlin/com/logseq/chat/AndroidAudioPlayer.kt', - ).readAsStringSync(); - final activity = File( - 'android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt', - ).readAsStringSync(); - - expect(player, contains('MediaPlayer')); - expect(player, contains('fun start(path: String)')); - expect(player, contains('fun pause(sessionId: Int)')); - expect(player, contains('fun resume(sessionId: Int)')); - expect(player, contains('fun status(sessionId: Int)')); - expect(player, contains('fun stop(sessionId: Int)')); - expect(activity, contains('"startAudioPlayback"')); - expect(activity, contains('"pauseAudioPlayback"')); - expect(activity, contains('"resumeAudioPlayback"')); - expect(activity, contains('"audioPlaybackStatus"')); - expect(activity, contains('"stopAudioPlayback"')); - }); - - test('audio finalization stays off the Android main thread', () { - final activity = File( - 'android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt', - ).readAsStringSync(); - - expect( - activity, - contains( - '"stopAudioRecording" -> withContext(Dispatchers.IO) {\n' - ' audioRecorder.stop()\n' - ' }', - ), - ); - }); -} diff --git a/flutter/test/android_audio_playback_test.dart b/flutter/test/android_audio_playback_test.dart deleted file mode 100644 index a0ce4abb..00000000 --- a/flutter/test/android_audio_playback_test.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_audio_playback.dart'; - -void main() { - test('recognizes Android audio assets by MIME type or extension', () { - expect(isAndroidAudioAsset('audio/mp4', ''), isTrue); - expect(isAndroidAudioAsset('m4a', ''), isTrue); - expect(isAndroidAudioAsset('', '/tmp/Voice.WAV'), isTrue); - expect(isAndroidAudioAsset('image/jpeg', '/tmp/photo.jpg'), isFalse); - }); - - testWidgets('plays, pauses, and stops an inline audio asset', (tester) async { - final backend = _FakeAudioPlaybackBackend(); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: AndroidAudioPlayer( - title: 'Voice note.m4a', - path: '/tmp/voice.m4a', - backend: backend, - ), - ), - ), - ); - - expect(find.byKey(const ValueKey('player.asset.audio')), findsOneWidget); - expect(find.text('Play audio'), findsOneWidget); - - await tester.tap(find.byKey(const ValueKey('button.audio.play-pause'))); - await tester.pump(); - expect(backend.startedPaths, ['/tmp/voice.m4a']); - expect(find.text('Pause audio'), findsOneWidget); - - await tester.tap(find.byKey(const ValueKey('button.audio.play-pause'))); - await tester.pump(); - expect(backend.pausedSessions, [41]); - expect(find.text('Play audio'), findsOneWidget); - - await tester.pumpWidget(const SizedBox.shrink()); - await tester.pump(); - expect(backend.stoppedSessions, [41]); - }); - - testWidgets('shows playback failures without getting stuck', (tester) async { - final backend = _FakeAudioPlaybackBackend( - startError: Exception('bad file'), - ); - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: AndroidAudioPlayer( - title: 'Broken audio', - path: '/tmp/broken.m4a', - backend: backend, - ), - ), - ), - ); - - await tester.tap(find.byKey(const ValueKey('button.audio.play-pause'))); - await tester.pump(); - - expect(find.text('Could not play audio'), findsOneWidget); - expect(find.text('Play audio'), findsOneWidget); - }); -} - -final class _FakeAudioPlaybackBackend implements AndroidAudioPlaybackBackend { - _FakeAudioPlaybackBackend({this.startError}); - - final Object? startError; - final List startedPaths = []; - final List pausedSessions = []; - final List stoppedSessions = []; - - @override - Future start(String path) async { - startedPaths.add(path); - if (startError case final error?) throw error; - return const AndroidAudioPlaybackSession( - id: 41, - duration: Duration(seconds: 4), - ); - } - - @override - Future pause(int sessionId) async => pausedSessions.add(sessionId); - - @override - Future resume(int sessionId) async {} - - @override - Future status(int sessionId) async => - const AndroidAudioPlaybackStatus( - isActive: true, - isPlaying: true, - position: Duration(seconds: 1), - duration: Duration(seconds: 4), - ); - - @override - Future stop(int sessionId) async => stoppedSessions.add(sessionId); -} diff --git a/flutter/test/android_audio_recording_test.dart b/flutter/test/android_audio_recording_test.dart deleted file mode 100644 index 808af433..00000000 --- a/flutter/test/android_audio_recording_test.dart +++ /dev/null @@ -1,264 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_audio_recording.dart'; - -void main() { - const asset = RecordedAudioAsset( - uuid: 'asset-a', - title: 'Audio-2026-09-01 11-10-00.m4a', - assetType: 'm4a', - size: 2048, - checksum: 'abc123', - localPath: '/data/user/0/com.logseq.chat/files/Assets/Audio.m4a', - ); - - test('encodes a recorded asset through the authoritative core action', () { - expect(asset.coreRequest(targetBlockId: 'block-a'), { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'addAsset', - 'payload': jsonEncode({ - 'uuid': 'asset-a', - 'title': 'Audio-2026-09-01 11-10-00.m4a', - 'assetType': 'm4a', - 'assetSize': 2048, - 'assetChecksum': 'abc123', - 'localPath': '/data/user/0/com.logseq.chat/files/Assets/Audio.m4a', - 'targetBlockId': 'block-a', - }), - }, - }); - final payload = jsonDecode( - ((asset.coreRequest()['params']! as Map)['payload']! - as String), - ) as Map; - expect(payload, isNot(contains('targetBlockId'))); - }); - - test('encodes a transcript as a child of the recorded asset', () { - expect( - asset.transcriptCoreRequest( - transcriptUuid: 'transcript-a', - transcript: 'Recorded words', - ), - { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'addChildBlock', - 'payload': jsonEncode({ - 'uuid': 'transcript-a', - 'title': 'Recorded words', - 'parentId': 'asset-a', - }), - }, - }, - ); - }); - - testWidgets('records and returns an audio asset from a Material sheet', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend(asset: asset); - RecordedAudioRecordingResult? result; - await tester.pumpWidget( - _RecordingHarness(backend: backend, onResult: (value) => result = value), - ); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - - expect(backend.startCount, 1); - expect(find.byKey(const ValueKey('sheet.audio-recording')), findsOneWidget); - expect(find.text('Audio recording'), findsOneWidget); - expect(find.text('Recording…'), findsOneWidget); - expect( - find.byKey(const ValueKey('toggle.audio.transcription')), - findsOneWidget, - ); - expect(find.byKey(const ValueKey('button.audio.stop')), findsOneWidget); - - await tester.tap(find.byKey(const ValueKey('button.audio.stop'))); - await tester.pumpAndSettle(); - - expect(backend.stopCount, 1); - expect(result?.asset, same(asset)); - expect(result?.transcriptionEnabled, isTrue); - expect(find.byKey(const ValueKey('sheet.audio-recording')), findsNothing); - }); - - testWidgets('canceling a recording deletes it and returns no asset', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend(asset: asset); - RecordedAudioRecordingResult? result = const RecordedAudioRecordingResult( - asset: asset, - transcriptionEnabled: true, - ); - await tester.pumpWidget( - _RecordingHarness(backend: backend, onResult: (value) => result = value), - ); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - await tester.tap(find.byKey(const ValueKey('button.audio.cancel'))); - await tester.pumpAndSettle(); - - expect(backend.cancelCount, 1); - expect(result, isNull); - }); - - testWidgets('the transcription preference is returned with the recording', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend(asset: asset); - RecordedAudioRecordingResult? result; - await tester.pumpWidget( - _RecordingHarness(backend: backend, onResult: (value) => result = value), - ); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - await tester.tap(find.byKey(const ValueKey('toggle.audio.transcription'))); - await tester.tap(find.byKey(const ValueKey('button.audio.stop'))); - await tester.pumpAndSettle(); - - expect(result?.asset, same(asset)); - expect(result?.transcriptionEnabled, isFalse); - }); - - testWidgets('unsupported devices do not offer audio transcription', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend( - asset: asset, - transcriptionSupported: false, - ); - RecordedAudioRecordingResult? result; - await tester.pumpWidget( - _RecordingHarness(backend: backend, onResult: (value) => result = value), - ); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - - expect( - find.byKey(const ValueKey('toggle.audio.transcription')), - findsNothing, - ); - await tester.tap(find.byKey(const ValueKey('button.audio.stop'))); - await tester.pumpAndSettle(); - expect(result?.transcriptionEnabled, isFalse); - }); - - testWidgets('a microphone start failure stays visible and cannot be saved', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend( - asset: asset, - startError: StateError('Microphone access is required'), - ); - await tester.pumpWidget(_RecordingHarness(backend: backend)); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - - expect( - find.textContaining('Microphone access is required'), - findsOneWidget, - ); - expect( - tester - .widget(find.byKey(const ValueKey('button.audio.stop'))) - .onPressed, - isNull, - ); - }); - - testWidgets('a stop failure keeps the recorder open with a useful error', ( - tester, - ) async { - final backend = _FakeAudioRecordingBackend( - asset: asset, - stopError: StateError('The recording is empty'), - ); - await tester.pumpWidget(_RecordingHarness(backend: backend)); - - await tester.tap(find.text('Open recorder')); - await tester.pumpAndSettle(); - await tester.tap(find.byKey(const ValueKey('button.audio.stop'))); - await tester.pumpAndSettle(); - - expect(find.textContaining('The recording is empty'), findsOneWidget); - expect(find.byKey(const ValueKey('sheet.audio-recording')), findsOneWidget); - }); -} - -final class _RecordingHarness extends StatelessWidget { - const _RecordingHarness({required this.backend, this.onResult}); - - final AndroidAudioRecordingBackend backend; - final ValueChanged? onResult; - - @override - Widget build(BuildContext context) => MaterialApp( - home: Scaffold( - body: Builder( - builder: (context) => TextButton( - onPressed: () async { - final result = await showAndroidAudioRecordingSheet( - context: context, - backend: backend, - ); - onResult?.call(result); - }, - child: const Text('Open recorder'), - ), - ), - ), - ); -} - -final class _FakeAudioRecordingBackend implements AndroidAudioRecordingBackend { - _FakeAudioRecordingBackend({ - required this.asset, - this.startError, - this.stopError, - this.transcriptionSupported = true, - }); - - final RecordedAudioAsset asset; - final Object? startError; - final Object? stopError; - final bool transcriptionSupported; - var startCount = 0; - var stopCount = 0; - var cancelCount = 0; - - @override - Future supportsTranscription() async => transcriptionSupported; - - @override - Future transcribe(String path) async => 'Recorded words'; - - @override - Future start() async { - startCount += 1; - if (startError case final error?) throw error; - } - - @override - Future stop() async { - stopCount += 1; - if (stopError case final error?) throw error; - return asset; - } - - @override - Future cancel() async { - cancelCount += 1; - } -} diff --git a/flutter/test/android_cloze_test.dart b/flutter/test/android_cloze_test.dart deleted file mode 100644 index 273460c6..00000000 --- a/flutter/test/android_cloze_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_cloze.dart'; - -void main() { - testWidgets('reveals and hides cloze content with Material semantics', ( - tester, - ) async { - await tester.pumpWidget( - const MaterialApp( - home: Scaffold(body: AndroidCloze(text: 'Paris')), - ), - ); - - final finder = find.byKey(const ValueKey('button.cloze.reveal')); - expect(find.text('Tap to reveal'), findsOneWidget); - expect(find.text('Paris'), findsNothing); - - await tester.tap(finder); - await tester.pump(); - expect(find.text('Paris'), findsOneWidget); - - await tester.tap(finder); - await tester.pump(); - expect(find.text('Tap to reveal'), findsOneWidget); - }); -} diff --git a/flutter/test/android_embedded_media_test.dart b/flutter/test/android_embedded_media_test.dart deleted file mode 100644 index adc9f1ac..00000000 --- a/flutter/test/android_embedded_media_test.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_embedded_media.dart'; - -void main() { - test('builds safe YouTube embed URLs with timestamp parity', () { - expect( - androidEmbeddedMediaUri( - 'https://youtu.be/dQw4w9WgXcQ', - startSeconds: 83, - ).toString(), - 'https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ?playsinline=1&start=83', - ); - expect( - androidEmbeddedMediaUri('https://www.youtube.com/watch?v=dQw4w9WgXcQ') - .toString(), - 'https://www.youtube-nocookie.com/embed/dQw4w9WgXcQ?playsinline=1', - ); - expect( - androidEmbeddedMediaUri('https://example.com/video.mp4').toString(), - 'https://example.com/video.mp4', - ); - }); - - test('rejects unsafe or malformed embedded media URLs', () { - expect(androidEmbeddedMediaUri('javascript:alert(1)'), isNull); - expect(androidEmbeddedMediaUri('file:///tmp/private'), isNull); - expect(androidEmbeddedMediaUri('https://youtu.be/not valid'), isNull); - expect(androidEmbeddedMediaUri(''), isNull); - }); - - testWidgets('does not create a platform view until the preview is tapped', ( - tester, - ) async { - final loaded = []; - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: AndroidEmbeddedMedia( - url: 'https://youtu.be/dQw4w9WgXcQ', - webViewBuilder: (uri) { - loaded.add(uri); - return const SizedBox(key: ValueKey('fake.webview')); - }, - ), - ), - ), - ); - - expect(loaded, isEmpty); - expect(find.text('Video preview'), findsOneWidget); - expect(find.text('Tap to load'), findsOneWidget); - - await tester.tap(find.byKey(const ValueKey('button.media.load'))); - await tester.pump(); - - expect(find.byKey(const ValueKey('fake.webview')), findsOneWidget); - final semantics = tester.getSemantics( - find.byKey(const ValueKey('media.webview.loaded')), - ); - expect(semantics.identifier, 'media.webview.loaded'); - expect(loaded.single.host, 'www.youtube-nocookie.com'); - }); -} diff --git a/flutter/test/android_graph_lifecycle_test.dart b/flutter/test/android_graph_lifecycle_test.dart deleted file mode 100644 index 0d2e4415..00000000 --- a/flutter/test/android_graph_lifecycle_test.dart +++ /dev/null @@ -1,321 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_graph_lifecycle.dart'; -import 'package:logseq_chat_flutter/android_platform_effects.dart'; -import 'package:logseq_chat_flutter/native_effect_drain.dart'; - -void main() { - test( - 'creating a graph downloads and imports its first local snapshot', - () async { - final core = _RecordingCore(); - final platform = _GraphPlatform(); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect( - id: 1, - kind: 'create-graph', - text: 'Android notes', - value: 0, - ), - ); - - expect(resolution.succeeded, isTrue); - expect(resolution.output, NativeEffectOutputKind.coreResponse); - expect(core.actions, [ - 'createSyncGraph', - 'selectGraph', - 'importSnapshot', - ]); - expect(platform.downloadedGraphIds, ['graph-new']); - expect(platform.persistedGraphIds, ['graph-new']); - expect(platform.deletedTemporaryFiles, ['/tmp/graph-new.snapshot']); - expect(core.payloadFor('importSnapshot'), { - 'graphId': 'graph-new', - 'activePath': '/data/graphs/graph-new/graph.sqlite', - 'checkpointPath': '/data/graphs/graph-new/sync.checkpoint', - 'metadataBody': '{"ok":true,"t":0,"row-count":1}', - 'downloadPath': '/tmp/graph-new.snapshot', - 'isEncrypted': false, - }); - }, - ); - - test('opening an existing local graph avoids a snapshot download', () async { - final core = _RecordingCore(); - final platform = _GraphPlatform(localGraphIds: const ['graph-local']); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 2, kind: 'open-graph', text: 'graph-local'), - ); - - expect(resolution.succeeded, isTrue); - expect(core.actions, ['selectGraph', 'openGraph']); - expect(platform.downloadedGraphIds, isEmpty); - expect(platform.persistedGraphIds, ['graph-local']); - expect(core.payloadFor('openGraph'), { - 'graphId': 'graph-local', - 'activePath': '/data/graphs/graph-local/graph.sqlite', - 'checkpointPath': '/data/graphs/graph-local/sync.checkpoint', - 'isEncrypted': false, - }); - }); - - test('an encrypted graph is imported with encryption enabled', () async { - final core = _RecordingCore(encryptedGraphIds: const {'graph-private'}); - final platform = _GraphPlatform(); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 3, kind: 'open-graph', text: 'graph-private'), - ); - - expect(resolution.succeeded, isTrue); - expect(core.payloadFor('importSnapshot')?['isEncrypted'], isTrue); - expect(platform.persistedGraphIds, ['graph-private']); - }); - - test('traces each remote graph download and import stage', () async { - final core = _RecordingCore(); - final platform = _GraphPlatform(); - final traces = []; - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - trace: traces.add, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 7, kind: 'open-graph', text: 'graph-remote'), - ); - - expect(resolution.succeeded, isTrue); - expect(traces, [ - 'open.start graphId=graph-remote', - 'select.complete graphId=graph-remote', - 'storage.loaded graphId=graph-remote local=false', - 'snapshot.download.start graphId=graph-remote baseUrl=http://127.0.0.1:8787', - 'snapshot.download.complete graphId=graph-remote path=/tmp/graph-remote.snapshot', - 'snapshot.import.start graphId=graph-remote', - 'snapshot.import.complete graphId=graph-remote', - 'selection.persist.complete graphId=graph-remote', - 'open.complete graphId=graph-remote', - ]); - }); - - test('a failed graph creation does not open or persist a graph', () async { - final core = _RecordingCore(failingAction: 'createSyncGraph'); - final platform = _GraphPlatform(); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect( - id: 4, - kind: 'create-graph', - text: 'Broken graph', - value: 0, - ), - ); - - expect(resolution.succeeded, isFalse); - expect(core.actions, ['createSyncGraph']); - expect(platform.persistedGraphIds, isEmpty); - expect(platform.downloadedGraphIds, isEmpty); - }); - - test('a failed import cleans its download and does not persist', () async { - final core = _RecordingCore(failingAction: 'importSnapshot'); - final platform = _GraphPlatform(); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 5, kind: 'open-graph', text: 'graph-remote'), - ); - - expect(resolution.succeeded, isFalse); - expect(platform.deletedTemporaryFiles, ['/tmp/graph-remote.snapshot']); - expect(platform.persistedGraphIds, isEmpty); - }); - - test('a snapshot transport exception becomes a graph open error', () async { - final core = _RecordingCore(); - final platform = _GraphPlatform( - downloadError: const HttpExceptionForTest('Connection refused'), - ); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 8, kind: 'open-graph', text: 'graph-remote'), - ); - - expect(resolution.succeeded, isFalse); - expect( - resolution.message, - 'graph_open_failed\nHttpExceptionForTest: Connection refused', - ); - expect(platform.persistedGraphIds, isEmpty); - }); - - test('unlock delegates to the core without reopening storage', () async { - final core = _RecordingCore(); - final platform = _GraphPlatform(); - final lifecycle = AndroidGraphLifecycle( - callCore: core.call, - platform: platform, - ); - - final resolution = await lifecycle.execute( - const NativeEffect(id: 6, kind: 'unlock-graph', text: 'secret'), - ); - - expect(resolution.succeeded, isTrue); - expect(core.actions, ['unlockGraph']); - expect(platform.downloadedGraphIds, isEmpty); - }); -} - -final class _RecordingCore { - _RecordingCore({this.failingAction, this.encryptedGraphIds = const {}}); - - final String? failingAction; - final Set encryptedGraphIds; - final List> requests = []; - - List get actions => requests - .map((request) => request['params']! as Map) - .map((params) => params['action']! as String) - .toList(growable: false); - - Map? payloadFor(String action) { - final request = requests.firstWhere( - (request) => - (request['params']! as Map)['action'] == action, - ); - final payload = (request['params']! as Map)['payload']; - return payload is String - ? jsonDecode(payload) as Map - : null; - } - - Future call(String encoded) async { - final request = jsonDecode(encoded) as Map; - requests.add(request); - final params = request['params']! as Map; - final action = params['action']! as String; - if (action == failingAction) { - return _response( - ok: false, - result: const {}, - errorCode: 'test_failure', - errorMessage: '$action failed', - ); - } - if (action == 'createSyncGraph') { - return _response(result: _snapshot(selectedGraphId: 'graph-new')); - } - if (action == 'selectGraph') { - final graphId = params['payload']! as String; - return _response(result: _snapshot(selectedGraphId: graphId)); - } - return _response(result: _snapshot(selectedGraphId: 'graph-open')); - } - - Map _snapshot({required String selectedGraphId}) => { - 'selectedGraphId': selectedGraphId, - 'graphs': [ - { - 'id': selectedGraphId, - 'name': selectedGraphId, - 'isEncrypted': encryptedGraphIds.contains(selectedGraphId), - 'ready': true, - }, - ], - }; - - String _response({ - bool ok = true, - required Map result, - String? errorCode, - String? errorMessage, - }) => jsonEncode({ - 'apiVersion': 1, - 'ok': ok, - if (ok) 'result': result, - if (!ok) 'error': {'code': errorCode, 'message': errorMessage}, - }); -} - -final class _GraphPlatform extends AndroidPlatformServices { - _GraphPlatform({this.localGraphIds = const [], this.downloadError}); - - final List localGraphIds; - final Object? downloadError; - final List downloadedGraphIds = []; - final List persistedGraphIds = []; - final List deletedTemporaryFiles = []; - - @override - Future loadStorageState() async => AndroidStorageState( - databasePath: '/data/catalog.sqlite', - graphsDirectory: '/data/graphs', - baseUrl: 'http://127.0.0.1:8787', - selectedGraphId: '', - localGraphIds: localGraphIds, - ); - - @override - Future downloadGraphSnapshot({ - required String baseUrl, - required String graphId, - required String accessToken, - required String workingDirectory, - }) async { - final error = downloadError; - if (error != null) throw error; - downloadedGraphIds.add(graphId); - return AndroidDownloadedSnapshot( - metadataBody: '{"ok":true,"t":0,"row-count":1}', - filePath: '/tmp/$graphId.snapshot', - ); - } - - @override - Future persistSelectedGraphId(String graphId) async { - persistedGraphIds.add(graphId); - } - - @override - Future deleteTemporaryFile(String path) async { - deletedTemporaryFiles.add(path); - } -} - -final class HttpExceptionForTest implements Exception { - const HttpExceptionForTest(this.message); - - final String message; - - @override - String toString() => 'HttpExceptionForTest: $message'; -} diff --git a/flutter/test/android_icon_button_layout_test.dart b/flutter/test/android_icon_button_layout_test.dart deleted file mode 100644 index bcecd465..00000000 --- a/flutter/test/android_icon_button_layout_test.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/flutter_patch_applier.dart'; -import 'package:logseq_chat_flutter/logseq_chat_icons.dart'; -import 'package:logseq_chat_flutter/logseq_chat_theme.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -void main() { - for (final direction in TextDirection.values) { - testWidgets( - 'search icon is centered in its entire touch target ($direction)', - (tester) async { - final backend = LUIFlutterBackend(appIcons: logseqChatAppIcons); - addTearDown(backend.dispose); - FlutterPatchApplier(backend).applyJson( - jsonEncode({ - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'button'}, - for (final property in { - 'icon': 'app:search', - 'size': 'icon', - 'variant': 'secondary', - 'width': 58, - 'height': 58, - 'accessibility-label': 'Search', - }.entries) - { - 'op': 'set-prop', - 'id': 1, - 'property': property.key, - 'value': property.value, - }, - ], - }), - ); - await tester.pumpWidget( - MaterialApp( - theme: LogseqChatTheme.light(), - home: Scaffold( - body: Directionality( - textDirection: direction, - child: Center(child: backend.widget(node: 1)), - ), - ), - ), - ); - expect( - tester.getCenter(find.byIcon(Icons.search_rounded)), - tester.getCenter(find.byType(FilledButton)), - ); - }, - ); - } -} diff --git a/flutter/test/android_launcher_assets_test.dart b/flutter/test/android_launcher_assets_test.dart deleted file mode 100644 index e83bd359..00000000 --- a/flutter/test/android_launcher_assets_test.dart +++ /dev/null @@ -1,115 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('Flutter owns a complete Android launcher asset set', () { - const densities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi', 'xxxhdpi']; - const rasterNames = [ - 'ic_launcher.png', - 'ic_launcher_background.png', - 'ic_launcher_foreground.png', - 'ic_launcher_monochrome.png', - ]; - - for (final density in densities) { - for (final name in rasterNames) { - final asset = File('android/app/src/main/res/mipmap-$density/$name'); - expect(asset.existsSync(), isTrue, reason: asset.path); - expect( - asset.readAsBytesSync().take(8), - [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], - reason: '${asset.path} must be a PNG image', - ); - } - } - - for (final name in ['ic_launcher.xml', 'ic_launcher_round.xml']) { - final adaptive = File('android/app/src/main/res/mipmap-anydpi-v26/$name'); - expect(adaptive.existsSync(), isTrue, reason: adaptive.path); - final source = adaptive.readAsStringSync(); - expect(source, contains('@color/ic_launcher_background')); - expect(source, contains('@drawable/ic_launcher_foreground')); - expect(source, contains('@drawable/ic_launcher_monochrome')); - } - - final foregroundFile = File( - 'android/app/src/main/res/drawable/ic_launcher_foreground.xml', - ); - final foreground = foregroundFile.readAsStringSync(); - expect(foreground, contains('android:width="108dp"')); - expect(foreground, contains('android:height="108dp"')); - expect(foreground, contains('android:viewportWidth="108"')); - expect(foreground, contains('android:viewportHeight="108"')); - expect(foreground, contains('android:pivotX="54"')); - expect(foreground, contains('android:pivotY="54"')); - expect(foreground, contains('android:scaleX="0.86"')); - expect(foreground, contains('android:scaleY="0.86"')); - - final monochrome = File( - 'android/app/src/main/res/drawable/ic_launcher_monochrome.xml', - ).readAsStringSync(); - expect(monochrome, contains('android:strokeColor="#FF000000"')); - expect(monochrome, contains('android:scaleX="0.86"')); - expect(monochrome, contains('android:scaleY="0.86"')); - - final manifest = File('android/app/src/main/AndroidManifest.xml') - .readAsStringSync(); - expect(manifest, contains('android:roundIcon="@mipmap/ic_launcher_round"')); - expect(manifest, contains('android.intent.action.SEND_MULTIPLE')); - expect(manifest, contains('android:mimeType="*/*"')); - expect(manifest, contains('android:scheme="logseqchat"')); - expect(manifest, contains('android.app.shortcuts')); - - final shortcuts = File('android/app/src/main/res/xml/shortcuts.xml') - .readAsStringSync(); - expect(shortcuts, contains('android:shortcutId="capture"')); - expect(shortcuts, contains('android:shortcutId="journal"')); - expect(shortcuts, contains('@drawable/ic_shortcut_capture')); - expect(shortcuts, contains('@drawable/ic_shortcut_journal')); - expect(shortcuts, contains('android:targetPackage="com.logseq.chat"')); - expect( - manifest, - contains('android.permission.RECORD_AUDIO'), - reason: - 'The Audio recording action needs the native microphone permission.', - ); - - final platformServices = File( - 'android/app/src/main/kotlin/com/logseq/chat/AndroidPlatformServices.kt', - ).readAsStringSync(); - expect( - platformServices, - contains('ClipData.newPlainText("Logseq Chat", text)'), - ); - expect( - platformServices, - contains('Intent.createChooser(intent, "Share from Logseq Chat")'), - ); - - final recorderFile = File( - 'android/app/src/main/kotlin/com/logseq/chat/AndroidAudioRecorder.kt', - ); - expect(recorderFile.existsSync(), isTrue, reason: recorderFile.path); - final recorder = recorderFile.readAsStringSync(); - expect(recorder, contains('MediaRecorder')); - expect(recorder, contains('Manifest.permission.RECORD_AUDIO')); - expect(recorder, contains('MessageDigest.getInstance("SHA-256")')); - expect(recorder, contains('File(context.filesDir, "Assets")')); - - final activity = File( - 'android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt', - ).readAsStringSync(); - expect(activity, contains('"startAudioRecording"')); - expect(activity, contains('"stopAudioRecording"')); - expect(activity, contains('"cancelAudioRecording"')); - - final outlinerCommands = File('lib/android_outliner_commands.dart') - .readAsStringSync(); - expect(outlinerCommands, contains('presentAudioRecording(command.uuid)')); - - final main = File('lib/main.dart').readAsStringSync(); - expect(main, contains('showAndroidAudioRecordingSheet')); - expect(main, contains('asset.coreRequest')); - }); -} diff --git a/flutter/test/android_math_test.dart b/flutter/test/android_math_test.dart deleted file mode 100644 index 582f9e2c..00000000 --- a/flutter/test/android_math_test.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_math.dart'; - -void main() { - testWidgets('renders TeX as an accessible native Flutter equation', ( - tester, - ) async { - await tester.pumpWidget( - const MaterialApp( - home: Scaffold(body: AndroidMath(expression: r'\frac{1}{2}')), - ), - ); - - final semantics = tester.getSemantics( - find.byKey(const ValueKey('math.rendered')), - ); - expect(semantics.identifier, 'block.rich.math.rendered'); - expect(semantics.label, r'Math: \frac{1}{2}'); - expect(find.text(r'\frac{1}{2}'), findsNothing); - }); - - testWidgets('falls back to readable source when TeX is invalid', ( - tester, - ) async { - await tester.pumpWidget( - const MaterialApp( - home: Scaffold(body: AndroidMath(expression: r'\definitelyUnknown{')), - ), - ); - - expect(find.text(r'\definitelyUnknown{'), findsOneWidget); - }); -} diff --git a/flutter/test/android_outliner_commands_test.dart b/flutter/test/android_outliner_commands_test.dart deleted file mode 100644 index 2af3e59f..00000000 --- a/flutter/test/android_outliner_commands_test.dart +++ /dev/null @@ -1,228 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_outliner_commands.dart'; -import 'package:logseq_chat_flutter/android_imported_asset.dart'; -import 'package:logseq_chat_flutter/android_platform_effects.dart'; - -void main() { - test('delivers each outliner command revision exactly once', () async { - final batches = []; - final dispatcher = OutlinerPlatformCommandDispatcher(batches.add); - final response = jsonEncode({ - 'ok': true, - 'result': { - 'outlinerCommandRevision': 7, - 'graphName': 'E2E Graph', - 'outlinerCommands': [ - { - 'type': 'confirmDelete', - 'uuids': ['first', 'second'], - }, - ], - }, - }); - - await dispatcher.deliver(response); - await dispatcher.deliver(response); - - expect(batches, hasLength(1)); - expect(batches.single.revision, 7); - expect(batches.single.graphName, 'E2E Graph'); - expect(batches.single.commands.single.type, 'confirmDelete'); - expect(batches.single.commands.single.uuids, ['first', 'second']); - }); - - testWidgets('confirms block deletion with a native Material dialog', ( - tester, - ) async { - final navigatorKey = GlobalKey(); - final events = >[]; - await tester.pumpWidget( - MaterialApp(navigatorKey: navigatorKey, home: const SizedBox()), - ); - final handler = AndroidOutlinerPlatformCommandHandler( - navigatorKey: navigatorKey, - platform: _RecordingPlatformServices(), - sendOutlinerEvent: (event) async => events.add(event), - presentAttachment: (_, _) async {}, - presentAudioRecording: (_) async {}, - ); - final completed = handler.handle( - const OutlinerPlatformCommandBatch( - revision: 1, - graphName: 'E2E Graph', - commands: [ - OutlinerPlatformCommand( - type: 'confirmDelete', - uuids: ['first', 'second'], - ), - ], - ), - ); - - await tester.pumpAndSettle(); - expect(find.text('Delete blocks?'), findsOneWidget); - expect( - find.text('This deletes the blocks and all of their children.'), - findsOneWidget, - ); - final cancel = find.byKey( - const ValueKey('button.outliner-delete.cancel'), - ); - final confirm = find.byKey( - const ValueKey('button.outliner-delete.confirm'), - ); - expect(cancel, findsOneWidget); - expect(confirm, findsOneWidget); - expect( - tester.getSemantics(cancel).getSemanticsData().identifier, - 'button.outliner-delete.cancel', - ); - expect( - tester.getSemantics(confirm).getSemanticsData().identifier, - 'button.outliner-delete.confirm', - ); - final confirmButton = tester.widget( - find.descendant(of: confirm, matching: find.byType(TextButton)), - ); - expect( - confirmButton.style?.foregroundColor?.resolve({}), - Theme.of(navigatorKey.currentContext!).colorScheme.error, - ); - await tester.tap(confirm); - await tester.pumpAndSettle(); - await completed; - - expect(events, [ - {'type': 'confirmDelete'}, - ]); - }); - - test('maps clipboard commands to Android platform services', () async { - final platform = _RecordingPlatformServices(); - final handler = AndroidOutlinerPlatformCommandHandler( - navigatorKey: GlobalKey(), - platform: platform, - sendOutlinerEvent: (_) async {}, - presentAttachment: (_, _) async {}, - presentAudioRecording: (_) async {}, - ); - - await handler.handle( - const OutlinerPlatformCommandBatch( - revision: 1, - graphName: 'Work', - commands: [ - OutlinerPlatformCommand( - type: 'setClipboardReferences', - uuids: ['a', 'b'], - ), - OutlinerPlatformCommand(type: 'setClipboardURLs', uuids: ['c']), - ], - ), - ); - - expect(platform.copied, ['[[a]]\n[[b]]', 'logseq://graph/Work?block-id=c']); - }); - - test( - 'never routes the Audio recording command through a file picker', - () async { - final platform = _RecordingPlatformServices(); - final recordingTargets = []; - final handler = AndroidOutlinerPlatformCommandHandler( - navigatorKey: GlobalKey(), - platform: platform, - sendOutlinerEvent: (_) async {}, - presentAttachment: (_, _) async {}, - presentAudioRecording: (target) async => recordingTargets.add(target), - ); - - await handler.handle( - const OutlinerPlatformCommandBatch( - revision: 1, - graphName: 'Work', - commands: [ - OutlinerPlatformCommand(type: 'recordAudio', uuid: 'block-a'), - ], - ), - ); - - expect(platform.presentedAttachments, isEmpty); - expect(recordingTargets, ['block-a']); - }, - ); - - test('imports picked files into the command target block', () async { - final imported = <({String kind, String? targetBlockId})>[]; - final handler = AndroidOutlinerPlatformCommandHandler( - navigatorKey: GlobalKey(), - platform: _RecordingPlatformServices(), - sendOutlinerEvent: (_) async {}, - presentAttachment: (kind, targetBlockId) async { - imported.add((kind: kind, targetBlockId: targetBlockId)); - }, - presentAudioRecording: (_) async {}, - ); - - await handler.handle( - const OutlinerPlatformCommandBatch( - revision: 1, - graphName: 'Work', - commands: [ - OutlinerPlatformCommand(type: 'pickAttachment', uuid: 'block-a'), - OutlinerPlatformCommand(type: 'takePhoto', uuid: 'block-b'), - ], - ), - ); - - expect(imported, [ - (kind: 'files', targetBlockId: 'block-a'), - (kind: 'camera', targetBlockId: 'block-b'), - ]); - }); - - test('imported assets produce the core addAsset request', () { - final asset = AndroidImportedAsset.fromMap({ - 'uuid': 'asset-a', - 'title': 'Photo.jpg', - 'assetType': 'image/jpeg', - 'size': 123, - 'checksum': 'abc123', - 'localPath': 'Assets/asset-a-Photo.jpg', - }); - - expect(asset.coreRequest(targetBlockId: 'block-a'), { - 'apiVersion': 1, - 'method': 'dispatch', - 'params': { - 'action': 'addAsset', - 'payload': jsonEncode({ - 'uuid': 'asset-a', - 'title': 'Photo.jpg', - 'assetType': 'image/jpeg', - 'assetSize': 123, - 'assetChecksum': 'abc123', - 'localPath': 'Assets/asset-a-Photo.jpg', - 'targetBlockId': 'block-a', - }), - }, - }); - }); -} - -final class _RecordingPlatformServices extends AndroidPlatformServices { - final copied = []; - final presentedAttachments = []; - - @override - Future copyText(String text) async => copied.add(text); - - @override - Future presentAttachment(String kind) async { - presentedAttachments.add(kind); - return true; - } -} diff --git a/flutter/test/android_platform_effects_test.dart b/flutter/test/android_platform_effects_test.dart deleted file mode 100644 index 7578c6a7..00000000 --- a/flutter/test/android_platform_effects_test.dart +++ /dev/null @@ -1,350 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/android_platform_effects.dart'; -import 'package:logseq_chat_flutter/native_effect_drain.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - test('resolves relative assets after Android storage is loaded', () async { - const channel = MethodChannel('test/storage-state'); - final messenger = - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; - messenger.setMockMethodCallHandler(channel, (call) async { - expect(call.method, 'loadStorageState'); - return { - 'databasePath': '/data/user/0/com.logseq.chat/files/logseq-chat.sqlite', - 'graphsDirectory': '/data/user/0/com.logseq.chat/files/graphs', - 'baseUrl': 'http://127.0.0.1:8787', - 'selectedGraphId': '', - 'localGraphIds': [], - 'composerDraft': 'Persisted draft', - 'settings': { - 'appearance': 'dark', - 'language': 'zh-Hans', - 'spellCheck': false, - 'autoCorrection': false, - 'sidebarTabs': ['journals', 'graphs'], - 'baseURL': 'https://example.test', - 'version': '1.2.3', - 'revision': '42', - }, - }; - }); - addTearDown(() => messenger.setMockMethodCallHandler(channel, null)); - final services = MethodChannelAndroidPlatformServices(channel: channel); - - expect(services.resolveAssetPath('Assets/photo.png'), 'Assets/photo.png'); - final state = await services.loadStorageState(); - - expect( - services.resolveAssetPath('Assets/photo.png'), - '/data/user/0/com.logseq.chat/files/Assets/photo.png', - ); - expect( - services.resolveAssetPath('/data/user/0/com.logseq.chat/cache/photo.png'), - '/data/user/0/com.logseq.chat/cache/photo.png', - ); - expect(state.composerDraft, 'Persisted draft'); - expect(state.settings.appearance, 'dark'); - expect(state.settings.language, 'zh-Hans'); - expect(state.settings.spellCheck, isFalse); - expect(state.settings.autoCorrection, isFalse); - expect(state.settings.sidebarTabs, ['journals', 'graphs']); - expect(state.settings.baseUrl, 'https://example.test'); - expect(state.settings.version, '1.2.3'); - expect(state.settings.revision, '42'); - expect(state.settings.hostPayload, { - 'appearance': 'dark', - 'language': 'zh-Hans', - 'spellCheck': false, - 'autoCorrection': false, - 'sidebarTabs': ['journals', 'graphs'], - 'baseURL': 'https://example.test', - 'version': '1.2.3', - 'revision': '42', - }); - expect( - state.startupHostUpdates - .map((update) => (update.kind, update.payload)) - .toList(), - [ - ('graph-loading', 'true'), - ( - 'settings', - '{"appearance":"dark","language":"zh-Hans","spellCheck":false,' - '"autoCorrection":false,"sidebarTabs":["journals","graphs"],' - '"baseURL":"https://example.test","version":"1.2.3",' - '"revision":"42"}', - ), - ('composer-draft', '"Persisted draft"'), - ], - ); - }); - - test('restores signed-in state only when a non-empty token exists', () async { - final signedInAuthentication = _FakeAuthentication( - restoredToken: 'access-token', - ); - final signedIn = AndroidPlatformEffects( - authentication: signedInAuthentication, - ); - final signedOut = AndroidPlatformEffects( - authentication: _FakeAuthentication(restoredToken: ''), - ); - - expect(await signedIn.initialAuthenticationCode(), 3); - expect(await signedOut.initialAuthenticationCode(), 1); - expect(signedInAuthentication.restoreCalls, 0); - }); - - test('treats stored-session inspection failure as signed out', () async { - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication( - storedSessionError: StateError('keystore unavailable'), - ), - ); - - expect(await effects.initialAuthenticationCode(), 1); - }); - - test('surfaces background access-token refresh failures', () async { - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication(restoreError: StateError('expired')), - ); - - expect(effects.restoreAccessToken(), throwsStateError); - }); - - test( - 'sign-in succeeds only when native authentication returns a token', - () async { - final authentication = _FakeAuthentication(signInToken: 'new-token'); - final effects = AndroidPlatformEffects(authentication: authentication); - - final result = await effects.execute( - const NativeEffect(id: 1, kind: 'sign-in', text: ''), - ); - - expect(authentication.signInCalls, 1); - expect(result.succeeded, isTrue); - expect(result.output, NativeEffectOutputKind.discard); - }, - ); - - test('empty sign-in token is returned to LG as a failure', () async { - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication(signInToken: ''), - ); - - final result = await effects.execute( - const NativeEffect(id: 2, kind: 'sign-in', text: ''), - ); - - expect(result.succeeded, isFalse); - expect(result.message, 'Hosted sign-in did not return an access token'); - }); - - test('native sign-in errors are returned to LG', () async { - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication( - signInError: StateError('custom tab closed'), - ), - ); - - final result = await effects.execute( - const NativeEffect(id: 3, kind: 'sign-in', text: ''), - ); - - expect(result.succeeded, isFalse); - expect(result.message, contains('custom tab closed')); - }); - - test( - 'sign-out clears native authentication and resolves successfully', - () async { - final authentication = _FakeAuthentication(); - final effects = AndroidPlatformEffects(authentication: authentication); - - final result = await effects.execute( - const NativeEffect(id: 4, kind: 'sign-out', text: ''), - ); - - expect(authentication.signOutCalls, 1); - expect(result.succeeded, isTrue); - expect(result.output, NativeEffectOutputKind.discard); - }, - ); - - test('unsupported platform effects fail explicitly', () async { - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication(), - ); - - final result = await effects.execute( - const NativeEffect(id: 5, kind: 'unknown-effect', text: ''), - ); - - expect(result.succeeded, isFalse); - expect( - result.message, - 'Unsupported Android platform effect: unknown-effect', - ); - }); - - test( - 'routes persisted state and Android intents through platform services', - () async { - final platform = _FakePlatformServices(); - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication(), - platform: platform, - ); - - await effects.execute( - const NativeEffect( - id: 6, - kind: 'persist-composer-draft', - text: 'Draft', - ), - ); - await effects.execute( - const NativeEffect( - id: 7, - kind: 'save-settings', - text: '{"appearance":"dark"}', - ), - ); - final opened = await effects.execute( - const NativeEffect( - id: 8, - kind: 'open-external-url', - text: 'https://logseq.com', - ), - ); - await effects.execute( - const NativeEffect( - id: 9, - kind: 'copy-runtime-log', - text: - '[{"timestamp":"12:00","level":"INFO","source":"ui",' - '"message":"Ready"}]', - ), - ); - - expect(platform.persistedDraft, 'Draft'); - expect(platform.savedSettings, '{"appearance":"dark"}'); - expect(platform.openedUrl, 'https://logseq.com'); - expect(platform.copiedText, '12:00 INFO ui Ready'); - expect(opened.succeeded, isTrue); - }, - ); - - test('publishes Android runtime log records as a host update', () async { - final platform = _FakePlatformServices(runtimeLog: '[{"id":"1"}]'); - final effects = AndroidPlatformEffects( - authentication: _FakeAuthentication(), - platform: platform, - ); - - final result = await effects.execute( - const NativeEffect( - id: 10, - kind: 'refresh-runtime-log', - text: 'ui', - value: 3, - ), - ); - - expect(platform.runtimeLogSource, 'ui'); - expect(platform.runtimeLogFlags, 3); - expect(result.output, NativeEffectOutputKind.hostUpdate); - expect(result.hostUpdateKind, 'runtime-log'); - expect(result.message, '[{"id":"1"}]'); - }); -} - -final class _FakeAuthentication implements AndroidAuthentication { - _FakeAuthentication({ - this.restoredToken, - this.restoreError, - this.storedSessionError, - this.signInToken = 'access-token', - this.signInError, - }); - - final String? restoredToken; - final Object? restoreError; - final Object? storedSessionError; - final String signInToken; - final Object? signInError; - int signInCalls = 0; - int signOutCalls = 0; - int restoreCalls = 0; - - @override - Future hasStoredSession() async { - if (storedSessionError case final error?) throw error; - return restoredToken != null && restoredToken!.isNotEmpty; - } - - @override - Future restoreAccessToken() async { - restoreCalls += 1; - if (restoreError case final error?) throw error; - return restoredToken; - } - - @override - Future signIn() async { - signInCalls += 1; - if (signInError case final error?) throw error; - return signInToken; - } - - @override - Future signOut() async { - signOutCalls += 1; - } -} - -final class _FakePlatformServices extends AndroidPlatformServices { - _FakePlatformServices({this.runtimeLog = '[]'}); - - final String runtimeLog; - String? persistedDraft; - String? savedSettings; - String? openedUrl; - String? copiedText; - String? runtimeLogSource; - int? runtimeLogFlags; - - @override - Future copyText(String text) async => copiedText = text; - - @override - Future openExternalUrl(String url) async { - openedUrl = url; - return true; - } - - @override - Future persistComposerDraft(String draft) async { - persistedDraft = draft; - } - - @override - Future refreshRuntimeLog({ - required String source, - required int flags, - }) async { - runtimeLogSource = source; - runtimeLogFlags = flags; - return runtimeLog; - } - - @override - Future saveSettings(String settings) async { - savedSettings = settings; - } -} diff --git a/flutter/test/android_widget_assets_test.dart b/flutter/test/android_widget_assets_test.dart deleted file mode 100644 index 8e9eafc5..00000000 --- a/flutter/test/android_widget_assets_test.dart +++ /dev/null @@ -1,43 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_test/flutter_test.dart'; - -void main() { - test('ships native Android journal and capture widgets', () { - final manifest = File('android/app/src/main/AndroidManifest.xml') - .readAsStringSync(); - expect(manifest, contains('.TodayJournalWidgetProvider')); - expect(manifest, contains('.CaptureWidgetProvider')); - expect(manifest, contains('@xml/today_journal_widget_info')); - expect(manifest, contains('@xml/capture_widget_info')); - - final provider = File( - 'android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt', - ).readAsStringSync(); - expect(provider, contains('logseqchat://journal')); - expect(provider, contains('logseqchat://capture')); - - final capture = File( - 'android/app/src/main/res/layout/widget_capture.xml', - ).readAsStringSync(); - expect(capture, contains('@drawable/ic_widget_capture')); - expect(capture, isNot(contains('android:text="+"'))); - - for (final name in [ - 'widget_today_journal.xml', - 'widget_capture.xml', - ]) { - final layout = File( - 'android/app/src/main/res/layout/$name', - ).readAsStringSync(); - expect(layout, contains('@color/widget_on_surface')); - expect(layout, contains('@color/widget_secondary')); - } - - final night = File( - 'android/app/src/main/res/values-night/colors.xml', - ).readAsStringSync(); - expect(night, contains('name="widget_background"')); - expect(night, contains('name="widget_on_surface"')); - }); -} diff --git a/flutter/test/core_bootstrap_test.dart b/flutter/test/core_bootstrap_test.dart deleted file mode 100644 index 391ebc2b..00000000 --- a/flutter/test/core_bootstrap_test.dart +++ /dev/null @@ -1,167 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/core_bootstrap.dart'; - -void main() { - test( - 'opens the catalog, configures auth, and restores a local graph', - () async { - final requests = >[]; - final bootstrap = CoreBootstrap( - callCore: (encoded) async { - final request = jsonDecode(encoded) as Map; - requests.add(request); - final method = request['method']; - final params = request['params'] as Map; - final action = params['action']; - if (method == 'open') { - return _response({ - 'graphs': [ - {'id': 'graph-a', 'name': 'Work', 'isEncrypted': false}, - ], - }); - } - if (action == 'openGraph') { - return _response({ - 'selectedGraphId': 'graph-a', - 'outlinerRows': [], - }); - } - return _response({}); - }, - ); - - final result = await bootstrap.restore( - const CoreStartupState( - databasePath: '/data/logseq-chat.sqlite', - graphsDirectory: '/data/graphs', - baseUrl: 'https://api.logseq.test', - selectedGraphId: 'graph-a', - localGraphIds: ['graph-a'], - accessToken: 'token', - ), - ); - - expect(requests.map((request) => request['method']), [ - 'open', - 'dispatch', - 'dispatch', - ]); - expect( - (requests[1]['params'] as Map)['action'], - 'configure', - ); - final openGraphParams = requests[2]['params'] as Map; - expect(openGraphParams['action'], 'openGraph'); - expect( - jsonDecode(openGraphParams['payload']! as String), - containsPair('activePath', '/data/graphs/graph-a/graph.sqlite'), - ); - expect(result.graphResponse, isNotNull); - expect(result.localGraphIds, ['graph-a']); - }, - ); - - test( - 'shows the catalog without blocking on a missing selected graph', - () async { - final actions = []; - final bootstrap = CoreBootstrap( - callCore: (encoded) async { - final request = jsonDecode(encoded) as Map; - actions.add((request['params'] as Map)['action']); - return _response({'graphs': []}); - }, - ); - - final result = await bootstrap.restore( - const CoreStartupState( - databasePath: '/data/logseq-chat.sqlite', - graphsDirectory: '/data/graphs', - baseUrl: 'http://127.0.0.1:8787', - selectedGraphId: '', - localGraphIds: [], - accessToken: '', - ), - ); - - expect(actions, [null, 'configure']); - expect(result.graphResponse, isNull); - }, - ); - - test('does not open an encrypted graph until it is unlocked', () async { - final actions = []; - final bootstrap = CoreBootstrap( - callCore: (encoded) async { - final request = jsonDecode(encoded) as Map; - final action = (request['params'] as Map)['action']; - actions.add(action); - return action == null - ? _response({ - 'graphs': [ - {'id': 'private', 'name': 'Private', 'isEncrypted': true}, - ], - }) - : _response({}); - }, - ); - - final result = await bootstrap.restore( - const CoreStartupState( - databasePath: '/data/logseq-chat.sqlite', - graphsDirectory: '/data/graphs', - baseUrl: 'https://api.logseq.test', - selectedGraphId: 'private', - localGraphIds: ['private'], - accessToken: 'token', - ), - ); - - expect(actions, [null, 'configure']); - expect(result.graphResponse, isNull); - }); - - test('traces every startup core boundary with its elapsed time', () async { - final traces = []; - final bootstrap = CoreBootstrap( - trace: traces.add, - callCore: (encoded) async { - final request = jsonDecode(encoded) as Map; - final action = (request['params'] as Map)['action']; - return action == null - ? _response({ - 'graphs': [ - {'id': 'graph-a', 'name': 'Work', 'isEncrypted': false}, - ], - }) - : _response({}); - }, - ); - - await bootstrap.restore( - const CoreStartupState( - databasePath: '/data/logseq-chat.sqlite', - graphsDirectory: '/data/graphs', - baseUrl: 'https://api.logseq.test', - selectedGraphId: 'graph-a', - localGraphIds: ['graph-a'], - accessToken: 'token', - ), - ); - - expect(traces.where((trace) => trace.endsWith('started')), [ - 'open catalog started', - 'configure graph started', - 'open local graph started', - ]); - expect( - traces.where((trace) => trace.contains('completed durationMs=')), - hasLength(3), - ); - }); -} - -String _response(Map result) => - jsonEncode({'apiVersion': 1, 'ok': true, 'result': result}); diff --git a/flutter/test/core_effect_executor_test.dart b/flutter/test/core_effect_executor_test.dart deleted file mode 100644 index e4827aed..00000000 --- a/flutter/test/core_effect_executor_test.dart +++ /dev/null @@ -1,320 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/core_effect_executor.dart'; -import 'package:logseq_chat_flutter/native_effect_drain.dart'; - -void main() { - const successfulResponse = '{"apiVersion":1,"ok":true,"result":{}}'; - - test( - 'routes every core-backed effect through the native RPC contract', - () async { - final requests = >[]; - final executor = CoreEffectExecutor( - callCore: (request) async { - requests.add(jsonDecode(request) as Map); - return successfulResponse; - }, - executePlatformEffect: (_) async => - const NativeEffectResolution.discard(), - executeGraphEffect: (_) async => const NativeEffectResolution.discard(), - nowMilliseconds: () => 1234, - newUuid: () => 'operation-id', - ); - - final cases = <(NativeEffect, String)>[ - (const NativeEffect(id: 1, kind: 'send-capture', text: 'Note'), 'send'), - ( - const NativeEffect( - id: 2, - kind: 'send-task', - text: 'Task', - metadata: - '{"uuid":"todo","ident":"status.todo","title":"Todo",' - '"iconType":null,"iconId":null,"iconColor":null}', - ), - 'sendTask', - ), - ( - const NativeEffect(id: 3, kind: 'search-nodes', text: 'query'), - 'searchNodes', - ), - ( - const NativeEffect(id: 4, kind: 'open-node', text: 'node'), - 'openNode', - ), - ( - const NativeEffect(id: 5, kind: 'close-node', text: 'node'), - 'closeNode', - ), - ( - const NativeEffect(id: 6, kind: 'select-sidebar-page', text: 'page'), - 'selectPage', - ), - ( - const NativeEffect(id: 7, kind: 'clear-selected-page', text: ''), - 'clearSelectedPage', - ), - ( - const NativeEffect(id: 8, kind: 'load-older-journals', text: ''), - 'loadOlderJournals', - ), - ( - const NativeEffect( - id: 9, - kind: 'set-page-favorite', - text: 'page', - value: 1, - ), - 'setPageFavorite', - ), - ( - const NativeEffect(id: 10, kind: 'delete-page', text: 'page'), - 'deletePage', - ), - ( - const NativeEffect(id: 11, kind: 'load-flashcards', text: ''), - 'loadFlashcards', - ), - ( - const NativeEffect( - id: 12, - kind: 'review-flashcard', - text: 'good', - uuid: 'card', - ), - 'reviewFlashcard', - ), - ( - const NativeEffect(id: 13, kind: 'refresh-graphs', text: ''), - 'refresh', - ), - ( - const NativeEffect(id: 17, kind: 'tap-outliner-block', text: 'block'), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 18, - kind: 'toggle-outliner-collapsed', - text: 'block', - ), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 19, - kind: 'long-press-outliner-block', - text: 'block', - ), - 'outlinerEvent', - ), - ( - const NativeEffect(id: 20, kind: 'add-root-block', text: 'block'), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 21, - kind: 'drop-outliner-blocks', - text: 'target', - metadata: 'inside', - ), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 22, - kind: 'set-outliner-task-status', - text: 'block', - metadata: - '{"uuid":"done","ident":"status.done","title":"Done",' - '"iconType":null,"iconId":null,"iconColor":null}', - ), - 'outlinerEvent', - ), - ( - const NativeEffect(id: 23, kind: 'outliner-toolbar', text: 'indent'), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 24, - kind: 'choose-outliner-autocomplete', - text: '[[Page]]', - ), - 'outlinerEvent', - ), - ( - const NativeEffect(id: 25, kind: 'cancel-outliner-editing', text: ''), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 26, - kind: 'change-outliner-text', - text: 'Updated', - uuid: 'block', - value: 7, - ), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 27, - kind: 'return-outliner-editor', - text: 'Updated', - uuid: 'block', - value: 7, - ), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 28, - kind: 'backspace-outliner-editor', - text: '', - uuid: 'block', - value: 0, - ), - 'outlinerEvent', - ), - ( - const NativeEffect( - id: 29, - kind: 'move-outliner-caret', - text: '', - uuid: 'block', - value: 4, - ), - 'outlinerEvent', - ), - ]; - - for (final (effect, expectedAction) in cases) { - final resolution = await executor.execute(effect); - expect(resolution.succeeded, isTrue, reason: effect.kind); - expect(resolution.output, NativeEffectOutputKind.coreResponse); - expect( - ((requests.last['params'] as Map)['action']), - expectedAction, - reason: effect.kind, - ); - } - }, - ); - - test('delegates Android-owned effects without touching the core', () async { - final delegated = []; - final executor = CoreEffectExecutor( - callCore: (_) async => fail('platform effects must not call the core'), - executePlatformEffect: (effect) async { - delegated.add(effect.kind); - return const NativeEffectResolution.discard(); - }, - executeGraphEffect: (_) async => const NativeEffectResolution.discard(), - ); - - const kinds = [ - 'persist-composer-draft', - 'present-attachment', - 'present-asset', - 'present-page-share', - 'sync-now', - 'delete-local-graph', - 'save-settings', - 'export-graph-database', - 'open-external-url', - 'refresh-runtime-log', - 'copy-runtime-log', - 'sign-in', - 'sign-out', - ]; - - for (final kind in kinds) { - await executor.execute(NativeEffect(id: 1, kind: kind, text: '')); - } - - expect(delegated, kinds); - }); - - test('delegates graph lifecycle effects without issuing raw RPCs', () async { - final delegated = []; - final executor = CoreEffectExecutor( - callCore: (_) async => fail('graph effects must use the lifecycle'), - executePlatformEffect: (_) async => - const NativeEffectResolution.discard(), - executeGraphEffect: (effect) async { - delegated.add(effect.kind); - return const NativeEffectResolution.discard(); - }, - ); - - for (final kind in ['open-graph', 'unlock-graph', 'create-graph']) { - await executor.execute(NativeEffect(id: 1, kind: kind, text: 'graph')); - } - - expect(delegated, ['open-graph', 'unlock-graph', 'create-graph']); - }); - - test( - 'surfaces typed native core failures without applying a snapshot', - () async { - final executor = CoreEffectExecutor( - callCore: (_) async => - '{"apiVersion":1,"ok":false,"error":{"code":"invalid",' - '"message":"Bad request"}}', - executePlatformEffect: (_) async => - const NativeEffectResolution.discard(), - executeGraphEffect: (_) async => const NativeEffectResolution.discard(), - ); - - final resolution = await executor.execute( - const NativeEffect(id: 1, kind: 'search-nodes', text: 'query'), - ); - - expect(resolution.succeeded, isFalse); - expect(resolution.output, NativeEffectOutputKind.discard); - expect(resolution.message, 'invalid\nBad request'); - }, - ); - - test('rejects unknown effects explicitly', () async { - final executor = CoreEffectExecutor( - callCore: (_) async => successfulResponse, - executePlatformEffect: (_) async => - const NativeEffectResolution.discard(), - executeGraphEffect: (_) async => const NativeEffectResolution.discard(), - ); - - final resolution = await executor.execute( - const NativeEffect(id: 1, kind: 'unknown-effect', text: ''), - ); - - expect(resolution.succeeded, isFalse); - expect(resolution.message, 'Unsupported LG effect: unknown-effect'); - }); - - test('autosave reuses the authoritative core saveEditing event', () async { - Map? request; - final executor = CoreEffectExecutor( - callCore: (encoded) async { - request = jsonDecode(encoded) as Map; - return successfulResponse; - }, - executePlatformEffect: (_) async => - const NativeEffectResolution.discard(), - executeGraphEffect: (_) async => const NativeEffectResolution.discard(), - ); - - final resolution = await executor.execute( - const NativeEffect(id: 0, kind: 'save-outliner-editing', text: ''), - ); - - final params = request!['params']! as Map; - expect(params['action'], 'outlinerEvent'); - expect(jsonDecode(params['payload']! as String), {'type': 'saveEditing'}); - expect(resolution.succeeded, isTrue); - }); -} diff --git a/flutter/test/flutter_patch_applier_test.dart b/flutter/test/flutter_patch_applier_test.dart deleted file mode 100644 index e5366fac..00000000 --- a/flutter/test/flutter_patch_applier_test.dart +++ /dev/null @@ -1,339 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/flutter_patch_applier.dart'; -import 'package:logseq_chat_flutter/logseq_chat_icons.dart'; -import 'package:logseq_chat_flutter/logseq_chat_theme.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -void main() { - test('applies consecutive Settings and Add graph sheets', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'sheet'), - _setProperty(1, 'text', 'Settings'), - _setProperty(1, 'style-class', 'navigation-scroll'), - ]), - ); - applier.applyJson( - _patch(2, [ - _createNode(2, 'sheet'), - _setProperty(2, 'text', 'Add sync graph'), - _setProperty(2, 'style-class', 'navigation-form'), - ]), - ); - - expect(backend.generation, 2); - expect(backend.containsNode(1), isTrue); - expect(backend.containsNode(2), isTrue); - }); - - test('notifies the host only when a mounted structure changes', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - applier.applyJson( - _patch(1, [ - _createNode(1, 'stack'), - _createNode(2, 'text'), - _setProperty(2, 'text', 'Before'), - _insertChild(1, 2, 0), - ]), - ); - var notifications = 0; - applier.addListener(() => notifications += 1); - - applier.applyJson(_patch(2, [_setProperty(2, 'text', 'Updated')])); - - expect(notifications, 0); - - applier.applyJson( - _patch(3, [ - _createNode(3, 'text'), - _setProperty(3, 'text', 'After'), - _insertChild(1, 3, 0), - _removeChild(1, 2), - _dropNode(2), - ]), - ); - - expect(notifications, 1); - }); - - for (final sheet in const [ - (title: 'Settings', styleClass: 'navigation-scroll'), - (title: 'Add sync graph', styleClass: 'navigation-form'), - ]) { - testWidgets('renders the ${sheet.title} bottom sheet', (tester) async { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - final operations = >[ - _createNode(1, 'sheet'), - _setProperty(1, 'text', sheet.title), - _setProperty(1, 'style-class', sheet.styleClass), - ]; - if (sheet.title == 'Settings') { - operations.addAll([ - _setProperty(1, 'height', 640), - _createNode(2, 'column'), - _setProperty(2, 'grow', 1.0), - _createNode(5, 'scroll'), - _setProperty(5, 'grow', 1.0), - _createNode(6, 'column'), - for (var id = 10; id < 50; id++) ...[ - _createNode(id, 'text'), - _setProperty(id, 'text', 'Settings row $id'), - _insertChild(6, id, id - 10), - ], - _insertChild(5, 6, 0), - _insertChild(2, 5, 0), - _createNode(3, 'toolbar'), - _setProperty(3, 'accessibility-label', 'Settings actions'), - _createNode(4, 'button'), - _setProperty(4, 'text', 'Apply'), - _insertChild(3, 4, 0), - _insertChild(2, 3, 1), - _insertChild(1, 2, 0), - ]); - } - - applier.applyJson(_patch(1, operations)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.pumpAndSettle(); - - expect(find.byKey(const ValueKey('lui-sheet-surface-1')), findsOneWidget); - expect(find.text(sheet.title), findsOneWidget); - expect( - tester - .getSize(find.byKey(const ValueKey('lui-sheet-surface-1'))) - .height, - greaterThan(0), - ); - expect(tester.takeException(), isNull); - }); - } - - testWidgets('renders Material navigation chrome at standard size', ( - tester, - ) async { - final backend = LUIFlutterBackend(appIcons: logseqChatAppIcons); - final applier = FlutterPatchApplier(backend); - applier.applyJson( - _patch(1, [ - _createNode(1, 'row'), - _createNode(2, 'button'), - _setProperty(2, 'icon', 'app:sidebar-toggle'), - _setProperty(2, 'size', 'icon'), - _setProperty(2, 'variant', 'ghost'), - _setProperty(2, 'accessibility-label', 'Open sidebar'), - _createNode(3, 'heading'), - _setProperty(3, 'text', 'Journals'), - _setProperty(3, 'heading-level', 3), - _insertChild(1, 2, 0), - _insertChild(1, 3, 1), - ]), - ); - - await tester.pumpWidget( - MaterialApp( - theme: LogseqChatTheme.light(), - home: Scaffold(body: Center(child: backend.widget(node: 1))), - ), - ); - - final icon = tester.widget(find.byIcon(Icons.menu_rounded)); - final button = find.byType(TextButton); - final buttonWidget = tester.widget(button); - final title = tester.widget(find.text('Journals')); - expect(icon.size, 24); - expect( - buttonWidget.style?.minimumSize?.resolve({}), - const Size.square(48), - ); - expect(title.style?.fontSize, 22); - }); - - test('keeps generation continuous when an ignored property is removed', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'dialog'), - _setProperty(1, 'text', 'Delete page'), - _setProperty(1, 'style-class', 'alert'), - ]), - ); - applier.applyJson(_patch(2, [_removeProperty(1, 'style-class')])); - - expect(backend.generation, 2); - }); - - test('drops SwiftUI container sizing hints', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'column'), - _setProperty(1, 'container-relative-frame', 'vertical'), - _setProperty(1, 'container-relative-frame-inset', 136), - ]), - ); - - expect(backend.generation, 1); - expect(backend.containsNode(1), isTrue); - }); - - test('drops unsupported list and top icon presentation hints', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'list-item'), - _setProperty(1, 'text', 'Journals'), - _setProperty(1, 'role', 'navigation'), - _setProperty(1, 'icon-placement', 'trailing'), - _createNode(2, 'button'), - _setProperty(2, 'text', 'Copy'), - _setProperty(2, 'icon-placement', 'top'), - ]), - ); - - expect(backend.generation, 1); - }); - - test('preserves supported context menu presentation metadata', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'list-item'), - _setProperty(1, 'text', 'Graph'), - _setProperty(1, 'press-enabled', true), - _createNode(2, 'context-menu'), - _createNode(3, 'menu-item'), - _setProperty(3, 'text', 'Delete local graph'), - _setProperty(3, 'icon', 'trash'), - _setProperty(3, 'foreground', 'destructive'), - _setProperty(3, 'press-enabled', true), - _setProperty(3, 'enabled', true), - _insertChild(2, 3, 0), - _insertChild(1, 2, 0), - ]), - ); - - expect(backend.generation, 1); - expect(backend.containsNode(3), isTrue); - }); - - test('drops the SwiftUI retained-pane selection hint from virtual lists', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'virtual-list'), - _setProperty(1, 'selected', true), - ]), - ); - - expect(backend.generation, 1); - expect(backend.containsNode(1), isTrue); - }); - - test( - 'drops axis-specific padding from controls that only support total padding', - () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'button'), - _setProperty(1, 'text', 'Capture'), - _setProperty(1, 'padding-horizontal', 8), - ]), - ); - - expect(backend.generation, 1); - expect(backend.containsNode(1), isTrue); - }, - ); - - test('preserves Flutter-supported presentation properties', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - applier.applyJson( - _patch(1, [ - _createNode(1, 'toolbar'), - _setProperty(1, 'accessibility-label', 'Actions'), - _setProperty(1, 'style-class', 'navigation-actions'), - _createNode(2, 'button'), - _setProperty(2, 'text', 'Continue'), - _setProperty(2, 'icon-placement', 'trailing'), - ]), - ); - - expect(backend.generation, 1); - }); - - test('does not hide unsupported behavioral properties', () { - final backend = LUIFlutterBackend(); - final applier = FlutterPatchApplier(backend); - - expect( - () => applier.applyJson( - _patch(1, [_createNode(1, 'text'), _setProperty(1, 'enabled', true)]), - ), - throwsA(isA()), - ); - expect(backend.generation, 0); - expect(backend.containsNode(1), isFalse); - }); -} - -String _patch(int generation, List> operations) => - jsonEncode({'generation': generation, 'ops': operations}); - -Map _createNode(int id, String kind) => { - 'op': 'create-node', - 'id': id, - 'kind': kind, -}; - -Map _setProperty(int id, String property, Object value) => { - 'op': 'set-prop', - 'id': id, - 'property': property, - 'value': value, -}; - -Map _removeProperty(int id, String property) => { - 'op': 'remove-prop', - 'id': id, - 'property': property, -}; - -Map _insertChild(int parent, int child, int index) => { - 'op': 'insert-child', - 'parent': parent, - 'child': child, - 'index': index, -}; - -Map _removeChild(int parent, int child) => { - 'op': 'remove-child', - 'parent': parent, - 'child': child, -}; - -Map _dropNode(int id) => {'op': 'drop-node', 'id': id}; diff --git a/flutter/test/graph_catalog_auto_refresh_test.dart b/flutter/test/graph_catalog_auto_refresh_test.dart deleted file mode 100644 index f0926cbc..00000000 --- a/flutter/test/graph_catalog_auto_refresh_test.dart +++ /dev/null @@ -1,175 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/graph_catalog_auto_refresh.dart'; - -void main() { - test( - 'refreshes the graph catalog and applies the authoritative response', - () async { - final requests = >[]; - final applied = []; - final refresher = GraphCatalogAutoRefresh( - callCore: (encoded) async { - requests.add(jsonDecode(encoded) as Map); - return _response({'graphs': const []}); - }, - applyCoreResponse: (response) async => applied.add(response), - ); - - final refreshed = await refresher.refresh(); - - expect(refreshed, isTrue); - expect(requests, hasLength(1)); - expect(requests.single['method'], 'dispatch'); - expect( - (requests.single['params'] as Map)['action'], - 'refreshGraphCatalog', - ); - expect(applied, hasLength(1)); - }, - ); - - test('coalesces overlapping automatic refresh requests', () async { - final response = Completer(); - var requestCount = 0; - var applyCount = 0; - final refresher = GraphCatalogAutoRefresh( - callCore: (_) { - requestCount += 1; - return response.future; - }, - applyCoreResponse: (_) async => applyCount += 1, - ); - - final first = refresher.refresh(); - final second = refresher.refresh(); - response.complete(_response({'graphs': const []})); - - expect(await first, isTrue); - expect(await second, isTrue); - expect(requestCount, 1); - expect(applyCount, 1); - }); - - test('skips applying an unchanged catalog after bootstrap', () async { - final initial = _response({ - 'graphs': [ - {'id': 'graph-a', 'name': 'Graph A'}, - ], - }); - var applyCount = 0; - final refresher = GraphCatalogAutoRefresh( - callCore: (_) async => initial, - applyCoreResponse: (_) async => applyCount += 1, - ); - refresher.rememberCatalog(initial); - - expect(await refresher.refresh(), isTrue); - expect(applyCount, 0); - }); - - test('applies a catalog when its graph collection changes', () async { - final initial = _response({ - 'graphs': [ - {'id': 'graph-a', 'name': 'Graph A'}, - ], - }); - final changed = _response({ - 'graphs': [ - {'id': 'graph-a', 'name': 'Graph A'}, - {'id': 'graph-b', 'name': 'Graph B'}, - ], - }); - var applyCount = 0; - final refresher = GraphCatalogAutoRefresh( - callCore: (_) async => changed, - applyCoreResponse: (_) async => applyCount += 1, - ); - refresher.rememberCatalog(initial); - - expect(await refresher.refresh(), isTrue); - expect(applyCount, 1); - }); - - test('does not apply a rejected graph catalog response', () async { - var applyCount = 0; - final traces = []; - final refresher = GraphCatalogAutoRefresh( - callCore: (_) async => jsonEncode({ - 'apiVersion': 1, - 'ok': false, - 'error': {'code': 'offline', 'message': 'Server unavailable'}, - }), - applyCoreResponse: (_) async => applyCount += 1, - trace: traces.add, - ); - - expect(await refresher.refresh(), isFalse); - expect(applyCount, 0); - expect( - traces, - contains( - 'refresh.rejected code=offline message=Server unavailable', - ), - ); - }); - - test('periodically refreshes the graph catalog while started', () async { - Duration? scheduledInterval; - void Function()? scheduledTick; - final applied = Completer(); - final refresher = GraphCatalogAutoRefresh( - callCore: (_) async => _response({'graphs': const []}), - applyCoreResponse: (_) async => applied.complete(), - schedulePeriodic: (interval, tick) { - scheduledInterval = interval; - scheduledTick = tick; - return _TestTimer(); - }, - ); - - refresher.startPeriodic(interval: const Duration(seconds: 15)); - scheduledTick!(); - await applied.future; - - expect(scheduledInterval, const Duration(seconds: 15)); - }); - - test('starts only one periodic refresh loop and cancels it when stopped', () { - final timers = <_TestTimer>[]; - final refresher = GraphCatalogAutoRefresh( - callCore: (_) async => _response({'graphs': const []}), - applyCoreResponse: (_) async {}, - schedulePeriodic: (_, _) { - final timer = _TestTimer(); - timers.add(timer); - return timer; - }, - ); - - refresher.startPeriodic(); - refresher.startPeriodic(); - refresher.stopPeriodic(); - - expect(timers, hasLength(1)); - expect(timers.single.isActive, isFalse); - }); -} - -final class _TestTimer implements Timer { - var _isActive = true; - - @override - bool get isActive => _isActive; - - @override - int get tick => 0; - - @override - void cancel() => _isActive = false; -} - -String _response(Map result) => - jsonEncode({'apiVersion': 1, 'ok': true, 'result': result}); diff --git a/flutter/test/graph_catalog_polling_policy_test.dart b/flutter/test/graph_catalog_polling_policy_test.dart deleted file mode 100644 index 3c4cfa2e..00000000 --- a/flutter/test/graph_catalog_polling_policy_test.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/graph_catalog_polling_policy.dart'; - -void main() { - test('polls only while an authenticated graph picker is foreground', () { - expect( - shouldPollGraphCatalog( - authenticated: true, - hasOpenGraph: false, - foreground: true, - ), - isTrue, - ); - expect( - shouldPollGraphCatalog( - authenticated: true, - hasOpenGraph: true, - foreground: true, - ), - isFalse, - ); - expect( - shouldPollGraphCatalog( - authenticated: true, - hasOpenGraph: false, - foreground: false, - ), - isFalse, - ); - }); -} diff --git a/flutter/test/lazy_journal_list_test.dart b/flutter/test/lazy_journal_list_test.dart deleted file mode 100644 index daca71ef..00000000 --- a/flutter/test/lazy_journal_list_test.dart +++ /dev/null @@ -1,58 +0,0 @@ -import 'dart:convert'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -void main() { - testWidgets('journal virtual list lazily builds offscreen rows', ( - tester, - ) async { - final backend = LUIFlutterBackend(); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_journalPatch(rowCount: 100))); - - await tester.pumpWidget( - MaterialApp( - home: Scaffold( - body: SizedBox(height: 320, child: backend.widget(node: 1)), - ), - ), - ); - - expect(find.byType(ListView), findsOneWidget); - expect(find.text('Journal row 0'), findsOneWidget); - expect(find.text('Journal row 99'), findsNothing); - - await tester.scrollUntilVisible( - find.text('Journal row 99'), - 300, - scrollable: find.byType(Scrollable), - ); - - expect(find.text('Journal row 99'), findsOneWidget); - }); -} - -Map _journalPatch({required int rowCount}) { - final operations = >[ - {'op': 'create-node', 'id': 1, 'kind': 'root'}, - {'op': 'create-node', 'id': 2, 'kind': 'virtual-list'}, - {'op': 'set-prop', 'id': 2, 'property': 'grow', 'value': 1.0}, - {'op': 'insert-child', 'parent': 1, 'child': 2, 'index': 0}, - ]; - for (var index = 0; index < rowCount; index += 1) { - final id = index + 3; - operations.addAll([ - {'op': 'create-node', 'id': id, 'kind': 'text'}, - { - 'op': 'set-prop', - 'id': id, - 'property': 'text', - 'value': 'Journal row $index', - }, - {'op': 'insert-child', 'parent': 2, 'child': id, 'index': index}, - ]); - } - return {'generation': 1, 'ops': operations}; -} diff --git a/flutter/test/logseq_chat_app_frame_test.dart b/flutter/test/logseq_chat_app_frame_test.dart deleted file mode 100644 index dec3ed26..00000000 --- a/flutter/test/logseq_chat_app_frame_test.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/logseq_chat_app_frame.dart'; - -void main() { - testWidgets('keeps app content outside Android system bars', (tester) async { - const systemPadding = EdgeInsets.only(top: 48, bottom: 24); - - await tester.pumpWidget( - const MaterialApp( - home: MediaQuery( - data: MediaQueryData(padding: systemPadding), - child: LogseqChatAppFrame( - child: SizedBox.expand(key: ValueKey('content')), - ), - ), - ), - ); - - final content = tester.getRect(find.byKey(const ValueKey('content'))); - expect(content.top, systemPadding.top); - expect(content.bottom, 600 - systemPadding.bottom); - }); -} diff --git a/flutter/test/logseq_chat_extensions_test.dart b/flutter/test/logseq_chat_extensions_test.dart deleted file mode 100644 index 94f37d38..00000000 --- a/flutter/test/logseq_chat_extensions_test.dart +++ /dev/null @@ -1,1456 +0,0 @@ -import 'dart:convert'; -import 'dart:ui' show SemanticsAction; - -import 'package:flutter/gestures.dart' show kLongPressTimeout; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/logseq_chat_extensions.dart'; -import 'package:logseq_chat_flutter/logseq_chat_icons.dart'; -import 'package:logseq_chat_flutter/logseq_chat_theme.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -void main() { - Future mountEditor( - WidgetTester tester, - List events, { - String title = 'Before', - }) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson( - jsonEncode({ - 'generation': 1, - 'ops': [ - ...(_editorPatch['ops']! as List>), - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': title, - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': title.length, - }, - ], - }), - ); - await tester.pumpWidget( - MaterialApp( - theme: LogseqChatTheme.light(), - home: Scaffold(body: backend.widget(node: 1)), - ), - ); - await tester.pump(); - events.clear(); - return backend; - } - - Iterable edits( - List events, - String name, - ) => events.whereType().where( - (event) => event.name == name, - ); - - testWidgets( - 'typing in an existing multiline block preserves its line breaks', - (tester) async { - final events = []; - await mountEditor(tester, events, title: 'first\nsecond'); - await tester.enterText(find.byType(TextField), 'first\nsecond!'); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'return'), isEmpty); - expect( - edits(events, 'text-change').single.values['title'], - 'first\nsecond!', - ); - }, - ); - - testWidgets('pasting multiline content does not create a block', ( - tester, - ) async { - final events = []; - await mountEditor(tester, events); - await tester.enterText(find.byType(TextField), 'first\nsecond'); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'return'), isEmpty); - expect( - edits(events, 'text-change').single.values['title'], - 'first\nsecond', - ); - }); - - testWidgets('Enter removes only the newly inserted line break', ( - tester, - ) async { - final events = []; - await mountEditor(tester, events, title: 'first\nsecond'); - await tester.enterText(find.byType(TextField), 'first\nsecond\n'); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'return').single.values, { - 'title': 'first\nsecond', - 'caret-utf16-offset': 12, - }); - expect(edits(events, 'text-change'), isEmpty); - }); - - testWidgets('Shift Enter inserts a newline without submitting', ( - tester, - ) async { - final events = []; - await mountEditor(tester, events); - await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft); - tester.testTextInput.updateEditingValue( - const TextEditingValue( - text: 'Before\n', - selection: TextSelection.collapsed(offset: 7), - ), - ); - await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'return'), isEmpty); - expect(edits(events, 'text-change').single.values['title'], 'Before\n'); - }); - - testWidgets('unrelated model updates cannot overwrite pending typing', ( - tester, - ) async { - final events = []; - final backend = await mountEditor(tester, events); - await tester.enterText(find.byType(TextField), 'Before!'); - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': 2, - }, - ], - }), - ); - await tester.pump(); - expect( - tester.widget(find.byType(TextField)).controller!.text, - 'Before!', - ); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'text-change').last.values['title'], 'Before!'); - }); - - testWidgets('model caret updates apply when block text is unchanged', ( - tester, - ) async { - final events = []; - final backend = await mountEditor(tester, events); - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': 2, - }, - ], - }), - ); - await tester.pump(); - expect( - tester - .widget(find.byType(TextField)) - .controller! - .selection - .baseOffset, - 2, - ); - expect(edits(events, 'text-change'), isEmpty); - }); - - testWidgets('IME composition is published only after committing', ( - tester, - ) async { - final events = []; - await mountEditor(tester, events); - tester.testTextInput.updateEditingValue( - const TextEditingValue( - text: 'Before中文', - selection: TextSelection.collapsed(offset: 8), - composing: TextRange(start: 6, end: 8), - ), - ); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'text-change'), isEmpty); - tester.testTextInput.updateEditingValue( - const TextEditingValue( - text: 'Before中文', - selection: TextSelection.collapsed(offset: 8), - ), - ); - await tester.pump(const Duration(milliseconds: 100)); - expect(edits(events, 'text-change').single.values['title'], 'Before中文'); - }); - - testWidgets( - 'search offers a clear action without dismissing or losing input focus', - (tester) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_searchPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.enterText(find.byType(SearchBar), 'project'); - await tester.pump(); - await tester.tap(find.byTooltip('Clear search')); - await tester.pump(); - expect( - tester.widget(find.byType(SearchBar)).controller!.text, - isEmpty, - ); - expect( - tester - .widget(find.byType(EditableText)) - .focusNode - .hasFocus, - isTrue, - ); - expect(edits(events, 'query-changed').last.values['query'], ''); - expect(edits(events, 'dismiss'), isEmpty); - }, - ); - - for (final title in ['Before', 'first\nsecond']) { - testWidgets('read and edit layout retain the same height for $title', ( - tester, - ) async { - final readBackend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - ); - addTearDown(readBackend.dispose); - readBackend.applyJson( - jsonEncode({ - 'generation': 1, - 'ops': [ - ...(_richMarkupPatch['ops']! as List>), - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': title, - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'markup-json', - 'value': '[]', - }, - ], - }), - ); - await tester.pumpWidget( - MaterialApp( - theme: LogseqChatTheme.light(), - home: Scaffold(body: readBackend.widget(node: 1)), - ), - ); - final height = tester - .getSize(find.byKey(const ValueKey('outliner-block-content-block-a'))) - .height; - await mountEditor(tester, [], title: title); - expect( - tester.getSize(find.byType(TextField)).height, - closeTo(height, 0.5), - ); - }); - } - - testWidgets( - 'search ignores unrelated patches while typing and animates dismissal', - (tester) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_searchPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.pump(const Duration(milliseconds: 200)); - await tester.enterText(find.byType(SearchBar), 'local query'); - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': 'Updated title', - }, - ], - }), - ); - await tester.pump(); - expect( - tester.widget(find.byType(SearchBar)).controller!.text, - 'local query', - ); - await tester.tap(find.byTooltip('Close search')); - await tester.pump(); - expect(edits(events, 'dismiss'), isEmpty); - await tester.pump(const Duration(milliseconds: 200)); - expect(edits(events, 'dismiss'), hasLength(1)); - }, - ); - - testWidgets( - 'delayed editing acknowledgements preserve newer text and caret', - (tester) async { - final events = []; - final backend = await mountEditor(tester, events); - await tester.enterText(find.byType(TextField), 'Before one'); - await tester.pump(const Duration(milliseconds: 100)); - await tester.enterText(find.byType(TextField), 'Before one two'); - await tester.pump(const Duration(milliseconds: 100)); - final controller = tester - .widget(find.byType(TextField)) - .controller!; - controller.selection = const TextSelection.collapsed(offset: 3); - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': 'Before one', - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': 10, - }, - ], - }), - ); - await tester.pump(); - expect(controller.text, 'Before one two'); - expect(controller.selection.baseOffset, 3); - backend.applyJson( - jsonEncode({ - 'generation': 3, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': 'Before one two', - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': 14, - }, - ], - }), - ); - await tester.pump(); - expect(controller.selection.baseOffset, 3); - }, - ); - - testWidgets('resolves relative image assets against Android app storage', ( - tester, - ) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry( - resolveAssetPath: (path) => '/data/user/0/com.logseq.chat/files/$path', - ), - ); - addTearDown(backend.dispose); - final patch = Map.from(_richMarkupPatch); - patch['ops'] = [ - ...(_richMarkupPatch['ops']! as List>), - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'is-asset', - 'value': true, - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'asset-type', - 'value': 'png', - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'local-path', - 'value': 'Assets/screenshot.png', - }, - ]; - backend.applyJson(jsonEncode(patch)); - - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final image = tester.widget(find.byType(Image)); - expect( - (image.image as FileImage).file.path, - '/data/user/0/com.logseq.chat/files/Assets/screenshot.png', - ); - final preview = tester.getSemantics( - find.byKey(const ValueKey('asset.preview.image')), - ); - expect(preview.identifier, 'asset.preview.image'); - }); - - testWidgets('registers and renders every Android Flutter extension', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - appIcons: logseqChatAppIcons, - onEvent: events.add, - ); - addTearDown(backend.dispose); - - backend.applyJson(jsonEncode(_extensionPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - expect(find.byType(PopScope), findsWidgets); - expect(find.byType(SearchBar), findsOneWidget); - expect(find.byType(MenuAnchor), findsWidgets); - final overflow = tester.getSemantics( - find.byWidgetPredicate( - (widget) => - widget is Semantics && - widget.properties.identifier == 'button.overflow-menu', - ), - ); - expect(overflow.identifier, 'button.overflow-menu'); - expect(find.byType(TextField), findsWidgets); - expect(find.text('Linked page'), findsOneWidget); - }); - - testWidgets('system back reaches the native navigation boundary', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_extensionPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - expect(await tester.binding.handlePopRoute(), isTrue); - await tester.pump(); - - expect( - events, - contains( - const LUIEvent.extension( - node: 5, - identifier: 'native-navigation-stack', - name: 'back', - values: {'count': 1}, - ), - ), - ); - }); - - testWidgets( - 'repaints when graph picker becomes the journal navigation tree', - (tester) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - ); - addTearDown(backend.dispose); - backend.applyJson( - jsonEncode({ - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'stack'}, - {'op': 'create-node', 'id': 2, 'kind': 'drawer'}, - {'op': 'set-prop', 'id': 2, 'property': 'selected', 'value': false}, - {'op': 'set-prop', 'id': 2, 'property': 'enabled', 'value': false}, - { - 'op': 'set-prop', - 'id': 2, - 'property': 'toggle-enabled', - 'value': true, - }, - {'op': 'set-prop', 'id': 2, 'property': 'width', 'value': 360}, - {'op': 'create-node', 'id': 3, 'kind': 'stack'}, - {'op': 'create-node', 'id': 4, 'kind': 'column'}, - {'op': 'create-node', 'id': 5, 'kind': 'text'}, - { - 'op': 'set-prop', - 'id': 5, - 'property': 'text', - 'value': 'Choose a graph', - }, - {'op': 'insert-child', 'parent': 4, 'child': 5, 'index': 0}, - {'op': 'insert-child', 'parent': 3, 'child': 4, 'index': 0}, - {'op': 'create-node', 'id': 6, 'kind': 'column'}, - {'op': 'insert-child', 'parent': 2, 'child': 3, 'index': 0}, - {'op': 'insert-child', 'parent': 2, 'child': 6, 'index': 1}, - {'op': 'insert-child', 'parent': 1, 'child': 2, 'index': 0}, - ], - }), - ); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.pumpAndSettle(); - expect(find.text('Choose a graph'), findsOneWidget); - expect(tester.binding.hasScheduledFrame, isFalse); - - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - {'op': 'remove-child', 'parent': 3, 'child': 4}, - {'op': 'remove-child', 'parent': 4, 'child': 5}, - {'op': 'drop-node', 'id': 4}, - { - 'op': 'create-extension', - 'id': 263, - 'identifier': 'native-navigation-stack', - 'fingerprint': _navigationFingerprint, - }, - for (final entry in { - 'depth': 0, - 'bottom-occupies-layout-space': false, - 'composer-dismissal-enabled': false, - 'title': 'Journals', - }.entries) - { - 'op': 'set-extension-prop', - 'id': 263, - 'property': entry.key, - 'value': entry.value, - }, - {'op': 'create-node', 'id': 264, 'kind': 'column'}, - {'op': 'insert-child', 'parent': 263, 'child': 264, 'index': 0}, - {'op': 'create-node', 'id': 265, 'kind': 'text'}, - { - 'op': 'set-prop', - 'id': 265, - 'property': 'text', - 'value': 'Journals', - }, - {'op': 'insert-child', 'parent': 264, 'child': 265, 'index': 0}, - {'op': 'insert-child', 'parent': 3, 'child': 263, 'index': 0}, - {'op': 'set-prop', 'id': 2, 'property': 'enabled', 'value': true}, - ], - }), - ); - expect(tester.binding.hasScheduledFrame, isTrue); - await tester.pump(); - - expect(find.text('Choose a graph'), findsNothing); - expect(find.text('Journals'), findsOneWidget); - expect(tester.getSize(find.text('Journals')).height, greaterThan(0)); - }, - ); - - testWidgets('overflow menu uses Android action icons', (tester) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - appIcons: logseqChatAppIcons, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_extensionPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - expect(find.byIcon(Icons.more_vert_rounded), findsOneWidget); - await tester.tap(find.byIcon(Icons.more_vert_rounded)); - await tester.pumpAndSettle(); - - expect(find.byIcon(Icons.star_outline_rounded), findsOneWidget); - expect(find.byIcon(Icons.share_outlined), findsOneWidget); - expect(find.byIcon(Icons.delete_outline_rounded), findsOneWidget); - expect(find.byIcon(Icons.settings_outlined), findsOneWidget); - - await tester.tap(find.text('Favorite')); - await tester.pumpAndSettle(); - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-prop', - 'id': 22, - 'property': 'text', - 'value': 'Unfavorite', - }, - { - 'op': 'set-prop', - 'id': 22, - 'property': 'icon', - 'value': 'app:star-filled', - }, - ], - }), - ); - await tester.pump(); - await tester.tap(find.byIcon(Icons.more_vert_rounded)); - await tester.pumpAndSettle(); - - expect(find.byIcon(Icons.star_rounded), findsOneWidget); - expect(find.byIcon(Icons.star_outline_rounded), findsNothing); - }); - - testWidgets('editor text changes preserve the caret boundary', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_editorPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final semantics = tester.getSemantics( - find.byKey(const ValueKey('outliner-editor-a')), - ); - expect(semantics.identifier, 'field.outliner.block.a'); - - await tester.enterText(find.byType(TextField), 'Updated'); - await tester.pump(const Duration(milliseconds: 100)); - - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-editor', - name: 'text-change', - values: {'title': 'Updated', 'caret-utf16-offset': 7}, - ), - ), - ); - }); - - testWidgets( - 'editor renders as inline outliner text instead of a form field', - (tester) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_editorPatch)); - await tester.pumpWidget( - MaterialApp( - theme: LogseqChatTheme.light(), - home: Scaffold(body: backend.widget(node: 1)), - ), - ); - - final decorator = tester.widget( - find.byType(InputDecorator), - ); - final field = tester.widget(find.byType(TextField)); - expect(decorator.decoration.filled, isFalse); - expect(decorator.decoration.border, InputBorder.none); - expect(decorator.decoration.enabledBorder, InputBorder.none); - expect(decorator.decoration.focusedBorder, InputBorder.none); - expect(decorator.decoration.contentPadding, EdgeInsets.zero); - expect(decorator.decoration.isCollapsed, isTrue); - expect(field.style?.fontSize, 14); - }, - ); - - testWidgets('editor coalesces a rapid text burst before entering LG', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_editorPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final field = find.byType(TextField); - await tester.enterText(field, 'E'); - await tester.enterText(field, 'E2'); - await tester.enterText(field, 'E2E'); - - expect( - events.where( - (event) => - event is LUIExtensionComponentEvent && event.name == 'text-change', - ), - isEmpty, - ); - - await tester.pump(const Duration(milliseconds: 100)); - expect( - events.where( - (event) => - event is LUIExtensionComponentEvent && event.name == 'text-change', - ), - [ - const LUIEvent.extension( - node: 2, - identifier: 'outliner-editor', - name: 'text-change', - values: {'title': 'E2E', 'caret-utf16-offset': 3}, - ), - ], - ); - }); - - testWidgets('editor publishes return, caret, and structural backspace', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_editorPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final field = tester.widget(find.byType(TextField)); - field.controller!.selection = const TextSelection.collapsed(offset: 2); - await tester.pump(); - await tester.enterText(find.byType(TextField), 'Before\n'); - await tester.pump(); - field.controller!.selection = const TextSelection.collapsed(offset: 0); - await tester.pump(); - await tester.sendKeyDownEvent(LogicalKeyboardKey.backspace); - await tester.sendKeyUpEvent(LogicalKeyboardKey.backspace); - - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-editor', - name: 'caret-change', - values: {'caret-utf16-offset': 2}, - ), - ), - ); - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-editor', - name: 'return', - values: {'title': 'Before', 'caret-utf16-offset': 6}, - ), - ), - ); - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-editor', - name: 'backspace', - values: {'title': 'Before', 'selection-length': 0}, - ), - ), - ); - }); - - testWidgets('search uses a Material search bar and publishes queries', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_searchPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final search = tester.getSemantics( - find.byKey(const ValueKey('search-field')), - ); - expect(search.identifier, 'field.search'); - expect( - tester.widget(find.byType(SearchBar)).hintText, - 'Search pages and blocks', - ); - expect(find.byIcon(Icons.arrow_back_rounded), findsOneWidget); - await tester.enterText(find.byType(SearchBar), 'project'); - - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'native-search-presentation', - name: 'query-changed', - values: {'query': 'project'}, - ), - ), - ); - }); - - testWidgets('search does not reopen the keyboard for a retained query', ( - tester, - ) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: (_) {}, - ); - addTearDown(backend.dispose); - final patch = Map.from(_searchPatch); - patch['ops'] = [ - ...(_searchPatch['ops']! as List>), - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'query', - 'value': 'project', - }, - ]; - backend.applyJson(jsonEncode(patch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.pump(); - - final editable = tester.widget(find.byType(EditableText)); - expect(editable.focusNode.hasFocus, isFalse); - }); - - testWidgets('search releases focus while a result is open', (tester) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: (_) {}, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_searchPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - await tester.pump(); - await tester.enterText(find.byType(SearchBar), 'project'); - expect( - tester.widget(find.byType(EditableText)).focusNode.hasFocus, - isTrue, - ); - - backend.applyJson( - jsonEncode({ - 'generation': 2, - 'ops': [ - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'depth', - 'value': 1, - }, - ], - }), - ); - await tester.pump(); - - expect( - tester.widget(find.byType(EditableText)).focusNode.hasFocus, - isFalse, - ); - }); - - testWidgets('rich block renders projected markup and opens node links', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - final listItemPatch = Map.from(_richMarkupPatch); - final richOps = - (_richMarkupPatch['ops']! as List>).skip(1).toList() - ..removeLast(); - listItemPatch['ops'] = [ - {'op': 'create-node', 'id': 1, 'kind': 'list-item'}, - {'op': 'set-prop', 'id': 1, 'property': 'press-enabled', 'value': true}, - {'op': 'create-node', 'id': 26, 'kind': 'column'}, - ...richOps, - {'op': 'insert-child', 'parent': 26, 'child': 2, 'index': 0}, - {'op': 'insert-child', 'parent': 1, 'child': 26, 'index': 0}, - ]; - backend.applyJson(jsonEncode(listItemPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final blockSemantics = tester.getSemantics( - find.byKey(const ValueKey('outliner-block-content-block-a')), - ); - expect(blockSemantics.label, 'Edit block See Project important'); - final inlineSemantics = tester.getSemantics( - find.byKey(const ValueKey('block.rich.inline.0')), - ); - expect(inlineSemantics.label, 'See Project important'); - - expect(find.text('See '), findsOneWidget); - expect(find.text('Project'), findsOneWidget); - expect(find.text('important'), findsOneWidget); - - final nodeLink = tester.getSemantics( - find.byKey(const ValueKey('link.node.page-a')), - ); - expect(nodeLink.identifier, 'link.node.page-a'); - expect(nodeLink.getSemanticsData().hasAction(SemanticsAction.tap), isTrue); - - tester.semantics.performAction( - find.semantics.byPredicate( - (node) => node.getSemanticsData().identifier == 'link.node.page-a', - ), - SemanticsAction.tap, - ); - await tester.pump(); - - expect(events, isNot(contains(const LUIEvent.press(node: 1)))); - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-block-content', - name: 'open-node', - values: {'uuid': 'page-a'}, - ), - ), - ); - }); - - testWidgets('rich markup exposes chunk identifiers matching iOS', ( - tester, - ) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - ); - addTearDown(backend.dispose); - final patch = Map.from(_richMarkupPatch); - patch['ops'] = [ - ...(_richMarkupPatch['ops']! as List>), - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'markup-json', - 'value': jsonEncode([ - {'type': 'text', 'text': 'Before'}, - {'type': 'video', 'url': 'https://example.com/video.mp4'}, - {'type': 'text', 'text': 'After'}, - { - 'type': 'quote', - 'children': [ - {'type': 'text', 'text': 'Quote'}, - ], - }, - {'type': 'math', 'text': 'x^2'}, - {'type': 'codeBlock', 'text': 'let x = 1', 'style': 'swift'}, - {'type': 'iframe', 'url': 'https://example.com'}, - {'type': 'youtubeTimestamp', 'text': '01:23', 'style': '83'}, - ]), - }, - ]; - backend.applyJson(jsonEncode(patch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - for (final identifier in [ - 'block.rich.inline.0', - 'block.rich.video', - 'block.rich.inline.2', - 'block.rich.quote', - 'block.rich.math', - 'block.rich.codeBlock', - 'block.rich.iframe', - 'block.rich.youtubeTimestamp', - ]) { - final semantics = tester.getSemantics(find.byKey(ValueKey(identifier))); - expect(semantics.identifier, identifier); - } - expect(find.text('swift'), findsOneWidget); - final highlightedCode = find.descendant( - of: find.byKey(const ValueKey('block.rich.codeBlock')), - matching: find.byType(SelectableText), - ); - expect(highlightedCode, findsOneWidget); - final selectable = tester.widget(highlightedCode); - final colors = {}; - final rootSpan = selectable.textSpan!; - void collectColors(InlineSpan span) { - final color = span.style?.color; - if (color != null) colors.add(color); - if (span is TextSpan) { - for (final child in span.children ?? const []) { - collectColors(child); - } - } - } - - collectColors(rootSpan); - expect(colors.length, greaterThan(1)); - }); - - testWidgets('youtube timestamp updates its preceding video start', ( - tester, - ) async { - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_youtubePatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - expect(find.byKey(const ValueKey('block.rich.video')), findsOneWidget); - await tester.tap(find.byKey(const ValueKey('block.rich.youtubeTimestamp'))); - await tester.pump(); - - expect( - find.byKey(const ValueKey('block.rich.youtubeTimestamp.start.83')), - findsOneWidget, - ); - expect( - find.byKey(const ValueKey('block.rich.video.start.83')), - findsOneWidget, - ); - }); - - testWidgets('long-press drag emits an inside drop on the target block', ( - tester, - ) async { - final events = []; - final backend = LUIFlutterBackend( - extensionRegistry: logseqChatExtensionRegistry(), - onEvent: events.add, - ); - addTearDown(backend.dispose); - backend.applyJson(jsonEncode(_dragPatch)); - await tester.pumpWidget( - MaterialApp(home: Scaffold(body: backend.widget(node: 1))), - ); - - final source = find.byKey(const ValueKey('outliner-block-content-source')); - final target = find.byKey(const ValueKey('outliner-block-content-target')); - final gesture = await tester.startGesture(tester.getCenter(source)); - await tester.pump(kLongPressTimeout + const Duration(milliseconds: 100)); - await gesture.moveTo(tester.getCenter(target)); - await tester.pump(); - await gesture.up(); - await tester.pump(); - - expect( - events, - contains( - const LUIEvent.extension( - node: 2, - identifier: 'outliner-block-content', - name: 'drag-start', - values: {'uuid': 'source'}, - ), - ), - ); - expect( - events, - contains( - const LUIEvent.extension( - node: 3, - identifier: 'outliner-block-content', - name: 'drop', - values: {'uuid': 'target', 'placement': 'inside'}, - ), - ), - ); - }); -} - -const _editorFingerprint = - 'lui-extension-v1|15:outliner-editor|profiles:android/flutter,' - 'ios/swiftui|standard-children:0|children:|' - 'properties:18:caret-utf16-offset:int:required:none,5:title:string:' - 'required:none,8:block-id:string:required:none|events:11:text-change[' - '18:caret-utf16-offset:int:required,5:title:string:required],12:caret-change[' - '18:caret-utf16-offset:int:required],6:return[18:caret-utf16-offset:int:' - 'required,5:title:string:required],9:backspace[16:selection-length:int:' - 'required,5:title:string:required]'; -const _richFingerprint = - 'lui-extension-v1|22:outliner-block-content|profiles:android/flutter,' - 'ios/swiftui|standard-children:0|children:|' - 'properties:10:asset-type:string:required:none,10:local-path:string:' - 'required:none,11:markup-json:string:required:none,12:is-completed:bool:' - 'required:none,18:youtube-target-url:string:required:none,5:title:string:' - 'required:none,8:block-id:string:required:none,8:is-asset:bool:required:none|' - 'events:10:drag-start[4:uuid:string:required],4:drop[4:uuid:string:required,' - '9:placement:string:required],4:edit[4:uuid:string:required],9:open-node[' - '4:uuid:string:required]'; -const _navigationFingerprint = - 'lui-extension-v1|23:native-navigation-stack|profiles:android/flutter,' - 'ios/swiftui|standard-children:1|children:|' - 'properties:26:composer-dismissal-enabled:bool:required:none,' - '28:bottom-occupies-layout-space:bool:required:none,5:depth:int:required:none,' - '5:title:string:required:none|events:16:dismiss-composer[],4:back[' - '5:count:int:required]'; -const _searchFingerprint = - 'lui-extension-v1|26:native-search-presentation|profiles:android/flutter,' - 'ios/swiftui|standard-children:1|children:|' - 'properties:5:depth:int:required:none,5:query:string:required:none,' - '5:title:string:required:none,9:presented:bool:required:none|events:' - '13:query-changed[5:query:string:required],4:back[5:count:int:required],' - '7:dismiss[]'; - -final _editorPatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'root'}, - { - 'op': 'create-extension', - 'id': 2, - 'identifier': 'outliner-editor', - 'fingerprint': _editorFingerprint, - }, - {'op': 'set-extension-prop', 'id': 2, 'property': 'block-id', 'value': 'a'}, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': 'Before', - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'caret-utf16-offset', - 'value': 6, - }, - {'op': 'insert-child', 'parent': 1, 'child': 2, 'index': 0}, - ], -}; - -final _searchPatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'root'}, - { - 'op': 'create-extension', - 'id': 2, - 'identifier': 'native-search-presentation', - 'fingerprint': _searchFingerprint, - }, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'presented', - 'value': true, - }, - {'op': 'set-extension-prop', 'id': 2, 'property': 'depth', 'value': 0}, - {'op': 'set-extension-prop', 'id': 2, 'property': 'query', 'value': ''}, - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': 'title', - 'value': 'Search', - }, - {'op': 'create-node', 'id': 3, 'kind': 'text'}, - {'op': 'set-prop', 'id': 3, 'property': 'text', 'value': 'Results'}, - {'op': 'insert-child', 'parent': 2, 'child': 3, 'index': 0}, - {'op': 'insert-child', 'parent': 1, 'child': 2, 'index': 0}, - ], -}; - -final _richMarkupPatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'root'}, - { - 'op': 'create-extension', - 'id': 2, - 'identifier': 'outliner-block-content', - 'fingerprint': _richFingerprint, - }, - for (final entry in { - 'block-id': 'block-a', - 'title': 'See Project important', - 'markup-json': jsonEncode([ - {'type': 'text', 'text': 'See '}, - {'type': 'nodeReference', 'uuid': 'page-a', 'title': 'Project'}, - {'type': 'text', 'text': ' '}, - {'type': 'code', 'text': 'important'}, - ]), - 'youtube-target-url': '', - 'is-asset': false, - 'is-completed': true, - 'asset-type': '', - 'local-path': '', - }.entries) - { - 'op': 'set-extension-prop', - 'id': 2, - 'property': entry.key, - 'value': entry.value, - }, - {'op': 'insert-child', 'parent': 1, 'child': 2, 'index': 0}, - ], -}; - -final _extensionPatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'root'}, - {'op': 'create-node', 'id': 30, 'kind': 'stack'}, - {'op': 'set-prop', 'id': 30, 'property': 'grow', 'value': 1.0}, - ...(_editorPatch['ops']! as List>).skip(1).take(4), - { - 'op': 'create-extension', - 'id': 4, - 'identifier': 'outliner-block-content', - 'fingerprint': _richFingerprint, - }, - for (final entry in { - 'block-id': 'b', - 'title': 'Linked page', - 'markup-json': '[]', - 'youtube-target-url': '', - 'is-asset': false, - 'is-completed': false, - 'asset-type': '', - 'local-path': '', - }.entries) - { - 'op': 'set-extension-prop', - 'id': 4, - 'property': entry.key, - 'value': entry.value, - }, - { - 'op': 'create-extension', - 'id': 5, - 'identifier': 'native-navigation-stack', - 'fingerprint': _navigationFingerprint, - }, - for (final entry in { - 'depth': 1, - 'bottom-occupies-layout-space': false, - 'composer-dismissal-enabled': false, - 'title': 'Journal', - }.entries) - { - 'op': 'set-extension-prop', - 'id': 5, - 'property': entry.key, - 'value': entry.value, - }, - {'op': 'create-node', 'id': 6, 'kind': 'text'}, - {'op': 'set-prop', 'id': 6, 'property': 'text', 'value': 'Navigation'}, - {'op': 'insert-child', 'parent': 5, 'child': 6, 'index': 0}, - ...(_searchPatch['ops']! as List>) - .skip(1) - .take(6) - .map( - (operation) => operation.map( - (key, value) => MapEntry(key, value is int ? value + 10 : value), - ), - ), - {'op': 'create-node', 'id': 20, 'kind': 'menu-trigger'}, - { - 'op': 'set-prop', - 'id': 20, - 'property': 'icon', - 'value': 'app:more-vert', - }, - { - 'op': 'set-prop', - 'id': 20, - 'property': 'accessibility-label', - 'value': 'More', - }, - { - 'op': 'set-prop', - 'id': 20, - 'property': 'accessibility-identifier', - 'value': 'button.overflow-menu', - }, - {'op': 'create-node', 'id': 21, 'kind': 'dropdown-menu'}, - {'op': 'insert-child', 'parent': 20, 'child': 21, 'index': 0}, - for (final item in [ - (22, 'Favorite', 'app:star', ''), - (23, 'Share', 'app:share', ''), - (24, 'Delete', 'app:toolbar-delete', 'destructive'), - (25, 'Settings', 'app:settings', ''), - ]) ...[ - {'op': 'create-node', 'id': item.$1, 'kind': 'menu-item'}, - {'op': 'set-prop', 'id': item.$1, 'property': 'text', 'value': item.$2}, - { - 'op': 'set-prop', - 'id': item.$1, - 'property': 'icon', - 'value': item.$3, - }, - if (item.$4.isNotEmpty) - { - 'op': 'set-prop', - 'id': item.$1, - 'property': 'variant', - 'value': item.$4, - }, - { - 'op': 'set-prop', - 'id': item.$1, - 'property': 'press-enabled', - 'value': true, - }, - {'op': 'insert-child', 'parent': 21, 'child': item.$1, 'index': 0}, - ], - for (final id in [20, 2, 4, 5, 12]) - {'op': 'insert-child', 'parent': 30, 'child': id, 'index': 0}, - {'op': 'insert-child', 'parent': 1, 'child': 30, 'index': 0}, - ], -}; - -final _youtubePatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'column'}, - for (final entry in [ - ( - id: 2, - blockId: 'video', - title: 'Video', - markup: [ - { - 'type': 'video', - 'url': 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', - }, - ], - target: '', - ), - ( - id: 3, - blockId: 'timestamp', - title: 'Timestamp', - markup: [ - {'type': 'youtubeTimestamp', 'text': '01:23', 'style': '83'}, - ], - target: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', - ), - ]) ...[ - { - 'op': 'create-extension', - 'id': entry.id, - 'identifier': 'outliner-block-content', - 'fingerprint': _richFingerprint, - }, - for (final property in { - 'block-id': entry.blockId, - 'title': entry.title, - 'markup-json': jsonEncode(entry.markup), - 'youtube-target-url': entry.target, - 'is-asset': false, - 'is-completed': false, - 'asset-type': '', - 'local-path': '', - }.entries) - { - 'op': 'set-extension-prop', - 'id': entry.id, - 'property': property.key, - 'value': property.value, - }, - { - 'op': 'insert-child', - 'parent': 1, - 'child': entry.id, - 'index': entry.id - 2, - }, - ], - ], -}; - -final _dragPatch = { - 'generation': 1, - 'ops': [ - {'op': 'create-node', 'id': 1, 'kind': 'column'}, - for (final entry in [(id: 2, uuid: 'source'), (id: 3, uuid: 'target')]) ...[ - { - 'op': 'create-extension', - 'id': entry.id, - 'identifier': 'outliner-block-content', - 'fingerprint': _richFingerprint, - }, - for (final property in { - 'block-id': entry.uuid, - 'title': entry.uuid, - 'markup-json': '[]', - 'youtube-target-url': '', - 'is-asset': false, - 'is-completed': false, - 'asset-type': '', - 'local-path': '', - }.entries) - { - 'op': 'set-extension-prop', - 'id': entry.id, - 'property': property.key, - 'value': property.value, - }, - { - 'op': 'insert-child', - 'parent': 1, - 'child': entry.id, - 'index': entry.id - 2, - }, - ], - ], -}; diff --git a/flutter/test/logseq_chat_icons_test.dart b/flutter/test/logseq_chat_icons_test.dart deleted file mode 100644 index 93905d9c..00000000 --- a/flutter/test/logseq_chat_icons_test.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'dart:io'; - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/logseq_chat_icons.dart'; - -Iterable _viewSource() => - Directory('../shared/src/logseq_chat') - .listSync() - .whereType() - .where((file) => file.path.endsWith('.ml')) - .map((file) => file.readAsStringSync()); - -void main() { - test('maps every app icon emitted by the LG view', () { - final emittedNames = _viewSource() - .expand( - (source) => RegExp( - r'"app:([a-z0-9]+(?:-[a-z0-9]+)*)"|`app "([a-z0-9]+(?:-[a-z0-9]+)*)"', - ) - .allMatches(source) - .map((match) => match.group(1) ?? match.group(2)!), - ) - .toSet(); - - expect(emittedNames, isNotEmpty); - expect( - logseqChatAppIcons.keys.toSet(), - containsAll(emittedNames), - reason: 'Every app:* icon must resolve to an Android Material icon.', - ); - expect(logseqChatAppIcons.values, isNot(contains(Icons.question_mark))); - }); - - test('routes every literal LG icon through the cross-platform app map', () { - final bareNames = _viewSource() - .expand( - (source) => RegExp(r'~(?:icon|name):\s*"(?!app:)([a-z0-9-]+)"') - .allMatches(source) - .map((match) => match.group(1)!), - ) - .toSet(); - - expect( - bareNames, - isEmpty, - reason: 'Bare icon names bypass the Android Material icon policy.', - ); - }); - - test('uses distinct Material semantics for high-impact Android actions', () { - expect(logseqChatAppIcons['sidebar-toggle'], Icons.menu_rounded); - expect(logseqChatAppIcons['sync-status'], Icons.sync_rounded); - expect(logseqChatAppIcons['task-backlog'], Icons.circle_outlined); - expect(logseqChatAppIcons['task-review'], Icons.mark_chat_read_outlined); - expect( - logseqChatAppIcons['toolbar-copy-reference'], - Icons.data_object_rounded, - ); - expect(logseqChatAppIcons['toolbar-copy-url'], Icons.link_rounded); - expect(logseqChatAppIcons['toolbar-unselect'], Icons.deselect_rounded); - expect(logseqChatAppIcons['add'], Icons.add_rounded); - expect(logseqChatAppIcons['arrow-up'], Icons.arrow_upward_rounded); - expect(logseqChatAppIcons['arrow-down'], Icons.arrow_downward_rounded); - expect(logseqChatAppIcons['chevron-right'], Icons.chevron_right_rounded); - expect(logseqChatAppIcons['selected'], Icons.check_circle_rounded); - expect( - logseqChatAppIcons['unselected'], - Icons.radio_button_unchecked_rounded, - ); - expect(logseqChatAppIcons['trash'], Icons.delete_outline_rounded); - expect(logseqChatAppIcons['search'], Icons.search_rounded); - expect(logseqChatAppIcons['send'], Icons.send_rounded); - expect(logseqChatAppIcons['download'], Icons.download_outlined); - expect(logseqChatAppIcons['open-external'], Icons.open_in_new_rounded); - expect(logseqChatAppIcons['refresh'], Icons.refresh_rounded); - expect(logseqChatAppIcons['sign-out'], Icons.logout_rounded); - expect(logseqChatAppIcons['terminal'], Icons.terminal_rounded); - expect(logseqChatAppIcons['warning'], Icons.warning_amber_rounded); - expect(logseqChatAppIcons['document'], Icons.article_outlined); - expect(logseqChatAppIcons['folder'], Icons.hub_outlined); - expect(logseqChatAppIcons['graph-local'], Icons.storage_rounded); - expect(logseqChatAppIcons['task-doing'], Icons.donut_large_rounded); - expect(logseqChatAppIcons['task-done'], Icons.check_circle_outline_rounded); - expect(logseqChatAppIcons['task-review'], Icons.mark_chat_read_outlined); - expect({ - logseqChatAppIcons['toolbar-copy-reference'], - logseqChatAppIcons['toolbar-copy-url'], - }, hasLength(2)); - }); -} diff --git a/flutter/test/logseq_chat_theme_test.dart b/flutter/test/logseq_chat_theme_test.dart deleted file mode 100644 index 686c4f9c..00000000 --- a/flutter/test/logseq_chat_theme_test.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/logseq_chat_theme.dart'; - -void main() { - for (final theme in [LogseqChatTheme.light(), LogseqChatTheme.dark()]) { - test( - 'navigation and secondary controls stay neutral in ${theme.brightness}', - () { - expect( - theme.colorScheme.secondaryContainer, - theme.colorScheme.surfaceContainerHighest, - ); - expect( - theme.colorScheme.onSecondaryContainer, - theme.colorScheme.onSurface, - ); - expect( - theme.textButtonTheme.style?.foregroundColor?.resolve({}), - theme.colorScheme.onSurface, - ); - expect(theme.colorScheme.primary, isNot(theme.colorScheme.onSurface)); - }, - ); - } - - test('uses a complete Material 3 surface and typography hierarchy', () { - final theme = LogseqChatTheme.light(); - - expect(theme.useMaterial3, isTrue); - expect(theme.scaffoldBackgroundColor, theme.colorScheme.surface); - expect(theme.colorScheme.surface, isNot(const Color(0xffffffff))); - expect( - theme.colorScheme.surfaceContainerLow, - isNot(theme.colorScheme.surface), - ); - expect(theme.textTheme.headlineLarge?.fontWeight, FontWeight.w600); - expect(theme.textTheme.titleLarge?.fontWeight, FontWeight.w600); - expect(theme.textTheme.bodyLarge?.height, greaterThanOrEqualTo(1.4)); - expect(theme.textTheme.labelLarge?.fontWeight, FontWeight.w600); - }); - - test('gives Android controls consistent shapes and 48dp touch targets', () { - final theme = LogseqChatTheme.light(); - final states = {}; - - expect( - theme.filledButtonTheme.style?.minimumSize?.resolve(states), - const Size(64, 48), - ); - expect( - theme.outlinedButtonTheme.style?.minimumSize?.resolve(states), - const Size(64, 48), - ); - expect( - theme.iconButtonTheme.style?.minimumSize?.resolve(states), - const Size.square(48), - ); - expect( - theme.filledButtonTheme.style?.shape?.resolve(states), - isA(), - ); - expect(theme.inputDecorationTheme.filled, isTrue); - final border = theme.inputDecorationTheme.border as OutlineInputBorder; - expect(border.borderSide, BorderSide.none); - expect(border.borderRadius.topLeft.x, 20); - }); - - test('styles app chrome as tonal Material surfaces', () { - final theme = LogseqChatTheme.light(); - - expect(theme.appBarTheme.elevation, 0); - expect(theme.appBarTheme.scrolledUnderElevation, 0); - expect( - theme.drawerTheme.backgroundColor, - theme.colorScheme.surfaceContainerLow, - ); - expect(theme.drawerTheme.width, 320); - final drawerShape = theme.drawerTheme.shape as RoundedRectangleBorder; - expect( - drawerShape.borderRadius, - const BorderRadius.horizontal(right: Radius.circular(28)), - ); - final sheetShape = theme.bottomSheetTheme.shape as RoundedRectangleBorder; - expect( - sheetShape.borderRadius, - const BorderRadius.vertical(top: Radius.circular(28)), - ); - final cardShape = theme.cardTheme.shape as RoundedRectangleBorder; - expect(cardShape.borderRadius, BorderRadius.circular(24)); - }); - - test('dark mode retains distinct tonal surfaces', () { - final theme = LogseqChatTheme.dark(); - - expect(theme.brightness, Brightness.dark); - expect( - theme.colorScheme.surfaceContainerLow, - isNot(theme.colorScheme.surface), - ); - expect( - theme.colorScheme.onSurface, - isNot(theme.colorScheme.onSurfaceVariant), - ); - }); -} diff --git a/flutter/test/lui_dispatch_test.dart b/flutter/test/lui_dispatch_test.dart deleted file mode 100644 index 937480a6..00000000 --- a/flutter/test/lui_dispatch_test.dart +++ /dev/null @@ -1,100 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/lui_dispatch.dart'; -import 'package:lui_flutter_backend/lui_flutter_backend.dart'; - -void main() { - test('routes Material control events to the native LG bridge', () { - final native = _RecordingNativeDispatch(); - - dispatchLUIEvent(const LUIEvent.appear(node: 6), native); - dispatchLUIEvent(const LUIEvent.press(node: 7), native); - dispatchLUIEvent( - const LUIEvent.textChanged(node: 8, text: 'Hello'), - native, - ); - dispatchLUIEvent( - const LUIEvent.toggleChanged(node: 9, checked: true), - native, - ); - - expect(native.events, [ - 'appear:6', - 'press:7', - 'text:8:Hello', - 'toggle:9:true', - ]); - }); - - test('preserves typed extension payloads', () { - final native = _RecordingNativeDispatch(); - - dispatchLUIEvent( - const LUIEvent.extension( - node: 11, - identifier: 'outliner-block-content', - name: 'edit', - values: {'uuid': 'block-a'}, - ), - native, - ); - - expect(native.events, [ - 'extension:11:outliner-block-content:edit:block-a:0', - ]); - }); -} - -final class _RecordingNativeDispatch implements LogseqChatNativeDispatch { - final events = []; - - @override - void appear(int node) => events.add('appear:$node'); - - @override - void change(int node) => events.add('change:$node'); - - @override - void dismiss(int node) => events.add('dismiss:$node'); - - @override - void doublePress(int node) => events.add('double:$node'); - - @override - void extensionEvent( - int node, - String identifier, - String name, - String text, - int value, - ) => events.add('extension:$node:$identifier:$name:$text:$value'); - - @override - void longPress(int node) => events.add('long:$node'); - - @override - void picked(int node, String payload) => events.add('picked:$node:$payload'); - - @override - void press(int node) => events.add('press:$node'); - - @override - void scrollCompleted(int node, int token, String outcome) => - events.add('scroll:$node:$token:$outcome'); - - @override - void visibleRange(int node, int first, int last) => - events.add('visible:$node:$first:$last'); - - @override - void submit(int node) => events.add('submit:$node'); - - @override - void textChanged(int node, String text) => events.add('text:$node:$text'); - - @override - void toggleChanged(int node, bool checked) => - events.add('toggle:$node:$checked'); - - @override - void valueChanged(int node, double value) => events.add('value:$node:$value'); -} diff --git a/flutter/test/native_effect_drain_test.dart b/flutter/test/native_effect_drain_test.dart deleted file mode 100644 index 2a4c27be..00000000 --- a/flutter/test/native_effect_drain_test.dart +++ /dev/null @@ -1,426 +0,0 @@ -import 'dart:async'; -import 'dart:convert'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/native_effect_drain.dart'; - -void main() { - test( - 'drains effects in order and applies core snapshots before resolution', - () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 1, kind: 'refresh-graphs', patch: 'dequeue-1'), - _dispatch(id: 2, kind: 'load-page', patch: 'dequeue-2'), - ]); - final operations = runtime.operations; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (effect) async { - operations.add('execute:${effect.id}:${effect.kind}'); - return NativeEffectResolution.coreResponse('response-${effect.id}'); - }, - applyPatch: (patch) => operations.add('patch:$patch'), - afterCoreResponseApplied: (response) async { - operations.add('commands:$response'); - }, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - - expect(operations, [ - 'take', - 'patch:dequeue-1', - 'execute:1:refresh-graphs', - 'snapshot:response-1', - 'patch:snapshot-patch', - 'commands:response-1', - 'resolve:1:true:response-1', - 'patch:resolve-patch', - 'take', - 'patch:dequeue-2', - 'execute:2:load-page', - 'snapshot:response-2', - 'patch:snapshot-patch', - 'commands:response-2', - 'resolve:2:true:response-2', - 'patch:resolve-patch', - 'take', - ]); - }, - ); - - test( - 'discard output resolves without applying a snapshot or host update', - () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 3, kind: 'persist-composer-draft', patch: 'dequeue'), - ]); - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => const NativeEffectResolution.discard(), - applyPatch: (patch) => runtime.operations.add('patch:$patch'), - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - - expect(runtime.operations, [ - 'take', - 'patch:dequeue', - 'resolve:3:true:', - 'patch:resolve-patch', - 'take', - ]); - }, - ); - - test('host output is published before the effect is resolved', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 4, kind: 'refresh-runtime-log', patch: 'dequeue'), - ]); - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => const NativeEffectResolution.hostUpdate( - kind: 'runtime-log', - payload: '[{"message":"ready"}]', - ), - applyPatch: (patch) => runtime.operations.add('patch:$patch'), - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - - expect(runtime.operations, [ - 'take', - 'patch:dequeue', - 'host:runtime-log:[{"message":"ready"}]', - 'patch:host-patch', - 'resolve:4:true:[{"message":"ready"}]', - 'patch:resolve-patch', - 'take', - ]); - }); - - test( - 'failed execution rolls back through resolve without publishing output', - () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 5, kind: 'sign-in', patch: 'signing-in'), - ]); - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => const NativeEffectResolution.discard( - succeeded: false, - message: 'Hosted sign-in failed', - ), - applyPatch: (patch) => runtime.operations.add('patch:$patch'), - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - - expect(runtime.operations, [ - 'take', - 'patch:signing-in', - 'resolve:5:false:Hosted sign-in failed', - 'patch:resolve-patch', - 'take', - ]); - }, - ); - - test('traces every effect from dequeue through resolution', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 14, kind: 'open-graph', text: 'graph-remote'), - ]); - final traces = []; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => const NativeEffectResolution.discard( - succeeded: false, - message: 'graph_open_failed\nSnapshot download timed out', - ), - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - trace: traces.add, - ); - - await drain.drain(); - - expect(traces, hasLength(5)); - expect(traces[0], 'empty patch from dispatch kind=open-graph'); - expect(traces[1], 'start id=14 kind=open-graph'); - expect( - traces[2], - startsWith( - 'finish id=14 kind=open-graph succeeded=false output=discard ' - 'elapsedMs=', - ), - ); - expect(traces[2], contains('message=graph_open_failed')); - expect(traces[2], contains('Snapshot download timed out')); - expect( - traces[3], - startsWith('applying patch from resolveEffect id=14 succeeded=false'), - ); - expect(traces[4], 'applied patch from resolveEffect id=14 succeeded=false'); - }); - - test('traces search response query and result count without result text', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 15, kind: 'search-nodes', text: 'private query'), - ]); - final traces = []; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => NativeEffectResolution.coreResponse( - jsonEncode({ - 'ok': true, - 'result': { - 'searchQuery': 'private query', - 'searchResults': [ - {'title': 'sensitive result'}, - {'title': 'another result'}, - ], - }, - }), - ), - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - trace: traces.add, - ); - - await drain.drain(); - - final finish = traces.firstWhere( - (trace) => trace.startsWith('finish id=15'), - ); - expect(finish, contains('searchQueryChars=13 searchResults=2')); - expect(finish, isNot(contains('private query'))); - expect(finish, isNot(contains('sensitive result'))); - }); - - test('preserves optional effect values for platform execution', () async { - final runtime = _RecordingRuntime([ - _dispatch( - id: 8, - kind: 'present-asset', - text: 'asset.png', - uuid: 'block-a', - value: 42, - metadata: '{"assetType":"image"}', - ), - ]); - NativeEffect? received; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (effect) async { - received = effect; - return const NativeEffectResolution.discard(); - }, - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - - expect(received?.id, 8); - expect(received?.kind, 'present-asset'); - expect(received?.text, 'asset.png'); - expect(received?.uuid, 'block-a'); - expect(received?.value, 42); - expect(received?.metadata, '{"assetType":"image"}'); - }); - - test( - 'reports malformed native payloads and stops the current drain', - () async { - final runtime = _RecordingRuntime(['not-json', _dispatch(id: 6)]); - final errors = []; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async => const NativeEffectResolution.discard(), - applyPatch: (patch) => runtime.operations.add('patch:$patch'), - onError: (error, _) => errors.add(error), - ); - - await drain.drain(); - - expect(errors.single, isA()); - expect(runtime.operations, ['take']); - }, - ); - - test( - 'coalesces concurrent drain requests without executing an effect twice', - () async { - final runtime = _RecordingRuntime([_dispatch(id: 7)]); - final executionStarted = Completer(); - final allowExecutionToFinish = Completer(); - var executions = 0; - final drain = NativeEffectDrain( - runtime: runtime, - execute: (_) async { - executions += 1; - executionStarted.complete(); - await allowExecutionToFinish.future; - return const NativeEffectResolution.discard(); - }, - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - final first = drain.drain(); - await executionStarted.future; - final second = drain.drain(); - allowExecutionToFinish.complete(); - await Future.wait([first, second]); - - expect(executions, 1); - expect( - runtime.operations.where((entry) => entry == 'take'), - hasLength(2), - ); - }, - ); - - test('debounces text editing into the core autosave action', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 9, kind: 'change-outliner-text', patch: 'dequeue'), - ]); - final effects = []; - final autosaved = Completer(); - final drain = NativeEffectDrain( - runtime: runtime, - outlinerAutosaveDelay: Duration.zero, - execute: (effect) async { - effects.add(effect.kind); - if (effect.kind == 'save-outliner-editing') autosaved.complete(); - return const NativeEffectResolution.coreResponse( - '{"ok":true,"result":{"outlinerState":{"autocomplete":null}}}', - ); - }, - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - await autosaved.future.timeout(const Duration(seconds: 1)); - - expect(effects, ['change-outliner-text', 'save-outliner-editing']); - drain.dispose(); - }); - - test('does not autosave while autocomplete is visible', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 10, kind: 'change-outliner-text', patch: 'dequeue'), - ]); - final effects = []; - final drain = NativeEffectDrain( - runtime: runtime, - outlinerAutosaveDelay: Duration.zero, - execute: (effect) async { - effects.add(effect.kind); - return const NativeEffectResolution.coreResponse( - '{"ok":true,"result":{"outlinerState":{"autocomplete":{"query":"#"}}}}', - ); - }, - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - await Future.delayed(Duration.zero); - - expect(effects, ['change-outliner-text']); - drain.dispose(); - }); - - test('rapid text changes collapse into one autosave', () async { - final runtime = _RecordingRuntime([ - _dispatch(id: 11, kind: 'change-outliner-text', patch: 'dequeue-1'), - _dispatch(id: 12, kind: 'change-outliner-text', patch: 'dequeue-2'), - ]); - final effects = []; - final autosaved = Completer(); - final drain = NativeEffectDrain( - runtime: runtime, - outlinerAutosaveDelay: const Duration(milliseconds: 10), - execute: (effect) async { - effects.add(effect.kind); - if (effect.kind == 'save-outliner-editing') autosaved.complete(); - return const NativeEffectResolution.coreResponse( - '{"ok":true,"result":{"outlinerState":{"autocomplete":null}}}', - ); - }, - applyPatch: (_) {}, - onError: (error, _) => fail('Unexpected error: $error'), - ); - - await drain.drain(); - await autosaved.future.timeout(const Duration(seconds: 1)); - - expect(effects, [ - 'change-outliner-text', - 'change-outliner-text', - 'save-outliner-editing', - ]); - drain.dispose(); - }); -} - -String _dispatch({ - int id = 1, - String kind = 'effect', - String text = '', - String patch = '', - String? uuid, - int? value, - String? metadata, -}) => jsonEncode({ - 'effect': { - 'id': id, - 'kind': kind, - 'text': text, - 'uuid': ?uuid, - 'value': ?value, - 'metadata': ?metadata, - }, - 'patch': patch, -}); - -final class _RecordingRuntime implements NativeEffectRuntime { - _RecordingRuntime(List effects) : _effects = List.of(effects); - - final List _effects; - final operations = []; - - @override - String applyHostUpdate({required String kind, required String payload}) { - operations.add('host:$kind:$payload'); - return 'host-patch'; - } - - @override - String applySnapshot(String response) { - operations.add('snapshot:$response'); - return 'snapshot-patch'; - } - - @override - String resolveEffect({ - required int id, - required bool succeeded, - required String message, - }) { - operations.add('resolve:$id:$succeeded:$message'); - return 'resolve-patch'; - } - - @override - String takeEffect() { - operations.add('take'); - return _effects.isEmpty ? '' : _effects.removeAt(0); - } -} diff --git a/flutter/test/native_runtime_scheduler_test.dart b/flutter/test/native_runtime_scheduler_test.dart deleted file mode 100644 index e17bb8a4..00000000 --- a/flutter/test/native_runtime_scheduler_test.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_test/flutter_test.dart'; -import 'package:logseq_chat_flutter/native_runtime_scheduler.dart'; - -void main() { - test('defers UI native calls while a core call owns the runtime', () async { - final scheduler = NativeRuntimeScheduler(); - final core = Completer(); - final events = []; - - final result = scheduler.runCore(() async { - events.add('core-start'); - return core.future; - }); - await Future.delayed(Duration.zero); - - scheduler.runUi(() => events.add('ui')); - expect(events, ['core-start']); - - core.complete('done'); - expect(await result, 'done'); - expect(events, ['core-start', 'ui']); - }); - - test( - 'serializes core calls and flushes UI only after all core work', - () async { - final scheduler = NativeRuntimeScheduler(); - final first = Completer(); - final events = []; - - final firstResult = scheduler.runCore(() async { - events.add('core-1-start'); - await first.future; - events.add('core-1-end'); - return 1; - }); - final secondResult = scheduler.runCore(() async { - events.add('core-2'); - return 2; - }); - scheduler.runUi(() => events.add('ui')); - await Future.delayed(Duration.zero); - - expect(events, ['core-1-start']); - first.complete(); - expect(await firstResult, 1); - expect(await secondResult, 2); - expect(events, ['core-1-start', 'core-1-end', 'core-2', 'ui']); - }, - ); - - test('reports idle after deferred UI calls are flushed', () async { - final events = []; - late final NativeRuntimeScheduler scheduler; - scheduler = NativeRuntimeScheduler(onIdle: () => events.add('idle')); - final core = Completer(); - - final result = scheduler.runCore(() => core.future); - scheduler.runUi(() => events.add('ui')); - await Future.delayed(Duration.zero); - expect(scheduler.isCoreBusy, isTrue); - - core.complete(); - await result; - expect(scheduler.isCoreBusy, isFalse); - expect(events, ['ui', 'idle']); - }); -} diff --git a/flutter/test/search_layout_contract_test.dart b/flutter/test/search_layout_contract_test.dart deleted file mode 100644 index 4827b694..00000000 --- a/flutter/test/search_layout_contract_test.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'dart:io'; - -import 'package:flutter_test/flutter_test.dart'; - -String _viewSource() { - final directory = Directory('../shared/src/logseq_chat'); - final files = directory - .listSync() - .whereType() - .where((file) => file.path.endsWith('.ml')) - .toList() - ..sort((a, b) => a.path.compareTo(b.path)); - return files.map((file) => file.readAsStringSync()).join('\n'); -} - -void main() { - test('Flutter search results list fills the remaining search surface', () { - final source = _viewSource(); - final searchResultsList = RegExp( - r'\blist\b(?=[\s\S]{0,200}~accessibility_identifier:\s*"screen\.search\.results")(?=[\s\S]{0,200}~grow:\s*1\.0)', - multiLine: true, - ); - - expect(source, matches(searchResultsList)); - }); -} diff --git a/flutter/tool/check_release_jni.py b/flutter/tool/check_release_jni.py deleted file mode 100644 index e29d74d8..00000000 --- a/flutter/tool/check_release_jni.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python3 -"""Verify that the release shrinker preserves the native JNI entry points.""" -import re -from pathlib import Path - -mapping = Path(__file__).resolve().parents[1] / "build/app/outputs/mapping/release/mapping.txt" -text = mapping.read_text() -for class_name, methods in { - "logseq.chat.AndroidHttpTransport": ["send", "uploadFile"], - "logseq.chat.AndroidE2EECrypto": ["call"], -}.items(): - match = re.search(r"^" + re.escape(class_name) + r" -> " + re.escape(class_name) + r":\n(.*?)(?=^[^ #\n]|\Z)", text, re.MULTILINE | re.DOTALL) - assert match, f"JNI class was removed or renamed: {class_name}" - for method in methods: - assert re.search(r"\b" + method + r"\([^\n]* -> " + method + r"$", match[1], re.MULTILINE), f"JNI method was removed or renamed: {class_name}.{method}" -print("PASS: release JNI transport and crypto entry points retain their names") diff --git a/scripts/build-android-native.sh b/scripts/build-android-native.sh index a6c9a8d8..3d59b32b 100755 --- a/scripts/build-android-native.sh +++ b/scripts/build-android-native.sh @@ -28,7 +28,7 @@ esac target="${target_arch}-linux-android${api_level}" target_prefix="$repo_root/_build/android-toolchain/$target-$ocaml_version" build_dir="$repo_root/_build/android-core/$android_abi" -jni_dir="$repo_root/flutter/android/app/src/main/jniLibs/$android_abi" +jni_dir="$repo_root/android/app/src/main/jniLibs/$android_abi" library="$build_dir/liblogseq_chat_core.so" "$repo_root/scripts/bootstrap-android-ocaml.sh" >/dev/null diff --git a/scripts/test-android-e2e-runner.sh b/scripts/test-android-e2e-runner.sh index 39e2bb41..f4e12bc6 100755 --- a/scripts/test-android-e2e-runner.sh +++ b/scripts/test-android-e2e-runner.sh @@ -125,7 +125,7 @@ mock_bin="$temporary_directory/bin" custom_flow="$temporary_directory/custom-flow.yaml" maestro_args="$temporary_directory/maestro-args" adb_args="$temporary_directory/adb-args" -flutter_args="$temporary_directory/flutter-args" +gradle_args="$temporary_directory/gradle-args" mkdir -p "$mock_bin" trap 'rm -rf "$temporary_directory"' EXIT @@ -165,12 +165,11 @@ case "$*" in esac EOF printf '#!/usr/bin/env bash\nprintf \"%%s\\n\" \"$@\" >\"$LOGSEQ_CHAT_MAESTRO_ARGS\"\n' >"$mock_bin/maestro" -printf '#!/usr/bin/env bash\nexit 0\n' >"$mock_bin/gradle" -cat >"$mock_bin/flutter" <<'EOF' +cat >"$mock_bin/gradle" <<'GMOCK' #!/usr/bin/env bash -printf '%s|%s\n' "$PWD" "$*" >"$LOGSEQ_CHAT_FLUTTER_ARGS" -EOF -chmod +x "$mock_bin/adb" "$mock_bin/maestro" "$mock_bin/gradle" "$mock_bin/flutter" +printf '%s\n' "$*" >"$LOGSEQ_CHAT_GRADLE_ARGS" +GMOCK +chmod +x "$mock_bin/adb" "$mock_bin/maestro" "$mock_bin/gradle" printf 'appId: com.logseq.chat\n---\n- launchApp\n' >"$custom_flow" PATH="$mock_bin:$PATH" \ @@ -184,13 +183,14 @@ PATH="$mock_bin:$PATH" \ PATH="$mock_bin:$PATH" \ ANDROID_SERIAL=test-device \ - LOGSEQ_CHAT_FLUTTER_ARGS="$flutter_args" \ + LOGSEQ_CHAT_ANDROID_GRADLE=gradle \ + LOGSEQ_CHAT_GRADLE_ARGS="$gradle_args" \ LOGSEQ_CHAT_MAESTRO_ARGS="$maestro_args" \ LOGSEQ_CHAT_ANDROID_E2E_SKIP_INSTALL=1 \ LOGSEQ_CHAT_ANDROID_E2E_SKIP_VISUAL_GATES=1 \ "$runner" signed-out >/dev/null -[[ $(<"$flutter_args") == "$repo_root/flutter|build apk --profile" ]] \ - || die "Android E2E runner did not build the Flutter profile APK" +[[ $(<"$gradle_args") == "-p $repo_root/android :app:assembleProfile" ]] \ + || die "Android E2E runner did not build the profile APK" : >"$adb_args" PATH="$mock_bin:$PATH" \ diff --git a/scripts/test-android-e2e.sh b/scripts/test-android-e2e.sh index 51e06bdb..4e98c728 100755 --- a/scripts/test-android-e2e.sh +++ b/scripts/test-android-e2e.sh @@ -251,7 +251,7 @@ LOGSEQ_CHAT_E2E_PASSWORD=${LOGSEQ_CHAT_E2E_PASSWORD:-Logseq-e2e} command -v adb >/dev/null 2>&1 || die "adb is not installed" command -v maestro >/dev/null 2>&1 || die "Maestro CLI is not installed" -command -v flutter >/dev/null 2>&1 || die "Flutter is not installed" +[[ -x $repo_root/android/gradlew ]] || die "android/gradlew is missing" temporary_files=() anr_watchdog_pid="" @@ -340,14 +340,12 @@ if [[ -n ${LOGSEQ_CHAT_E2E_BASE_URL:-} ]] \ fi if [[ ${LOGSEQ_CHAT_ANDROID_E2E_SKIP_BUILD:-0} != 1 ]]; then - ( - cd "$repo_root/flutter" - ANDROID_SERIAL=$device flutter build apk --profile - ) + gradle=${LOGSEQ_CHAT_ANDROID_GRADLE:-"$repo_root/android/gradlew"} + ANDROID_SERIAL=$device "$gradle" -p "$repo_root/android" :app:assembleProfile fi if [[ ${LOGSEQ_CHAT_ANDROID_E2E_SKIP_INSTALL:-0} != 1 ]]; then - apk="$repo_root/flutter/build/app/outputs/flutter-apk/app-profile.apk" + apk="$repo_root/android/app/build/outputs/apk/profile/app-profile.apk" [[ -f $apk ]] || die "Android profile APK was not produced at $apk" adb -s "$device" install -r "$apk" >/dev/null fi @@ -516,7 +514,7 @@ recover_device() { || return 1 # A fresh boot loses the app and the db-sync tunnel. adb -s "$device" install -r \ - "$repo_root/flutter/build/app/outputs/flutter-apk/app-profile.apk" \ + "$repo_root/android/app/build/outputs/apk/profile/app-profile.apk" \ >/dev/null if [[ -n ${local_backend_port:-} ]]; then adb -s "$device" reverse "tcp:$local_backend_port" "tcp:$local_backend_port" diff --git a/scripts/test-android-native-script.sh b/scripts/test-android-native-script.sh index 4bb80b2a..d907594d 100755 --- a/scripts/test-android-native-script.sh +++ b/scripts/test-android-native-script.sh @@ -39,7 +39,7 @@ require_file "scripts/build-mobile-ocaml.sh" require_file "scripts/build-android-native.sh" require_text "scripts/build-android-native.sh" "liblogseq_chat_core.so" -require_text "scripts/build-android-native.sh" 'flutter/android/app/src/main/jniLibs/$android_abi' +require_text "scripts/build-android-native.sh" 'android/app/src/main/jniLibs/$android_abi' require_text "scripts/build-android-native.sh" "logseq_chat_call" require_text "shared/native/logseq_chat_core_ffi.h" "logseq_chat_lui_root_node" require_text "shared/native/logseq_chat_core_ffi.c" "logseq_chat_lui_root_node" @@ -54,29 +54,30 @@ require_text "shared/native/dune" "link_deps" require_text "shared/native/dune" '%{env:LOGSEQ_CHAT_SQLITE_LINK_FILE=./libsqlite3.a}' require_text "scripts/build-android-native.sh" 'LOGSEQ_CHAT_SQLITE_LINK_FILE="$build_dir/libsqlite3.a"' require_file "shared/native/logseq_chat_crypto_android.c" -require_file "flutter/android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt" +require_file "android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt" require_text "shared/native/logseq_chat_https_android.c" "logseq_chat_crypto_jni_init" -require_text "flutter/android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt" "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" +require_text "android/app/src/main/kotlin/logseq/chat/AndroidE2EECrypto.kt" "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" reject_text "shared/native/logseq_chat_crypto_android.c" "Android crypto is not implemented" for forbidden in ".cmx" "ocamlopt" "output-complete-obj" "link-objects.txt" "build-mobile-ocaml-deps.sh"; do reject_text "scripts/build-android-native.sh" "$forbidden" done require_text "shared/native/logseq_chat_https_android.c" "JNI_OnLoad" require_text "shared/native/logseq_chat_https_android.c" "AndroidHttpTransport" -require_text "flutter/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "connectTimeout = 30_000" -require_text "flutter/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "outputStream.use" -require_text "flutter/android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "resolveAndroidFile" -require_text "flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt" "AndroidHttpTransport.initialize(applicationContext)" -require_text "flutter/android/app/src/main/kotlin/com/logseq/logseq_chat_flutter/MainActivity.kt" 'System.loadLibrary("logseq_chat_core")' -require_text "flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "Intent.ACTION_OPEN_DOCUMENT" -require_text "flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "Intent.EXTRA_ALLOW_MULTIPLE" -require_text "flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "contentResolver.openInputStream" +require_text "android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "connectTimeout = 30_000" +require_text "android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "outputStream.use" +require_text "android/app/src/main/kotlin/logseq/chat/AndroidHttpTransport.kt" "resolveAndroidFile" +require_text "android/app/src/main/kotlin/com/logseq/chat/MainActivity.kt" "AndroidHttpTransport.initialize(applicationContext)" +require_text "android/app/src/main/kotlin/com/logseq/chat/NativeCore.kt" 'System.loadLibrary("logseq_chat_jni")' +require_text "android/app/src/main/cpp/logseq_chat_jni.c" 'dlopen("liblogseq_chat_core.so"' +require_text "android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "Intent.ACTION_OPEN_DOCUMENT" +require_text "android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "Intent.EXTRA_ALLOW_MULTIPLE" +require_text "android/app/src/main/kotlin/com/logseq/chat/AndroidAssetImporter.kt" "contentResolver.openInputStream" reject_text "scripts/build-android-native.sh" "logseq_chat_https_stub.c" -require_text "flutter/android/app/build.gradle.kts" "buildAndroidNativeCore" -require_text "flutter/android/app/build.gradle.kts" "scripts/build-android-native.sh" -require_text "flutter/android/app/build.gradle.kts" 'dependsOn("buildAndroidNativeCore")' -require_text "flutter/android/app/build.gradle.kts" "inputs.files" -require_text "flutter/android/app/build.gradle.kts" "outputs.file" +require_text "android/app/build.gradle.kts" "buildAndroidNativeCore" +require_text "android/app/build.gradle.kts" "scripts/build-android-native.sh" +require_text "android/app/build.gradle.kts" 'dependsOn(buildAndroidNativeCore)' +require_text "android/app/build.gradle.kts" "inputs.files" +require_text "android/app/build.gradle.kts" "outputs.file" require_text "scripts/test-android-e2e.sh" "logseq.selectedGraphId" reject_text "scripts/test-android-e2e.sh" "find files/graphs -name graph.sqlite -type f" diff --git a/scripts/test-no-skip-support.sh b/scripts/test-no-skip-support.sh index 16525b9d..b26cf6b6 100644 --- a/scripts/test-no-skip-support.sh +++ b/scripts/test-no-skip-support.sh @@ -43,23 +43,23 @@ if grep -Eq 'SkipStone|Run skip gradle|Skip\.env|skip gradle' \ die "the Apple project still invokes Skip" fi -manifest="$repo_root/flutter/android/app/src/main/AndroidManifest.xml" -shortcuts="$repo_root/flutter/android/app/src/main/res/xml/shortcuts.xml" -widgets="$repo_root/flutter/android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt" +manifest="$repo_root/android/app/src/main/AndroidManifest.xml" +shortcuts="$repo_root/android/app/src/main/res/xml/shortcuts.xml" +widgets="$repo_root/android/app/src/main/kotlin/com/logseq/chat/AndroidWidgets.kt" grep -Fq 'android.app.shortcuts' "$manifest" \ - || die "Flutter Android manifest lost app shortcuts" + || die "Android manifest lost app shortcuts" grep -Fq '.TodayJournalWidgetProvider' "$manifest" \ - || die "Flutter Android manifest lost the journal widget" + || die "Android manifest lost the journal widget" grep -Fq '.CaptureWidgetProvider' "$manifest" \ - || die "Flutter Android manifest lost the capture widget" + || die "Android manifest lost the capture widget" grep -Fq 'logseqchat://capture' "$shortcuts" \ - || die "Flutter Android shortcuts lost Capture" + || die "Android shortcuts lost Capture" grep -Fq 'logseqchat://journal' "$shortcuts" \ - || die "Flutter Android shortcuts lost Journal" + || die "Android shortcuts lost Journal" grep -Fq 'class TodayJournalWidgetProvider' "$widgets" \ - || die "Flutter Android journal widget provider is missing" + || die "Android journal widget provider is missing" grep -Fq 'class CaptureWidgetProvider' "$widgets" \ - || die "Flutter Android capture widget provider is missing" + || die "Android capture widget provider is missing" -echo "No-Skip Flutter Android contract passed" +echo "No-Skip Android contract passed" From 54574f646267b7c155c42648f626529b9f8b7503 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Tue, 6 Oct 2026 10:18:40 +0000 Subject: [PATCH 2/2] Fix LUI wire property names in the vendored backend Align the vendored dev.lui renderers/props with src/lui_wire_schema.ml: TextValue is 'text' (not 'value'), IconName is 'name', GridColumns is 'columns', alignments are 'main'/'cross', ProgressValue is 'value', sizing uses 'sizing', and 'grow' fills width. Resolve 'app:'-prefixed icon names against the app icon map. Verified on the chat_test emulator: the signed-out authentication screen now renders the logo, heading, tagline, and Sign in button. --- .../arm64-v8a/configure_fingerprint.bin | 24 +++++++++---------- .../armeabi-v7a/configure_fingerprint.bin | 24 +++++++++---------- .../666c1h3t/x86/configure_fingerprint.bin | 24 +++++++++---------- .../666c1h3t/x86_64/configure_fingerprint.bin | 24 +++++++++---------- .../logseq/chat/runtime/LogseqChatIcons.kt | 7 +++++- .../lui/src/main/kotlin/dev/lui/LuiProps.kt | 11 +++++---- .../src/main/kotlin/dev/lui/LuiRenderers.kt | 24 +++++++++---------- 7 files changed, 72 insertions(+), 66 deletions(-) diff --git a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/configure_fingerprint.bin index 5952f996..41806ad9 100644 --- a/android/app/.cxx/Debug/666c1h3t/arm64-v8a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/666c1h3t/arm64-v8a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logb ` ^/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  Ó¹»…‘4  ¾ð¥…‘4_ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  úÕâ…‘4  ¾ð¥…‘4_ ] -[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build.json  Ó¹»…‘4¼ À𥅑4d +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build.json  úÕâ…‘4¼ À𥅑4d b -`/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build_mini.json  Ó¹»…‘4¬ Ì𥅑4Q +`/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/android_gradle_build_mini.json  úÕâ…‘4¬ Ì𥅑4Q O -M/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build.ninja  Ó¹»…‘4£´ ¢ð¥…‘4U +M/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build.ninja  úÕâ…‘4£´ ¢ð¥…‘4U S -Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build.ninja.txt  Ó¹»…‘4Z +Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build.ninja.txt  úÕâ…‘4Z X -V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build_file_index.txt  Ó¹»…‘4 ? Í𥅑4[ +V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/build_file_index.txt  úÕâ…‘4 ? Í𥅑4[ Y -W/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json  Ó¹»…‘4ø ¢ð¥…‘4_ +W/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json  úÕâ…‘4ø ¢ð¥…‘4_ ] -[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json.bin  Ó¹»…‘4 ï ¢ð¥…‘4e +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/compile_commands.json.bin  úÕâ…‘4 ï ¢ð¥…‘4e c -a/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/metadata_generation_command.txt  Ó¹»…‘4 +a/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/metadata_generation_command.txt  úÕâ…‘4 Ê Í𥅑4X V -T/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/prefab_config.json  Ó¹»…‘4  ( Í𥅑4] +T/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/prefab_config.json  úÕâ…‘4  ( Í𥅑4] [ -Y/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/symbol_folder_index.txt  Ó¹»…‘4  X Í𥅑4C +Y/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/arm64-v8a/symbol_folder_index.txt  úÕâ…‘4  X Í𥅑4C A -?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  Ó¹»…‘4 ¨ õÿ¶„‘4 \ No newline at end of file +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  úÕâ…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/configure_fingerprint.bin index bd430ee1..3039bc21 100644 --- a/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Logd b `/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ๻…‘4  �ò¥…‘4a +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  †Öâ…‘4  �ò¥…‘4a _ -]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json  ๻…‘4Ä ‚ò¥…‘4f +]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build.json  †Öâ…‘4Ä ‚ò¥…‘4f d -b/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json  ๻…‘4´ …ò¥…‘4S +b/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/android_gradle_build_mini.json  †Öâ…‘4´ …ò¥…‘4S Q -O/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja  ๻…‘4ë´ ûñ¥…‘4W +O/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja  †Öâ…‘4ë´ ûñ¥…‘4W U -S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja.txt  ๻…‘4\ +S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build.ninja.txt  †Öâ…‘4\ Z -X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt  ๻…‘4 ? …ò¥…‘4] +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/build_file_index.txt  †Öâ…‘4 ? …ò¥…‘4] [ -Y/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json  ๻…‘4“ ûñ¥…‘4a +Y/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json  †Öâ…‘4“ ûñ¥…‘4a _ -]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json.bin  ๻…‘4 ˜ ûñ¥…‘4g +]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/compile_commands.json.bin  †Öâ…‘4 ˜ ûñ¥…‘4g e -c/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/metadata_generation_command.txt  ๻…‘4 +c/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/metadata_generation_command.txt  †Öâ…‘4 Ô …ò¥…‘4Z X -V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/prefab_config.json  ๻…‘4  ( …ò¥…‘4_ +V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/prefab_config.json  †Öâ…‘4  ( …ò¥…‘4_ ] -[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/symbol_folder_index.txt  ๻…‘4  Z …ò¥…‘4C +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/armeabi-v7a/symbol_folder_index.txt  †Öâ…‘4  Z …ò¥…‘4C A -?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  ๻…‘4 ¨ õÿ¶„‘4 \ No newline at end of file +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  †Öâ…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin index 7f14d5ff..c9893111 100644 --- a/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/666c1h3t/x86/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Log\ Z X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  è¹»…‘4  Šó¥…‘4Y +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ”Öâ…‘4  Šó¥…‘4Y W -U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json  è¹»…‘4¤ ‹ó¥…‘4^ +U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build.json  ”Öâ…‘4¤ ‹ó¥…‘4^ \ -Z/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json  è¹»…‘4” Œó¥…‘4K +Z/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/android_gradle_build_mini.json  ”Öâ…‘4” Œó¥…‘4K I -G/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja  è¹»…‘4ϳ …ó¥…‘4O +G/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja  ”Öâ…‘4ϳ …ó¥…‘4O M -K/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja.txt  è¹»…‘4T +K/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build.ninja.txt  ”Öâ…‘4T R -P/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt  è¹»…‘4 ? �ó¥…‘4U +P/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/build_file_index.txt  ”Öâ…‘4 ? �ó¥…‘4U S -Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json  è¹»…‘4ï …ó¥…‘4Y +Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json  ”Öâ…‘4ï …ó¥…‘4Y W -U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin  è¹»…‘4 æ …ó¥…‘4_ +U/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/compile_commands.json.bin  ”Öâ…‘4 æ …ó¥…‘4_ ] -[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt  è¹»…‘4 +[/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/metadata_generation_command.txt  ”Öâ…‘4 ¬ �ó¥…‘4R P -N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json  è¹»…‘4  ( �ó¥…‘4W +N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/prefab_config.json  ”Öâ…‘4  ( �ó¥…‘4W U -S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt  è¹»…‘4  R �ó¥…‘4C +S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86/symbol_folder_index.txt  ”Öâ…‘4  R �ó¥…‘4C A -?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  è¹»…‘4 ¨ õÿ¶„‘4 \ No newline at end of file +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  ”Öâ…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin b/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin index 1df16ed1..3e730dd5 100644 --- a/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin +++ b/android/app/.cxx/Debug/666c1h3t/x86_64/configure_fingerprint.bin @@ -2,27 +2,27 @@ C/C++ Structured Log_ ] [/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/additional_project_files.txtC A -?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint  ò¹»…‘4  �ô¥…‘4\ +?com.android.build.gradle.internal.cxx.io.EncodedFileFingerPrint   Öâ…‘4  �ô¥…‘4\ Z -X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build.json  ò¹»…‘4° �ô¥…‘4a +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build.json   Öâ…‘4° �ô¥…‘4a _ -]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build_mini.json  ò¹»…‘4  �ô¥…‘4N +]/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/android_gradle_build_mini.json   Öâ…‘4  �ô¥…‘4N L -J/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja  ò¹»…‘4ú³ ˆô¥…‘4R +J/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja   Öâ…‘4ú³ ˆô¥…‘4R P -N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja.txt  ò¹»…‘4W +N/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build.ninja.txt   Öâ…‘4W U -S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build_file_index.txt  ò¹»…‘4 ? �ô¥…‘4X +S/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/build_file_index.txt   Öâ…‘4 ? �ô¥…‘4X V -T/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json  ò¹»…‘4ô ˆô¥…‘4\ +T/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json   Öâ…‘4ô ˆô¥…‘4\ Z -X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json.bin  ò¹»…‘4 ë ˆô¥…‘4b +X/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/compile_commands.json.bin   Öâ…‘4 ë ˆô¥…‘4b ` -^/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt  ò¹»…‘4 +^/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/metadata_generation_command.txt   Öâ…‘4 » �ô¥…‘4U S -Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json  ò¹»…‘4  ( �ô¥…‘4Z +Q/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/prefab_config.json   Öâ…‘4  ( �ô¥…‘4Z X -V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt  ò¹»…‘4  U �ô¥…‘4C +V/home/ubuntu/repos/chat/android/app/.cxx/Debug/666c1h3t/x86_64/symbol_folder_index.txt   Öâ…‘4  U �ô¥…‘4C A -?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt  ò¹»…‘4 ¨ õÿ¶„‘4 \ No newline at end of file +?/home/ubuntu/repos/chat/android/app/src/main/cpp/CMakeLists.txt   Öâ…‘4 ¨ õÿ¶„‘4 \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt index 580dc82a..12815f70 100644 --- a/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt +++ b/android/app/src/main/kotlin/com/logseq/chat/runtime/LogseqChatIcons.kt @@ -78,5 +78,10 @@ internal val logseqChatAppIcons: Map = mapOf( ) internal val logseqChatIconResolver = LuiIconResolver { name -> - logseqChatAppIcons[name] ?: LuiIconResolver.DEFAULT.icon(name) + // `app:`-prefixed names are app-owned icon identifiers from the schema. + val key = name.removePrefix("app:") + logseqChatAppIcons[key] + ?: logseqChatAppIcons[name] + ?: LuiIconResolver.DEFAULT.icon(name) + ?: LuiIconResolver.DEFAULT.icon(key) } diff --git a/android/lui/src/main/kotlin/dev/lui/LuiProps.kt b/android/lui/src/main/kotlin/dev/lui/LuiProps.kt index 9a41650f..80b118ad 100644 --- a/android/lui/src/main/kotlin/dev/lui/LuiProps.kt +++ b/android/lui/src/main/kotlin/dev/lui/LuiProps.kt @@ -53,12 +53,13 @@ internal fun LuiNode.styleModifier(): Modifier { int("max-width")?.let { modifier = modifier.widthIn(max = it.dp) } int("min-height")?.let { modifier = modifier.heightIn(min = it.dp) } int("max-height")?.let { modifier = modifier.heightIn(max = it.dp) } - when (string("width-mode") ?: string("sizing")) { + when (string("sizing")) { "fill" -> modifier = modifier.fillMaxWidth() else -> {} } if (flag("fill-width")) modifier = modifier.fillMaxWidth() if (flag("fill-height") || flag("fill")) modifier = modifier.fillMaxHeight() + if ((double("grow") ?: 0.0) > 0.0) modifier = modifier.fillMaxWidth() int("padding")?.let { modifier = modifier.padding(it.dp) } int("padding-horizontal")?.let { modifier = modifier.padding(horizontal = it.dp) } int("padding-vertical")?.let { modifier = modifier.padding(vertical = it.dp) } @@ -94,7 +95,7 @@ internal fun LuiNode.surfaceModifier(): Modifier { internal fun LuiNode.gapDp() = (int("gap") ?: 0).dp internal fun LuiNode.mainAxisAlignment(): androidx.compose.foundation.layout.Arrangement.Horizontal = - when (string("main-alignment")) { + when (string("main")) { "center" -> androidx.compose.foundation.layout.Arrangement.Center "end" -> androidx.compose.foundation.layout.Arrangement.End "space-between" -> androidx.compose.foundation.layout.Arrangement.SpaceBetween @@ -104,7 +105,7 @@ internal fun LuiNode.mainAxisAlignment(): androidx.compose.foundation.layout.Arr } internal fun LuiNode.mainAxisVertical(): androidx.compose.foundation.layout.Arrangement.Vertical = - when (string("main-alignment")) { + when (string("main")) { "center" -> androidx.compose.foundation.layout.Arrangement.Center "end", "bottom" -> androidx.compose.foundation.layout.Arrangement.Bottom "space-between" -> androidx.compose.foundation.layout.Arrangement.SpaceBetween @@ -114,14 +115,14 @@ internal fun LuiNode.mainAxisVertical(): androidx.compose.foundation.layout.Arra } internal fun LuiNode.crossAxisHorizontal(): androidx.compose.ui.Alignment.Horizontal = - when (string("cross-alignment")) { + when (string("cross")) { "center" -> androidx.compose.ui.Alignment.CenterHorizontally "end" -> androidx.compose.ui.Alignment.End else -> androidx.compose.ui.Alignment.Start } internal fun LuiNode.crossAxisVertical(): androidx.compose.ui.Alignment.Vertical = - when (string("cross-alignment")) { + when (string("cross")) { "center" -> androidx.compose.ui.Alignment.CenterVertically "end", "bottom" -> androidx.compose.ui.Alignment.Bottom else -> androidx.compose.ui.Alignment.Top diff --git a/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt b/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt index fe2637dc..7d7dd2ac 100644 --- a/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt +++ b/android/lui/src/main/kotlin/dev/lui/LuiRenderers.kt @@ -187,24 +187,24 @@ private fun NodeView(backend: LuiBackend, node: LuiNode) { ) "text", "label" -> TextNode(backend, node) "heading" -> Text( - text = node.string("value") ?: node.string("title").orEmpty(), + text = node.string("text") ?: node.string("title").orEmpty(), modifier = node.styleModifier().gestures(backend, node), style = node.headingStyle(), ) "paragraph" -> Text( - text = node.string("value").orEmpty(), + text = node.string("text").orEmpty(), modifier = node.styleModifier().gestures(backend, node), style = node.textStyle(), ) "kbd" -> Text( - text = node.string("value").orEmpty(), + text = node.string("text").orEmpty(), modifier = node.styleModifier(), style = node.textStyle().copy(fontFamily = FontFamily.Monospace), ) "icon" -> IconNode(backend, node) "button", "toggle-button" -> ButtonNode(backend, node) "link" -> Text( - text = node.string("value") ?: node.string("title").orEmpty(), + text = node.string("text") ?: node.string("title").orEmpty(), modifier = node.styleModifier().gestures(backend, node), style = node.textStyle().copy( color = MaterialTheme.colorScheme.primary, @@ -239,7 +239,7 @@ private fun NodeView(backend: LuiBackend, node: LuiNode) { modifier = node.styleModifier(), ) "progress" -> LinearProgressIndicator( - progress = { (node.double("progress-value") ?: 0.0).toFloat() }, + progress = { (node.double("value") ?: 0.0).toFloat() }, modifier = node.styleModifier().fillMaxWidth(), ) "spinner" -> CircularProgressIndicator( @@ -342,7 +342,7 @@ private fun RowNode(backend: LuiBackend, node: LuiNode) { @Composable private fun GridNode(backend: LuiBackend, node: LuiNode) { - val columns = (node.int("grid-columns") ?: 2).coerceAtLeast(1) + val columns = (node.int("columns") ?: 2).coerceAtLeast(1) Column( modifier = node.surfaceModifier().gestures(backend, node), verticalArrangement = node.mainAxisVertical(), @@ -436,7 +436,7 @@ private fun SpacerNode(node: LuiNode) { @Composable private fun TextNode(backend: LuiBackend, node: LuiNode) { Text( - text = node.string("value") ?: node.string("title").orEmpty(), + text = node.string("text") ?: node.string("title").orEmpty(), modifier = node.styleModifier().gestures(backend, node), style = node.textStyle(), textAlign = node.textAlign(), @@ -451,14 +451,14 @@ private fun TextNode(backend: LuiBackend, node: LuiNode) { @Composable private fun IconNode(backend: LuiBackend, node: LuiNode) { - val name = node.string("icon") ?: node.string("value") ?: return + val name = node.string("name") ?: node.string("icon") ?: return val vector = backend.icons.icon(name) if (vector != null) { Icon( imageVector = vector, contentDescription = node.string("accessibility-label"), tint = node.colorProp("foreground") ?: MaterialTheme.colorScheme.onSurface, - modifier = node.styleModifier().size((node.int("size-value") ?: 20).dp), + modifier = node.styleModifier().size((node.int("width") ?: 20).dp), ) } else { Text( @@ -485,7 +485,7 @@ private fun ButtonNode(backend: LuiBackend, node: LuiNode) { Spacer(Modifier.width(6.dp)) } } - node.string("value")?.let { Text(it) } + node.string("text")?.let { Text(it) } node.string("title")?.let { Text(it) } Children(backend, node) } @@ -521,7 +521,7 @@ private fun ButtonNode(backend: LuiBackend, node: LuiNode) { @Composable private fun TextFieldNode(backend: LuiBackend, node: LuiNode) { - val propValue = node.string("value") ?: "" + val propValue = node.string("text") ?: "" var fieldValue by remember(node.id) { mutableStateOf(TextFieldValue(propValue)) } // Keep local IME state in sync when the core patches `value` back. if (fieldValue.text != propValue && !node.enabled("editing")) { @@ -785,7 +785,7 @@ private fun ToastNode(backend: LuiBackend, node: LuiNode) { @Composable private fun BadgeNode(backend: LuiBackend, node: LuiNode) { Badge(modifier = node.styleModifier()) { - Text(node.string("value") ?: node.string("title").orEmpty()) + Text(node.string("text") ?: node.string("title").orEmpty()) } }