Commit Graph

38 Commits

Author SHA1 Message Date
Nik Clayton 5a35009e35
change: Remove unused code (#1044) 2024-10-23 15:16:07 +02:00
Nik Clayton e68ab54f95
feat: Ignore suggested accounts that haven't posted in 28 days (#1031)
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
2024-10-19 14:38:00 +02:00
Weblate (bot) 0cf50524f2
fix(l10n): Translations update from Hosted Weblate (#995)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pachli/Fastlane
Metadata](https://hosted.weblate.org/projects/pachli/fastlane-metadata/).


It also includes following components:

* [Pachli/App :
Main](https://hosted.weblate.org/projects/pachli/app-main/)

* [Pachli/App :
Fdroid](https://hosted.weblate.org/projects/pachli/app-fdroid/)

*
[Pachli/Feature/Login](https://hosted.weblate.org/projects/pachli/featurelogin/)

* [Pachli/Feature/Suggestions :
Main](https://hosted.weblate.org/projects/pachli/featuresuggestions-main/)

* [Pachli/Feature/Lists :
Main](https://hosted.weblate.org/projects/pachli/featurelists-main/)

* [Pachli/Core/Ui :
Main](https://hosted.weblate.org/projects/pachli/coreui-main/)

* [Pachli/App :
Google](https://hosted.weblate.org/projects/pachli/app-google/)

* [Pachli/Core/Designsystem :
Main](https://hosted.weblate.org/projects/pachli/coredesignsystem-main/)

* [Pachli/Core/Data :
Main](https://hosted.weblate.org/projects/pachli/coredata-main/)

* [Pachli/Core/Activity :
Main](https://hosted.weblate.org/projects/pachli/coreactivity-main/)

* [Pachli/Feature/About :
Main](https://hosted.weblate.org/projects/pachli/featureabout-main/)

* [Pachli/Core/Preferences :
Main](https://hosted.weblate.org/projects/pachli/corepreferences-main/)

* [Pachli/Core/Activity :
Orange](https://hosted.weblate.org/projects/pachli/coreactivity-orange/)

* [Pachli/Core/Network :
Main](https://hosted.weblate.org/projects/pachli/corenetwork-main/)



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pachli/fastlane-metadata/horizontal-auto.svg)

---------

Co-authored-by: Vaclovas Intas <vaclovas1999@gmail.com>
Co-authored-by: Languages add-on <noreply-addon-languages@weblate.org>
Co-authored-by: Weblate Translation Memory <noreply-mt-weblate-translation-memory@weblate.org>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
2024-10-10 21:42:59 +02:00
Nik Clayton 23121459ab
refactor: Implement SharedPreferencesRepository.showSelfUsername property (#996) 2024-10-10 20:15:46 +02:00
Nik Clayton e307796251
refactor: Provide properties for more shared preferences (#992)
Continues the work of providing properties with accessors for specific
shared preferences.
2024-10-10 13:12:56 +02:00
Nik Clayton 59a0e3087c
refactor: Pass the active account ID to activities, fragments, etc (#982)
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.
2024-10-07 15:56:37 +02:00
Nik Clayton 668c073822
refactor: Assorted code inspection cleanups (#985)
Code inspection found some mechanical code cleanups.
2024-10-07 12:38:35 +02:00
Languages add-on 0b8f36431f feat(l10n): Added Burmese translation 2024-10-06 19:08:25 +02:00
Nik Clayton 65c73625f6
refactor: Create V2 filters with one API call (#979)
Previous code didn't encode v2 filter keywords, so created v2 filters by
first creating the filter with no keywords (one API call) then making
1-N API calls to add each keyword to the filter.

Fix this by adding a dedicated converter for the `NewContentFilter` type
that encodes it correctly so the filter can be created with a single API
call.

This necessitates moving some types around,
2024-10-05 14:53:23 +02:00
Nik Clayton 0d5d118267
refactor: Move AccountManager to core.data.repository (#976) 2024-10-03 21:28:01 +02:00
Nik Clayton fe1c586dae
refactor: Move ServerOperation and related types to core.model (#969) 2024-10-03 13:41:46 +02:00
Nik Clayton 510717d46a
refactor: Rename "Filters" to "Content filters" (#927)
The new anti-harassment features will add several different types of
filtering options through the UI.

To ensure there is no confusion, rename the existing "Filters" UI and
code to "Content filters" to accurately describe what they operate on,
distinct from new filters which will act on account metadata.

Fixes #926.
2024-10-02 22:57:00 +02:00
Weblate (bot) 5505180868
fix(l10n): Translations update from Hosted Weblate (#933)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pachli/Fastlane
Metadata](https://hosted.weblate.org/projects/pachli/fastlane-metadata/).


It also includes following components:

* [Pachli/Core/Activity :
Main](https://hosted.weblate.org/projects/pachli/coreactivity-main/)

* [Pachli/App :
Google](https://hosted.weblate.org/projects/pachli/app-google/)

* [Pachli/Feature/Suggestions :
Main](https://hosted.weblate.org/projects/pachli/featuresuggestions-main/)

* [Pachli/Core/Designsystem :
Main](https://hosted.weblate.org/projects/pachli/coredesignsystem-main/)

* [Pachli/Core/Network :
Main](https://hosted.weblate.org/projects/pachli/corenetwork-main/)

*
[Pachli/Feature/Login](https://hosted.weblate.org/projects/pachli/featurelogin/)

* [Pachli/Core/Ui :
Main](https://hosted.weblate.org/projects/pachli/coreui-main/)

* [Pachli/Core/Activity :
Orange](https://hosted.weblate.org/projects/pachli/coreactivity-orange/)

* [Pachli/Feature/About :
Main](https://hosted.weblate.org/projects/pachli/featureabout-main/)

* [Pachli/Core/Data :
Main](https://hosted.weblate.org/projects/pachli/coredata-main/)

* [Pachli/App :
Main](https://hosted.weblate.org/projects/pachli/app-main/)

* [Pachli/App :
Fdroid](https://hosted.weblate.org/projects/pachli/app-fdroid/)

* [Pachli/Feature/Lists :
Main](https://hosted.weblate.org/projects/pachli/featurelists-main/)



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pachli/fastlane-metadata/horizontal-auto.svg)

---------

Co-authored-by: sunniva <schildkroteskoldpadda@gmail.com>
Co-authored-by: LibreTranslate <noreply-mt-libretranslate@weblate.org>
Co-authored-by: ButterflyOfFire <boffire@users.noreply.hosted.weblate.org>
2024-09-20 15:53:28 +02:00
josé m 09b4a08b59 fix(l10n): Update Galician translations
Currently translated at 100.0% (7 of 7 strings)

Translation: Pachli/Core/Data : Main
Translate-URL: https://hosted.weblate.org/projects/pachli/coredata-main/gl/
2024-08-26 14:28:42 +02:00
Juan M Sevilla 7c32a077ac fix(l10n): Update Spanish translations
Currently translated at 100.0% (7 of 7 strings)

Translation: Pachli/Core/Data : Main
Translate-URL: https://hosted.weblate.org/projects/pachli/coredata-main/es/
2024-08-05 13:47:29 +02:00
Kalle Kniivilä 8888a46fb1 fix(l10n): Update Finnish translations
Currently translated at 100.0% (7 of 7 strings)

Translation: Pachli/Core/Data : Main
Translate-URL: https://hosted.weblate.org/projects/pachli/coredata-main/fi/
2024-07-27 19:17:30 +02:00
Aindriú Mac Giolla Eoin 60fc806e12 fix(l10n): Update Irish translations
Currently translated at 100.0% (7 of 7 strings)

Translation: Pachli/Core/Data : Main
Translate-URL: https://hosted.weblate.org/projects/pachli/coredata-main/ga/
2024-07-27 19:17:30 +02:00
Nik Clayton b1d5cb548f
fix: Don't crash due to Filters/ServerRepository race condition (#837)
The `canFilter()` implementation could crash if `server` (marked
`lateinit`) hadn't been initialised at the point of use.

Fix this by removing it and adjusting the two callers to use the
`filters` flow and take appropriate action on error.
2024-07-25 18:43:34 +02:00
Nik Clayton 00a2cd32d3
change: Implement more of FiltersRepository (#816)
The previous code had a number of problems, including:

- Calls to the filters API were scattered through UI and viewmodel code.
- Repeated places where the differences between the v1 and v2 Mastodon
filters API had to be handled.
- UI and viewmodel code using the network filter classes, which tied
them to the API implementation.
- Error handling was inconsistent.

Fix this.

## FiltersRepository

- All filter management now goes through `FiltersRepository`.
- `FiltersRepository` exposes the current set of filters as a
`StateFlow`, and automatically updates it when the current server
changes or any changes to filters are made. This makes
`FilterChangeEvent` obsolete.
- Other operations on filters are exposed through `FiltersRepository` as
functions for viewmodels to call.
- Within the bulk of the app a new `Filter` class is used to represent a
filter; handling the differences between the v1 and v2 APIs is
encapsulated in `FiltersRepository`.
- Represent errors when handling filters as subclasses of `PachliError`,
and use `Result<V, E>` throughout, including using `ApiResult` for all
filter API results.
- Provide different types to distinguish between new-and-unsaved
filters, new-and-unsaved keywords, and in-progress edits to filters.

## Editing filters

- Accept an optional complete filter, or filter ID, as parameters in the
intent that launches `EditFilterActivity`. Pass those to the viewmodel
using assisted injection so the viewmodel has the info immediately.
- In the viewmodel use a new `FilterViewData` type to model the data
used to display and edit the filter.
- Start using the UiSuccess/UiError model. Refrain from cutting over to
full the action implementation as that would be a much larger change.
- Use `FiltersRepository` instead of making any API calls directly.

## Listing filters

- Use `FiltersRepository` instead of making any API calls directly.

## EventHub

- Remove `FilterChangedEvent`. Update everywhere that used it to use the
flow from `FiltersRepository`.
2024-07-14 15:36:52 +02:00
Aindriú Mac Giolla Eoin e8c6093d90 fix(l10n): Update Irish translations
Currently translated at 100.0% (6 of 6 strings)

Translation: Pachli/Core/Data : Main
Translate-URL: https://hosted.weblate.org/projects/pachli/coredata-main/ga/
2024-07-13 09:43:18 +02:00
Nik Clayton 3d5c2dd32f
feat: Show "Suggested accounts" (#734)
Implement suggestions as a new `feature:suggestions` module, with
associated activity, fragment, etc.

Suggested accounts are shown with their normal information, as well as
information about the number of follows / followers, and a guide to
posting frequency, so the user can make a more informed decision about
whether to follow or not.
2024-06-17 21:43:12 +02:00
Nik Clayton 00a88c7874
refactor: Allow PachliError.formatArgs to be null (#755)
Simplifies the case where there are no format args.
2024-06-17 21:29:22 +02:00
Nik Clayton d8d15ab5b0
change: Simplify mapBoth operations to mapEither and map (#746) 2024-06-13 22:55:16 +02:00
Weblate (bot) 6d266bce6d
fix(l10n): Translations update from Hosted Weblate (#737)
Translations update from [Hosted Weblate](https://hosted.weblate.org)
for [Pachli/Fastlane
Metadata](https://hosted.weblate.org/projects/pachli/fastlane-metadata/).


It also includes following components:

* [Pachli/Core/Network :
Main](https://hosted.weblate.org/projects/pachli/corenetwork-main/)

* [Pachli/App :
Main](https://hosted.weblate.org/projects/pachli/app-main/)

* [Pachli/Core/Data :
Main](https://hosted.weblate.org/projects/pachli/coredata-main/)

* [Pachli/App :
Google](https://hosted.weblate.org/projects/pachli/app-google/)

*
[Pachli/Feature/Login](https://hosted.weblate.org/projects/pachli/featurelogin/)

* [Pachli/Core/Activity :
Orange](https://hosted.weblate.org/projects/pachli/coreactivity-orange/)

* [Pachli/Core/Activity :
Main](https://hosted.weblate.org/projects/pachli/coreactivity-main/)

* [Pachli/App :
Fdroid](https://hosted.weblate.org/projects/pachli/app-fdroid/)

* [Pachli/Feature/About :
Main](https://hosted.weblate.org/projects/pachli/featureabout-main/)

* [Pachli/Feature/Lists :
Main](https://hosted.weblate.org/projects/pachli/featurelists-main/)

* [Pachli/Core/Designsystem :
Main](https://hosted.weblate.org/projects/pachli/coredesignsystem-main/)

* [Pachli/Core/Ui :
Main](https://hosted.weblate.org/projects/pachli/coreui-main/)



Current translation status:

![Weblate translation
status](https://hosted.weblate.org/widget/pachli/fastlane-metadata/horizontal-auto.svg)

---------

Co-authored-by: Languages add-on <noreply-addon-languages@weblate.org>
2024-06-13 22:54:02 +02:00
Nik Clayton efd1c8e556
refactor: Use the PachliError type for ApiError (#739)
In the previous code `PachliError` could correctly chain errors and
generate error messages, `ApiError` didn't, which is why there was the
temporary `ApiError.fmt()` extension function.

Rewrite `ApiError` to implement `PachliError` so it gets these benefits
and to reduce the number of different error-handling mechanisms in the
code.

Main changes:

- `PachliError` is now an interface so it can be extended by other
  error interfaces.
- All the `ApiError` subclasses implement `PachliError`, and can
  specify the error string and interpolated variables at the point of
  declaration.
- Update `ListsRepository` and `ServerRepository` to return
  `PachliError` subclasses.
2024-06-12 10:22:27 +02:00
Nik Clayton a68e1bf63b
refactor: Move StatusDisplayOptions and Repository to core.data (#731) 2024-06-10 17:29:09 +02:00
Nik Clayton dc61030b98
refactor: Move AccountPreferenceDataStore to core.data (#730) 2024-06-10 16:54:14 +02:00
Nik Clayton e4a065ca9f
refactor: Move ServerRepository to core.data (#728) 2024-06-10 16:08:48 +02:00
Nik Clayton 362cdfeb27
fix: Prevent crash when Pachli is a share target (#659)
Crash was occuring because the instance info hadn't been fetched, trying
to take the last item of an empty list.

To fix:

- Expose the instance info as a state flow, with a default. New instance
info is fetched whenever the active account changes.

- Do the same for the emojis supported by the server.

- Update call sites as appropriate.

- Mark `InstanceInfoRepository` as `@Singleton` so it isn't repeatedly
created causing fresh content fetches.

The tests needed updating to get this to work.

- Extract the network fake modules in to a network-test module so
multiple other modules can use them.

- Rewrite `InstanceInfoRepositoryTest` to use Hilt and use Turbine to
test the new flows.

Checking this showed cosmetic bugs in the About layout when instance
info is missing, clean those up.
2024-04-28 18:19:13 +02:00
Nik Clayton 8257ded395
refactor: Remove `TabData` type (#576)
`TabData` recorded the type of the timeline the user had added to a tab.
`TimelineKind` is another type that records general information about
configured timelines, with identical properties.

There's no need for both, so remove `TabData` and use `TimelineKind` in
its place.

`TimelineKind` is itself mis-named; it's not just the timeline's kind
but also holds data necessary to display that timeline (e.g., the list
ID if it's a `.UserList`, or the hashtags if it's a `.Hashtags`) so
rename to `Timeline` to better reflect its usage. Move it to a new
`core.model` module.
2024-03-30 23:27:25 +01:00
Nik Clayton bdbe2f85c2
feat: Allow the user to set a list's replies policy (#534)
The replies policy controls whether replies from members of the list
also appear in the list.

Display the replies policy as three radio buttons when a list is created
or updated, and send the chosen replies policy via the API.

Default value if not specified is always "list", for consistency with
the Mastodon API defaults.

While I'm here:

- Ensure the list dialog layout is inflated using the dialog's themed
context
- Use a `TextInputLayout` wrapper around the list name in the list
dialog for better UX
- Simplify the dialog layout, use LinearLayout, and standard padding and
margins
2024-03-14 23:56:16 +01:00
Nik Clayton 006c358053 fix: Sort lists by title wherever they occur 2024-03-12 19:52:45 +01:00
Nik Clayton 7da4bc090b fix: Update tabs when lists are renamed or deleted
If the user has tabs containing one or more lists, and any of those
lists are renamed or deleted then the change should be reflected in the
tabs.

To do that:

`MainActivity`:

- Re-create tabs whenever lists are loaded and there's a list in a tab
- Compare lists-in-tabs by the ID of the list when restoring the user's
  tab, so that a list rename doesn't lose their position.

`NetworkListsRepository`:

- Update the user's tab preferences whenever lists are loaded, removing
  tabs that contain lists that have been deleted, and updating the
  list's title for lists that have been renamed.

Fixes #192
2024-03-12 19:52:45 +01:00
Nik Clayton 442f3bc80c
feat: Show user's lists in the left-side navigation menu (#514)
Previously to view a list the user either had to add it to a tab, or tap
through "Lists" in the navigation menu to their list of lists, and then
tap the list they want.

Fix that, and show all their lists in a dedicated section in the menu,
with a new "Manage lists" entry that's functionality identical to the
old "Lists" entry (i.e., it shows their lists and allows them to create,
delete, and edit list settings).

To do that:

- Implement a proper `ListsRepository` as the single source of truth for
list implementation throughout the app. Expose the current list of lists
as a flow, with methods to perform operations on the lists.

- Collect the `ListsRepository` flow in `MainActivity` and use that to
populate the menu and update it whenever the user's lists change.

- Rewrite the activities and fragments that manipulate lists to use
`ListRepository`.

- Always show error snackbars when list operations fail. In particular,
the HTTP code and error are always shown.

- Delete the custom `Either` implementation, it's no longer used.

- Add types for modelling API responses and errors, `ApiResponse` and
`ApiError` respectively. The response includes the headers as well as
the body, so it can replace the use of `NetworkResult` and `Response`.
The actual result of the operation is expected to be carried in a
`com.github.michaelbull.result.Result` type. Implement a Retrofit call
adapter for these types.

Unit tests for these borrow heavily from
https://github.com/connyduck/networkresult-calladapter

Additional user-visible changes:

- Add an accessible "Refresh" menu item to `ListsActivity`.

- Adding a list to a tab has a dialog with a "Manage lists" option.
Previously that would close the dialog when clicked, so the user had to
re-open it on returning from list management. Now the dialog stays open.

- The soft keyboard automatically opens when creating or editing a list.
2024-03-10 23:14:21 +01:00
Nik Clayton af58de5a8f
refactor: Enable core library desugaring as build convention logic (#480)
Once desugaring is enabled it needs to be enabled for up/down the
dependency chain, so enable it in the shared configuration defined by
the build convention code.

Highlighted a failing test that wasn't being run, so fix that too.
2024-02-29 09:43:44 +01:00
Nik Clayton d943fa1aca
fix: Update InstanceV1/V2 related types based on real-world usage (#476)
Many servers that claim to be Mastodon-API compatible are not, as
evidenced by the content they include in the responses to
`/api/v1/instance` and `/api/v2/instance` requests.

Work around the worst of the breakage by providing defaults or marking
some fields as nullable (with a default null).

Bugs have been reported against the relevant projects.
2024-02-28 00:02:03 +01:00
Nik Clayton 96474a9ac3
change: Improve logging calls to Timber (#430)
- Use format strings so any overhead of building the string is only
incurred if the message is actually logged

- Pass throwables as the first parameter so they are logged with the
stacktrace
2024-02-09 17:33:01 +01:00
Nik Clayton 86d800b1c8
refactor: Modularise "about" activities (#405)
Continue modularisation by moving activities in the "About" feature to a
new `feature.about` module.

Implement `feature.about:
- Move `AboutActivity`, `LicenseActivity`, and `PrivacyPolicyActivity`
here.
- Update `markdown2resource` plugin to work with libraries

Implement `core.data`:
- Types and repositories used through the app
- Move `InstanceInfo` and `InstanceInfoRepository` here so they are
available to `feature.about`.

Implement `core.ui`:
- App-specific views, spans, and other UI content
- Move `ClickableSpanTextView` and `NoUnderlineURLSpan` here so they are
available to `feature.about`.
2024-02-02 15:14:31 +01:00