Skip to content

Desktop: Replace smalltalk with React Dialog to add password visibility in encryption setup#14739

Merged
laurent22 merged 12 commits intolaurent22:devfrom
himanshumishra1309:feature/encryption-password-visibility
Apr 2, 2026
Merged

Desktop: Replace smalltalk with React Dialog to add password visibility in encryption setup#14739
laurent22 merged 12 commits intolaurent22:devfrom
himanshumishra1309:feature/encryption-password-visibility

Conversation

@himanshumishra1309
Copy link
Copy Markdown
Contributor

@himanshumishra1309 himanshumishra1309 commented Mar 14, 2026

Description

Currently, when a user clicks "Enable encryption", the app asks for their password but masks the input entirely. Since this password is going to be used to encrypt their entire database, making a typo here can cause a lot of stress.

This PR adds a "show password" (eye icon) toggle to that prompt so users can easily view and verify their password while typing.

Technical details & Implementation

Initially, I looked into just adding an HTML button to the existing prompt, but I noticed we were using the dialogs.prompt() method there, which relies under the hood on the legacy smalltalk library. Because smalltalk generates its DOM outside of our React tree, we can't cleanly inject custom components or buttons into it.

To solve this and give the user the right to view their password, I completely replaced the legacy smalltalk prompt with our native, already-built React <Dialog> and <PasswordInput> components.

Here is exactly how I refactored the flow:

  • State Management: I introduced two new state variables (enableEncryptionPromptVisible and enableEncryptionPassword).
  • The Flow: Instead of halting javascript execution with an await dialogs.prompt(...) call, clicking the "Enable encryption" button now just sets enableEncryptionPromptVisible to true. This opens our custom React Dialog.
  • The Logic: When the user clicks "OK" in the new dialog, it passes the typed password directly to the exact same toggleAndSetupEncryption(...) function as before.

Why is this better?

  1. Safety: Absolutely no logical or encryption-related code was touched, only the frontend UI triggering it.
  2. Consistency: Using the pre-built <PasswordInput> gives us the show/hide eye toggle for free, and using <Dialog> ensures this popup natively respects Joplin's existing CSS system (like the dialog-root and dialog-content wrappers for dark/light themes).

Testing

  • Clicked "Enable encryption" and verified the customized React modal opens.
  • Typed a password and clicked the eye icon to verify it toggles text visibility properly.
  • Verified that hitting "Cancel" cleanly closes the modal by resetting the state, without triggering encryption.
  • Verified that confirming with a valid password successfully triggers the encryption background setup.

Before:

Screenshot From 2026-03-14 22-17-16 (Edited)

After:

image

After all alterations(both light and dark mode):

Screenshot From 2026-03-23 21-00-44 Screenshot From 2026-03-23 21-01-09

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 14, 2026

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 14, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Replaces the direct master-password prompt in EncryptionConfigScreen with an internal enable-encryption dialog implemented via component state and a Promise-like resolver; integrates password handling, validation and error paths, preserves existing master-password fallback, and updates styles and a password-input type alias.

Changes

Cohort / File(s) Summary
Encryption Enablement Dialog
packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx
Adds component state (enableEncryptionPromptVisible, enableEncryptionPassword, promptPromiseRef), renderEnableEncryptionDialog, and a two-stage enable flow that awaits the in-component dialog instead of calling dialogs.prompt; integrates password validation and error handling while keeping the master-password fallback.
Dialog Styling Inclusion
packages/app-desktop/main.scss
Extends existing master-password selectors to include .enable-encryption-dialog so the new dialog reuses the same .dialog-root, .dialog-content and .current-password-wrapper styles.
PasswordInput Types
packages/app-desktop/gui/PasswordInput/types.ts
Replaces the custom ChangeEvent interface with a type alias to React's ChangeEvent<HTMLInputElement>, updating exported event typing used by ChangeEventHandler.
Manifest / Package metadata
manifest_file, package.json
Minor metadata/manifest updates (lines changed: +78/-5); no public API changes reported.

Possibly related PRs

