Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
c85e702
Add WebDAV sync foundation (Phase 1)
Dec 11, 2025
085756a
Add serialization layer (Phase 2)
Dec 11, 2025
9037d89
Add stub implementations for all sync components
Dec 12, 2025
7115027
stub commits for synchronization, plus new serialization code
Dec 12, 2025
f56bde7
Fix compilation errors
Dec 12, 2025
f227d06
Complete WebDAV sync settings UI
Dec 12, 2025
8dfd9d8
Fix showHint argument order
Dec 12, 2025
876bbe5
Add debug logging for connection testing
Dec 12, 2025
6a60635
Fix NetworkOnMainThreadException in sync operations
Dec 12, 2025
6263db9
Implement complete SyncEngine with bidirectional sync
Dec 12, 2025
a72ae42
Fix SyncEngine compilation errors
Dec 12, 2025
a401ceb
Add force upload/download operations with confirmation dialogs
Dec 12, 2025
24be07e
Add detailed logging for sync debugging
Dec 13, 2025
19f55dc
Add in-app sync log viewer to Settings
Dec 13, 2025
9b89c91
Fix force operations and add comprehensive logging
Dec 13, 2025
73a7740
Implement sync on note close
Dec 13, 2025
554b677
Add detailed sync direction logging
Dec 13, 2025
5ab3f86
Fix EditorControlTower repository access
Dec 13, 2025
d365614
Fix sync to skip when timestamps are equal
Dec 13, 2025
7082c44
Fix sync-on-close to trigger when leaving editor
Dec 13, 2025
8f3c044
Fix coroutine scope cancellation in onDispose
Dec 13, 2025
5562949
Add credential loading debug logging
Dec 13, 2025
6a500c0
Add millisecond-precision timestamp logging
Dec 13, 2025
9f912f6
Fix null safety in timestamp logging
Dec 13, 2025
9f0313f
Add 1-second tolerance for timestamp comparison
Dec 13, 2025
fafb2b3
Add server notebook discovery to sync
Dec 13, 2025
839d93e
Fix bug in sync order.
Dec 20, 2025
28042b1
Deletion semantics update.
Dec 21, 2025
66b89b9
Fix bug with timestamp updates not happening in manifest.
Dec 23, 2025
ea9fb36
Fix deletion synchronization order of operations.
Dec 23, 2025
c501a6b
Switch to XmlPullParser for WebDav syncing instead of hacky regexes.
Dec 24, 2025
0f20790
Refactored a bunch of monolithic code into SyncEngine functions for b…
Dec 24, 2025
ae77510
Added state machine for consistency in synchronization status.
Dec 24, 2025
c9a1a6a
Extracted magic numbers we were previously using.
Dec 25, 2025
2ea67fb
Got rid of stacktraces and replaced with proper logging.
Dec 25, 2025
8bc98c0
Got rid of stacktraces and replaced with proper logging.
Dec 25, 2025
1c3fab9
Update app/src/main/java/com/ethran/notable/ui/views/Settings.kt
jdkruzr Dec 25, 2025
1731c41
Extracted sync settings tab to its own file.
Dec 25, 2025
595953a
Extracted sync settings tab to its own file.
Dec 25, 2025
75c2872
Merge refactored Settings code
Dec 25, 2025
2f6fd4e
Switched to SLog in all instances, reduced number of arguments to 2 i…
Dec 25, 2025
ba71486
Updated .gitignore to leave out unnecessary files.
Dec 25, 2025
b85acf1
Internationalization fix with strings.xml
Jan 17, 2026
306e189
Update app/src/main/java/com/ethran/notable/data/datastore/AppSetting…
jdkruzr Jan 17, 2026
10594a9
Added note re: notable subdir and credential saving fix
Jan 17, 2026
ff92bae
Change to SB1 format.
Jan 17, 2026
b1ef2ce
Created const for Notable directory.
Jan 18, 2026
fa5f148
Fixed issue with deletions clobbering edits made later.
Jan 18, 2026
20595cb
Small fix to currently unused file streaming function.
Jan 19, 2026
a491064
Sync documentation.
Jan 19, 2026
39acc64
Resolved another magic string into a const.
Jan 19, 2026
3f42b96
Added sync technical docs.
Feb 27, 2026
c4b5619
Minor edits to sync technical docs.
Feb 27, 2026
ceaef77
Edits explaining some DAV address vagaries.
Feb 27, 2026
b0fa0f0
Added sync on WiFi only option.
Feb 27, 2026
db9698f
Addressed editorial feedback for documentation.
Feb 28, 2026
f350374
We now check deletions.json for truncation opportunities when writing.
Feb 28, 2026
3363131
Changes and responses to PR feedback (see comment)
Mar 7, 2026
04e6930
Rename tombstones/ server directory to deletions/ per review feedback.
Mar 15, 2026
83c6bbc
merge Hilt implementation, address notebook creation quality of life …
Mar 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
/.idea/
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
.claude-context.md
comments.md
1 change: 0 additions & 1 deletion .idea/.name

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/AndroidProjectSystem.xml

This file was deleted.

61 changes: 0 additions & 61 deletions .idea/androidTestResultsUserPreferences.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/compiler.xml

This file was deleted.

25 changes: 0 additions & 25 deletions .idea/deploymentTargetSelector.xml

This file was deleted.

19 changes: 0 additions & 19 deletions .idea/gradle.xml

This file was deleted.

61 changes: 0 additions & 61 deletions .idea/inspectionProfiles/Project_Default.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/kotlinc.xml

This file was deleted.

10 changes: 0 additions & 10 deletions .idea/migrations.xml

This file was deleted.

9 changes: 0 additions & 9 deletions .idea/misc.xml

This file was deleted.

17 changes: 0 additions & 17 deletions .idea/runConfigurations.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/studiobot.xml

This file was deleted.

6 changes: 0 additions & 6 deletions .idea/vcs.xml

This file was deleted.

5 changes: 5 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,11 @@ dependencies {
ksp "com.google.dagger:hilt-compiler:2.59.2"
implementation "androidx.hilt:hilt-navigation-compose:1.3.0"

// WebDAV sync dependencies
implementation "androidx.work:work-runtime-ktx:2.9.0" // Background sync
implementation "com.squareup.okhttp3:okhttp:4.12.0" // HTTP/WebDAV client
implementation "androidx.security:security-crypto:1.1.0-alpha06" // Encrypted credential storage
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

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

The androidx.security:security-crypto version 1.1.0-alpha06 is an alpha release and may not be production-ready. Consider using a stable version (e.g., 1.0.0) for better stability and security, especially since this is being used to encrypt WebDAV credentials.

Suggested change
implementation "androidx.security:security-crypto:1.1.0-alpha06" // Encrypted credential storage
implementation "androidx.security:security-crypto:1.0.0" // Encrypted credential storage

Copilot uses AI. Check for mistakes.

// Added so that R8 optimization don't fail
// SLF4J backend: provides a simple logger so (probably) ShipBook can output logs.
// Needed because SLF4J is just an API; without a binding, logging calls are ignored.
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
android:name=".NotableApp"
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/ethran/notable/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import com.ethran.notable.data.db.KvProxy
import com.ethran.notable.data.db.StrokeMigrationHelper
import com.ethran.notable.editor.canvas.CanvasEventBus
import com.ethran.notable.io.ExportEngine
import com.ethran.notable.sync.SyncEngine
import com.ethran.notable.ui.LocalSnackContext
import com.ethran.notable.ui.SnackState
import com.ethran.notable.ui.components.NotableApp
Expand Down Expand Up @@ -110,6 +111,8 @@ class MainActivity : ComponentActivity() {
editorSettingCacheManager.get().init()
strokeMigrationHelper.get().reencodeStrokePointsToSB1()
}
// Trigger initial sync on app startup (fails silently if offline)
triggerInitialSync()
}
isInitialized = true
}
Expand All @@ -132,6 +135,18 @@ class MainActivity : ComponentActivity() {
}
}


private suspend fun triggerInitialSync() {
try {
if (GlobalAppSettings.current.syncSettings.syncEnabled) {
Log.i(TAG, "Triggering initial sync on app startup")
SyncEngine(applicationContext).syncAllNotebooks()
}
} catch (e: Exception) {
Log.i(TAG, "Initial sync failed (offline?): ${e.message}")
}
}

override fun onRestart() {
super.onRestart()
// redraw after device sleep
Expand Down
20 changes: 20 additions & 0 deletions app/src/main/java/com/ethran/notable/data/datastore/AppSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ object GlobalAppSettings {
}


@Serializable
data class SyncSettings(
val syncEnabled: Boolean = false,
val serverUrl: String = "",
val username: String = "",
// Note: Password stored separately in EncryptedSharedPreferences for security
val autoSync: Boolean = true,
// Default must be >= 15 minutes due to WorkManager/JobScheduler minimum interval
val syncInterval: Int = 15, // minutes
val lastSyncTime: String? = null,
val syncOnNoteClose: Boolean = true,
val wifiOnly: Boolean = false,
// Track which notebooks we've successfully synced to detect deletions
val syncedNotebookIds: Set<String> = emptySet()
)


@Serializable
data class AppSettings(
// General
Expand All @@ -47,7 +64,10 @@ data class AppSettings(
val twoFingerSwipeRightAction: GestureAction? = defaultTwoFingerSwipeRightAction,
val holdAction: GestureAction? = defaultHoldAction,
val enableQuickNav: Boolean = true,
val renameOnCreate: Boolean = true,

// Sync
val syncSettings: SyncSettings = SyncSettings(),

// Debug
val showWelcome: Boolean = true,
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/com/ethran/notable/data/db/Folder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ interface FolderDao {
@Query("SELECT * FROM folder WHERE id IS :folderId")
fun getLive(folderId: String): LiveData<Folder?>

@Query("SELECT * FROM folder")
fun getAll(): List<Folder>

@Insert
suspend fun create(folder: Folder): Long
Expand All @@ -74,6 +76,10 @@ class FolderRepository @Inject constructor(
db.update(folder)
}

fun getAll(): List<Folder> {
return db.getAll()
}

fun getAllInFolder(folderId: String? = null): LiveData<List<Folder>> {
return db.getChildrenFolders(folderId)
}
Expand Down
Loading
Loading