Skip to content

fix: DB sync, upload reliability, parallel uploads, and sticker bug#28

Open
AjayaDahal wants to merge 33 commits into
AKS-Labs:mainfrom
AjayaDahal:fix/sync-upload-bugs
Open

fix: DB sync, upload reliability, parallel uploads, and sticker bug#28
AjayaDahal wants to merge 33 commits into
AKS-Labs:mainfrom
AjayaDahal:fix/sync-upload-bugs

Conversation

@AjayaDahal
Copy link
Copy Markdown

Summary

Fixes 3 major bugs reported by users:

  1. Database sync not working — cloud photos disappearing after app restart
  2. Background upload stops after some time — batch uploads dying mid-way
  3. Uploading is slow — sequential single-file uploads

Changes

Bug Fixes

  • Remove destructive auto-clearManageUploadsViewModel was deleting all remote photo records older than 24h on every screen open
  • Fix sticker upload bug — Set disableContentTypeDetection=true so Telegram doesn't auto-convert small images to stickers (which broke remoteId tracking → infinite re-upload loop)
  • Fix upload stopping — Worker now auto re-enqueues itself when photos are still pending instead of waiting for daily schedule
  • Fix channel scan — Replaced broken getUpdates() call (only returns 24h of unprocessed updates) with upload-time tracking as source of truth
  • Protect cloud-linked photosSyncDbMediaStoreWorker no longer deletes photos from DB if they have a cloud backup
  • Prevent upload cancellation — Changed work policy from REPLACE to KEEP

Performance Improvements

  • Parallel uploads — 3 concurrent uploads using coroutines (~3x speedup)
  • Streaming file I/O — Files streamed via copyTo() instead of readBytes() into memory
  • Batch size limit — Max 50 photos per worker run (prevents WorkManager 10-min kill)
  • Immediate temp file cleanupdelete() instead of deleteOnExit()

New Features

  • Database deduplication — Auto-dedup after every import (safe: only removes 100% certain duplicates)
  • Rate limiting — 1.5s delay between upload chunks to respect Telegram API limits

Testing

  • Built and sideloaded on Samsung S24 Ultra
  • Verified 7,281 cloud photos restored from backup
  • Confirmed parallel uploads working (46 photos uploaded in first batch)
  • Confirmed no more sticker uploads
  • Confirmed auto re-enqueue keeps uploads running continuously

AjayaDahal added 30 commits May 10, 2026 12:29
The ManageUploadsViewModel was deleting all remote_photos records older
than 24 hours every time the Uploads screen was opened. This caused
imported/restored cloud photo records to be immediately wiped.
Adds deduplicateDatabase() to BackupHelper that:
- Removes duplicate remoteIds in remote_photos (keeps first)
- Removes duplicate localIds in photos (keeps the one with remoteId)
- Only deletes when 100% certain of duplication
- Runs automatically after every database import
- Logs results for debugging
- Set disableContentTypeDetection=true in sendDocument call
  (Telegram was auto-converting small/square images to stickers)
- Added sticker response handling in sendFileApi as fallback
- Photos that previously uploaded as stickers weren't getting
  remoteId tracked, causing infinite re-upload loop
After completing a batch of 50 uploads, the worker now checks if
there are still pending photos and re-enqueues itself. Previously
it would stop after one batch and wait for the daily periodic schedule.
- Worker now emits totalDone/totalPhotos in setProgress()
- ViewModel reads batch progress + overall counts for Background uploads
- New UploadProgressBar composable (Material3, animated, reusable)
- MainPage shows backup progress bar above photo grid during uploads
- ManageUploads shows richer progress text (batch + overall counts)
ExistingWorkPolicy.KEEP prevents new work from being enqueued when
work with the same name already exists in a terminal state. Changed
to REPLACE so the worker can successfully re-enqueue itself after
completing each batch of 50 uploads.
…ctive worker

Progress bar now visible on home page as long as there are un-uploaded
photos, even between worker batch runs. Shows overall progress like
'7,608 of 9,565 backed up'.
Adds a FAB share button (bottom-right) when viewing photos in full
screen. Uses Android's share intent system to share via Messenger,
SMS, WhatsApp, or any other installed app.
Shows a progress card above Active section with:
- Linear progress bar for current batch
- Remaining photo count
- Current filename being uploaded
- Visible whenever photos are pending
…rompt

- Snapshot photo list when pager opens so background uploads don't
  shift the currently viewed photo
- Cloud photos prompt 'Download first' when trying to share
Card-style progress bar with cloud icon, batch progress (Uploading X of 50),
remaining count, and photo ID - identical layout to Uploads screen.
Cloud photos are now downloaded to cache dir on share tap, then
shared via FileProvider URI. Shows 'Preparing to share...' toast
while downloading. No more 'Download first' error.
Replaced UploadProgressBar composable with exact same inline code
from ManageUploadsScreen - reads WorkManager directly, shows thumbnail,
batch progress, and remaining count.
MainActivity.onCreate now checks for pending uploads and automatically
enqueues the PeriodicBackup worker. Previously uploads would only start
on manual button press or worker self-re-enqueue.
Comprehensive plan covering:
- Laptop server architecture (FastAPI + ML)
- Photo organization (timeline, people, places, years)
- Face detection/recognition (InsightFace)
- Semantic search (CLIP embeddings)
- Server-phone sync protocol
- Database schema design
- 5-phase implementation plan
Server is local-only development. Bot tokens and configs must never
be in the repo.
Server (Docker):
- Phase 1-6: EXIF, Face Detection, Places, Search/Albums, Dashboard, Thumbnails
- Metadata export: generates metadata.db and pushes to Telegram
- Face detection with Python 3.12 compatibility fix
- Auto-push metadata every 30 min

App:
- Local thumbnail DB (zero-network grid scrolling)
- ThumbnailSyncWorker: parallel download, newest-first
- Amazon Photos-style grid UX (smart dates, 2dp gaps, 4dp corners)
- Full-screen preview: zoom, download, share, delete
- Server discovery + hybrid mode
- Metadata sync from Telegram (People, Places)
- People and Places screens
- Fixed DJI upload crash (image/jpg mime type)
- Fixed progress bar stale data
- Cleartext HTTP for local server
- Aggressive paging (200 per page)
- Mark undecidable thumbnails (HEIC) as synced to stop retrying
- Use itemCount instead of itemSnapshotList for layout cache trigger
  (prevents rebuilding grid on every thumbnail sync update)
Root cause: createRemoteLayoutCache called cloudPhotos[i] from
Dispatchers.Default, but LazyPagingItems can only be accessed
from the main thread. This silently broke paging after ~200 items.

Fix: snapshot all items on main thread first, then process layout
on background thread using the snapshot data.
LazyPagingItems must be accessed from main thread only.
Previous approach used Dispatchers.Default which silently broke paging.
The grid was using currentLayoutItems.size which was capped at
however many items the layout cache had built. Now uses
cloudPhotos.itemCount directly so the grid knows about ALL items
and can trigger paging properly. Falls back to direct paging
access for items not yet in the layout cache.
- Paging trigger now loops with 500ms interval until all pages loaded
- Added getAllLightFlow (excludes thumbnailBytes BLOB) for memory efficiency
- Grid uses cloudPhotos.itemCount with fallback rendering
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant