Skip to content

Refactor backup and import processes to use profile for CSV#367

Merged
yogeshpaliyal merged 2 commits intomasterfrom
featAddProfilesInCsv
Feb 7, 2026
Merged

Refactor backup and import processes to use profile for CSV#367
yogeshpaliyal merged 2 commits intomasterfrom
featAddProfilesInCsv

Conversation

@yogeshpaliyal
Copy link
Copy Markdown
Owner

@yogeshpaliyal yogeshpaliyal commented Feb 7, 2026

This pull request updates the backup and import functionality to support exporting and importing bookmarks with associated profile information. The main change is switching from the ListDeeprWithTagsAsc data structure to the new GetLinksForBackup structure, which includes the profile name. Several importers now use the correct coroutine method for retrieving the selected profile ID, improving reliability.

Backup and Export Enhancements:

  • Changed backup/export logic to use GetLinksForBackup instead of ListDeeprWithTagsAsc, allowing profile information to be included in exported data. (AutoBackupWorker.kt, ExportRepositoryImpl.kt, CsvWriter.kt) [1] [2] [3] [4] [5]
  • Added PROFILE_NAME to CSV export header and data rows, so exported bookmarks now include the profile name. (CsvWriter.kt, Constants.kt) [1] [2] [3]

Import Functionality Improvements:

  • Updated CsvBookmarkImporter to accept AppPreferenceDataStore and use the selected profile ID from preferences, defaulting correctly when not found. (ImportRepositoryImpl.kt, CsvBookmarkImporter.kt) [1] [2] [3]
  • Ensured imported bookmarks are assigned the correct profile ID, using the selected profile or defaulting as needed. (CsvBookmarkImporter.kt) [1] [2]

Consistency in Profile ID Retrieval:

  • Switched from singleOrNull() to first() or firstOrNull() for retrieving the selected profile ID in Chrome, Mozilla, and HTML importers, improving coroutine usage and reliability. (ChromeBookmarkImporter.kt, MozillaBookmarkImporter.kt, HtmlBookmarkImporter.kt) [1] [2] [3] [4] [5] [6]

Copilot AI review requested due to automatic review settings February 7, 2026 19:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors bookmark backup/export and import flows so CSV backups include profile information and CSV imports can map entries to profiles.

Changes:

  • Add a profileName column to CSV exports and include it in the CSV writer output.
  • Update CSV import to resolve/create profiles based on the CSV’s profile column, with a fallback to the currently selected profile.
  • Replace Flow.singleOrNull() usage with first() / firstOrNull() when reading the selected profile id from DataStore.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
app/src/main/java/com/yogeshpaliyal/deepr/util/Constants.kt Adds PROFILE_NAME CSV header constant.
app/src/main/java/com/yogeshpaliyal/deepr/backup/importer/MozillaBookmarkImporter.kt Uses DataStore first() for selected profile id during import.
app/src/main/java/com/yogeshpaliyal/deepr/backup/importer/HtmlBookmarkImporter.kt Uses DataStore firstOrNull() for selected profile id during import.
app/src/main/java/com/yogeshpaliyal/deepr/backup/importer/CsvBookmarkImporter.kt Injects AppPreferenceDataStore and maps CSV rows to profiles.
app/src/main/java/com/yogeshpaliyal/deepr/backup/importer/ChromeBookmarkImporter.kt Uses DataStore first() for selected profile id during import.
app/src/main/java/com/yogeshpaliyal/deepr/backup/ImportRepositoryImpl.kt Wires AppPreferenceDataStore into CsvBookmarkImporter.
app/src/main/java/com/yogeshpaliyal/deepr/backup/ExportRepositoryImpl.kt Switches export query to getLinksForBackup() to include profile name.
app/src/main/java/com/yogeshpaliyal/deepr/backup/CsvWriter.kt Writes profileName column and uses GetLinksForBackup query model.
app/src/main/java/com/yogeshpaliyal/deepr/backup/AutoBackupWorker.kt Uses getLinksForBackup() for auto-backup CSV generation.

Comment on lines 84 to 86
createdAt = createdAt,
profileId = profileID ?: 1L,
profileId = profileID,
)
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

Variable profileID (used to populate profileId) is inconsistently named compared to Kotlin style and the surrounding code. Renaming it to profileId would improve readability and avoid confusion.

Copilot uses AI. Check for mistakes.
Comment on lines 67 to 73
val profileID =
profileName?.let {
val profile = deeprQueries.getProfileByName(profileName).executeAsOneOrNull()
if (profile == null) {
deeprQueries.insertProfile(profileName)
deeprQueries.lastInsertRowId().executeAsOneOrNull()
} else {
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

When the profile doesn’t exist, the code inserts via insertProfile (which is INSERT OR IGNORE) and then uses lastInsertRowId() as the new profile id. If the insert is ignored (e.g., race with another import/profile creation), lastInsertRowId() can be unrelated, leading to an incorrect profileId on imported links. Safer approach: after the insert, re-query getProfileByName(...) and use its id (or change the insert/query to return the id deterministically).

Copilot uses AI. Check for mistakes.
Comment on lines 33 to 38
bookmarks.forEach { bookmark ->
val existing = deeprQueries.getDeeprByLink(bookmark.url).executeAsOneOrNull()
if (bookmark.url.isNotBlank() && existing == null) {
try {
val profileId = appPreferenceDataStore.getSelectedProfileId.singleOrNull() ?: 1L
val profileId = appPreferenceDataStore.getSelectedProfileId.firstOrNull() ?: 1L
deeprQueries.transaction {
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

getSelectedProfileId.firstOrNull() is called for every bookmark inside the loop. Since the selected profile id is the same for the whole import, read it once before iterating to avoid repeated DataStore reads (can be noticeable for large bookmark files).

Copilot uses AI. Check for mistakes.
Comment on lines 26 to 37
links.forEach { link ->
val url = link.attr("href")
val title = link.text()
val folder = extractMozillaFolder(link)

// Firefox-specific attributes
val addDate = link.attr("add_date")
val lastModified = link.attr("last_modified")
val shortcutUrl = link.attr("shortcuturl")
val tags = link.attr("tags")
val profileId = appPreferenceDataStore.getSelectedProfileId.singleOrNull() ?: 1L
val profileId = appPreferenceDataStore.getSelectedProfileId.first()
if (url.isNotBlank() && !url.startsWith("place:")) {
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

getSelectedProfileId.first() is executed inside the links.forEach loop. Fetch the selected profile id once before iterating so importing large Firefox exports doesn’t repeatedly hit DataStore.

Copilot uses AI. Check for mistakes.
return RequestResult.Error(context.getString(R.string.no_data_to_export))
}
val dataToExportInCsvFormat = deeprQueries.listDeeprWithTagsAsc().executeAsList()
val dataToExportInCsvFormat = deeprQueries.getLinksForBackup().executeAsList()
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

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

Switching to getLinksForBackup() changes the export ordering: the SQL query has no ORDER BY, whereas the previous listDeeprWithTagsAsc() was ordered by createdAt. If deterministic CSV output matters (diffing backups, stable user experience), add ordering (in SQL or sort the list before writing).

Suggested change
val dataToExportInCsvFormat = deeprQueries.getLinksForBackup().executeAsList()
val dataToExportInCsvFormat =
deeprQueries.getLinksForBackup().executeAsList().sortedBy { it.createdAt }

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 7, 2026

@yogeshpaliyal I've opened a new pull request, #368, to work on those changes. Once the pull request is ready, I'll request review from you.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 7, 2026

📱 APK Build Complete!

Your debug APK has been built successfully and is ready for testing.

📥 Download APK

Download app-debug.apk

Note: Click the link above, scroll down to the "Artifacts" section, and download the app-debug artifact.

Retention: This artifact will be available for 3 days.

…eation (#368)

* Initial plan

* Handle blank/whitespace profile names in CSV import

Co-authored-by: yogeshpaliyal <9381846+yogeshpaliyal@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: yogeshpaliyal <9381846+yogeshpaliyal@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 7, 2026

🧪 Integrated Test Results

The integrated UI tests have completed.

View full test results: Test Run #21785475248

Test reports are available in the artifacts section of the workflow run.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 7, 2026

📱 APK Build Complete!

Your debug APK has been built successfully and is ready for testing.

📥 Download APK

Download app-debug.apk

Note: Click the link above, scroll down to the "Artifacts" section, and download the app-debug artifact.

Retention: This artifact will be available for 3 days.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 7, 2026

🧪 Integrated Test Results

The integrated UI tests have completed.

View full test results: Test Run #21785625646

Test reports are available in the artifacts section of the workflow run.

@yogeshpaliyal yogeshpaliyal merged commit 44a6c12 into master Feb 7, 2026
2 checks passed
@yogeshpaliyal yogeshpaliyal deleted the featAddProfilesInCsv branch February 7, 2026 19:48
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.

3 participants