A few places in the code were calling `moshi.adapter` to marshall
to/from strings in the database where type converters either already
exist, or are straightforward to create.
Create the missing type converters, and use them throughout. This
simplifies several places where a Moshi instance no longer needs to be
passed through several layers of method calls.
Since this doesn't change the underlying database representation of the
data there's no need to bump the database version number.
Previous code ran the setup routine whenever the account changed. I
think this could result in the content being cleared when a notification
arrived (processing the notification updates the marker, which updates
the account, which triggers a new collection).
Fix this by only taking the first emission of the account from the flow
to do the setup.
Previous code showed the error message for the underlying cause, which
might be too technical for the user. Prefer to use top level error
message; hopefully that is more actionable.
Contributes to #1083
getItemViewType is occasionally called with a position that's out of
range; trying to get the item at that position throws an
`IndexOutOfBoundsException`.
Catch it, and return the placeholder view type.
Allow the user to define filtering rules for notifications by sending
account:
- Not followed
- Younger than 30d
- Limited by moderators
and a policy for each of either show, warn, or hide.
To do this:
## Manage followers
- Create a new `FollowingAccountEntity`, to record accounts the logged
in account is following.
- Fetch the account's followers when an account is made active, and
persist to this table.
- Provide the followers as a property on `PachliAccount`
- Update this table if the user follows/unfollows accounts during normal
operation.
## Track account creation time
- Record account creation time in `TimelineAccount`.
## Track notification creation time
- Record notification creation time in `Notification`.
## API
- Always fetch all notifications, including those the server is
filtering.
## UX and storage for account filters
- Show a new Account preference to edit account notification filters.
- Display a dialog to manage account notification filters.
- Persist the user's choice to new properties in `AccountEntity`.
- New `AccountManager` methods to update the properties
## Filtering notifications
- New `NotificationFilter.filterNotificationByAccount()` method to make
the filtering decision based on the user's preferences.
- Use this in `NotificationFetcher` to filter notifications before
creating Android notifications.
- Use this in `NotificationsViewModel` to filter notifications before
display in `NotificationsFragment`.
## UX for filtered notifications
- Display filtered (with warning) notifications inline with other
notifications, with UI to disclose the notification or edit the filters.
This code will be used elsewhere in an upcoming change, so extract it
now to minimise the diffs.
While I'm here, provide an icon for mentions, and an attribute for the
"favourite" colour.
Pleroma (and possibly other servers) can return dates that have no
timezone. Previous code would fail to deserialise JSON in this state and
show an error.
Patch around this by assuming anything with a missing timezone is in UTC
(timezone suffix "Z").
Fixes#562
Chooser dialog could start before any accounts have loaded. Fix by
collecting the account flow and waiting for the first emission (convert
the flow to shared instead of state so there's no initial empty list).
Guard against the potential for a similar issue when fetching
notifications.
Order the list of accounts with active account first so that code that
skips it by ignoring the first item works correctly.
Previous code was inconsistent about whether or not a notification toast
was shown after copying text (contrary to platform guidelines), and
there was some code duplication.
Fix this with a new `ClipboardUseCase` with a `copyTextTo` method that
handles copying text to the clipboard and showing a message afterwards
(depending on platform level).
Extend the "suggested accounts" accessibility actions to include any
mentions in the account's bio. Links, mentions, and hashtags are now
shown with a button to easily copy them.
Extend the "trending links" accessibility actions with a new "copy link"
action.
Consolidate common functionality in to the new
`PachliRecyclerviewAccessibilityDelegate` base class.
The copy button meant that some dialogs did not return the item click.
Fix this by having the adapter listen for clicks and forward them on.
Pre-emptively move the adapter to core.ui, as it's going to be useful
for the other accessiblity delegates.
Fixes#1108
`IStatusViewData.filterAction` was the `FilterAction` to apply to the
status based on the status' content.
As new filter options will apply filters based on the account that sent
the status, rename to `contentFilterAction` so it's easy to distinguish
between the two.
Some tests were assuming the uiState would transition from .Loading to
.Success, without considering there might be a .LoadingThread
intermediate step. Cater for that to prevent test flakes.
Previous code was missing the JSON name of the event, so it wasn't
present when it should have been, resulting in a crash.
Also, the Mastodon documentation is incorrect about the relationship
count, which is instead represented as two properties, one for followers
and one for following. So model that, and display them separately in the
UI.
Fixes#1086
Continue the work to remove the "activeAccount" idiom.
- Uses a new PachliAccount type through most of the app. This holds
information that was previously accessed separately (e.g., content
filters, lists) in one place. The information is loaded when the app
launches or the active account switches.
- Fetching data when the account is switched / loaded simplifies error
handling, as more code can now assume the data has already been loaded.
If it hasn't the code path is simply unreachable.
- This opens up the possibility of "acting as one account while logged
in as another". E.g., have two accounts, and be logged in to one account
and boost a post you've seen from your other account.
- Add a database migration to populate existing accounts with default
data when the user updates the app.
- Refactor code that used those list and filter repositories to get the
data from the PachliAccount instead. New local and remote data sources
are implemented, and the list and filter repositories mediate between
those sources.
- Start a ViewModel for MainActivity, which includes:
- Sending user actions as UiAction objects
- Providing a flow of uiState for MainActivity to react to
- Remove most uses of SharedPreferencesRepository from MainActivity
- Show messages about errors that occur when logging in
- Refactor intent routing in MainActivity to make the logic clearer.
- Add new `core.data` types to push more `core.network` types out of the
UI code
- `core.data.model.MastodonList` for `core.network.model.MastoList`
- `core.data.model.Server` for `core.network.model.Server`
- Continue the work to send the Pachli account ID to the code that uses
it.
- Most view models now get the account ID via assisted injection.
- QueuedMedia now includes the AccountEntity so it can operate with any
account. Modify the `uploadMedia` API call to include explicit
authentication details.
---------
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Previous code would remove image attachments from the compose editor if
there was a problem uploading or updating them.
This caused a particular problem with image captions. You could attach a
valid image, then write a caption that was too long for the server. The
server would reject the status, and the status was saved to drafts.
Then you open the draft, which tries to upload the image again with a
too-long caption. The upload is rejected, and the image, along with the
caption, is removed.
Fix this.
- Change `QueuedMedia` to track the upload state as a `Result<_,_>`, so
any error messages are preserved and available to the UI.
- The different `Ok` types for the upload state contain the upload
progress percentage (if appropriate) or the server's ID for the uploaded
media.
- Change `ProgressImageView` to accept the upload state `Result`. If the
result is an error the image is drawn with a red overlay and white
"error" icon.
- If an upload is in an error state allow the user to click on it. That
shows a dialog explaining the error, and provides options to edit the
image, change the caption, etc.
- When changing the caption make the API call to change it on the server
(if the attachment has been uploaded). This makes the user aware of any
errors sooner in the process, so they can correct them.
Fixes#879
Some users report that returning to the `ComposeActivity` loses content
they've entered and returns to `MainActivity`. I can't reproduce this,
but it's possible that Android is clearing the task state and returning
to the root activity (`MainActivity` in this case).
Set `alwaysRetainTaskState` to true to keep the activity stack, and
hopefully prevent this from happening.