Skip to content

First draft of import support for Clue #140 #254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

EmmaTellblom
Copy link
Owner

@carstenhag Need help with getting the file to new class ClueImport. I think the rest might work?

@EmmaTellblom EmmaTellblom marked this pull request as draft April 21, 2025 10:59
var expanded by remember { mutableStateOf(false) }

Column(modifier = modifier) {
OutlinedTextField(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would be nice if the value would be clickable, so that the user doesn't have to specifically tap on the arrow. I couldn't find a way to do it nicely though...

It's possible to set a clickable on the OutlinedTextField, but the ripple animation does not look good. I think a different UI element should be used, not OutlinedTextField.

val impSuccess = stringResource(id = R.string.import_success_toast)
val impFailure = stringResource(id = R.string.import_failure_toast)

var selectedOption by remember { mutableStateOf("Mensinator") }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use an enum for this, not a String.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Introduced enum but have not gotten it to work with the dialog. When clicked it crashes...

// Call the import function
onImportClick(file.absolutePath)
if (selectedOption == "Clue") {
ClueImport(context).importFileToDatabase(file.absolutePath) // Pass the Uri
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't handle this on the UI layer :P. The mensinator import is handled from the ViewModel, same thing should be done for the Clue import

Copy link
Collaborator

Choose a reason for hiding this comment

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

onImportClick should be called with the path and the import option. The VM then decides what to do with it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Please rename IExportImport/ExportImport to IMensinatorExportImport/MensinatorExportImport.


Toast.makeText(context, "Importing file: ${file.name}", Toast.LENGTH_SHORT).show()

if (file.name != "measurements.json") {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should not be there. The user should be allowed to name their export/backup in the way they want.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ah, but here is the problem, when exporting from Clue you get 12 json-files;
Consents.json (we do not need this information)
CycleSettings.json (contains if Clue should track ovulation, we do not have this right now)
Devices.json (we do not need this information)
Integrations.json (weird stuff, not needed we do not integrate to other stuff)
Measurements.json (Contains period dates, what we want to import)
Medical_records.json (we do not need this information)
Profile.json (contains users birthday and cycle length set by user, we dont need this)
Push.json (contains weird stuff, do not need. Does not contain anything about push notifications)
Reminders.json (contains information about reminders, we could use this for notification settings also, but Im not sure this is something the users want. In any case that could be next step when import of period data works)
Subscriptions.json (we do not need this information)
User.json (we do not need this information since we dont store information about email and names)
UserModeEvents.json (information about which 'mode' you are using in Clue, we do not need this).

The export from Clue is in a password protected zipfile and the folder then contains the 12 files mentioned above. I want to make it easy for the user that they should only select the Measurements file. So that's why I have that check, for Clue we are only interested in that specific file.


private fun cleanUpTables(db: SQLiteDatabase) {
// Clean up the "periods" table before importing new data
db.delete("periods", null, null)
Copy link
Collaborator

Choose a reason for hiding this comment

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

While importing it should be made clear that existing data gets removed.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ah, this is something we do currently for Mensinator import because I did not have a unique constraint on the periods and ovulations table. I have implemented it now so for Clue, we don't need to delete any period data.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Added new db-functionality for this, so we do not need to delete data in periods/ovulations when importing data (if we use the function addDateToPeriod).

private val context: Context
) : IClueImport {

private val dbHelper = PeriodDatabaseHelper(context, DefaultDispatcherProvider())
Copy link
Collaborator

Choose a reason for hiding this comment

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

This must not be done! We don't want to create new classes manually. This must be injected via koin, same as at ExportImport.kt.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Agreed! Not yet familiar with Koin...

@carstenhag
Copy link
Collaborator

Also please include an example import json into the project. Else this is difficult to maintain or test. For now just include it in a testing folder, at some point unit tests should be written for the imports.

@EmmaTellblom
Copy link
Owner Author

In the linked issue I have example of exportfile from Clue and some information that is good to know:
#140

@@ -136,6 +136,7 @@
<string name="import_path_label">Import Path: %1$s</string>
<string name="import_dialog_message">Select file to import data.</string>
<string name="export_dialog_message">Select the output path to export calendar entries, symptoms and other data.</string>
<string name="select_source">Select app source</string>

Check warning

Code scanning / Android Lint

Incomplete translation Warning

"select_source" is not translated in "de" (German), "hi" (Hindi), "ru" (Russian), "sv" (Swedish), "it" (Italian), "bn" (Bangla), "fr" (French), "ta" (Tamil), "es" (Spanish), "zh" (Chinese), "sl" (Slovenian), "pl" (Polish), "ro" (Romanian)
@EmmaTellblom EmmaTellblom marked this pull request as ready for review April 24, 2025 19:51
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.

2 participants