Commit graph

92 commits

Author SHA1 Message Date
and
d1ada8ddbf Remove getClientOnlyColors helper 2025-10-20 17:11:09 +02:00
and
34d4614900 Initialize calendars in the CalendarModel and implement CalendarInfoBase
- This commit introduces CalendarInfoBase as a base type to hold common fields between CalendarInfo and BirthdayCalendarInfo
- It also makes CalendarModel provide the available calendars.
- SearchViewModel dependency on the locator is removed and CalendarModel is now injected.
2025-10-20 17:11:09 +02:00
and
6f6bf58c7b Rename birthday calendar constants and remove local clients setup
With our new approach we no longer need to set up and store the birthday calendar locally.
Color will be stored in the server and name won't be editable.

Co-authored-by: bed <bed@tutao.de>
2025-10-20 17:11:09 +02:00
paw
435fb98bd0 Use offline storage for autosaved drafts
We want to use offline storage (SQLite) for autosaved drafts as it will
allow the locally saved draft to be accessible when offline. This means
we refactor ConfigurationDatabase.

We still want to use the same encoding methods, as it provides a simple
way to put in data without having to worry about making some complex
schema.

Closes #9743

Co-authored-by: ivk <ivk@tutao.de>
2025-10-02 13:17:57 +02:00
bir
5592c69125 Use material 3 colors for whitelabel
- Remove the ability to customize all colors, instead only allowing the
user to choose the base theme (light/dark) and the source color from
which the theme will be generated.
- Adjust newToOldColorTokenMap to correctly render new Material 3 theme
on old clients.
- Generate new Material 3 theme from old whitelabel config for non admin
users.
- Migrate whitelabel to new Material 3 theme post login of admin.

Close #9459

Co-authored-by: paw <paw-hub@users.noreply.github.com>
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
Co-authored-by: ivk <ivk@tutao.de>
2025-09-26 14:15:49 +02:00
yoy
f164e39c94 feat(theme): Mitigate color token update for whitelabel users
- Added mapper of new/old color tokens.
- Added a message to prompt admin users with whitelabel customisation to check and update their settings.
2025-09-26 13:35:52 +02:00
paw
d956f2b2e9 Autosave drafts
Every five seconds while the user is typing, save a local copy of the
draft to ConfigurationDatabase.

If the draft has not been touched for five minutes, it gets uploaded to
the server.

If the user restarts the client with an autosaved draft, it will open
automatically. Only one draft can be autosaved at a time.

Additionally, if an entity update for a draft is received while the user
has that draft open for editing, saving will prompt a confirmation
dialog to overwrite the draft on the server, as this draft data may be
outdated.

Next, if the user attempts to open a new draft while there is an
autosaved draft, display a confirmation dialog to the user to delete
it.

And lastly, if the user has two separate drafts open on different
windows, we handle this by preventing saving over them.

Closes #4419
2025-09-26 10:35:24 +02:00
wrd
63ccec5482 Allow for editing of groupInfo and groupSettings name
After the group was shared it was not possible to change the original
name anymore, neither for the owner nor for participants.

Show groupInfo name in the editing dialog for shared groups
Add GroupSettingsModel for editing the name of groups
Used in ContactList, Templates, and Calendar
Do not set name on groupSettings when accepting invitation, so that
groupInfo name take priority

Closes: #8639

Co-authored-by: ivk <ivk@tutao.de>
2025-09-17 14:11:56 +02:00
abp
488c72c25f
rework mail list-unsubscribe flow
This commit modifies the list-unsubscribe flow for unsubscription from
newsletters, with the following scenarios:
- Link with POST: The mail has a link and a List-Unsubscribe-Post header
to allow one-click unsubscribe. In that case, we send the POST request
from the client for the Desktop, iOS, and Android app. For the web app,
we send the link to the server and do a ListUnsubscribeService request.
- Link with GET: The mail has a link but does not allow one-click
unsubscribe. In this case, we show a dialog which has the option to open
the link in the browser.
- Link with mailto: The mail does not have a http link in the
list-unsubscribe header, but it has a mailto link for unsubscription.
In this case, we show a dialog which has the option to open a new mail
dialog which uses the mailto link.

Co-authored-by: das <das@tutao.de>
Co-authored-by: jomapp <17314077+jomapp@users.noreply.github.com>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: kib <104761667+kibibytium@users.noreply.github.com>
2025-09-15 15:22:01 +02:00
ivk
5bf10e0466 Introduce UndoModel
MailViewModel should not be used outside of mail view, e.g. in search.
Extract generic UndoModel that can be reused for various undo actions.

Pull some move actions up to the top level to use it.
2025-08-29 10:26:11 +02:00
and
e2944d4812 Drag and drop for edit this and future events operations
Co-authored-by: Murilo Pereira <34790144+murilopereirame@users.noreply.github.com>
2025-08-28 17:03:31 +02:00
ivk
70f62079d6
Fix external image replacement serialization
Chromium changed how HTML is serialized:

https://developer.chrome.com/release-notes/138?

https://chromestatus.com/feature/6264983847174144

https://github.com/whatwg/html/issues/6235

Which caused some of our HTML sanitizing tests to fail.

To prevent any possible issues with serialization we instead create
a Blob URL for our svg. This way we sidestep DOM serialization
peculiarities. As a side effect DOM should be smaller.

Close #9465

Co-authored-by: paw <paw-hub@users.noreply.github.com>
2025-08-14 14:54:11 +02:00
sas
82fe66f6b4
Refactor key verification
* split PublicKeyProvider into PublicIdentityKeyProvider and PublicEncryptionKeyProvider
* move database queries to new IdentityKeyTrustDatabase
* only have one function loading public identity key and directly load from server if not in trust db (and add to trust db in this case) in PublicIdentityKeyProvider
* KeyVerificationFacade.verify() only needs to be called once to get a valid verification state
* introduce Not_Supported as source of trust (for web client)
* introduce Not_Supported verification state (e.g. for web client and when loading via group id)
* and handle Not_Supported verification state in the RecipientsModel (presentable state is none because verification was not available)
2025-08-07 09:59:21 +02:00
mab
b148062572
Remove lazy/eager option for resolving recipients
Recipients will now only get resolved when `resolve()` is called
explicitly.
2025-08-07 09:59:21 +02:00
vaf
a0892a01e6
Sign public encryption keys
implement PublicKeySignatueFacade to encode public encryption keys and sign them

sign public encryption keys where it is needed (e.g. key rotation, identity key pair creation)

add ecc keys to current rsa key pairs when creating identity key pairs

refactor GroupManagementFacade, extract loading keys via admin group key, extract creation of identity key pairs

tuta#2083
2025-08-07 09:59:21 +02:00
mab
fb9a30d33c
Replace encryption key management with identity key management
tuta#2106

* display own identity key and default sender
* support scanning identity keys using qr codes
* service to request identity keys
* rework key verification database for identity keys

Co-authored-by: bedhub <bedhub@users.noreply.github.com>
Co-authored-by: mab <mab@tutao.de>
2025-08-07 09:59:17 +02:00
bir
30b3ef1845 Add undo move mails
Show a snackbar that can undo moving mails. The user can click "Undo" or
press CTRL-Z (CMD-Z) to undo moving mails. If they do, this will move
the mails back and close the snackbar. Additionally, if the mails were
to be reported as spam, they won't be reported, either.

Removed the reporting snackbar and added a new message specifically
for mails being moved to spam.

Close #9321
Close #9319
Close #9318
Close #9312
Close #9205
Close #9386
Close #9428

Co-authored-by: paw <paw-hub@users.noreply.github.com>
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
2025-08-04 13:34:21 +02:00
ivk
c451cf6a3c Reformat JS with Prettier 3.5.3
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
2025-07-18 10:01:01 +02:00
wrd
5207da4a84 Add functionality to change Primary mail address with a registered alias
Close #8933

Co-authored-by: ivk <ivk@tutao.de>
2025-07-10 16:03:15 +02:00
and
24b6646fcc Fix imports and rename common/calendar/import to common/calendar/gui
Lazyload EventBannerImpl.ts to allow EventBanner.ts to stay with MailView
Adds a new directory mail-app/gui/date to date-gui chunk allowing calendar
related ui to stay inside mail-app folder structure.

Co-authored-by: ivk <ivk@tutao.de>
2025-07-10 14:14:02 +02:00
and
6d1668ebfe Implements v1 for new Event Banner
Co-authored-by: Murilo Pereira <34790144+murilopereirame@users.noreply.github.com>
2025-07-10 14:09:44 +02:00
paw
71acf94182 Create ContactSearchFacade, Refactor search in ContactModel
Surrounding a query in quotes has a different meaning between FTS5 and
IndexedDb searching. We don't want to expose which search model we are
using in this case, so we can just create a simple ContactSearchFacade
that handles any backend-specific details.

This simplifies a few details, like ContactModel originally needing a
lambda now only needing a ContactSearchFacade.

Avoid loading contacts one by one in ContactModel, make the control flow
clearer.

Closes #9088

Co-authored-by: ivk <ivk@tutao.de>
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
2025-06-12 16:58:23 +02:00
wrd
900bd4c16f Lazy load inboxRuleHandel to prevent null mailModel
Close #9094

Co-authored-by: ivk <ivk@tutao.de>
2025-06-12 16:58:23 +02:00
wrd
a76562e5b8 Add search highlighting for calendar
Close #9098
2025-06-12 16:58:23 +02:00
ivk
36294d696d Resolve circular dependency for InboxRuleHandler.ts 2025-06-04 11:18:48 +02:00
bir
fb1a6138f2 Highlight search results
When searching, we need to highlight the text matching the search query.

Added "beforeSanitizeElements" in HTMLSanitizer to handle highlighting
search queries inline of text bodies. This will handle both exact and
non-exact (partial) matches depending on quotes inside the query.

Close #8883

Co-authored-by: paw <paw-hub@users.noreply.github.com>
2025-06-04 10:36:46 +02:00
wrd
90e5a239d9 Use date instead of number for OfflineTimeRange, connect to search
Search extends range on login based on the OfflineTimeRangeDate

Extending search range extends OfflineTimeRangeDate

Co-authored-by: ivk <ivk@tutao.de>

Close #8549
2025-06-04 10:36:46 +02:00
ivk
86d5775e16 Add SQLite search on clients where offline storage is available
- Introduce a separate Indexer for SQLite using FTS5
- Split search backends and use the right one based on client (IndexedDB
  for Browser, and OfflineStorage everywhere else)
- Split SearchFacade into two implementations
- Adds a table for storing unindexed metadata for mails
- Escape special character for SQLite search
  To escape special characters from fts5 syntax. However, simply
  surrounding each token in quotes is sufficient to do this.
  See section 3.1 "FTS5 Strings" here: https://www.sqlite.org/fts5.html
  which states that a string may be specified by surrounding it in
  quotes, and that special string requirements only exist for strings
  that are not in quotes.
- Add EncryptedDbWrapper
- Simplify out of sync logic in IndexedDbIndexer
- Fix deadlock when initializing IndexedDbIndexer
- Cleanup indexedDb index when migrating to offline storage index
- Pass contactSuggestionFacade to IndexedDbSearchFacade
    The only suggestion facade used by IndexedDbSearchFacade was the
    contact suggestion facade. So we made it clearer.
- Remove IndexerCore stats
- Split custom cache handlers into separate files
  We were already doing this with user, so we should do this with the
  other entity types.

- Rewrite IndexedDb tests
- Add OfflineStorage indexer tests
- Add custom cache handlers tests to OfflineStorageTest
- Add tests for custom cache handlers with ephemeral storage
- Use dbStub instead of dbMock in IndexedDbIndexerTest
- Replace spy with testdouble in IndexedDbIndexerTest

Close #8550

Co-authored-by: ivk <ivk@tutao.de>
Co-authored-by: paw <paw-hub@users.noreply.github.com>
Co-authored-by: wrd <wrd@tutao.de>
Co-authored-by: bir <bir@tutao.de>
Co-authored-by: hrb-hub <hrb-hub@users.noreply.github.com>
2025-06-04 10:36:46 +02:00
kib
11617861cd fix server model info not being initialized
We observed clients that managed to get stuck with a missing server
model, which made login from stored credentials impossible and required
getting a new session.

The reason was that only the service executor, rest client and event bus
client cared to update the server model if they were missing.
However, the offline database also stores data in the server's model and
thus requires it to read any data. Since logging in will hit
the cache before requesting the server, a corrupted or missing server
model causes us to not be able to log in.

This commit gives the responsibility of acquiring the models to
ServerModelInfo.resolveServerTypeReference if they are missing or out
of date to avoid situations where we call resolveServerTypeReference
without first checking if the model is initialized.

Additionally, we show a dialog to the user if the models cannot be
initialized instead of an uncaught error.

We considered having the error handler try to repeat model
initialization, but since the original request already failed at that
point, getting back to a normal state would require an extra manual
retry.

fix #9004

Co-authored-by: nig <nig@tutao.de>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: kib <104761667+kibibytium@users.noreply.github.com>
2025-05-27 14:52:44 +02:00
ivk
9e31ee0409 Inject type model resolvers
Passing instances explicitly avoids the situations where some of them
might not be initialized.

We also simplified the entity handling by converting entity updates to
data with resolved types early so that the listening code doesn't have
to deal with it.

We did fix some of the bad test practices, e.g. setting/restoring env
incorrectly. This matters now because accessors for type model
initializers check env.mode.

Co-authored-by: paw <paw-hub@users.noreply.github.com>
2025-05-27 14:52:44 +02:00
mup
dcb30e6e3f [Android] Handle url changes and eventDetail column
Co-authored-by: and <and@tutao.de>
2025-04-02 15:16:33 +02:00
mup
000703f34c [Android] Registers Origin url on startup 2025-04-02 15:16:33 +02:00
mup
e7168749f2 [Android] Implements refresh after event create/update/delete
Co-authored-by: and <and@tutao.de>
2025-04-02 15:16:33 +02:00
mup
2ef6c867c8 [Android] Adds interaction handler for Widget parts 2025-04-02 15:16:33 +02:00
mab
7e78fccce1 Fix key verification dependencies for prod build 2025-03-19 15:01:40 +01:00
mab
b9d0c735cc Add feature type guard to key verification
Co-authored-by: hec <hec@tutao.de>
2025-03-19 09:38:30 +01:00
mab
2d35ab0d6e Introduce key verification (squash) 2025-03-19 09:29:34 +01:00
wrd
6b06e03d81 Label action applies to all emails in conversation 2025-03-05 16:26:09 +01:00
paw
0321b53e3e Add ConversationListModel
- This list model groups all emails by conversation in the mail list
- Also adds setting for grouping by conversation (i.e. enables this)
- The setting is overridden for SENT and DRAFT folder types (it uses the
  other per-mail list model instead)
- Adds MailSetListModel which provides a common interface for the
  MailViewModel so that additional list models can be created; it is
  used for MailListModel and the new ConversationListModel, but it can
  be extended to even more list models in the future if it is ever
  desired.

Note: This does not include actions. Any action you do (delete, archive,
etc.) will be applied to the selected email. The purpose of this commit
is to just implement the list model. See #5051 for more information.

Closes #8223

Co-authored-by: bir <bir@tutao.de>
Co-authored-by: ivk <ivk@tutao.de>
2025-03-05 16:26:09 +01:00
wrd
ae9ecf59f6 Show dialog asking user to update when logging into an outdated client
Adds TutanotaModelV84

Close #8373

Co-authored-by: Willow <ivk@tutao.de>
Co-authored-by: bir <bir@tutao.de>
2025-03-05 16:26:08 +01:00
mup
937300e2d9 Adds SyncTracker to track initial sync status
Calendar subscriptions can collide with entity updates during
application startup. This commit adds a SyncTracker to track the
progress of initial entity updates, and after processing the entire
batch, mark the sync as done, allowing calendars to synchronize with
fewer chance to collisions.
2025-02-26 13:34:56 +01:00
ivk
357fc58def
Fix being unable to log in after a partially failed login
In some cases LoginFacade does succeed with the partial login, but
some login actions fail on the page side, e.g. loading of
`TutanotaProperties`. This leads to an inconsistent state where the
worker is in the logged in state while the page context is not.

We solve the issue by catching the errors during page context init and
resetting the state on both sides.

In the future we could make the process more robust by loading all the
necessary parts in `LoginFacade` or making some parts lazy-loaded.

Fix #5537
2025-01-28 15:18:40 +01:00
hrb-hub
c286131d7e Only allow one window to run export per user
Export will continue in a different window if one was closed

Close #8063

Co-authored-by: wrd <wrd@tutao.de>
Co-authored-by: ivk <ivk@tutao.de>
2025-01-27 12:04:14 +01:00
ivk
5c147bb4e0 Use mailbox export tokens, Extract MailExportTokenFacade
#8098

Make `createTestEntity` deterministic and fix tests related to it.

Co-authored-by: bir <bir@tutao.de>
2025-01-27 12:02:44 +01:00
ivk
b3147c23ed Mailbox export: downloading & persistence
Remove unused method from FileFacade

Co-authored-by: wrd <wrd@tutao.de>
2025-01-27 12:02:44 +01:00
bir
23a7d41813 UI for Export mailbox in settings
close: #7952

Co-authored-by: ivk <ivk@tutao.de>
2025-01-27 12:02:44 +01:00
map
3618eee082 Rewrite state handling for mail file import, improve UI
we're moving to persisting the import state only on the server,
with the files to be imported on disk the only local state that
is kept by the importer.

Most errors happen during import preparation after we receive the files
to import. These can be caught & handled immediately. If no errors
happen, the remote state will be set up on the server at this stage and
can be subscribed to by the UI by loading it via its ID

Some other errors can happen asynchronously while the importer is
running in the background. For those, the importer sets a hook to
receive and handle them as they happen.

any normal state updates are sent to the server in node-mimimi and
received in the UI via entity updates.

Co-authored-by: nig <nig@tutao.de>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: map <mpfau@users.noreply.github.com>
Co-authored-by: jhm <17314077+jomapp@users.noreply.github.com>
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
Co-authored-by: abp <abp@tutao.de>
2025-01-20 15:27:27 +01:00
Kinan
e1baa01f63 refactor LanguageViewModel to use new translation types
The reason for this refactor is to make it possible to put "data-testid"
attributes on HTML tags. Those attributes can be used with UI test
frameworks to make automated testing independent of the translation
language or text.

The idea is to get rid of the lazy<string> types and instead use a new type
called Translation wherever possible. Translation replaces the old
TranslationText and contains both translation key and translation text.

The type MaybeTranslation is a legacy type left to make the transition feasible.
It can be replaced with either TranslationKey or Translation in the future.

Co-authored-by: map <mpfau@users.noreply.github.com>
2025-01-17 14:48:32 +01:00
paw
8c1ed56072
update eslint to v9
Co-authored-by: paw-hub <paw-hub@users.noreply.github.com>
2025-01-09 14:55:11 +01:00
Kinan
593d17d9d7
[mimimi] refactor to allow quitting and multi-window usage
Co-authored-by: Kinan <104761667+kibibytium@users.noreply.github.com>
Co-authored-by: sug <sug@tutao.de>
Co-authored-by: nig <nig@tutao.de>
2025-01-08 12:49:52 +01:00