[WIP] TF-4449 Implement external drive attachments#4581
[WIP] TF-4449 Implement external drive attachments#4581tddang-linagora wants to merge 3 commits into
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This PR has been deployed to https://linagora.github.io/tmail-flutter/4581. |
| final response = await _dio.post( | ||
| '$platformUrl/intents', | ||
| options: Options( | ||
| headers: {'Authorization': 'Bearer $accessToken'}, |
There was a problem hiding this comment.
Using Dio with an interceptor already in place. Why do we need to set authentication in the header? What about token refresh cases?
There was a problem hiding this comment.
This is token for other service not for jmap, so we must have a dedicated http client for this.
Yes, good question for refreshToken here @zatteo
There was a problem hiding this comment.
Good question, we will need to get and manage refreshToken or we can take hypothesis that these are one shot call that must be done directly after token_exchange. I am writing this in backend questions.
There was a problem hiding this comment.
Pending until further progress regarding token for external drive's service.
| data: { | ||
| 'data': { | ||
| 'type': 'io.cozy.intents', | ||
| 'attributes': { | ||
| 'action': 'PICK', | ||
| 'type': 'io.cozy.files', | ||
| 'permissions': ['GET'], | ||
| }, | ||
| }, | ||
| }, |
There was a problem hiding this comment.
We should create a model for payload data.
There was a problem hiding this comment.
Agree, now 1 case of intent, but in the future we have variety intents
| ); | ||
| final parsed = DriveIntentResponse.fromJson(response.data as Map<String, dynamic>); | ||
| final intentId = parsed.data.id; | ||
| final href = parsed.data.attributes.services.first.href; |
There was a problem hiding this comment.
Should we return an error earlier if parsed.data.attributes.services is empty?
There was a problem hiding this comment.
If services is empty, .first will throw and the function will stop here.
| priorityHeader: isMarkAsImportant | ||
| ? {IndividualHeaderIdentifier.priorityHeader: MailPriorityHeader.urgentPriority} | ||
| : null, | ||
| xLinkedFileHeader: _buildLinkedFileHeader(driveAttachments), |
There was a problem hiding this comment.
Is this drive button displayed only on environment that supports it?
There was a problem hiding this comment.
Current implementation: If you have workplaceFqdn url, you have the button.
After discussed with the team and Zoe: The button will have 2 more gates, one in env.file file, the other in Preferences toggle (experimental flag, hide behind 7 taps on the title of settings).
| this.savedEmailDraftId, | ||
| this.keywords, | ||
| this.isUpdateDraftToClose = false, | ||
| this.driveAttachments, |
There was a problem hiding this comment.
No I disagree with this !
The concept of drive attachment should not leak into our main model.
We should have the "drive layer" do the translation and provide the "create_email_request" properties that we need!
| if (driveAttachmentButton != null) ...[ | ||
| const SizedBox(width: MobileAppBarComposerWidgetStyle.space), | ||
| driveAttachmentButton!, | ||
| ], |
There was a problem hiding this comment.
(if spotted - if your remeber what I said yesterday during the MOB it may ring a bell)
There was a problem hiding this comment.
Yeah a good point to invest: how we can plug and play the UI component?
| import 'package:drive_attachment/drive_attachment/domain/entity/drive_document.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/notifier/drive_attachment_notifier.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/notifier/drive_attachment_state.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/provider/drive_access_token_notifier.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/provider/workplace_fqdn_notifier.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/view/drive_intent_web_view_modal.dart'; |
There was a problem hiding this comment.
Can we avoid this direct dependency?
In Java I would...
- define an interface with the behaviour / info needed
- implement the interface in my extension
- Use the interface in the other part of the code
- And do the link with dependency injection
That avoids direct dependency and allow pluging alternative mechanisms in alternative extensions eg JMAP file extension. At a very minimal cost.
There was a problem hiding this comment.
Until there are multiple behavior that can be injected to this particular button of external drive, it is moved into its function's module, and we respect YAGNI in the meantime.
| import 'package:drive_attachment/drive_attachment/presentation/notifier/drive_attachment_notifier.dart'; | ||
| import 'package:drive_attachment/drive_attachment/presentation/widget/drive_attachment_chip.dart'; |
| ref: "feature/linked-file-header" | ||
| resolved-ref: "6d730da063638080a8fe96939c4d0c9f8b3d4275" |
There was a problem hiding this comment.
Why do we need changes in JMAP dart client ?
There was a problem hiding this comment.
Why do we need to overload this ?
Can't we just have a list of headers and associated tyes we pass to the jmap client ?
There was a problem hiding this comment.
@chibenwa does "X-LinkedFile:all:asText" need to be individual header that needs header: prefix or it can be inside headers field? If individual header, jmap-dart-client's current implementation only allows specified header to be parsed from and to json. And need at least 1 commit to allow dynamically adding more.
There was a problem hiding this comment.
If it can be inside headers field then the PR for "feature/linked-file-header" can be closed.
There was a problem hiding this comment.
We cannot set headers and individual header indiviually i't one or the other.
I'm fine with the proposal to add extra headers (though I want us to improve the user experience of it)
There was a problem hiding this comment.
Now I understood what you meant. For now we will not update jmap-dart-client dependency of tmail-flutter and inject/parse the desired header from headers field.
Nevermind. it is still needed after all.
|
@coderabbitai review this please |
| IconButton( | ||
| icon: const Icon(Icons.close), |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Fetch PR details
gh pr view 4581 --repo linagora/tmail-flutter --json title,body,state,additions,deletions,changedFiles,labels,reviewRequests
echo "=== FILES CHANGED ==="
gh pr diff 4581 --repo linagora/tmail-flutter --name-only
echo "=== FULL DIFF ==="
gh pr diff 4581 --repo linagora/tmail-flutterLength of output: 71484
Overall SummaryThe PR introduces a new 🔴 Blocking Issues1. Unguarded
|
|
|
||
| const DriveAttachment({required this.document}); | ||
|
|
||
| String get linkedFileHeader { |
There was a problem hiding this comment.
to generate expected format for the header
| import 'package:drive_attachment/drive_attachment/domain/usecase/exchange_drive_token_interactor.dart'; | ||
| import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
|
|
||
| Dio? _dio; |
There was a problem hiding this comment.
It quite orphan? It will keep dio for this provider?
There was a problem hiding this comment.
Gates Failed
New code is healthy
(1 new file with code health below 10.00)
Our agent can fix these. Install it.
Gates Passed
2 Quality Gates Passed
Reason for failure
| New code is healthy | Violations | Code Health Impact | |
|---|---|---|---|
| drive_intent_message_handler_mixin.dart | 1 rule | 9.69 | Suppress |
Absence of Expected Change Pattern
- tmail-flutter/lib/features/composer/presentation/widgets/mobile/app_bar_composer_widget.dart is usually changed with: tmail-flutter/lib/features/composer/presentation/widgets/mobile/landscape_app_bar_composer_widget.dart
Quality Gate Profile: The Bare Minimum
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.
Issue