This makes it easier to share links from a regular timeline (where text
is not selectable).
Listen for long clicks on spans by launching a delayed runnable that
waits `getLongPressTimeout()` ms before sending an intent that shows the
share sheet for the clicked span.
If the span's link is not the same as the text (e.g., it's a mention or
a hashtag) then the text of the span is also sent as the title to show
in the share sheet.
While I'm here, the official LinkMovementMethodCompat does the same job
as NoTrailingSpaceLinkMovementMethod, so delete the latter code in
favour of the former.
Fixes#695
Users report that copying items can be difficult using Talkback.
Make this easier in the dialogs that appear for links, mentions, and
hashtags by using a dedicated adapter that displays a "Copy" button at
the end of each item.
Fixes#1038
Provide two new lab preferences for controlling the layout and content
of main navigation tabs.
Tabs can now be justfied to start, end, or fully (if room). Start/end
justification may put the tabs closer to the user's fingers, depending
on how they hold the device. Fully justified uses the full width of the
tab bar (if the tabs don't require scrolling).
The content can be set to one of:
- Icon only (previous behaviour)
- Text only
- Icon with text beside
- Icon with text below
Fixes#336
Previous code didn't send the language to ComposeActivity when editing a
scheduled status so it always appeared to be dirty. This prompted the
user to save/discard changes when backing out, even if they hadn't made
any changes.
Fix this by collecting the language code when fetching scheduled posts
and passing it in `ComposeOptions`.
Previous code accepted the `scheduledAt` value as a String, and kept it
as a String (including when serialising as part of a draft). Then it was
converted to an actual Date for display.
Refactor to keep it as a Date for as long as possible. Moshi decodes
Dates correctly over the network, and the database is configured to
serialise Dates as Longs.
This necessitates two migration steps to preserve any existing
`scheduledAt` values for drafts. The first step adds a new column to
store the date as a Long and copies over existing data. The second step
replaces the old column with the new column.
The "Suggested accounts" API returns dormant accounts. See this bug
report: https://github.com/mastodon/mastodon/issues/30674.
That's bad UX, so filter out any account that hasn't posted in the last
28 days.
Fixes#1029
For some users this feature has too many false positives, particularly
when emojis are used.
Provide a preference that enables/disables the feature, default to
"enable".
When the user is prompted the dialog has a third "Don't ask again"
option. If chosen the preference is set to prevent future prompts and
the status is sent as-is.
Fixes#893
GoToSocial servers don't support scheduled posts; they return the wrong
type, and this can cause a loop of posting.
The GoToSocial bug to implement scheduled posts is
https://github.com/superseriousbusiness/gotosocial/issues/1006.
Fix this by adding a new server capability for scheduled post support,
using it for most servers, and disabling it for GoToSocial.
If scheduled post support is not available for an account:
- The "Scheduled posts" menu option is not shown.
- The scheduling button (clock) when composing a post is hidden, so the
user cannot set scheduling parameters.
Fixes#963
This wasn't acting as a preference.
It presented as a switch. If the user toggled it some notification
settings were changed for all accounts.
It wasn't clear what was changed, and if the user changed some of those
settings back the switch position did not change (it couldn't, you
couldn't meaningfully represent a partial change using a single switch).
Since the user has full control over the notification filters on a
per-account basis remove this "preference" to reduce confusion.
Fixes#935
ForeignKey constraints can be invalidated in the middle of a transaction
even if a later statement in the same transaction will make them valid
again. This seems to be causing production crashes.
Defer foreign key constraint checks until the end of the transaction to
prevent this.
Tests that rely on stubbing the MastodonAPI may have incorrect behaviour
if some of the API methods called by the system-under-test are not
stubbed. This can be difficult to track down.
Make this easier by adding a default answer for the MastodonAPI used in
tests. Any un-stubbed methods will throw an `AssertionError` with enough
information to identify the method that should be stubbed and where it
was called from.
The `Status` type associated with an announcement is entirely different
to the regular `Status` type, with a different JSON shape. The incorrect
type meant a deserialisation error when loading announcements with
associated statuses.
Previous code assumed the active account could always be determined from
the account manager.
This causes a few problems.
1. The account manager has to handle the case where there is no active
account (e.g., the user is logging out of the last account). This meant
the `activeAccount` property had to be nullable, so every consumer of
that property either used it with a `let` or `!!` expression.
2. The active account can change over the life of the UI component, for
example, when the user is switching accounts. There's a theoretical race
condition where the UI component has started an operation for one
account, then the account changes and the network authentication code
uses the new account.
3. All operations assume they operate on whatever the active account is,
making it difficult to provide any features that allow the user to
temporarily operate as another account ("Boost as...", etc).
This "ambient account" was effectively global mutable state, with all
the problems that can cause.
Start to fix this. The changes in this commit do not fix the problem
completely, but they are some progress.
Each activity (except LoginActivity) is expected to be launched with an
intent that includes the ID of the Pachli account it defaults to
operating with. This is `pachliAccountId`, and is the *database ID*
(not the server ID) of the account. This is non-null, which removes one
class of bugs.
This account is passed to each fragment and any piece of code that has
to perform an operation on behalf of this account. It's not used in
most of those places yet, that will be done over a number of followup
PRs as part of modernising each module.