Suggested reviewers

  • mrjo118
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: replacing smalltalk with React Dialog and adding password visibility to the encryption setup prompt.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Pr Description Must Follow Guidelines ✅ Passed The PR description contains all three required sections: problem/user-impact clearly articulated with rationale, comprehensive solution explanation with implementation details, and test plan with specific verification steps covering multiple scenarios. Screenshots demonstrating light and dark theme implementations are included.
Description check ✅ Passed The PR description clearly explains the purpose (add password visibility toggle), the technical implementation (replace smalltalk with React Dialog), and testing performed.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added enhancement Feature requests and code enhancements desktop All desktop platforms labels Mar 14, 2026
@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request Mar 14, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx (1)

271-276: Narrow error type before accessing .message.

For consistency with the existing pattern at lines 85-87, narrow the error type to avoid potential runtime issues if a non-Error value is thrown.

Proposed fix
         try {
             await toggleAndSetupEncryption(EncryptionService.instance(), newEnabled, masterKey, '');
         } catch (error) {
-            await dialogs.alert(error.message);
+            const message = error instanceof Error ? error.message : String(error);
+            await dialogs.alert(message);
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`
around lines 271 - 276, The catch block that calls dialogs.alert(error.message)
should narrow the error type before accessing .message to avoid runtime issues;
update the catch to check if the caught value is an instance of Error (or has a
message property) and call dialogs.alert(error.message) for Error instances,
otherwise call dialogs.alert(String(error)) or a fallback string; apply this
change around the toggleAndSetupEncryption(...) call in the try/catch so it
matches the pattern used earlier (lines ~85-87).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 239-258: onEnableEncryptionConfirm currently closes the password
prompt immediately, causing the dialog to disappear on validation failure; move
setEnableEncryptionPromptVisible(false) to after successful validation and after
toggleAndSetupEncryption completes so the dialog stays open on errors; ensure
the invalid-password alert uses localization via _('Invalid password. Please try
again. If you have forgotten your password you will need to reset it.') and when
catching errors from toggleAndSetupEncryption narrow the error type before
accessing .message (follow the existing pattern used elsewhere) and pass a
localized message to dialogs.alert; references: onEnableEncryptionConfirm,
masterPasswordIsValid, toggleAndSetupEncryption, EncryptionService.instance(),
dialogs.alert, props.masterPassword.

---

Nitpick comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 271-276: The catch block that calls dialogs.alert(error.message)
should narrow the error type before accessing .message to avoid runtime issues;
update the catch to check if the caught value is an instance of Error (or has a
message property) and call dialogs.alert(error.message) for Error instances,
otherwise call dialogs.alert(String(error)) or a fallback string; apply this
change around the toggleAndSetupEncryption(...) call in the try/catch so it
matches the pattern used earlier (lines ~85-87).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a3c3c8f9-f0cf-4dcf-b222-6b551efaffba

📥 Commits

Reviewing files that changed from the base of the PR and between d20cc87 and 8bd7623.

📒 Files selected for processing (1)
  • packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx

Comment thread packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx Outdated
@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 14, 2026

Currently, when a user clicks "Enable encryption", the app asks for their password but masks the input entirely. Since this password is going to be used to encrypt their entire database, making a typo here can cause a lot of stress

This is not the case anymore, as a recent change means that the manage master password dialog will open instead when clicking enable encryption if the password is not yet set. So now the current smalltalk dialog will only open when needing to match against an existing password. A show password button here would still be nice, but the change is no longer a necessity

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx (1)

344-353: Consider adding accessibility attributes for the error state.

The PasswordInput component accepts aria-invalid and aria-errormessage props (per context snippet 4). When an error is present, these attributes should be set to improve screen reader support.

Proposed enhancement
+							const errorId = 'enable-encryption-error';
 							<PasswordInput
 								inputId="enable-encryption-password"
 								value={enableEncryptionPassword}
 								onChange={onPasswordInputChange}
+								aria-invalid={!!enableEncryptionError}
+								aria-errormessage={enableEncryptionError ? errorId : undefined}
 							/>
 							{enableEncryptionError && (
-								<div style={{ ...theme.textStyle, color: theme.colorError, marginTop: 10, marginBottom: 10 }}>
+								<div id={errorId} role="alert" style={{ ...theme.textStyle, color: theme.colorError, marginTop: 10, marginBottom: 10 }}>
 									{enableEncryptionError}
 								</div>
 							)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`
around lines 344 - 353, When render shows PasswordInput with
enableEncryptionPassword and enableEncryptionError, mark the input as accessible
by passing aria-invalid={!!enableEncryptionError} and aria-errormessage pointing
to the error message element (e.g., "enable-encryption-password-error"); give
the error <div> that id and only render aria-errormessage when
enableEncryptionError exists so screen readers announce the message; update the
PasswordInput props (from the onPasswordInputChange render) to include these
attributes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 279-284: The catch block in the disable-encryption flow calls
dialogs.alert(error.message) without narrowing the caught value; update the
catch in the handler that calls
toggleAndSetupEncryption(EncryptionService.instance(), newEnabled, masterKey,
'') to check if error is an instance of Error before accessing .message and
otherwise fallback to String(error) (mirror the pattern used in
onEnableEncryptionConfirm), then pass that safe string to dialogs.alert so
non-Error throws can't cause a runtime crash.

---

Nitpick comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 344-353: When render shows PasswordInput with
enableEncryptionPassword and enableEncryptionError, mark the input as accessible
by passing aria-invalid={!!enableEncryptionError} and aria-errormessage pointing
to the error message element (e.g., "enable-encryption-password-error"); give
the error <div> that id and only render aria-errormessage when
enableEncryptionError exists so screen readers announce the message; update the
PasswordInput props (from the onPasswordInputChange render) to include these
attributes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc71c29a-48fd-4766-92f1-c5c434e1b579

📥 Commits

Reviewing files that changed from the base of the PR and between 8bd7623 and 50fc121.

📒 Files selected for processing (1)
  • packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx

Comment thread packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx Outdated
@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

This is not the case anymore, as a recent change means that the manage master password dialog will open instead when clicking enable encryption if the password is not yet set. So now the current smalltalk dialog will only open when needing to match against an existing password. A show password button here would still be nice, but the change is no longer a necessity

Thanks for the context! By the way, this change is specifically for the scenario where a user has already set a password, disabled encryption, and then tries to re-enable it. During that re-enabling step, the smalltalk prompt still pops up, and they currently can't see the password they are typing to confirm.

Aside from the eye icon, I thought replacing it would be a good change for UI consistency (using a native React ) and reducing reliance on the 3rd-party smalltalk dependency.

What are your thoughts on this? Is it still a worthwhile improvement to keep?

@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 14, 2026

@himanshumishra1309 I had a quick look through your code change and in light of #14664 being merged, I think your change is over-engineered and potentially incorrect. You have effectively removed some of the logic from #14664 which was just added, and changed the conditions to show your dialog instead, which it's unclear whether it supports create new master password functionality as well.

If you want to continue with this code change, I would suggest that you do not change any of the conditions for which the existing smalltalk dialog opens, but only replace this dialog with a React Dialog that includes a show password button.

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

@himanshumishra1309 I had a quick look through your code change and in light of #14664 being merged, I think your change is over-engineered and potentially incorrect. You have effectively removed some of the logic from #14664 which was just added, and changed the conditions to show your dialog instead, which it's unclear whether it supports create new master password functionality as well.

If you want to continue with this code change, I would suggest that you do not change any of the conditions for which the existing smalltalk dialog opens, but only replace this dialog with a React Dialog that includes a show password button.

Sure, I'll work on this

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

@himanshumishra1309 I had a quick look through your code change and in light of #14664 being merged, I think your change is over-engineered and potentially incorrect. You have effectively removed some of the logic from #14664 which was just added, and changed the conditions to show your dialog instead, which it's unclear whether it supports create new master password functionality as well.

If you want to continue with this code change, I would suggest that you do not change any of the conditions for which the existing smalltalk dialog opens, but only replace this dialog with a React Dialog that includes a show password button.

I have made the changes accordingly and kept the existing conditions intact, please let me know if there is any other sort of improvement required from my side. Thank you very much for your guidance.

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Hi @mrjo118, just following up on this PR.

Based on your suggestion, I reverted the earlier changes and updated the implementation so that the existing conditions and flow remain exactly the same. The only thing changed now is replacing the smalltalk dialog with a React Dialog that includes the show/hide password toggle.

I just wanted to ask if this approach looks good to you, or if you would like me to make any further changes.

Happy to update the PR if something else is expected from my side. Thanks again for the guidance!

@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 16, 2026

@himanshumishra1309 The change looks ok now, but there is one thing that feels off. The width of the new dialog is not consistent with the width of the React Dialog when you click manage master password:

Capture1 Capture2

It would be good if you can make the width match and the grey background shading as well. See in main.scss it has this css for the manage master password dialog:

.master-password-dialog .dialog-root {
	min-width: 500px;
	max-width: 600px;
}

.master-password-dialog .dialog-content {
	background-color: var(--joplin-background-color3);
	padding: 1em;
	padding-bottom: 1px;
}

.master-password-dialog .current-password-wrapper {
	display: flex;
	flex-direction: row;
	align-items: center;
}

Change it to:

.master-password-dialog .dialog-root, .enable-encryption-dialog .dialog-root {
	min-width: 500px;
	max-width: 600px;
}

.master-password-dialog .dialog-content, .enable-encryption-dialog .dialog-content {
	background-color: var(--joplin-background-color3);
	padding: 1em;
	padding-bottom: 1px;
}

.master-password-dialog .current-password-wrapper, .enable-encryption-dialog .current-password-wrapper {
	display: flex;
	flex-direction: row;
	align-items: center;
}

And add the enable-encryption-dialog class to your dialog, to make the styling consistent. Then it will look like this:

Capture3

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx (1)

264-269: ⚠️ Potential issue | 🟠 Major

The OK path still dismisses the dialog before validation finishes.

Resolving promptPromiseRef and hiding the modal in the OK handler reintroduces the earlier retry problem: if masterPasswordIsValid(...) fails, or toggleAndSetupEncryption(...) throws, the user has to reopen the dialog and retype the password. With the current one-shot promise, the validation/toggle needs to happen before resolving and closing, or the dialog needs to re-arm itself after a failed attempt.

Also applies to: 275-282, 303-310

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`
around lines 264 - 269, The OK handler currently calls
promptPromiseRef.current(resolve) and hides the modal
(setEnableEncryptionPromptVisible(false)) before running
masterPasswordIsValid(...) and toggleAndSetupEncryption(...), which forces the
user to re-open and retype on failure; change the flow so the handler runs
validation and toggleAndSetupEncryption first and only on success call the
stored resolve and then hide the modal (i.e., keep promptPromiseRef.current set
and keep setEnableEncryptionPromptVisible(true) while validation/setup is in
progress and on error show the validation error and do not resolve/close), and
ensure cancel still resolves/nulls and clears promptPromiseRef appropriately;
update the same pattern for the other instances referenced around lines 275-282
and 303-310.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 314-316: Update PasswordInput's exported types to reflect the
actual native input event and then remove any usage of `any` in the handler:
change the types in PasswordInput/types.ts to export ChangeEvent as
React.ChangeEvent<HTMLInputElement> and ChangeEventHandler as (event:
ChangeEvent) => void so the component's declared contract matches its runtime
behavior, then modify the handler in EncryptionConfigScreen.tsx
(onPasswordInputChange and the other similar handler near lines ~329) to accept
the typed ChangeEvent and call setEnableEncryptionPassword(event.target.value)
without using `any`.

---

Duplicate comments:
In `@packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx`:
- Around line 264-269: The OK handler currently calls
promptPromiseRef.current(resolve) and hides the modal
(setEnableEncryptionPromptVisible(false)) before running
masterPasswordIsValid(...) and toggleAndSetupEncryption(...), which forces the
user to re-open and retype on failure; change the flow so the handler runs
validation and toggleAndSetupEncryption first and only on success call the
stored resolve and then hide the modal (i.e., keep promptPromiseRef.current set
and keep setEnableEncryptionPromptVisible(true) while validation/setup is in
progress and on error show the validation error and do not resolve/close), and
ensure cancel still resolves/nulls and clears promptPromiseRef appropriately;
update the same pattern for the other instances referenced around lines 275-282
and 303-310.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6220323f-908b-44ee-adc5-b58bb75816f2

📥 Commits

Reviewing files that changed from the base of the PR and between f76e701 and 65c834f.

📒 Files selected for processing (2)
  • packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx
  • packages/app-desktop/main.scss

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

@himanshumishra1309 The change looks ok now, but there is one thing that feels off. The width of the new dialog is not consistent with the width of the React Dialog when you click manage master password:

Capture1 Capture2
It would be good if you can make the width match and the grey background shading as well. See in main.scss it has this css for the manage master password dialog:

.master-password-dialog .dialog-root {
	min-width: 500px;
	max-width: 600px;
}

.master-password-dialog .dialog-content {
	background-color: var(--joplin-background-color3);
	padding: 1em;
	padding-bottom: 1px;
}

.master-password-dialog .current-password-wrapper {
	display: flex;
	flex-direction: row;
	align-items: center;
}

Change it to:

.master-password-dialog .dialog-root, .enable-encryption-dialog .dialog-root {
	min-width: 500px;
	max-width: 600px;
}

.master-password-dialog .dialog-content, .enable-encryption-dialog .dialog-content {
	background-color: var(--joplin-background-color3);
	padding: 1em;
	padding-bottom: 1px;
}

.master-password-dialog .current-password-wrapper, .enable-encryption-dialog .current-password-wrapper {
	display: flex;
	flex-direction: row;
	align-items: center;
}

And add the enable-encryption-dialog class to your dialog, to make the styling consistent. Then it will look like this:

Capture3

Thank you for the guidance! I've pushed the fix, and the dialog now perfectly matches the width and background styling of the 'Manage master password' UI. Please let me know if anything else needs adjusting. I'll be happy to work on it.

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Also, thinking about consistency, right now, if a user clicks 'Disable encryption' or enters an incorrect password, they get the standard, system-style alert/confirm dialog boxes. Since we are updating this UI, would you like me to replace those alerts with this same custom React <Dialog> component, or should we leave those simple alerts as they are?

@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 16, 2026

Also, thinking about consistency, right now, if a user clicks 'Disable encryption' or enters an incorrect password, they get the standard, system-style alert/confirm dialog boxes. Since we are updating this UI, would you like me to replace those alerts with this same custom React <Dialog> component, or should we leave those simple alerts as they are?

I noticed many inconsistencies with dialogs on this screen to be honest. Lets not go down that rabbit hole and stick to changing this one dialog

@laurent22
Copy link
Copy Markdown
Owner

Please address the rabbit's comment

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Please address the rabbit's comment

All fixed! Just pushed the changes requested by the rabbit. Please let me know if there is anything else required from my side!

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Please address the rabbit's comment

Hi! I pushed the fixes requested by the bot (updated both the PasswordInput and the EncryptionConfigScreen.tsx).

I noticed the CI checks failed twice: once with an Android NDK download timeout, and just now on the macOS arm64 runner during the Yarn link phase (YN0009: root@workspace:. couldn't be built successfully). Since my changes were strictly related to React component typings, I believe these might be environment/cache flakes on the runners, so I didn't want to keep spamming empty commits.

Let me know if you are able to review the code changes in the meantime!

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

All tests have officially passed! Let me know if you need anything else from my end.

Comment thread packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx Outdated
Comment thread packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx Outdated
Comment thread packages/app-desktop/gui/PasswordInput/types.ts Outdated
@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 22, 2026

Still has lint errors unfortunately:

/home/runner/work/joplin/joplin/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx
Error: 284:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs

/home/runner/work/joplin/joplin/packages/app-desktop/gui/PasswordInput/types.ts
Error: 2:1 error Expected indentation of 1 tab but found 4 spaces @typescript-eslint/indent
Error: 5:62 error Newline required at end of file but not found eol-last

✖ 3 problems (3 errors, 0 warnings)
2 errors and 0 warnings potentially fixable with the --fix option.

Error: Process completed with exit code 1.

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Still has lint errors unfortunately:

/home/runner/work/joplin/joplin/packages/app-desktop/gui/EncryptionConfigScreen/EncryptionConfigScreen.tsx Error: 284:2 error Mixed spaces and tabs no-mixed-spaces-and-tabs

/home/runner/work/joplin/joplin/packages/app-desktop/gui/PasswordInput/types.ts Error: 2:1 error Expected indentation of 1 tab but found 4 spaces @typescript-eslint/indent Error: 5:62 error Newline required at end of file but not found eol-last

✖ 3 problems (3 errors, 0 warnings) 2 errors and 0 warnings potentially fixable with the --fix option.

Error: Process completed with exit code 1.

Thanks for pointing that out, I've fixed the lint issues and pushed the changes. Please let me know if anything else needs adjustment.

@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Mar 22, 2026

CI still failed. Please come back 30-60 mins after you push a change to check whether it passed. In this case it looks like an intermittent CI failure, so either update the branch (if it is behind) or push an empty commit to rerun the CI

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

CI still failed. Please come back 30-60 mins after you push a change to check whether it passed. In this case it looks like an intermittent CI failure, so either update the branch (if it is behind) or push an empty commit to rerun the CI

Got it, thanks for the clarification!
I wasn’t sure if pushing an empty commit was preferred, so I held off earlier. I’ll go ahead and rerun the CI now.

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

All review comments have been addressed and CI is passing. Let me know if anything else is needed!

Comment thread packages/app-desktop/gui/PasswordInput/types.ts
@laurent22
Copy link
Copy Markdown
Owner

Hello, the top post needs to be updated with the latest screenshot, ideally in both dark and light theme

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Hello, the top post needs to be updated with the latest screenshot, ideally in both dark and light theme

I have updated the first post, let me know if anything else is required.

@laurent22
Copy link
Copy Markdown
Owner

Still some CodeRabbit's comments. Please confirm you'd like to complete this PR

@himanshumishra1309
Copy link
Copy Markdown
Contributor Author

Still some CodeRabbit's comments. Please confirm you'd like to complete this PR

Yes, I’ve reviewed the remaining CodeRabbit comments and confirmed that all relevant points have been addressed in the latest changes.

The current implementation is complete from my side and ready to be merged. Please let me know if anything else is required.

};

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Required because PasswordInput's ChangeEventHandler type is incorrect
const onPasswordInputChange = (event: any) => {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

But that looks like a DOM event. Surely there's a type for this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're right that this should ideally use React.ChangeEvent<HTMLInputElement>.

I initially updated the PasswordInput types (as suggested by CodeRabbit) so that this handler could be properly typed. However, that change was marked as out of scope for this PR, so I reverted it to keep the changes focused.

Since PasswordInput currently defines an incompatible onChange type, I've kept 'any' here as a temporary workaround to match the existing typing.

I can open a separate PR to fix the PasswordInput typing if needed or I can also update this handler here to use React.ChangeEvent<HTMLInputElement> rather than any if that’s preferred? please let me know which approach you’d like.

@laurent22
Copy link
Copy Markdown
Owner

@mrjo118, does this change make sense to you? Was there an issue for it? Or was that related to other similar recent changes on the E2EE dialog boxes?

@mrjo118
Copy link
Copy Markdown
Collaborator

mrjo118 commented Apr 2, 2026

@mrjo118, does this change make sense to you? Was there an issue for it? Or was that related to other similar recent changes on the E2EE dialog boxes?

Yes, the change does make sense, as it allows the password to be shown / hidden on the relevant dialog, which gives a better user experience even if there is no consequence of entering an incorrect password in this context

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

desktop All desktop platforms enhancement Feature requests and code enhancements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants