mirror of
https://codeberg.org/tom79/Fedilab.git
synced 2025-07-23 12:00:31 +03:00
Compare commits
No commits in common. "main" and "3.0.9" have entirely different histories.
2486 changed files with 38299 additions and 134619 deletions
|
@ -1,40 +0,0 @@
|
|||
---
|
||||
|
||||
name: "Bug"
|
||||
about: "Something isn't working"
|
||||
labels:
|
||||
|
||||
- Bug
|
||||
|
||||
---
|
||||
|
||||
<!-- Please, describe the issue here -->
|
||||
|
||||
## # Steps for reproducing the issue
|
||||
|
||||
<!-- Step, to reproduce it -->
|
||||
|
||||
|
||||
---
|
||||
<!-- The instance you are using -->
|
||||
Instance:
|
||||
|
||||
<!-- Your social network -->
|
||||
<!-- Put a x between brackets like: - [x] Mastodon -->
|
||||
|
||||
- [ ] Mastodon
|
||||
- [ ] Pleroma
|
||||
- [ ] Friendica
|
||||
- [ ] Pixelfed
|
||||
|
||||
<!-- If you know the version of Fedilab that you are using (can be found in about page) -->
|
||||
Version of Fedilab:
|
||||
|
||||
|
||||
<!-- Your Android version -->
|
||||
Android version:
|
||||
|
||||
|
||||
<!-- If you read our contributing advice -->
|
||||
- [ ] I read the [contributing page](https://codeberg.org/tom79/Fedilab/src/branch/main/CONTRIBUTING.md)
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
|
||||
name: "Feature"
|
||||
about: "A new feature or an enhancement to an existing feature"
|
||||
labels:
|
||||
|
||||
- Feature
|
||||
|
||||
---
|
||||
|
||||
## # Describe the improvement
|
||||
|
||||
<!-- Your social network -->
|
||||
<!-- Put a x between brackets like: - [x] Mastodon -->
|
||||
|
||||
- [ ] Mastodon
|
||||
- [ ] Pleroma
|
||||
- [ ] Friendica
|
||||
- [ ] Pixelfed
|
||||
|
||||
<!-- Describe the improvement here -->
|
||||
|
||||
|
||||
<!-- If you read our contributing advice -->
|
||||
- [ ] I read the [contributing page](https://codeberg.org/tom79/Fedilab/src/branch/main/CONTRIBUTING.md)
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- Allow to define the max chars count when not detected (In about the instance)
|
||||
- Add emoji one picker when composing (must be enabled in settings)
|
||||
- Add release notes with the ability to translate them
|
||||
|
||||
Fixed:
|
||||
- Friendica custom emojis not displayed
|
||||
- Long press to store media
|
||||
- Some bug fixes
|
|
@ -1,11 +0,0 @@
|
|||
Changed:
|
||||
- Composing messages is no longer forced to max chars
|
||||
|
||||
Fixed:
|
||||
- Cross-account follow
|
||||
- Cannot subscribe to notifications for an account
|
||||
- Issues when sharing
|
||||
- Wrong profile for emoji reactions in notifications
|
||||
- Issue with cards
|
||||
- Crashes with tabs
|
||||
- Tabs cannot be renamed
|
|
@ -1,15 +0,0 @@
|
|||
Added:
|
||||
- New theme: Dark Elephant from S1m
|
||||
- Error messages from server side when posting fails
|
||||
- Allow to set the fetch time for delayed notifications
|
||||
|
||||
Changed:
|
||||
- Fetch more buttons more visible
|
||||
|
||||
Fixed:
|
||||
- Issue when fetching missing messages
|
||||
- Some issues with themes
|
||||
- Too much lost space with reaction (Pleroma)
|
||||
- Delete and redraft crashes
|
||||
- Crash when playing a video
|
||||
- Other crash fixes
|
|
@ -1,20 +0,0 @@
|
|||
Added:
|
||||
- Export Settings
|
||||
- Propagate manual reordering of lists in timeline to "Lists" submenu
|
||||
- Allow to change the push distributor in settings
|
||||
|
||||
Changed:
|
||||
- Improve fit preview images
|
||||
- Improve notifications
|
||||
- Profile media displayed in a grid
|
||||
|
||||
Fixed:
|
||||
- Some Peertube videos not working
|
||||
- Respect the default visibility account when replying
|
||||
- Discriminate gif from images
|
||||
- App crashes when opening external instance timeline
|
||||
- Remove button in thread composer crashes the app
|
||||
- Back button opens a lot of old activities before closing the app
|
||||
- Problems with sharing
|
||||
- Reorder Lists with UI issue on change the visibility
|
||||
- Link is not shown correctly in posts from Friendica
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- Settings to set all timelines at the top (default disabled)
|
||||
- Settings to display timelines in a list (default disabled)
|
||||
- Display counters for fav/reblog in timelines (default disabled)
|
||||
|
||||
Fixed:
|
||||
- Visibility issue when replying
|
||||
- Some theme issues when composing
|
||||
- Some crashes
|
|
@ -1,5 +0,0 @@
|
|||
- Improve speed for Nitter instances
|
||||
- Allow to edit Nitter accounts with a long press on tabs
|
||||
- Fix pagination issue with pinned timelines
|
||||
- Fix some crashes
|
||||
- Fix visibility when displaying counters
|
|
@ -1,5 +0,0 @@
|
|||
- Fix an issue with cache and home timeline
|
||||
- Nitter timelines use the custom instance from settings
|
||||
- Fix Nitter issues (only RT)
|
||||
- No longer accepts invalid certificate for onion URLs(Google)
|
||||
- Fix some crashes
|
|
@ -1,4 +0,0 @@
|
|||
- New cache mechanism
|
||||
- Cache can be disabled in settings
|
||||
- Add counters for new messages
|
||||
- Some fixes.
|
|
@ -1,3 +0,0 @@
|
|||
- Fix post message with media
|
||||
- Set thumbnails load behavior Always/Wifi only /ask
|
||||
- Some other small fixes
|
|
@ -1,5 +0,0 @@
|
|||
- Fix post message with media
|
||||
- Fix encoding issue with media descriptions
|
||||
- Fix Friendica tag search
|
||||
- Fixes when composing
|
||||
- Some other small fixes
|
|
@ -1,10 +0,0 @@
|
|||
Added:
|
||||
- New cache mechanism (can be disabled in settings)
|
||||
- Set thumbnails load behavior Always/Wifi only /ask
|
||||
- Add counters for new messages in timelines
|
||||
Fixed:
|
||||
- Contextual menu not working in threads
|
||||
- Tag search issue with Friendica
|
||||
- Notifications click open the wrong tab
|
||||
- Encoding issue with media descriptions
|
||||
- Some other fixes.
|
|
@ -1,7 +0,0 @@
|
|||
Added:
|
||||
- Disable counters in settings
|
||||
Fixed:
|
||||
- Duplicated messages from cache
|
||||
- Notifications in double
|
||||
- Drafts not automatically removed
|
||||
- Messages not removed from cache after deletion
|
|
@ -1,2 +0,0 @@
|
|||
Fixed:
|
||||
- Attach media to a reply
|
|
@ -1,12 +0,0 @@
|
|||
Changed:
|
||||
- Swipe between timelines
|
||||
- Improve cache
|
||||
- Button sizes in messages follow defined scale
|
||||
|
||||
Fixed:
|
||||
- Pleroma: Emoji reactions
|
||||
- Sharing (several fixes)
|
||||
- Theme issues
|
||||
- Rendering issue for links
|
||||
- Notifications not removed from cache
|
||||
- Some crashes
|
|
@ -1,15 +0,0 @@
|
|||
Changed:
|
||||
- Swipe between timelines
|
||||
- Improve cache
|
||||
- Button sizes can be changed in settings
|
||||
- French translation
|
||||
|
||||
Fixed:
|
||||
- Pleroma: Emoji reactions
|
||||
- Sharing (several fixes)
|
||||
- Theme issues
|
||||
- Rendering issue for links
|
||||
- Notifications not removed from cache
|
||||
- Issue with watermarks
|
||||
- Pagination with bookmarks/favourites
|
||||
- Some crashes
|
|
@ -1,15 +0,0 @@
|
|||
Added:
|
||||
- Change app icon (Settings > Interface)
|
||||
- Allow to disable "remember position" in timelines
|
||||
- Allow to disable notification aggregation in settings
|
||||
|
||||
Changed:
|
||||
- Allow to disable/enable media for notifications
|
||||
|
||||
Fixed:
|
||||
- Post loses "spoiler message" when adding a media
|
||||
- Camera not working on Android 11
|
||||
- Notification aggregation
|
||||
- Vibrations when fetching new notifications
|
||||
- Fix an issue with media timelines
|
||||
- Some crashes
|
|
@ -1,11 +0,0 @@
|
|||
Added:
|
||||
- Pin/Unpin messages
|
||||
- Set the default language for translations
|
||||
|
||||
Changed:
|
||||
- Allow to disable/enable media for notifications
|
||||
|
||||
Fixed:
|
||||
- Wrong images in notification timeline
|
||||
- Double icon bug
|
||||
- Fix some crashes
|
|
@ -1,2 +0,0 @@
|
|||
- Edit messages (if your instance supports that feature)
|
||||
- Some fixes
|
|
@ -1,22 +0,0 @@
|
|||
Added:
|
||||
- Edit messages (if your instance supports that feature)
|
||||
- Pin/Unpin messages
|
||||
- Set the default language for translations
|
||||
- Change app icon (Settings > Interface)
|
||||
- Allow to disable "remember position" in timelines
|
||||
- Allow to disable notification aggregation in settings
|
||||
- Icon on media previews if a description is available
|
||||
|
||||
Changed:
|
||||
- Allow to disable/enable media for notifications
|
||||
|
||||
Fixed:
|
||||
- Post loses "spoiler message" when adding a media
|
||||
- Camera not working on Android 11
|
||||
- Notification aggregation
|
||||
- Vibrations when fetching new notifications
|
||||
- Fix an issue with media timelines
|
||||
- Fix some theme issues
|
||||
- Fix an issue with built-in browser & openId
|
||||
- Bad behaviours with Art Timelines
|
||||
- Some crashes
|
|
@ -1,13 +0,0 @@
|
|||
Added:
|
||||
- Display client in detailed messages
|
||||
- Visual support for quotes starting with ">"
|
||||
- Increase indentations for threads (zero to 20, default 5)
|
||||
- Visibility for public replies set to unlisted (can be disabled)
|
||||
|
||||
Changed:
|
||||
- Reduce title size when text size is increased
|
||||
|
||||
Fixed:
|
||||
- Filters are not applied
|
||||
- Blocking an account doesn't remove messages in cache
|
||||
- Fix some crashes
|
|
@ -1,5 +0,0 @@
|
|||
Fixed:
|
||||
- Order of notifications
|
||||
- URL when sharing boosted message
|
||||
- Blank pages when restarting
|
||||
- Fix some crashes
|
|
@ -1,5 +0,0 @@
|
|||
Fixed:
|
||||
- Issue with messages/notifications not correctly displayed
|
||||
- Friendica: issues with mentions and tags (open browser)
|
||||
- Improve sharing behaviour
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
Changed:
|
||||
- Tag search ordered by popularity
|
||||
|
||||
Fixed:
|
||||
- Unable to get client ID on some devices
|
||||
- Issue with messages/notifications not correctly displayed
|
||||
- Notifications not received
|
||||
- Friendica: issues with mentions and tags (open browser)
|
||||
- Improve sharing behaviour
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- Two new Light themes
|
||||
- More moderation features
|
||||
|
||||
Fixed:
|
||||
- Filter not working
|
||||
- Crash with trends
|
||||
- Some content lost when sending messages (mentions)
|
||||
- Some other fixes
|
|
@ -1,16 +0,0 @@
|
|||
Added:
|
||||
- Follow tags (dedicated entry in menu)
|
||||
- Reduce the list of languages when composing (Settings > Compose)
|
||||
- Language indicator when composing
|
||||
- Replies are automatically set to first message language
|
||||
- Two new Light themes
|
||||
- More moderation features
|
||||
- List name can be edited
|
||||
|
||||
Fixed:
|
||||
- Filter not working
|
||||
- Crash with trends
|
||||
- Issue with themes
|
||||
- Some content lost when sending messages (mentions)
|
||||
- Fix freezes in timelines
|
||||
- Some other fixes
|
|
@ -1,14 +0,0 @@
|
|||
Added:
|
||||
- Support to open links containing /@display_name/ in their path (works on older devices)
|
||||
- Display reply count when counters are enabled
|
||||
- Add support for filtering profile messages
|
||||
|
||||
Changed:
|
||||
- Compose view takes the whole width even in threads
|
||||
- Reset push notification marker when clearing cache
|
||||
|
||||
Fixed:
|
||||
- Draft stored when replying "no" or dialog prompted without changes
|
||||
- Filters not working with tags
|
||||
- Add a specific error message for followed tags
|
||||
- Empty pages when starting the app
|
|
@ -1,2 +0,0 @@
|
|||
Added:
|
||||
- Full support to new filters for Mastodon 4
|
|
@ -1,5 +0,0 @@
|
|||
Added:
|
||||
- Visit profiles without being authenticated / Allow to display all their messages
|
||||
|
||||
Fixed:
|
||||
- Saving media fails on some devices
|
|
@ -1,14 +0,0 @@
|
|||
Added:
|
||||
- Full support to new filters for Mastodon 4
|
||||
- Visit profiles without being authenticated / Allow to display all their messages
|
||||
|
||||
Changed:
|
||||
- Compose view takes the whole width even in threads
|
||||
- Accounts can be timed-mute from their profile
|
||||
|
||||
Fixed:
|
||||
- Draft stored when replying "no" or dialog prompted without changes
|
||||
- Empty pages when starting the app
|
||||
- Saving and sharing media fails on some devices
|
||||
- Add support for admin notifications
|
||||
- Copying content of a message
|
|
@ -1,13 +0,0 @@
|
|||
Added:
|
||||
- List of blocked domains (allow to unblock)
|
||||
- Support gemini links
|
||||
- Suggested followers
|
||||
|
||||
Changed:
|
||||
- Allow search term to be edited
|
||||
|
||||
Fixed:
|
||||
- Drafts deleted with no warning
|
||||
- App crashes when proxy is set
|
||||
- Filter not synced after being edited
|
||||
- Some crashes
|
|
@ -1,18 +0,0 @@
|
|||
Added:
|
||||
- List of blocked domains (allow to unblock)
|
||||
- Support gemini links
|
||||
- Suggested followers
|
||||
- Mod/Adm: Manage instance blocked domains
|
||||
- Open messages with another account
|
||||
- Allow to disable notifications for admins
|
||||
- Sort lists
|
||||
|
||||
Changed:
|
||||
- Allow search term to be edited
|
||||
|
||||
Fixed:
|
||||
- Drafts deleted with no warning
|
||||
- Remove lists from "Manage timelines"
|
||||
- App crashes when proxy is set
|
||||
- Filter not synced after being edited
|
||||
- Some crashes / improvements
|
|
@ -1,12 +0,0 @@
|
|||
Added:
|
||||
- Mute tags with long press in timelines
|
||||
|
||||
Changed:
|
||||
- Muted account messages are now removed from cache
|
||||
|
||||
Fixed:
|
||||
- Open with another account
|
||||
- Fix jumps in profiles
|
||||
- Media not displayed in album -> force indexation
|
||||
- Built-in browser does not give admin scope
|
||||
- Some crashes
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- Migrate to Material Design 3
|
||||
- 5 Themes (Light, Dark, Solarized Light/Dark, Black)
|
||||
- Automatically switch between Light/Dark
|
||||
- Light and Dark theme can be defined for time-based switch
|
||||
- Android 12+: Dynamic color
|
||||
|
||||
Fixed:
|
||||
- Jumps in timelines
|
|
@ -1,10 +0,0 @@
|
|||
Changed:
|
||||
- Remove built-in browser support
|
||||
- More spaces between action buttons in messages
|
||||
|
||||
Fixed:
|
||||
- Text size issue
|
||||
- Text overlap
|
||||
- Wrong background for solarized black
|
||||
- Mix between light and dark theme
|
||||
- Save button hidden
|
|
@ -1,14 +0,0 @@
|
|||
Added:
|
||||
- New design with 5 themes
|
||||
|
||||
Changed:
|
||||
- Remove built-in browser support
|
||||
- Fit preview image displays images vertically
|
||||
- Add counters next to images
|
||||
|
||||
Fixed:
|
||||
- Jumps in timelines
|
||||
- Replies to wrong messages with followed instances
|
||||
- Bug with delete&redraft with a media
|
||||
- List cannot be hidden
|
||||
- Some crashes
|
|
@ -1,6 +0,0 @@
|
|||
Changed:
|
||||
- Remove card presentation
|
||||
- Link color for black theme
|
||||
|
||||
Fixed:
|
||||
- Crash when changing the theme
|
|
@ -1,4 +0,0 @@
|
|||
Fixed:
|
||||
- Custom emoji are not always displayed
|
||||
- Jumps in timeline when using "fit preview images"
|
||||
- Dark theme: timeline buttons without toggle
|
|
@ -1,3 +0,0 @@
|
|||
Fixed:
|
||||
- Jumps with fit preview images when scrolling up
|
||||
- Fetch more button broken with cache
|
|
@ -1,11 +0,0 @@
|
|||
Added:
|
||||
- Dracula theme
|
||||
|
||||
Changed:
|
||||
- Colors for Light/Dark/Black themes
|
||||
|
||||
Fixed:
|
||||
- Animated profile pictures not displayed
|
||||
- Mentions broken in profile bio and fields
|
||||
- Tag patterns in URL break the link
|
||||
- Typo in followed tags
|
|
@ -1,16 +0,0 @@
|
|||
Added:
|
||||
- Dracula theme
|
||||
- Customize message colors
|
||||
- Enable/Disable Card presentation
|
||||
|
||||
Changed:
|
||||
- Colors for some themes
|
||||
- Space between buttons
|
||||
|
||||
Fixed:
|
||||
- Animated profile pictures not displayed
|
||||
- Mentions broken in profile bio and fields
|
||||
- Jumps with fit preview images when scrolling up
|
||||
- Fetch more button broken with cache
|
||||
- Tag patterns in URL break the link
|
||||
- Typo in followed tags
|
|
@ -1,4 +0,0 @@
|
|||
Added:
|
||||
- Display all messages in threads from remote instances (when possible)
|
||||
* Only public messages for instances using the Mastodon API
|
||||
* A dedicated button is displayed at the top right when conditions are filled.
|
|
@ -1,11 +0,0 @@
|
|||
Added:
|
||||
- Allow to unmute/unfollow/unpin a tag from tag timelines
|
||||
- Automatically add the tag when composing from a tag timeline
|
||||
- Add a translate button at the bottom of messages (default: disabled)
|
||||
- Add account role in profiles
|
||||
|
||||
Fixed:
|
||||
- Contact not working when composing
|
||||
- Status bar for black theme
|
||||
- Message duplicated in conversations when edited
|
||||
- Color issue on Android 5
|
|
@ -1,18 +0,0 @@
|
|||
Added:
|
||||
- Display all messages in threads from remote instances (when possible)
|
||||
- Allow to unmute/unfollow/unpin a tag from tag timelines
|
||||
- Display most used accounts in header menu for an easy switch
|
||||
- Automatically add the tag when composing from a tag timeline
|
||||
- Add a translate button at the bottom of messages (default: disabled)
|
||||
- Add account role in profiles
|
||||
- Translate morse
|
||||
|
||||
Changed:
|
||||
- Disable animations after a refresh
|
||||
|
||||
Fixed:
|
||||
- Contact not working when composing
|
||||
- Status bar for black theme
|
||||
- Message duplicated in conversations when edited
|
||||
- Color issue on Android 5
|
||||
- Several crashes
|
|
@ -1,4 +0,0 @@
|
|||
Added:
|
||||
- Mute/Unmute accounts in the Home timeline from their messages or their profiles
|
||||
- Add all users from a list to "Muted home" in one click
|
||||
- Display/Manage users that are muted for home
|
|
@ -1,7 +0,0 @@
|
|||
Added:
|
||||
- Mute/Unmute accounts in the Home timeline from their messages or their profiles
|
||||
- Add all users from a list to "Muted home" in one click
|
||||
- Display/Manage users that are muted for home
|
||||
|
||||
Fixed:
|
||||
- Timeline crashes
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- Add more targeted languages in picker for translations
|
||||
- Add account name in push notifications
|
||||
|
||||
Fixed:
|
||||
- Fix a crash when changing language
|
||||
- Fix counter colors
|
||||
- Fix default link color
|
||||
- Fix a crash when clicking on mentions
|
|
@ -1,12 +0,0 @@
|
|||
Added:
|
||||
- Full data import/export feature
|
||||
- Android 13 themed icon support
|
||||
|
||||
Fixed:
|
||||
- Fix a regression with filters
|
||||
- Fix dark solarized theme
|
||||
- Fix hide link previews for CW
|
||||
- Fix status bar color for all themes
|
||||
- Fix language in compose "..."
|
||||
- Fix add all home muted accounts from lists
|
||||
- Fix top notification badges
|
|
@ -1,12 +0,0 @@
|
|||
Added:
|
||||
- Post random quotes
|
||||
- Group reblogs in home timeline
|
||||
|
||||
Changed:
|
||||
- Display translate button only when language is different
|
||||
- Respect blank spaces between words in messages
|
||||
- Focus button more accessible when editing media
|
||||
|
||||
Fixed:
|
||||
- Behavior with cw toggle
|
||||
- Truncated gimini links
|
|
@ -1,16 +0,0 @@
|
|||
Added:
|
||||
- Rename Nitter timelines
|
||||
- Android 13 support
|
||||
|
||||
Changed:
|
||||
- Visual feedback for block on account list
|
||||
- Visual changes with compose / top bar
|
||||
|
||||
Fixed:
|
||||
- Nav buttons not visible with media (Light theme)
|
||||
- Status bar with Android 5
|
||||
- Fix links not clickable
|
||||
- Fix deep links
|
||||
- Fix remote threads not fetched for some instances
|
||||
- Adding description to shared media
|
||||
- Fix crashes
|
|
@ -1,8 +0,0 @@
|
|||
Added:
|
||||
- Pagination with search / trending
|
||||
|
||||
Fixed:
|
||||
- Long press on Nitter tabs
|
||||
- Open with another accounts
|
||||
- Chars size not respected for Android 5-6
|
||||
- Wrong instance fetched for instances.social
|
|
@ -1,33 +0,0 @@
|
|||
Added:
|
||||
- Post random quotes
|
||||
- Group reblogs in home timeline
|
||||
- Rename Nitter timelines
|
||||
- Android 13 support
|
||||
- Pagination with search / trending
|
||||
- Allow to remove left margin in messages (default: disabled)
|
||||
|
||||
Changed:
|
||||
- Display translate button only when language is different
|
||||
- Respect blank spaces between words in messages
|
||||
- Focus button more accessible when editing media
|
||||
- Visual feedback for block on account list
|
||||
- Visual changes with compose / top bar
|
||||
- Use custom Nitter timeline name in manage timelines
|
||||
|
||||
Fixed:
|
||||
- Behavior with cw toggle
|
||||
- Truncated gimini links
|
||||
- Nav buttons not visible with media (Light theme)
|
||||
- Status bar with Android 5
|
||||
- Fix links not clickable
|
||||
- Fix deep links
|
||||
- Fix remote threads not fetched for some instances
|
||||
- Adding description to shared media
|
||||
- Open with another accounts
|
||||
- Chars size not respected for Android 5-6
|
||||
- Wrong instance fetched for instances.social
|
||||
- Bouncing Timeline on refresh
|
||||
- Links to mentions, tags, urls, not visible.
|
||||
- Custom channel sounds not applied
|
||||
- users with short username are not linked
|
||||
- Fix crashes
|
|
@ -1,9 +0,0 @@
|
|||
Added:
|
||||
- DeepL translation support free/pro keys
|
||||
|
||||
Changed:
|
||||
- Hide buttons for media when editing
|
||||
|
||||
Fixed:
|
||||
- GIF loaded as static images
|
||||
- Suggested accounts cannot be followed
|
|
@ -1,10 +0,0 @@
|
|||
Changed:
|
||||
- Hidden media smaller with preview images
|
||||
|
||||
Fixed:
|
||||
- Issue with Media for Android 11+
|
||||
- Crash when not setting a translation key
|
||||
- Fix DeepL for API pro
|
||||
- Crash when visiting a profile with a lot of media
|
||||
- Home muted accounts not working without filters
|
||||
- Animated custom emoji not displayed
|
|
@ -1,14 +0,0 @@
|
|||
Added:
|
||||
- Allow to enable extra features in Settings
|
||||
- Customizable settings for extra features
|
||||
- Support quotes, reactions with messages
|
||||
- Support text format (html, markdown, etc.) when composing
|
||||
|
||||
Changed:
|
||||
- Context menu when long pressing a link
|
||||
- Display bookmark and translate buttons are now per account
|
||||
|
||||
Fixed:
|
||||
- CW not working with media
|
||||
- Media not displayed for older instances
|
||||
- Some crashes
|
|
@ -1,10 +0,0 @@
|
|||
Added:
|
||||
- Add Bubble timeline support in extra-features with filters
|
||||
- Allow to display public profiles by default to get all messages (Settings > Interface)
|
||||
|
||||
Changed:
|
||||
- Full rework on links in messages (also mentions and tags)
|
||||
|
||||
Fixed:
|
||||
- Spoiler text when editing
|
||||
- Fix watermarks
|
|
@ -1,5 +0,0 @@
|
|||
Added:
|
||||
- Glitch: Allow to post messages locally (Can be turned off in Settings)
|
||||
|
||||
Fixed:
|
||||
- Crashes
|
|
@ -3,19 +3,9 @@ CONTRIBUTING
|
|||
|
||||
### Localizations:
|
||||
|
||||
Fedilab works only with [Weblate](https://hosted.weblate.org/projects/fedilab), which offers nice
|
||||
Fedilab works only with [Weblate]https://hosted.weblate.org/projects/fedilab), which offers nice
|
||||
tools for helping in translations. New translations will be automatically merged in a branch.
|
||||
|
||||
If you're submiting a merge request and your work adds new strings to the app, make sure they only
|
||||
exist in the default strings.xml file (res/values/strings.xml). If you add or modify strings of
|
||||
other languages, it will interfere with weblate's translations.
|
||||
|
||||
### Issues and Reports:
|
||||
|
||||
Before creating an issue please take a moment and search the repository issues to avoid duplicates.
|
||||
For bug reports, please provide as much details as possible to better debug the problem. The
|
||||
important part is how to reproduce the bug and steps to reproduce it.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Please target the develop branch and not the main branch.
|
||||
other languages, it will interfere with weblate's translations.
|
49
README.md
49
README.md
|
@ -1,46 +1,23 @@
|
|||
[](https://hosted.weblate.org/engage/fedilab/)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
|
||||
<img src="src/fdroid/fastlane/metadata/android/en/images/icon.png" width="100"/>
|
||||
|
||||
# Fedilab
|
||||
A multi-accounts client for Mastodon, Pleroma, Friendica and Pixelfed
|
||||
|
||||
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](https://hosted.weblate.org/engage/fedilab/)
|
||||
[](https://f-droid.org/app/fr.gouv.etalab.mastodon)
|
||||
[](https://liberapay.com/tom79/donate)
|
||||
[](https://opencollective.com/fedilab)
|
||||
|
||||
## Screenshots
|
||||
|
||||
<img src="src/fdroid/fastlane/metadata/android/en/images/phoneScreenshots/1.png" width="150"/>
|
||||
|
||||
<img src="src/fdroid/fastlane/metadata/android/en/images/phoneScreenshots/2.png" width="150"/>
|
||||
|
||||
<img src="src/fdroid/fastlane/metadata/android/en/images/phoneScreenshots/4.png" width="150"/>
|
||||
|
||||
<img src="src/fdroid/fastlane/metadata/android/en/images/phoneScreenshots/7.png" width="150"/>
|
||||
|
||||
## Download
|
||||
|
||||
[<img alt='Get it on F-Droid' src='./images/get-it-on-fdroid.png' height="80"/>](https://f-droid.org/app/fr.gouv.etalab.mastodon) [<img alt='Get it on Google Play' src='./images/get-it-on-play.png' height="80"/>](https://play.google.com/store/apps/details?id=app.fedilab.android)
|
||||
|
||||
## Translate
|
||||
|
||||
- [Weblate](https://hosted.weblate.org/engage/fedilab/)
|
||||
# Fedilab is a multi-accounts client for Mastodon, Pleroma, Friendica and Pixelfed
|
||||
|
||||
## Donate
|
||||
|
||||
- [Liberapay](https://liberapay.com/tom79/donate)
|
||||
- [Open Collective](https://opencollective.com/fedilab)
|
||||
- [More...](https://fedilab.app/page/donations/)
|
||||
[<img alt="Donate using Liberapay" src="https://img.shields.io/liberapay/patrons/tom79.svg?logo=liberapay"/>](https://liberapay.com/tom79/donate)
|
||||
|
||||
## Download
|
||||
|
||||
[<img alt='Get it on Google Play' src='./images/get-it-on-play.png' height="80"/>](https://play.google.com/store/apps/details?id=app.fedilab.android)
|
||||
[<img alt='Get it on F-Droid' src='./images/get-it-on-fdroid.png' height="80"/>](https://f-droid.org/app/fr.gouv.etalab.mastodon)
|
||||
|
||||
## Resources
|
||||
|
||||
- [Wiki](https://wiki.fedilab.app)
|
||||
- [Releases + Changelogs](https://codeberg.org/tom79/Fedilab/releases)
|
||||
[WIKI](https://fedilab.app/wiki/home/)
|
||||
|
||||
## Contact
|
||||
- Fedi:<br>[toot.fedilab.app/@apps](https://toot.fedilab.app/@apps)
|
||||
[Release notes](https://codeberg.org/tom79/Fedilab/tags)
|
||||
|
||||
Lead developer: [toot.fedilab.app/@apps](https://toot.fedilab.app/@apps)
|
||||
|
||||
|
||||
|
|
195
app/build.gradle
195
app/build.gradle
|
@ -1,20 +1,16 @@
|
|||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'androidx.navigation.safeargs.kotlin'
|
||||
}
|
||||
def flavor
|
||||
android {
|
||||
compileSdk 34
|
||||
compileSdk 31
|
||||
|
||||
defaultConfig {
|
||||
minSdk 21
|
||||
targetSdk 34
|
||||
versionCode 534
|
||||
versionName "3.33.1"
|
||||
targetSdk 31
|
||||
versionCode 399
|
||||
versionName "3.0.9"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
flavorDimensions "default"
|
||||
|
@ -23,15 +19,10 @@ android {
|
|||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
applicationIdSuffix '.debug'
|
||||
pseudoLocalesEnabled true
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
productFlavors {
|
||||
fdroid {
|
||||
|
@ -47,11 +38,16 @@ android {
|
|||
flavor = "playstore"
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
abortOnError false
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
sourceSets {
|
||||
playstore {
|
||||
manifest.srcFile "src/playstore/AndroidManifest.xml"
|
||||
java.srcDirs = ['src/main/java', 'src/playstore/java']
|
||||
res.srcDirs = ['src/main/res', 'src/playstore/res']
|
||||
}
|
||||
|
@ -59,39 +55,12 @@ android {
|
|||
java.srcDirs = ['src/main/java', 'src/fdroid/java']
|
||||
res.srcDirs = ['src/main/res', 'src/fdroid/res']
|
||||
}
|
||||
main {
|
||||
res.srcDirs = [
|
||||
'src/main/res/layouts/mastodon',
|
||||
'src/main/res/layouts/peertube',
|
||||
'src/main/res/layouts',
|
||||
|
||||
'src/main/res/drawables/mastodon',
|
||||
'src/main/res/drawables/peertube',
|
||||
'src/main/res/drawables',
|
||||
|
||||
'src/main/res/menus/mastodon',
|
||||
'src/main/res/menus/peertube',
|
||||
'src/main/res/menus',
|
||||
|
||||
'src/main/res/values',
|
||||
|
||||
'src/main/res'
|
||||
]
|
||||
}
|
||||
}
|
||||
configurations {
|
||||
cleanedAnnotations
|
||||
implementation.exclude group: 'org.jetbrains', module: 'annotations'
|
||||
all {
|
||||
exclude group: 'androidx.lifecycle', module: 'lifecycle-viewmodel-ktx'
|
||||
}
|
||||
}
|
||||
namespace 'app.fedilab.android'
|
||||
lint {
|
||||
abortOnError false
|
||||
checkReleaseBuilds false
|
||||
}
|
||||
buildToolsVersion '35.0.0'
|
||||
}
|
||||
allprojects {
|
||||
repositories {
|
||||
|
@ -100,140 +69,60 @@ allprojects {
|
|||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation 'org.unifiedpush.android:connector:3.0.9'
|
||||
|
||||
playstoreImplementation('org.unifiedpush.android:embedded-fcm-distributor:3.0.0')
|
||||
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
|
||||
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation "com.google.code.gson:gson:2.10.1"
|
||||
implementation project(':autoimageslider')
|
||||
implementation 'androidx.appcompat:appcompat:1.4.2'
|
||||
implementation 'com.google.android.material:material:1.6.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation "com.google.code.gson:gson:2.8.6"
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-simplexml:2.9.0'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
implementation 'androidx.preference:preference:1.2.1'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation "org.conscrypt:conscrypt-android:2.5.2"
|
||||
implementation 'com.github.evozi:Cyanea:1.0.7'
|
||||
implementation 'com.vanniktech:emoji-one:0.6.0'
|
||||
implementation 'com.github.GrenderG:Toasty:1.5.2'
|
||||
implementation "com.github.bumptech.glide:glide:4.14.2"
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:4.14.2"
|
||||
implementation("com.github.bumptech.glide:recyclerview-integration:4.14.2") {
|
||||
// Excludes the support library because it's already included by Glide.
|
||||
transitive = false
|
||||
}
|
||||
implementation 'org.framagit.tom79:SparkButton:1.0.13'
|
||||
implementation "com.github.bumptech.glide:glide:4.12.0"
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:4.12.0"
|
||||
|
||||
implementation "org.jsoup:jsoup:1.18.1"
|
||||
implementation 'com.github.mergehez:ArgPlayer:v3.1'
|
||||
|
||||
implementation project(':autoimageslider')
|
||||
implementation project(path: ':mytransl')
|
||||
implementation project(path: ':ratethisapp')
|
||||
implementation project(path: ':sparkbutton')
|
||||
implementation project(path: ':colorPicker')
|
||||
implementation project(path: ':mathjaxandroid')
|
||||
implementation project(path: ':doubletapplayerview')
|
||||
|
||||
|
||||
|
||||
implementation 'com.burhanrashid52:photoeditor:1.5.1'
|
||||
implementation("com.vanniktech:android-image-cropper:4.3.3")
|
||||
implementation project(path: ':cropper')
|
||||
annotationProcessor "com.github.bumptech.glide:compiler:4.12.0"
|
||||
implementation 'jp.wasabeef:glide-transformations:4.3.0'
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:3.0.5'
|
||||
implementation 'androidx.media3:media3-exoplayer-hls:1.2.1'
|
||||
implementation "androidx.media3:media3-exoplayer:1.2.1"
|
||||
implementation "androidx.media3:media3-exoplayer-dash:1.2.1"
|
||||
implementation "androidx.media3:media3-ui:1.2.1"
|
||||
implementation "androidx.media3:media3-session:1.2.1"
|
||||
|
||||
|
||||
implementation "androidx.viewpager2:viewpager2:1.1.0"
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.22.0'
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.16.1'
|
||||
implementation "androidx.viewpager2:viewpager2:1.0.0"
|
||||
implementation 'com.github.piasy:rxandroidaudio:1.7.0'
|
||||
implementation 'com.github.piasy:AudioProcessor:1.7.0'
|
||||
implementation "androidx.work:work-runtime:2.9.0"
|
||||
implementation "androidx.work:work-runtime:2.7.1"
|
||||
implementation 'app.futured.hauler:hauler:5.0.0'
|
||||
implementation "com.github.chrisbanes:PhotoView:2.3.0"
|
||||
implementation "ch.acra:acra-mail:5.11.3"
|
||||
implementation "ch.acra:acra-limiter:5.11.3"
|
||||
implementation "ch.acra:acra-dialog:5.11.3"
|
||||
implementation "ch.acra:acra-mail:5.9.3"
|
||||
implementation "ch.acra:acra-limiter:5.9.3"
|
||||
implementation "ch.acra:acra-dialog:5.9.3"
|
||||
|
||||
implementation "com.madgag.spongycastle:bctls-jdk15on:1.58.0.0"
|
||||
implementation 'com.github.UnifiedPush:android-connector:2.0.0'
|
||||
// implementation 'com.github.UnifiedPush:android-foss_embedded_fcm_distributor:1.0.0-beta1'
|
||||
playstoreImplementation 'com.github.UnifiedPush:android-embedded_fcm_distributor:1.1.0'
|
||||
implementation 'com.burhanrashid52:photoeditor:1.5.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata:2.8.7'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.8.7'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.8.7'
|
||||
implementation 'androidx.navigation:navigation-ui:2.8.7'
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata:2.4.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.4.1'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.4.2'
|
||||
implementation 'androidx.navigation:navigation-ui:2.4.2'
|
||||
testImplementation 'junit:junit:'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
// debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
|
||||
implementation 'com.r0adkll:slidableactivity:2.1.0'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
// debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8.1'
|
||||
|
||||
implementation 'androidx.vectordrawable:vectordrawable:1.2.0'
|
||||
implementation "androidx.fragment:fragment:1.8.6"
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||
implementation 'androidx.browser:browser:1.8.0'
|
||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||
implementation 'com.github.amoskorir:avatarimagegenerator:1.5.0'
|
||||
|
||||
implementation "com.github.mabbas007:TagsEditText:1.0.5"
|
||||
implementation "net.gotev:uploadservice:4.9.2"
|
||||
implementation "net.gotev:uploadservice-okhttp:4.9.2"
|
||||
implementation 'androidx.media:media:1.7.0'
|
||||
implementation 'com.github.mancj:MaterialSearchBar:0.8.5'
|
||||
|
||||
implementation 'com.github.androidmads:QRGenerator:1.0.1'
|
||||
|
||||
implementation 'io.noties.markwon:core:4.6.2'
|
||||
implementation 'io.noties.markwon:ext-tables:4.6.2'
|
||||
implementation 'io.noties.markwon:syntax-highlight:4.6.2'
|
||||
implementation 'io.noties.markwon:ext-strikethrough:4.6.2'
|
||||
implementation 'io.noties.markwon:inline-parser:4.6.2'
|
||||
annotationProcessor 'io.noties:prism4j-bundler:2.0.0'
|
||||
|
||||
//************ CAST **************///
|
||||
|
||||
//---> Google libs (google_full)
|
||||
playstoreImplementation "com.google.android.gms:play-services-cast-tv:21.1.1"
|
||||
playstoreImplementation "com.google.android.gms:play-services-cast:22.0.0"
|
||||
playstoreImplementation "androidx.mediarouter:mediarouter:1.7.0"
|
||||
playstoreImplementation 'com.google.android.gms:play-services-cast-framework:22.0.0'
|
||||
|
||||
|
||||
//----> Other flavors
|
||||
fdroidImplementation 'su.litvak.chromecast:api-v2:0.11.3'
|
||||
fdroidImplementation 'com.fasterxml.jackson.core:jackson-core:2.12.0'
|
||||
fdroidImplementation 'org.slf4j:slf4j-simple:1.7.30'
|
||||
|
||||
}
|
||||
def getCurrentFlavor() {
|
||||
Gradle gradle = getGradle()
|
||||
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
|
||||
println("tskReqStr:" +tskReqStr)
|
||||
Pattern pattern
|
||||
|
||||
if( tskReqStr.contains( "assemble" ) ) // to run ./gradlew assembleRelease to build APK
|
||||
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
|
||||
else if( tskReqStr.contains( "bundle" ) ) // to run ./gradlew bundleRelease to build .aab
|
||||
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
|
||||
else
|
||||
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
|
||||
|
||||
Matcher matcher = pattern.matcher( tskReqStr )
|
||||
println(tskReqStr)
|
||||
if( matcher.find() )
|
||||
return matcher.group(1).toLowerCase()
|
||||
else
|
||||
{
|
||||
println "NO MATCH FOUND"
|
||||
return ""
|
||||
}
|
||||
}
|
||||
println("Flavor: ${getCurrentFlavor()}")
|
||||
if ( getCurrentFlavor() == "playstore" ){
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
package app.fedilab.android;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
{
|
||||
"project_info": {
|
||||
"project_number": "479837431022",
|
||||
"project_id": "pc-api-4835782490875392372-140",
|
||||
"storage_bucket": "pc-api-4835782490875392372-140.appspot.com"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:479837431022:android:1102a97a55202beb547fff",
|
||||
"android_client_info": {
|
||||
"package_name": "app.fedilab.android"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "479837431022-mettpakdcso72c35djvikfc57l4i7n53.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCklTEEgLUxy__0Vzcr5_H179kYPXGjmGo"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "479837431022-mettpakdcso72c35djvikfc57l4i7n53.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:479837431022:android:529536f519b8f4ce547fff",
|
||||
"android_client_info": {
|
||||
"package_name": "app.fedilab.android.debug"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "479837431022-mettpakdcso72c35djvikfc57l4i7n53.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCklTEEgLUxy__0Vzcr5_H179kYPXGjmGo"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"appinvite_service": {
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "479837431022-mettpakdcso72c35djvikfc57l4i7n53.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
<resources>
|
||||
<string name="app_name" translatable="false">Fedilab dbg</string>
|
||||
</resources>
|
|
@ -1,19 +0,0 @@
|
|||
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<shortcut
|
||||
android:shortcutId="compose"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_baseline_add_comment_24"
|
||||
android:shortcutShortLabel="@string/compose_shortcut_short_label1"
|
||||
tools:targetApi="n_mr1">
|
||||
<intent
|
||||
android:action="app.fedilab.android.shorcut.compose"
|
||||
android:targetClass="app.fedilab.android.activities.MainActivity"
|
||||
android:targetPackage="fr.gouv.etalab.mastodon.debug" />
|
||||
|
||||
<categories android:name="android.shortcut.conversation" />
|
||||
<capability-binding android:key="actions.intent.CREATE_MESSAGE" />
|
||||
</shortcut>
|
||||
|
||||
|
||||
</shortcuts>
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<external-path
|
||||
name="my_images"
|
||||
path="Android/data/fr.gouv.etalab.mastodon.debug/files/Pictures" />
|
||||
|
||||
<cache-path
|
||||
name="*"
|
||||
path="." />
|
||||
|
||||
</paths>
|
|
@ -1,215 +0,0 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2023 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
|
||||
import static app.fedilab.android.peertube.helper.Helper.CAST_ID;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.media3.common.Player;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import app.fedilab.android.BuildConfig;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.databinding.ActivityPeertubeBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseBarActivity;
|
||||
import app.fedilab.android.peertube.client.data.VideoData;
|
||||
import app.fedilab.android.peertube.helper.Helper;
|
||||
import su.litvak.chromecast.api.v2.ChromeCast;
|
||||
import su.litvak.chromecast.api.v2.MediaStatus;
|
||||
import su.litvak.chromecast.api.v2.Status;
|
||||
|
||||
|
||||
public class BasePeertubeActivity extends BaseBarActivity {
|
||||
|
||||
protected ActivityPeertubeBinding binding;
|
||||
protected VideoData.Video peertube;
|
||||
protected ExoPlayer player;
|
||||
protected String videoURL;
|
||||
protected String subtitlesStr;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
binding = ActivityPeertubeBinding.inflate(getLayoutInflater());
|
||||
View view = binding.getRoot();
|
||||
setContentView(view);
|
||||
|
||||
|
||||
binding.minController.castPlay.setOnClickListener(v -> {
|
||||
binding.minController.castLoader.setVisibility(View.VISIBLE);
|
||||
if (PeertubeBaseMainActivity.chromeCast != null) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
int icon = -1;
|
||||
if (PeertubeBaseMainActivity.chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
|
||||
PeertubeBaseMainActivity.chromeCast.pause();
|
||||
icon = R.drawable.ic_baseline_play_arrow_32;
|
||||
} else if (PeertubeBaseMainActivity.chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
|
||||
PeertubeBaseMainActivity.chromeCast.play();
|
||||
icon = R.drawable.ic_baseline_pause_32;
|
||||
}
|
||||
if (icon != -1) {
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
int finalIcon = icon;
|
||||
Runnable myRunnable = () -> binding.minController.castPlay.setImageResource(finalIcon);
|
||||
mainHandler.post(myRunnable);
|
||||
}
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> binding.minController.castLoader.setVisibility(View.GONE);
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.action_cast) {
|
||||
if (PeertubeBaseMainActivity.chromeCasts != null && PeertubeBaseMainActivity.chromeCasts.size() > 0) {
|
||||
String[] chromecast_choice = new String[PeertubeBaseMainActivity.chromeCasts.size()];
|
||||
AlertDialog.Builder alt_bld = new MaterialAlertDialogBuilder(this);
|
||||
alt_bld.setTitle(R.string.chromecast_choice);
|
||||
int i = 0;
|
||||
for (ChromeCast cc : PeertubeBaseMainActivity.chromeCasts) {
|
||||
chromecast_choice[i] = cc.getTitle();
|
||||
i++;
|
||||
}
|
||||
i = 0;
|
||||
for (ChromeCast cc : PeertubeBaseMainActivity.chromeCasts) {
|
||||
if (PeertubeBaseMainActivity.chromecastActivated && cc.isConnected()) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
alt_bld.setSingleChoiceItems(chromecast_choice, i, (dialog, position) -> {
|
||||
PeertubeBaseMainActivity.chromeCast = PeertubeBaseMainActivity.chromeCasts.get(position);
|
||||
new Thread(() -> {
|
||||
if (PeertubeBaseMainActivity.chromeCast != null) {
|
||||
Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
|
||||
Bundle b = new Bundle();
|
||||
if (PeertubeBaseMainActivity.chromecastActivated) {
|
||||
b.putInt("displayed", 0);
|
||||
intentBC.putExtras(b);
|
||||
intentBC.setPackage(BuildConfig.APPLICATION_ID);
|
||||
sendBroadcast(intentBC);
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
binding.doubleTapPlayerView.setVisibility(View.VISIBLE);
|
||||
binding.minController.castMiniController.setVisibility(View.GONE);
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
|
||||
} else {
|
||||
b.putInt("displayed", 1);
|
||||
b.putSerializable("castedTube", peertube);
|
||||
intentBC.putExtras(b);
|
||||
intentBC.setPackage(BuildConfig.APPLICATION_ID);
|
||||
sendBroadcast(intentBC);
|
||||
try {
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
invalidateOptionsMenu();
|
||||
binding.minController.castLoader.setVisibility(View.VISIBLE);
|
||||
player.setPlayWhenReady(false);
|
||||
binding.doubleTapPlayerView.setVisibility(View.GONE);
|
||||
binding.minController.castMiniController.setVisibility(View.VISIBLE);
|
||||
dialog.dismiss();
|
||||
if (videoURL != null) {
|
||||
if (player != null && player.getCurrentPosition() > 0) {
|
||||
videoURL += "?start=" + (player.getCurrentPosition() / 1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
if (!PeertubeBaseMainActivity.chromeCast.isConnected()) {
|
||||
PeertubeBaseMainActivity.chromeCast.connect();
|
||||
}
|
||||
myRunnable = this::invalidateOptionsMenu;
|
||||
mainHandler.post(myRunnable);
|
||||
Status status = PeertubeBaseMainActivity.chromeCast.getStatus();
|
||||
if (PeertubeBaseMainActivity.chromeCast.isAppAvailable(CAST_ID) && !status.isAppRunning(CAST_ID)) {
|
||||
PeertubeBaseMainActivity.chromeCast.launchApp(CAST_ID);
|
||||
}
|
||||
if (videoURL != null) {
|
||||
String mime = MimeTypeMap.getFileExtensionFromUrl(videoURL);
|
||||
PeertubeBaseMainActivity.chromeCast.setRequestTimeout(60000);
|
||||
PeertubeBaseMainActivity.chromeCast.load(peertube.getTitle(), null, videoURL, mime);
|
||||
PeertubeBaseMainActivity.chromeCast.play();
|
||||
binding.minController.castPlay.setImageResource(R.drawable.ic_baseline_pause_32);
|
||||
}
|
||||
myRunnable = () -> binding.minController.castLoader.setVisibility(View.GONE);
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (IOException | GeneralSecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
invalidateOptionsMenu();
|
||||
dialog.dismiss();
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
alt_bld.setPositiveButton(R.string.close, (dialog, id) -> dialog.dismiss());
|
||||
AlertDialog alert = alt_bld.create();
|
||||
alert.show();
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NotNull Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.video_menu, menu);
|
||||
MenuItem castItem = menu.findItem(R.id.action_cast);
|
||||
if (PeertubeBaseMainActivity.chromeCasts != null && PeertubeBaseMainActivity.chromeCasts.size() > 0) {
|
||||
castItem.setVisible(true);
|
||||
if (PeertubeBaseMainActivity.chromeCast != null && PeertubeBaseMainActivity.chromeCast.isConnected()) {
|
||||
castItem.setIcon(R.drawable.ic_baseline_cast_connected_24);
|
||||
} else {
|
||||
castItem.setIcon(R.drawable.ic_baseline_cast_24);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2023 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.android.BuildConfig;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.databinding.ActivityMainPeertubeBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseActivity;
|
||||
import app.fedilab.android.peertube.client.data.VideoData;
|
||||
import app.fedilab.android.peertube.helper.Helper;
|
||||
import su.litvak.chromecast.api.v2.ChromeCast;
|
||||
import su.litvak.chromecast.api.v2.ChromeCasts;
|
||||
import su.litvak.chromecast.api.v2.ChromeCastsListener;
|
||||
import su.litvak.chromecast.api.v2.MediaStatus;
|
||||
|
||||
public abstract class PeertubeBaseMainActivity extends BaseActivity implements ChromeCastsListener {
|
||||
|
||||
public static List<ChromeCast> chromeCasts;
|
||||
public static ChromeCast chromeCast;
|
||||
public static boolean chromecastActivated = false;
|
||||
protected ActivityMainPeertubeBinding parentBinding;
|
||||
private BroadcastReceiver manage_chromecast;
|
||||
private VideoData.Video castedTube;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
parentBinding = ActivityMainPeertubeBinding.inflate(getLayoutInflater());
|
||||
View view = parentBinding.getRoot();
|
||||
setContentView(view);
|
||||
ChromeCastsListener chromeCastsListener = this;
|
||||
ChromeCasts.registerListener(chromeCastsListener);
|
||||
|
||||
|
||||
parentBinding.castClose.setOnClickListener(v -> {
|
||||
Intent intentBC = new Intent(Helper.RECEIVE_CAST_SETTINGS);
|
||||
Bundle b = new Bundle();
|
||||
b.putInt("displayed", 0);
|
||||
intentBC.putExtras(b);
|
||||
intentBC.setPackage(BuildConfig.APPLICATION_ID);
|
||||
sendBroadcast(intentBC);
|
||||
});
|
||||
|
||||
parentBinding.castTogglePlay.setOnClickListener(v -> {
|
||||
if (chromeCast != null) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> parentBinding.castTogglePlay.setVisibility(View.GONE);
|
||||
mainHandler.post(myRunnable);
|
||||
int icon = -1;
|
||||
if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PLAYING) {
|
||||
chromeCast.pause();
|
||||
icon = R.drawable.ic_baseline_play_arrow_32;
|
||||
} else if (chromeCast.getMediaStatus().playerState == MediaStatus.PlayerState.PAUSED) {
|
||||
chromeCast.play();
|
||||
icon = R.drawable.ic_baseline_pause_32;
|
||||
}
|
||||
if (icon != -1) {
|
||||
int finalIcon = icon;
|
||||
myRunnable = () -> parentBinding.castTogglePlay.setImageResource(finalIcon);
|
||||
mainHandler.post(myRunnable);
|
||||
}
|
||||
myRunnable = () -> parentBinding.castTogglePlay.setVisibility(View.VISIBLE);
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
manage_chromecast = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Bundle b = intent.getExtras();
|
||||
assert b != null;
|
||||
int state = b.getInt("state_asked", -1);
|
||||
int displayed = b.getInt("displayed", -1);
|
||||
castedTube = (VideoData.Video) b.getSerializable("castedTube");
|
||||
|
||||
if (state == 1) {
|
||||
discoverCast();
|
||||
} else if (state == 0) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
if (chromeCast != null) {
|
||||
chromeCast.stopApp();
|
||||
chromeCast.disconnect();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
if (displayed == 1) {
|
||||
chromecastActivated = true;
|
||||
if (castedTube != null) {
|
||||
parentBinding.castInfo.setVisibility(View.VISIBLE);
|
||||
Helper.loadGiF(PeertubeBaseMainActivity.this, castedTube.getThumbnailPath(), parentBinding.castView);
|
||||
parentBinding.castTitle.setText(castedTube.getTitle());
|
||||
parentBinding.castDescription.setText(castedTube.getDescription());
|
||||
}
|
||||
} else if (displayed == 0) {
|
||||
chromecastActivated = false;
|
||||
parentBinding.castInfo.setVisibility(View.GONE);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
if (chromeCast != null) {
|
||||
chromeCast.stopApp();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
};
|
||||
ContextCompat.registerReceiver(PeertubeBaseMainActivity.this, manage_chromecast, new IntentFilter(Helper.RECEIVE_CAST_SETTINGS), ContextCompat.RECEIVER_NOT_EXPORTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newChromeCastDiscovered(ChromeCast chromeCast) {
|
||||
if (chromeCasts == null) {
|
||||
chromeCasts = new ArrayList<>();
|
||||
chromeCasts.add(chromeCast);
|
||||
} else {
|
||||
boolean canBeAdded = true;
|
||||
for (ChromeCast cast : chromeCasts) {
|
||||
if (cast.getName().compareTo(chromeCast.getName()) == 0) {
|
||||
canBeAdded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canBeAdded) {
|
||||
chromeCasts.add(chromeCast);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (chromeCast.isAppRunning(Helper.CAST_ID) && chromeCast.getMediaStatus() != null && chromeCast.getMediaStatus().playerState != null) {
|
||||
if (parentBinding.castInfo.getVisibility() == View.GONE) {
|
||||
parentBinding.castInfo.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chromeCastRemoved(ChromeCast chromeCast) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
ChromeCasts.unregisterListener(this);
|
||||
if (manage_chromecast != null) {
|
||||
try {
|
||||
unregisterReceiver(manage_chromecast);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
new Thread(() -> {
|
||||
if (chromeCasts != null && chromeCasts.size() > 0) {
|
||||
for (ChromeCast cast : chromeCasts) {
|
||||
try {
|
||||
cast.stopApp();
|
||||
cast.disconnect();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
if (chromeCasts != null) {
|
||||
chromeCasts = null;
|
||||
}
|
||||
if (chromeCast != null) {
|
||||
chromeCast = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Method for discovering cast devices
|
||||
public void discoverCast() {
|
||||
|
||||
new Thread(() -> {
|
||||
if (chromeCasts != null) {
|
||||
for (ChromeCast cast : chromeCasts) {
|
||||
try {
|
||||
cast.disconnect();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
chromeCasts = null;
|
||||
}
|
||||
chromeCasts = new ArrayList<>();
|
||||
try {
|
||||
List<NetworkInterface> interfaces;
|
||||
interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
for (NetworkInterface ni : interfaces) {
|
||||
if ((!ni.isLoopback()) && ni.isUp() && (ni.getName().equals("wlan0"))) {
|
||||
Enumeration<InetAddress> inetAddressEnumeration = ni.getInetAddresses();
|
||||
while (inetAddressEnumeration.hasMoreElements()) {
|
||||
InetAddress inetAddress = inetAddressEnumeration.nextElement();
|
||||
ChromeCasts.restartDiscovery(inetAddress);
|
||||
int tryFind = 0;
|
||||
while (ChromeCasts.get().isEmpty() && tryFind < 5) {
|
||||
try {
|
||||
//noinspection BusyWait
|
||||
Thread.sleep(1000);
|
||||
tryFind++;
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ChromeCasts.stopDiscovery();
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = this::invalidateOptionsMenu;
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/castMiniController"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/cast_play"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/play"
|
||||
android:src="@drawable/ic_baseline_play_arrow_32"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cast_loader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/cast_loader_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/please_wait"
|
||||
android:textColor="?colorAccent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/cast_loader_small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/cast_loader_small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="18dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="5dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/cast_loader_text"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_cast"
|
||||
android:icon="@drawable/ic_baseline_cast_24"
|
||||
android:title="@string/cast"
|
||||
android:visible="false"
|
||||
app:showAsAction="always" />
|
||||
</menu>
|
|
@ -1,19 +0,0 @@
|
|||
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<shortcut
|
||||
android:shortcutId="compose"
|
||||
android:enabled="true"
|
||||
android:icon="@drawable/ic_baseline_add_comment_24"
|
||||
android:shortcutShortLabel="@string/compose_shortcut_short_label1"
|
||||
tools:targetApi="n_mr1">
|
||||
<intent
|
||||
android:action="app.fedilab.android.shorcut.compose"
|
||||
android:targetClass="app.fedilab.android.activities.MainActivity"
|
||||
android:targetPackage="fr.gouv.etalab.mastodon" />
|
||||
|
||||
<categories android:name="android.shortcut.conversation" />
|
||||
<capability-binding android:key="actions.intent.CREATE_MESSAGE" />
|
||||
</shortcut>
|
||||
|
||||
|
||||
</shortcuts>
|
|
@ -1,47 +1,36 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="app.fedilab.android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||
</intent>
|
||||
</queries>
|
||||
<application
|
||||
android:name="app.fedilab.android.MainApplication"
|
||||
android:name=".MainApplication"
|
||||
tools:replace="android:allowBackup"
|
||||
android:allowBackup="false"
|
||||
android:dataExtractionRules="@xml/extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:icon="@mipmap/ic_launcher_bubbles"
|
||||
android:label="@string/app_name"
|
||||
android:largeHeap="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:replace="android:allowBackup">
|
||||
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppThemeDark"
|
||||
>
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:configChanges="orientation|screenSize|keyboardHidden|screenLayout|smallestScreenSize"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
@ -61,33 +50,15 @@
|
|||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="video/*" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- The app is a good candidate for URL in https://domain.name/@xxxxxx-->
|
||||
<!-- It should cover every URLs for statuses but some others not related to mastodon matching this scheme -->
|
||||
<data
|
||||
android:host="*"
|
||||
android:pathPrefix="/@"
|
||||
android:scheme="https" />
|
||||
<data
|
||||
android:host="*"
|
||||
android:pathPrefix="/notes"
|
||||
android:scheme="https" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
<activity
|
||||
android:exported="true"
|
||||
android:name=".activities.LoginActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
|
@ -96,74 +67,63 @@
|
|||
android:scheme="fedilab" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.StatusHistoryActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/status_history"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ContextActivity"
|
||||
android:name=".activities.WebviewConnectActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.DirectMessageActivity"
|
||||
android:name=".activities.ContextActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.DraftActivity"
|
||||
android:name=".activities.DraftActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.imageeditor.EditImageActivity"
|
||||
android:name=".imageeditor.EditImageActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ComposeActivity"
|
||||
android:name=".activities.ComposeActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/compose" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.StatusInfoActivity"
|
||||
android:name=".activities.StatusInfoActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.FollowRequestActivity"
|
||||
android:name=".activities.FollowRequestActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ProfileActivity"
|
||||
android:name=".activities.WebviewActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".activities.ProfileActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/account" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.admin.AdminAccountActivity"
|
||||
android:name=".activities.AdminAccountActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/account" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.AccountReportActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/account"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.admin.AdminReportActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/report"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ScheduledActivity"
|
||||
android:name=".activities.ScheduledActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/scheduled" />
|
||||
<activity
|
||||
android:name="com.canhub.cropper.CropImageActivity"
|
||||
android:name="com.theartofdev.edmodo.cropper.CropImageActivity"
|
||||
android:theme="@style/Base.Theme.AppCompat" />
|
||||
|
||||
<service
|
||||
android:name=".services.PostMessageService"
|
||||
android:label="@string/post_message" />
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.SearchResultTabActivity"
|
||||
android:name=".activities.SearchResultTabActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/search"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
android:theme="@style/AppThemeBar"
|
||||
android:label="@string/search" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.TrendsActivity"
|
||||
android:name=".activities.TrendsActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/trending"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ReorderTimelinesActivity"
|
||||
android:name=".activities.ReorderTimelinesActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/reorder_timelines"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
|
@ -172,107 +132,86 @@
|
|||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/action_about"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.TimelineActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.CheckHomeCacheActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/home_cache"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.admin.AdminDomainBlockActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/blocked_domains"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.SuggestionActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/Suggestions"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.DirectoryActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/Directory"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.PartnerShipActivity"
|
||||
android:name=".activities.PartnerShipActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/action_about"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.ActionActivity"
|
||||
android:name=".activities.ActionActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/interactions"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.admin.AdminActionActivity"
|
||||
android:name=".activities.AdminActionActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/administration"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.MastodonListActivity"
|
||||
android:name=".activities.MastodonListActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/action_lists"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.FollowedTagActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/followed_tags"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.SettingsActivity"
|
||||
android:name=".activities.SettingsActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:label="@string/settings"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.HashTagActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.AnnouncementActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.MediaActivity"
|
||||
android:hardwareAccelerated="true"
|
||||
android:name=".activities.InstanceActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:theme="@style/Transparent" />
|
||||
android:label="@string/action_about_instance"
|
||||
android:theme="@style/DialogDark" />
|
||||
<activity
|
||||
android:name=".activities.InstanceProfileActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/DialogDark" />
|
||||
<activity
|
||||
android:name=".activities.ProxyActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/DialogDark" />
|
||||
<activity
|
||||
android:name=".activities.HashTagActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".activities.AnnouncementActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".activities.MediaActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
android:theme="@style/TransparentDark" />
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.ReportActivity"
|
||||
android:theme="@style/AppThemeBar"
|
||||
android:name=".activities.InstanceHealthActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:theme="@style/DialogDark" />
|
||||
|
||||
<activity
|
||||
android:name=".activities.ReportActivity"
|
||||
android:theme="@style/AppThemeBarDark"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.CustomSharingActivity"
|
||||
android:name=".activities.CustomSharingActivity"
|
||||
android:label="@string/settings_title_custom_sharing"
|
||||
android:theme="@style/AppThemeBar"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
android:windowSoftInputMode="stateVisible"
|
||||
android:theme="@style/AppThemeBarDark" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.FilterActivity"
|
||||
android:name=".activities.FilterActivity"
|
||||
android:label="@string/filters"
|
||||
android:theme="@style/AppThemeBar"
|
||||
android:theme="@style/AppThemeBarDark"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
<activity
|
||||
android:name=".mastodon.activities.EditProfileActivity"
|
||||
android:name=".activities.EditProfileActivity"
|
||||
android:label="@string/edit_profile"
|
||||
android:theme="@style/AppThemeBar"
|
||||
android:theme="@style/AppThemeBarDark"
|
||||
android:windowSoftInputMode="stateVisible" />
|
||||
|
||||
<activity
|
||||
android:name=".mastodon.activities.CacheActivity"
|
||||
android:name=".activities.CacheActivity"
|
||||
android:label="@string/action_cache"
|
||||
android:theme="@style/AppThemeBar" />
|
||||
|
||||
<activity android:name=".activities.WebActivityPub"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="web+ap" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
android:theme="@style/AppThemeBarDark" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
|
@ -285,476 +224,24 @@
|
|||
</provider>
|
||||
|
||||
<receiver
|
||||
android:name=".mastodon.broadcastreceiver.ToastMessage"
|
||||
android:name=".broadcastreceiver.ToastMessage"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="RECEIVE_TOAST_MESSAGE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name=".mastodon.services.PushServiceImpl"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.unifiedpush.android.connector.PUSH_EVENT"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
|
||||
<activity
|
||||
android:name=".peertube.activities.PeertubeMainActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".peertube.activities.PeertubeActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:launchMode="singleTask"
|
||||
android:resizeableActivity="true"
|
||||
android:supportsPictureInPicture="true"
|
||||
tools:targetApi="n" />
|
||||
<activity
|
||||
android:name=".peertube.activities.PeertubeEditUploadActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="false"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
|
||||
<activity
|
||||
android:name=".peertube.activities.ShowChannelActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.ShowAccountActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.AccountActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.MyAccountActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.SearchActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.AllPlaylistsActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.AllLocalPlaylistsActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.PlaylistsActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.VideosTimelineActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.SepiaSearchActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/sepia_search"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.ManageInstancesActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/instances_picker"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.WebviewActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize" />
|
||||
<activity
|
||||
android:name=".peertube.activities.LoginActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:exported="true"
|
||||
android:windowSoftInputMode="stateAlwaysHidden">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:host="backtotubelab"
|
||||
android:scheme="tubelab" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".peertube.activities.SettingsActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/settings"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name=".peertube.activities.PeertubeUploadActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:label="@string/upload_video"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
|
||||
<service
|
||||
android:name=".peertube.services.RetrieveInfoService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name="androidx.work.impl.foreground.SystemForegroundService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
tools:node="merge" />
|
||||
|
||||
<!-- ============ -->
|
||||
<!-- CUSTOM ICONS -->
|
||||
<!-- ============ -->
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Bubbles"
|
||||
<receiver
|
||||
android:name=".services.CustomReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<action android:name="org.unifiedpush.android.connector.MESSAGE" />
|
||||
<action android:name="org.unifiedpush.android.connector.UNREGISTERED" />
|
||||
<action android:name="org.unifiedpush.android.connector.NEW_ENDPOINT" />
|
||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_FAILED" />
|
||||
<action android:name="org.unifiedpush.android.connector.REGISTRATION_REFUSED" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BubblesUA"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles_ua"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_ua_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BubblesPeaGreen"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles_pea_green"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_pea_green_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BubblesPride"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles_pride"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_pride_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BubblesPink"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles_pink"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_pink_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BubblesPirate"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_bubbles_pirate"
|
||||
android:roundIcon="@mipmap/ic_launcher_bubbles_pirate_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Fediverse"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_fediverse"
|
||||
android:roundIcon="@mipmap/ic_launcher_fediverse_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Hero"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_hero"
|
||||
android:roundIcon="@mipmap/ic_launcher_hero_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Atom"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_atom"
|
||||
android:roundIcon="@mipmap/ic_launcher_atom_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.BrainCrash"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_crash"
|
||||
android:roundIcon="@mipmap/ic_launcher_crash_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Mastalab"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_mastalab"
|
||||
android:roundIcon="@mipmap/ic_launcher_mastalab_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Leaf"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_leaf"
|
||||
android:roundIcon="@mipmap/ic_launcher_leaf_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Offset"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_offset"
|
||||
android:roundIcon="@mipmap/ic_launcher_offset_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Jungle"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_jungle"
|
||||
android:roundIcon="@mipmap/ic_launcher_jungle_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Confetti"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_confetti"
|
||||
android:roundIcon="@mipmap/ic_launcher_confetti_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Spaghetti"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_spaghetti"
|
||||
android:roundIcon="@mipmap/ic_launcher_spaghetti_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Warm"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_warm"
|
||||
android:roundIcon="@mipmap/ic_launcher_warm_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Purple1"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_purple_1"
|
||||
android:roundIcon="@mipmap/ic_launcher_purple_1_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Purple2"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_purple_2"
|
||||
android:roundIcon="@mipmap/ic_launcher_purple_2_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.YellowHeadedRedBubble"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_yellow_headed_red_bubble"
|
||||
android:roundIcon="@mipmap/ic_launcher_yellow_headed_red_bubble_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
|
||||
<activity-alias
|
||||
android:name=".activities.MainActivity.Mosaic"
|
||||
android:enabled="false"
|
||||
android:exported="true"
|
||||
android:icon="@mipmap/ic_launcher_mosaic"
|
||||
android:roundIcon="@mipmap/ic_launcher_mosaic_round"
|
||||
android:targetActivity=".activities.MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/compose_shortcuts" />
|
||||
</activity-alias>
|
||||
</receiver>
|
||||
</application>
|
||||
</manifest>
|
||||
</manifest>
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"1": "Music",
|
||||
"2": "Films",
|
||||
"3": "Vehicles",
|
||||
"4": "Art",
|
||||
"5": "Sports",
|
||||
"6": "Travels",
|
||||
"7": "Gaming",
|
||||
"8": "People",
|
||||
"9": "Comedy",
|
||||
"10": "Entertainment",
|
||||
"11": "News & Politics",
|
||||
"12": "How To",
|
||||
"13": "Education",
|
||||
"14": "Activism",
|
||||
"15": "Science & Technology",
|
||||
"16": "Animals",
|
||||
"17": "Kids",
|
||||
"18": "Food"
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
{
|
||||
"aa": "Afar",
|
||||
"ab": "Abkhazian",
|
||||
"af": "Afrikaans",
|
||||
"ak": "Akan",
|
||||
"am": "Amharic",
|
||||
"ar": "Arabic",
|
||||
"an": "Aragonese",
|
||||
"ase": "American Sign Language",
|
||||
"as": "Assamese",
|
||||
"av": "Avaric",
|
||||
"avk": "Kotava",
|
||||
"ay": "Aymara",
|
||||
"az": "Azerbaijani",
|
||||
"ba": "Bashkir",
|
||||
"bm": "Bambara",
|
||||
"be": "Belarusian",
|
||||
"bn": "Bengali",
|
||||
"bfi": "British Sign Language",
|
||||
"bi": "Bislama",
|
||||
"bo": "Tibetan",
|
||||
"bs": "Bosnian",
|
||||
"br": "Breton",
|
||||
"bg": "Bulgarian",
|
||||
"bzs": "Brazilian Sign Language",
|
||||
"ca": "Catalan",
|
||||
"cs": "Czech",
|
||||
"ch": "Chamorro",
|
||||
"ce": "Chechen",
|
||||
"cv": "Chuvash",
|
||||
"kw": "Cornish",
|
||||
"co": "Corsican",
|
||||
"cr": "Cree",
|
||||
"cse": "Czech Sign Language",
|
||||
"csl": "Chinese Sign Language",
|
||||
"cy": "Welsh",
|
||||
"da": "Danish",
|
||||
"de": "German",
|
||||
"dv": "Dhivehi",
|
||||
"dsl": "Danish Sign Language",
|
||||
"dz": "Dzongkha",
|
||||
"el": "Greek",
|
||||
"en": "English",
|
||||
"eo": "Esperanto",
|
||||
"et": "Estonian",
|
||||
"eu": "Basque",
|
||||
"ee": "Ewe",
|
||||
"fo": "Faroese",
|
||||
"fa": "Persian",
|
||||
"fj": "Fijian",
|
||||
"fi": "Finnish",
|
||||
"fr": "French",
|
||||
"fy": "Western Frisian",
|
||||
"fsl": "French Sign Language",
|
||||
"ff": "Fulah",
|
||||
"gd": "Scottish Gaelic",
|
||||
"ga": "Irish",
|
||||
"gl": "Galician",
|
||||
"gv": "Manx",
|
||||
"gn": "Guarani",
|
||||
"gsg": "German Sign Language",
|
||||
"gu": "Gujarati",
|
||||
"ht": "Haitian",
|
||||
"ha": "Hausa",
|
||||
"sh": "Serbo-Croatian",
|
||||
"he": "Hebrew",
|
||||
"hz": "Herero",
|
||||
"hi": "Hindi",
|
||||
"ho": "Hiri Motu",
|
||||
"hr": "Croatian",
|
||||
"hu": "Hungarian",
|
||||
"hy": "Armenian",
|
||||
"ig": "Igbo",
|
||||
"ii": "Sichuan Yi",
|
||||
"iu": "Inuktitut",
|
||||
"id": "Indonesian",
|
||||
"ik": "Inupiaq",
|
||||
"is": "Icelandic",
|
||||
"it": "Italian",
|
||||
"jv": "Javanese",
|
||||
"jbo": "Lojban",
|
||||
"ja": "Japanese",
|
||||
"jsl": "Japanese Sign Language",
|
||||
"kab": "Kabyle",
|
||||
"kl": "Kalaallisut",
|
||||
"kn": "Kannada",
|
||||
"ks": "Kashmiri",
|
||||
"ka": "Georgian",
|
||||
"kr": "Kanuri",
|
||||
"kk": "Kazakh",
|
||||
"km": "Khmer",
|
||||
"ki": "Kikuyu",
|
||||
"rw": "Kinyarwanda",
|
||||
"ky": "Kirghiz",
|
||||
"kv": "Komi",
|
||||
"kg": "Kongo",
|
||||
"ko": "Korean",
|
||||
"kj": "Kuanyama",
|
||||
"ku": "Kurdish",
|
||||
"lo": "Lao",
|
||||
"la": "Latin",
|
||||
"lv": "Latvian",
|
||||
"li": "Limburgan",
|
||||
"ln": "Lingala",
|
||||
"lt": "Lithuanian",
|
||||
"lb": "Luxembourgish",
|
||||
"lu": "Luba-Katanga",
|
||||
"lg": "Ganda",
|
||||
"mh": "Marshallese",
|
||||
"ml": "Malayalam",
|
||||
"mr": "Marathi",
|
||||
"mk": "Macedonian",
|
||||
"mg": "Malagasy",
|
||||
"mt": "Maltese",
|
||||
"mn": "Mongolian",
|
||||
"mi": "Maori",
|
||||
"ms": "Malay (macrolanguage)",
|
||||
"my": "Burmese",
|
||||
"na": "Nauru",
|
||||
"nv": "Navajo",
|
||||
"nr": "South Ndebele",
|
||||
"nd": "North Ndebele",
|
||||
"ng": "Ndonga",
|
||||
"ne": "Nepali (macrolanguage)",
|
||||
"nl": "Dutch",
|
||||
"nn": "Norwegian Nynorsk",
|
||||
"nb": "Norwegian Bokmål",
|
||||
"no": "Norwegian",
|
||||
"ny": "Nyanja",
|
||||
"oc": "Occitan",
|
||||
"oj": "Ojibwa",
|
||||
"or": "Oriya (macrolanguage)",
|
||||
"om": "Oromo",
|
||||
"os": "Ossetian",
|
||||
"pa": "Panjabi",
|
||||
"pks": "Pakistan Sign Language",
|
||||
"pl": "Polish",
|
||||
"pt": "Portuguese",
|
||||
"ps": "Pushto",
|
||||
"qu": "Quechua",
|
||||
"rm": "Romansh",
|
||||
"ro": "Romanian",
|
||||
"rsl": "Russian Sign Language",
|
||||
"rn": "Rundi",
|
||||
"ru": "Russian",
|
||||
"sg": "Sango",
|
||||
"sdl": "Saudi Arabian Sign Language",
|
||||
"sfs": "South African Sign Language",
|
||||
"si": "Sinhala",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"se": "Northern Sami",
|
||||
"sm": "Samoan",
|
||||
"sn": "Shona",
|
||||
"sd": "Sindhi",
|
||||
"so": "Somali",
|
||||
"st": "Southern Sotho",
|
||||
"es": "Spanish",
|
||||
"sq": "Albanian",
|
||||
"sc": "Sardinian",
|
||||
"sr": "Serbian",
|
||||
"ss": "Swati",
|
||||
"su": "Sundanese",
|
||||
"sw": "Swahili (macrolanguage)",
|
||||
"sv": "Swedish",
|
||||
"swl": "Swedish Sign Language",
|
||||
"ty": "Tahitian",
|
||||
"ta": "Tamil",
|
||||
"tt": "Tatar",
|
||||
"te": "Telugu",
|
||||
"tg": "Tajik",
|
||||
"tl": "Tagalog",
|
||||
"th": "Thai",
|
||||
"ti": "Tigrinya",
|
||||
"tlh": "Klingon",
|
||||
"to": "Tonga (Tonga Islands)",
|
||||
"tn": "Tswana",
|
||||
"ts": "Tsonga",
|
||||
"tk": "Turkmen",
|
||||
"tr": "Turkish",
|
||||
"tw": "Twi",
|
||||
"ug": "Uighur",
|
||||
"uk": "Ukrainian",
|
||||
"ur": "Urdu",
|
||||
"uz": "Uzbek",
|
||||
"ve": "Venda",
|
||||
"vi": "Vietnamese",
|
||||
"wa": "Walloon",
|
||||
"wo": "Wolof",
|
||||
"xh": "Xhosa",
|
||||
"yi": "Yiddish",
|
||||
"yo": "Yoruba",
|
||||
"za": "Zhuang",
|
||||
"zh": "Chinese",
|
||||
"zu": "Zulu",
|
||||
"zxx": "No linguistic content",
|
||||
"zh-Hans": "Simplified Chinese",
|
||||
"zh-Hant": "Traditional Chinese"
|
||||
}
|
|
@ -381,7 +381,7 @@
|
|||
},
|
||||
{
|
||||
"code": "lo",
|
||||
"language": "ລາວ"
|
||||
"language": "ພາສາ"
|
||||
},
|
||||
{
|
||||
"code": "lt",
|
||||
|
@ -726,109 +726,5 @@
|
|||
{
|
||||
"code": "zu",
|
||||
"language": "isiZulu"
|
||||
},
|
||||
{
|
||||
"code": "ast",
|
||||
"language": "Asturianu"
|
||||
},
|
||||
{
|
||||
"code": "ckb",
|
||||
"language": "سۆرانی"
|
||||
},
|
||||
{
|
||||
"code": "cnr",
|
||||
"language": "crnogorski"
|
||||
},
|
||||
{
|
||||
"code": "jbo",
|
||||
"language": "la .lojban."
|
||||
},
|
||||
{
|
||||
"code": "kab",
|
||||
"language": "Taqbaylit"
|
||||
},
|
||||
{
|
||||
"code": "kmr",
|
||||
"language": "Kurmancî"
|
||||
},
|
||||
{
|
||||
"code": "ldn",
|
||||
"language": "Láadan"
|
||||
},
|
||||
{
|
||||
"code": "lfn",
|
||||
"language": "lingua franca nova"
|
||||
},
|
||||
{
|
||||
"code": "sco",
|
||||
"language": "Scots"
|
||||
},
|
||||
{
|
||||
"code": "sma",
|
||||
"language": "Åarjelsaemien Gïele"
|
||||
},
|
||||
{
|
||||
"code": "smj",
|
||||
"language": "Julevsámegiella"
|
||||
},
|
||||
{
|
||||
"code": "szl",
|
||||
"language": "ślůnsko godka"
|
||||
},
|
||||
{
|
||||
"code": "tai",
|
||||
"language": "ภาษาไท or ภาษาไต"
|
||||
},
|
||||
{
|
||||
"code": "tok",
|
||||
"language": "toki pona"
|
||||
},
|
||||
{
|
||||
"code": "zba",
|
||||
"language": "باليبلن"
|
||||
},
|
||||
{
|
||||
"code": "zgh",
|
||||
"language": "ⵜⴰⵎⴰⵣⵉⵖⵜ"
|
||||
},
|
||||
{
|
||||
"code": "en-GB",
|
||||
"language": "English (British)"
|
||||
},
|
||||
{
|
||||
"code": "es-AR",
|
||||
"language": "Español (Argentina)"
|
||||
},
|
||||
{
|
||||
"code": "es-MX",
|
||||
"language": "Español (México)"
|
||||
},
|
||||
{
|
||||
"code": "fr-QC",
|
||||
"language": "Français (Canadien)"
|
||||
},
|
||||
{
|
||||
"code": "pt-BR",
|
||||
"language": "Português (Brasil)"
|
||||
},
|
||||
{
|
||||
"code": "pt-PT",
|
||||
"language": "Português (Portugal)"
|
||||
},
|
||||
{
|
||||
"code": "sr-Latn",
|
||||
"language": "Srpski (latinica)"
|
||||
},
|
||||
{
|
||||
"code": "zh-CN",
|
||||
"language": "简体中文"
|
||||
},
|
||||
{
|
||||
"code": "zh-HK",
|
||||
"language": "繁體中文(香港)"
|
||||
},
|
||||
{
|
||||
"code": "zh-TW",
|
||||
"language": "繁體中文(臺灣)"
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load diff
|
@ -1,298 +0,0 @@
|
|||
[
|
||||
{
|
||||
"version": "3.33.1",
|
||||
"code": "534",
|
||||
"note": "Added:\n- Highlight bottom hashtags\n- Support Trending Links\n- Featured tags displayed in profiles\n- Add/Remove featured tags from the profile editor\n\nChanged:\n- Add confirmation dialog when long pressing the boost button\n- Open messages by tapping on Scheduled Boost\n- Improve language picker when filtered with some languages\n\nFixed:\n- Limits number of fetch for filters\n- Pleroma instances cannot select media\n- Wrong messages deleted for scheduled (messages and boosts)\n- Fix a crash with long threads\n- Fix a potential memory issue for not cropped media\n- Fix embedded quotes not displayed\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.32.3",
|
||||
"code": "532",
|
||||
"note": "Fixed:\n- Polls not displayed\n- Pagination with trends\n- Push notifications not working on some devices"
|
||||
},
|
||||
{
|
||||
"version": "3.32.2",
|
||||
"code": "531",
|
||||
"note": "Added:\n- An outline around media\n\nChanged:\n- Make username, display name in nav drawer clickable\n- Gif media not animated by default\n- Disable by default the mention to the booster when replying. Can be enabled in Settings > Compose (per account)\n\nFixed:\n- Wrong preview picture on share from another app\n- Crash when translating with MinT\n- Refresh and pagination broken for the Trending timeline\n- Fix lags / Crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.32.1",
|
||||
"code": "530",
|
||||
"note": "Fixed:\n- Fix a crash on some devices\n- Hide quote button\n- Fix a layout issue with pictures in landscape\n- Fix a crash when opening the original message from a picture"
|
||||
},
|
||||
{
|
||||
"version": "3.32.0",
|
||||
"code": "529",
|
||||
"note": "Added:\n- Add option to disable auto hiding compose button\n\nChanged:\n- Add more content descriptions for buttons\n- Update some buttons\n- Update navigation drawer header\n- Squeeze action buttons when needed to prevent overlapping\n\nFixed:\n- Fix crash when media are too heavy\n- Some custom emojis in bio do not render\n- Posting messages does not work on some Friendica instances\n- Fix a crash with auto-split messages\n- Fix a crash when opening conversations\n- Fix a background color issue when displaying media"
|
||||
},
|
||||
{
|
||||
"version": "3.31.3",
|
||||
"code": "528",
|
||||
"note": "Added:\n- Add new icon launchers (Settings > Interface)\n\nChanged:\n- Make logout/proxy button more visible in main menu\n- Remove permission FOREGROUND_SERVICE\n- Improve a little more media layout with translations\n\nFixed:\n- Fix status bar icons not visible in light theme with custom accent color\n- Reaction buttons not clickable for some instances"
|
||||
},
|
||||
{
|
||||
"version": "3.31.2",
|
||||
"code": "527",
|
||||
"note": "Added:\n- Add support to URL scheme \"web+ap\" for opening profiles with the app\n\nChanged:\n- Layout for media descriptions\n\nFixed:\n- Fix a crash when translating media descriptions\n- Handle included twice when replying to a self user's boost\n- Fix color issues when using a custom theme"
|
||||
},
|
||||
{
|
||||
"version": "3.31.1",
|
||||
"code": "526",
|
||||
"note": "Added:\n- Add MinT machine translation system support\n- Add support \"instance only\" for GoToSocial\n\nFixed:\n- GIF not displayed in timelines\n- Fix a crash when unpinning timelines\n- Top bar coloring at scroll for conversations\n- Black screen when going back from the Peertube section"
|
||||
},
|
||||
{
|
||||
"version": "3.31.0",
|
||||
"code": "524",
|
||||
"note": "Added:\n- Pinned Trending Timeline (can be hidden in Manage Timelines)\n- Add a fallback to the default translator\n- New Pixelfed entry in Settings to disable fullscreen for media\n- Add tooltips for tabs in profiles\n\nChanged:\n- Increase touch area of reply buttons\n- Show a dialog after settings export\n\nFixed:\n- Fix media description not updated when there are several\n- Only a part of DeepL translations are shown\n- Fix Lingva truncated translations\n- Fix a crash when fetching remote profiles\n- Fix a crash with animated emoji\n- Fix a crash when displaying Home cache charts"
|
||||
},
|
||||
{
|
||||
"version": "3.30.1",
|
||||
"code": "523",
|
||||
"note": "Added:\n- Follow Twitter tags\n\nChange:\n- Remove automatic backup (Google only)\n\nFixed:\n- Push notifications not working for some devices\n- Filters not applied to media description\n- Fix a crash with animated images in timelines\n- Fix a crash for long threads\n- Fix a crash due to some messages (happened in different timelines)"
|
||||
},
|
||||
{
|
||||
"version": "3.30.0",
|
||||
"code": "522",
|
||||
"note": "Added:\n- Allow to follow the discover timelines of Pixelfed instances\n- Keep media proportions in timeline for Pixelfed\n- Add a like button in timelines for Pixelfed\n- Allow to login with a token\n\nChange:\n- Use Pixelfed layout when following Pixelfed instances\n- Allow to scroll buttons for larger screens in conversations\n- Move QR code into header\n\nFixed:\n- Not clickable URLs when Markdown is enabled\n- Nitter to follow Twitter accounts\n- Pixelfed timeline not displayed by default\n- Fix admin reports not accessible\n- Top bar coloring at scroll\n- Drafts not saved when adding/editing media descriptions\n- User search suggestions have duplicates\n- Some minor crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.29.2",
|
||||
"code": "518",
|
||||
"note": "Fixed:\n- Fix crash when changing the type of notifications\n- Fix issue with names not displayed fully\n- Fix a crash with notifications and Sharkey\n- Fix a crash when app is back to the foreground\n- Fix xmpp links not opening xmpp clients\n- Fix wrong muted time"
|
||||
},
|
||||
{
|
||||
"version": "3.29.1",
|
||||
"code": "517",
|
||||
"note": "Added:\n- Allow to edit scheduled messages from server side\n\nChanged:\n- Order list name alphabetically in profiles\n- Remove registration for Google\n\nFixed:\n- Push notifications\n- Peertube instances picker\n- Edit scheduled threads (local)\n- Instant search of Hashtag repeats results\n- Quotes broken with Markdowns\n- Fix reports crashes after submitting\n- Fix emoji picker when there is no result\n- Fix other crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.28.2",
|
||||
"code": "515",
|
||||
"note": "Added:\n- Display a QR code on profiles\n\nFixed:\n- Fix tap on messages in conversations\n- Pronouns taking too much place"
|
||||
},
|
||||
{
|
||||
"version": "3.28.1",
|
||||
"code": "514",
|
||||
"note": "Added:\n- Allow to disable pronouns support (default: enabled)\n- Add more support for pronouns (localization in different languages)\n\nFixed:\n- Fix a crash when reporting messages\n- Fix a crash when following tags\n- Fix some display issues\n- Several fixes from the last release (3.28.0)"
|
||||
},
|
||||
{
|
||||
"version": "3.28.0",
|
||||
"code": "513",
|
||||
"note": "Added:\n- Pronouns support (Timeline/Compose/Autocomplete)\n\nChanged:\n- Use Media3 library\n\nFixed:\n- Timed mute duration too long\n- Sharing videos only download them\n- Crashes from previous release"
|
||||
},
|
||||
{
|
||||
"version": "3.27.1",
|
||||
"code": "511",
|
||||
"note": "Added:\n- Tap on account banners to display them as media\n\nFixed:\n- Position lost when switching between accounts\n- Wrong profiles when enabling remote conversations\n- Peertube local timeline\n- Peertube instances search\n- Crashes of the previous release"
|
||||
},
|
||||
{
|
||||
"version": "3.27.0",
|
||||
"code": "510",
|
||||
"note": "Added:\n- Fixed top bar (default: disabled)\n- Usage frequency of tags when composing\n\nChanged:\n- Markdown support disabled by default\n\nFixed:\n- Fix crashes during interactions or when opening a new screen\n- Fix color of dialogs in Settings\n- Some minor crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.26.0",
|
||||
"code": "505",
|
||||
"note": "Added:\n- Android 14 support\n- Automatically split long messages in threads (default: ASK)\n- Links and media are clickable when composing\n- Allow to underline clickable elements (Settings > Timelines - default: disabled)\n- Allow to disable relative date in messages\n- Add a scroll bar for timelines (default: disabled)\n- Add a search bar for custom emojis\n- Links clickable in media descriptions\n\nChanged:\n- Counters close to action buttons\n- Hide emoji picker if the instance has no emoji\n- Followed tags are ordered\n- Account picker when opening with another account\n\nFixed:\n- Avoid error 429 with NTFY\n- Fix custom colors (Android 14)\n- Fix a crash when composing\n- Display issue with followed tags\n- Crashes with profiles\n- Fix an issue with poll and Pleroma\n- Emoji not displayed in the picker\n- Several crashes are fixed"
|
||||
},
|
||||
{
|
||||
"version": "3.25.3",
|
||||
"code": "504",
|
||||
"note": "Added:\n- Add a scroll bar for timelines (default: disabled)\n- Add a search bar for custom emojis\n\nFixed:\n- Fix prompt to split asked several times when refusing\n- Crashes with profiles\n- Fix an issue with poll and Pleroma\n- Emoji not displayed in the picker"
|
||||
},
|
||||
{
|
||||
"version": "3.25.2",
|
||||
"code": "503",
|
||||
"note": "Added:\n- Allow to underline clickable elements (Settings > Timelines - default: disabled)\n- Allow to disable relative date in messages\n\nChanged:\n- Counters close to action buttons\n- Hide emoji picker if the instance has no emoji\n- Followed tags are ordered\n- Account picker when opening with another account\n\nFixed:\n- Fix a crash when composing\n- Fix an issue with the back button\n- Display issue with followed tags"
|
||||
},
|
||||
{
|
||||
"version": "3.25.1",
|
||||
"code": "502",
|
||||
"note": "Fix a crash from release 3.25.0"
|
||||
},
|
||||
{
|
||||
"version": "3.25.0",
|
||||
"code": "501",
|
||||
"note": "Added:\n- Android 14 support\n- Automatically split long messages in threads (default: ASK)\n- Links and media are clickable when composing\n\nFixed:\n- Avoid error 429 with NTFY\n- Several crashes are fixed"
|
||||
},
|
||||
{
|
||||
"version": "3.24.1",
|
||||
"code": "500",
|
||||
"note": "Added:\n- Three new app icons (Pride, Pink and Pirate)\n- Keep position with remote conversations\n\nFixed:\n- Markdown: stop parsing tags and support strike text\n- Cursor more visible when composing\n- Fix custom instance max char length not working\n- Tabs in profiles\n- Fix not clickable tags for some languages\n- Bug with account having huge amount of followers\n- Crash with several gif in same message\n- Poll max chars\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.24.0",
|
||||
"code": "499",
|
||||
"note": "Added:\n- Markdown support (can be disabled in Settings > Timelines)\n- Hide / Show Self boosts, self replies and your own messages (Long press the Home tab)\n\nChanged:\n- Full screen size when writing media descriptions.\n- Move media descriptions to the top\n\nFixed:\n- Holes in timelines due to a cache bug\n- Spoiler issue when composing threads\n- CamelCase tags when forwarding them in replies\n- Buttons hidden by keyboard when composing\n- Overlay with menu and buttons when playing videos\n- Clicks on card do not open Mastodon posts inside the app\n- Scrollable bio when editing profiles\n- Crash when adding a user into a list\n- Longer fields when editing bio\n- Crash with Pixelfed\n"
|
||||
},
|
||||
{
|
||||
"version": "3.23.5",
|
||||
"code": "498",
|
||||
"note": "Added:\n- Hide / Show Self boosts and self replies (Long press the Home tab)\n\nChanged:\n- Full screen size when writing media descriptions."
|
||||
},
|
||||
{
|
||||
"version": "3.23.4",
|
||||
"code": "497",
|
||||
"note": "Fixed:\n\n- Holes in timelines due to a cache bug\n- Fix tags issue with RTL and the markdown format\n- Scrollable bio when editing profiles\n- Crash when adding a user into a list"
|
||||
},
|
||||
{
|
||||
"version": "3.23.3",
|
||||
"code": "496",
|
||||
"note": "- Longer fields when editing bio\n- Clicks on card do not open Mastodon posts inside the app\n- Crash with Pixelfed\n- Line breaks with Markdown\n- Side effects with Markdown and some links"
|
||||
},
|
||||
{
|
||||
"version": "3.23.2",
|
||||
"code": "495",
|
||||
"note": "Added:\n- Markdown support (can be disabled in Settings > Timelines)"
|
||||
},
|
||||
{
|
||||
"version": "3.23.1",
|
||||
"code": "494",
|
||||
"note": "Added:\n- Scrollable media description\n\nFixed:\n- Crashes with profiles"
|
||||
},
|
||||
{
|
||||
"version": "3.23.0",
|
||||
"code": "493",
|
||||
"note": "Added:\n- Add preview for app icons\n- Two new app icons\n\nFixed:\n- Fix Nitter feeds\n- Crash with Pixelfed accounts\n- Lingva encoding issue\n- Avoid sleep mode for media activity\n- Videos are played simultaneously\n- Voice messages for Android 10+\n- Punycode not supported for domains"
|
||||
},
|
||||
{
|
||||
"version": "3.22.2",
|
||||
"code": "492",
|
||||
"note": "Added:\n- Follow Lemmy instances (from Manage Timelines)\n- View remote conversations (default: disabled - Settings > Interface)\n\nFixed:\n- Add 50 chars max for poll options\n- Too many requests\n- Blank Home page\n- Crashes when visiting profiles\n- Some audio files cannot be uploaded\n- Multiple notifications\n- Fix some other crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.22.1",
|
||||
"code": "491",
|
||||
"note": "Added:\n- Follow Lemmy instance (from Manage Timelines)\nFixed:\n- Add 50 chars max for poll options"
|
||||
},
|
||||
{
|
||||
"version": "3.22.0",
|
||||
"code": "490",
|
||||
"note": "Fixed:\n- Too many requests\n- Blank Home page\n- Crashes when visiting profiles\n- Some audio files cannot be uploaded"
|
||||
},
|
||||
{
|
||||
"version": "3.21.2",
|
||||
"code": "489",
|
||||
"note": "Added:\n- Android 12+ : Customize accent colors for light/dark theme and per account (Settings > Theming > Custom accent color)\n"
|
||||
},
|
||||
{
|
||||
"version": "3.21.1",
|
||||
"code": "488",
|
||||
"note": "Added:\n- Filter messages in profiles (hide/show boosts or replies) via a long press on the tab\n\nChanged:\n- Some layout improvements for Peertube\n- Better management of resolution with Peertube\n- Improve instance picker for Peertube\n\nFixed:\n- URL in upper cases\n- Issues with Peertube player\n- False positive error when listening to audio\n- GIF does not honor nsfw\n- Polls having html\n- Fix crashes when scrolling timeline with animated gif"
|
||||
},
|
||||
{
|
||||
"version": "3.21.0",
|
||||
"code": "487",
|
||||
"note": "Added:\n- Dedicated Peertube entry in main menu (My app)\n- Select instances (Instances picker with Filters)\n- Comment/Boost/Fav Peertube videos with Mastodon accounts\n\nFixed:\n- Fix a crash when searching and with the user directory"
|
||||
},
|
||||
{
|
||||
"version": "3.20.3",
|
||||
"code": "486",
|
||||
"note": "Added:\n- Display all following/followers lists from remote profiles\n- Display all accounts that boosted/fav from a remote message\n\nFixed:\n- Fix a crash with auto-fetch messages"
|
||||
},
|
||||
{
|
||||
"version": "3.20.2",
|
||||
"code": "485",
|
||||
"note": "Added:\n- Visual indicator when fetching missing messages\n- Open media description when it is missing from the warning dialog\n\nChanged:\n- Maths formula aligned to the left\n- Faster access to delete all notifications\n\nFixed:\n- Fix an issue with Nitter and some URLs\n- Fix refresh issue with notifications\n- Fix an issue when entering a Peertube instance\n- Fix jumps with Akkoma/Pleroma when media preview size is not set\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.20.1",
|
||||
"code": "484",
|
||||
"note": "Added:\n- Add a button to fetch remote media when it fails\n- Add a settings to automatically fetch remote media when it fails (default: disabled)\n- Display on profiles & list of accounts if users have requested to follow you\n- Warn before boosting a message having no media descriptions (default: enabled)\n\nChanged:\n- Warn when there are missing descriptions enabled by default\n\nFixed:\n- Some settings not properly restored (multiple choices)\n- Cancel a follow request\n- Media with a lot of height in landscape\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.20.0",
|
||||
"code": "483",
|
||||
"note": "Added:\n- \"Follows you\" indicator in accounts list\n- Settings compose: display a dialog to warn if there are missing media description (default: disabled)\n- Settings > Cache: disable battery optimization\n- Settings > Cache - Add charts to check cache logs\n- Settings > Timelines: AutoPlay gif media (default: enabled)\n- Google: Automatic backup of data and settings\n\nChanged:\n- Improve detections of gap in timelines\n- Improve media description\n- Chat view by default\n- Chat view add an indicator for messages when not direct\n\nFixed:\n- Fix an issue with cache and fetch more\n- Cache view with large fonts\n- Bad behaviors with truncated messages"
|
||||
},
|
||||
{
|
||||
"version": "3.19.1",
|
||||
"code": "482",
|
||||
"note": "Added:\n- Settings compose: display a dialog to warn if there are missing media description (default disabled)\n- Settings > Notification: disable battery optimization\n- Settings > Timelines: AutoPlay gif media (default: enabled)\n\nFixed:\n- Fix an issue with cache and fetch more\n- Cache view with large fonts\n- Bad behaviors with truncated messages"
|
||||
},
|
||||
{
|
||||
"version": "3.19.0",
|
||||
"code": "481",
|
||||
"note": "Added:\n- Settings compose: don't send media if there are no description (default: disabled)\n- Settings Timelines: Enable/Disable truncate links\n- Allow to set max link length (20 - 150 chars)\n\nChanged:\n- Align media with text (left margin enabled)\n\nFixed:\n- Media previews remain the same when sharing\n- Edit media description not working\n- Accessibility (larger fonts): profiles/DM\n- Cross replies: Wrong visibility with the selected account\n- Several crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.18.2",
|
||||
"code": "480",
|
||||
"note": "Changed:\n- First media layout will depend of its ratio\n\nFixed:\n- Impossible to add media with the chat view\n- Chat view limited in chars\n- Freezes / bad behaviors due to the new media presentation"
|
||||
},
|
||||
{
|
||||
"version": "3.18.1",
|
||||
"code": "479",
|
||||
"note": "Added:\n- Add Lingva translator (Settings > Timelines)\n- Add support for Nyastodon-style emoji reactions (skyevg)\n- Add chat view for DM (default: disable / Settings > Timelines)"
|
||||
},
|
||||
{
|
||||
"version": "3.18.0",
|
||||
"code": "478",
|
||||
"note": "Added:\n- Support camel case tags (automatically recorded when composing)\n- Manage tags when composing (top right menu)\n- Custom tabs (default: enabled)\n\nChanged:\n- Media heights now use the screen size\n- Remove horizontal scroll for media\n- Reduce size of emoji when text size is increased\n- Update available languages in picker\n\nFixed:\n- Forwarded tags are added back after being deleted\n- TalkBack issues\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.17.0",
|
||||
"code": "477",
|
||||
"note": "Added:\n- Peertube 2FA support\n- Cache home in background (default disabled -> New settings category and per account) / change frequency\n- Auto-fetch missing messages for the Home (default disabled -> in Settings - Timelines)\n- Automatically switch between tabs when searching\n- More deep links detection\n- Allow to group mentions at the top (default: disabled)\n\n\nFixed:\n- Dynamic color for Android 12+\n- Missing media description for previews\n- Fix a crash when replying\n- Fix button size not changed\n- Forward tags in replies\n- Media cannot be downloaded or shared with Android 10\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.16.4",
|
||||
"code": "476",
|
||||
"note": "Added:\n- Cache home in background (default disabled -> New settings category and per account) / change frequency\n- Auto-fetch missing messages for the Home (default disabled -> in Settings - Timelines)\n- Automatically switch between tabs when searching\n\nFixed:\n- Some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.16.3",
|
||||
"code": "475",
|
||||
"note": "Added:\n- Peertube 2FA support\n\nFixed:\n- Dynamic color for Android 12+"
|
||||
},
|
||||
{
|
||||
"version": "3.16.2",
|
||||
"code": "474",
|
||||
"note": "Added:\n- Peertube support\n- Compose shortcut (long press launcher)\n- Long press compose button to write with another account\n- Edit description and focus for media (for the next Mastodon release)\n\nChanged:\n- Cross actions with two accounts display a dialog\n- Order & compact og values when sharing > title - url - content\n- Tap on top message (user info) open threads\n\nFixed:\n- Text cleared when adding a media\n- Fix Maths not working with quotes\n- Fix crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.16.1",
|
||||
"code": "473",
|
||||
"note": "Changed:\n- Edit description and focus for media (for the next Mastodon release)\n\nChanged:\n- Peertube: remove role support to avoid crashes with older instances\n\nFixed:\n- Fix some crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.16.0",
|
||||
"code": "472",
|
||||
"note": "Changed:\n- Peertube support\n- Compose shortcut\n- Long press compose button to write with another account\n\nChanged:\n- Cross actions with two accounts display a dialog\n- Order & compact og values when sharing > title - url - content\n\nFixed:\n- Text cleared when adding a media\n- Fix crashes"
|
||||
},
|
||||
{
|
||||
"version": "3.15.2",
|
||||
"code": "471",
|
||||
"note": "Changed:\n- Add instance name when sharing\n\nFixed:\n- Fix a crash when removing media\n- Other minor fixes"
|
||||
},
|
||||
{
|
||||
"version": "3.15.1",
|
||||
"code": "470",
|
||||
"note": "Changed:\n- Material dialogs\n\nFixed:\n- Light theme issues"
|
||||
},
|
||||
{
|
||||
"version": "3.15.0",
|
||||
"code": "469",
|
||||
"note": "Added:\n- Maths support (view and compose)\n- Filter DMs in HOME (long press on the tab)\n- Filter languages for users in home timeline (from their profile)\n- Add several targeted languages for translator\n\nChanged:\n- Hide single media with preview is now a setting (default: disabled)\n- Group items in menu of messages\n\nFixed:\n- Cross-actions didn't display account instances"
|
||||
},
|
||||
{
|
||||
"version": "3.14.6",
|
||||
"code": "468",
|
||||
"note": "Added:\n- Maths support (view and compose)\n\nChanged:\n- Hide single media with preview is now a setting (default: disabled)"
|
||||
},
|
||||
{
|
||||
"version": "3.14.5",
|
||||
"code": "467",
|
||||
"note": "Changed:\n- Allow to swipe media for profiles\n\nFixed:\n- Fix crashes with pinch zoom\n- Copy/Paste in threads\n- Fix crash when checking redirection on http links\n- Display menu in media viewer resets pinch-zoom"
|
||||
},
|
||||
{
|
||||
"version": "3.14.4",
|
||||
"code": "466",
|
||||
"note": "Changed:\n- Media viewer (pinch zoom)\n\nFixed:\n- Cross account actions (long press)\n- Boost color\n- Buttons not visible with custom themes.\n- Fix some bad behaviors with media viewer"
|
||||
},
|
||||
{
|
||||
"version": "3.14.3",
|
||||
"code": "465",
|
||||
"note": "Added:\n- Display date of the message instead of the boost (default: disabled)\n- Allow to disable release notes popup in Settings\n\nFixed:\n- Fix timelines slow down and stuttering after some scrolls\n- Fix color issues with follow buttons\n- Fix import from settings (import from login was OK)"
|
||||
}
|
||||
|
||||
]
|
|
@ -0,0 +1,13 @@
|
|||
base_theme,2
|
||||
author,Fedilab
|
||||
name,Breeze Dark - Yellow
|
||||
theme_boost_header_color,-14012878
|
||||
theme_statuses_color,-14473687
|
||||
theme_link_color,-12734743
|
||||
theme_icons_color,-4340793
|
||||
pref_color_background,-15658735
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-148405
|
||||
theme_text_color,-1052431
|
||||
theme_primary,-13552069
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,Roboron
|
||||
name,Cyberpunk Neon
|
||||
theme_boost_header_color,-16776697,
|
||||
theme_text_header_1_line,-1441575,
|
||||
theme_text_header_2_line,-5242717,
|
||||
theme_statuses_color,-16181197,
|
||||
theme_link_color,-1441575,
|
||||
theme_icons_color,-16138810,
|
||||
pref_color_background,-16774370,
|
||||
pref_color_navigation_bar,true,
|
||||
pref_color_status_bar,true,
|
||||
theme_accent,-1441575,
|
||||
theme_text_color,-16138810,
|
||||
theme_primary,-16774370,
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,Jøta Seth
|
||||
name,Grey Orange
|
||||
theme_boost_header_color,-14869219
|
||||
theme_text_header_1_line,-1
|
||||
theme_text_header_2_line,-1
|
||||
theme_statuses_color,-14145496
|
||||
theme_link_color,-26624
|
||||
theme_icons_color,-26624
|
||||
pref_color_background,-13092808
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-26624
|
||||
theme_text_color,-1
|
||||
theme_primary,-14408668
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,@AntoineD@h.kher.nl
|
||||
name,Gruvbox OLED
|
||||
theme_boost_header_color,-16777216
|
||||
theme_text_header_1_line,-265785
|
||||
theme_text_header_2_line,-6777062
|
||||
theme_statuses_color,-16777216
|
||||
theme_link_color,-2647775
|
||||
theme_icons_color,-7175308
|
||||
pref_color_background,-16777216
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-9921174
|
||||
theme_text_color,-265785
|
||||
theme_primary,-16777216
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,AngryTux
|
||||
name,Less Angry Orange
|
||||
theme_boost_header_color,-15855063
|
||||
theme_text_header_1_line,-2128640
|
||||
theme_text_header_2_line,-5329234
|
||||
theme_statuses_color,-1
|
||||
theme_link_color,-12146699
|
||||
theme_icons_color,-2128640
|
||||
pref_color_background,-15987700
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-3968000
|
||||
theme_text_color,-197380
|
||||
theme_primary,-14408668
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,Mondstern
|
||||
name,Mondstern Fedilab
|
||||
theme_boost_header_color,-1,
|
||||
theme_text_header_1_line,-13855804,
|
||||
theme_text_header_2_line,-16227945,
|
||||
theme_statuses_color,-14935012,
|
||||
theme_link_color,-15542685,
|
||||
theme_icons_color,-10723999,
|
||||
pref_color_background,-15921907,
|
||||
pref_color_navigation_bar,false,
|
||||
pref_color_status_bar,false,
|
||||
theme_accent,-15542685,
|
||||
theme_text_color,-1,
|
||||
theme_primary,-14474461,
|
|
|
@ -0,0 +1,13 @@
|
|||
base_theme,2
|
||||
author,Fedilab
|
||||
name,Nocturnal
|
||||
theme_boost_header_color,-12895429
|
||||
theme_statuses_color,-13553359
|
||||
theme_link_color,-16747570
|
||||
theme_icons_color,-10158118
|
||||
pref_color_background,-14606047
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-13136013
|
||||
theme_text_color,-2236963
|
||||
theme_primary,-14013910
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,Jøta Seth
|
||||
name,Photon Dark
|
||||
theme_boost_header_color,-14145496
|
||||
theme_text_header_1_line,-1
|
||||
theme_text_header_2_line,-1
|
||||
theme_statuses_color,-14935012
|
||||
theme_link_color,-14059009
|
||||
theme_icons_color,-9474193
|
||||
pref_color_background,-15921907
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-14059009
|
||||
theme_text_color,-1
|
||||
theme_primary,-14474461
|
|
|
@ -0,0 +1,15 @@
|
|||
base_theme,2
|
||||
author,Fedilab
|
||||
name,Solarized Dark - Purple
|
||||
theme_boost_header_color,-16506327
|
||||
theme_text_header_1_line,-1120043
|
||||
theme_text_header_2_line,-1120043
|
||||
theme_statuses_color,-16304574
|
||||
theme_link_color,-14251054
|
||||
theme_icons_color,-7102047
|
||||
pref_color_background,-16766154
|
||||
pref_color_navigation_bar,true
|
||||
pref_color_status_bar,true
|
||||
theme_accent,-9670204
|
||||
theme_text_color,-133405
|
||||
theme_primary,-16304574
|
|
47
app/src/main/assets/themes/cyanea_themes.json
Normal file
47
app/src/main/assets/themes/cyanea_themes.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
[
|
||||
{
|
||||
"theme_name": "Dark",
|
||||
"base_theme": "DARK",
|
||||
"primary": "#FF272727",
|
||||
"primary_dark": "#FF272727",
|
||||
"primary_light": "#FFd9e1e8",
|
||||
"accent": "#FF2b90d9",
|
||||
"accent_dark": "#FF1b80c9",
|
||||
"accent_light": "#FF772b90d9",
|
||||
"background": "#FF272727",
|
||||
"background_dark": "#FF282c37",
|
||||
"background_light": "#FF282c37",
|
||||
"should_tint_statusbar": true,
|
||||
"should_tint_navbar": true
|
||||
},
|
||||
{
|
||||
"theme_name": "Light",
|
||||
"base_theme": "LIGHT",
|
||||
"primary": "#FFFFFF",
|
||||
"primary_dark": "#FFFFFFFF",
|
||||
"primary_light": "#FFd9e1e8",
|
||||
"accent": "#FF2b90d9",
|
||||
"accent_dark": "#FF1b80c9",
|
||||
"accent_light": "#FF772b90d9",
|
||||
"background": "#FFFFFFFF",
|
||||
"background_dark": "#FFFFFFFF",
|
||||
"background_light": "#FFFFFFFF",
|
||||
"should_tint_statusbar": true,
|
||||
"should_tint_navbar": true
|
||||
},
|
||||
{
|
||||
"theme_name": "Black",
|
||||
"base_theme": "DARK",
|
||||
"primary": "#FF000000",
|
||||
"primary_dark": "#FF000000",
|
||||
"primary_light": "#FF000000",
|
||||
"accent": "#FF606984",
|
||||
"accent_dark": "#FF606984",
|
||||
"accent_light": "#FF606984",
|
||||
"background": "#FF000000",
|
||||
"background_dark": "#FF000000",
|
||||
"background_light": "#FF000000",
|
||||
"should_tint_statusbar": true,
|
||||
"should_tint_navbar": true
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load diff
|
@ -15,20 +15,16 @@ package app.fedilab.android;
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.os.StrictMode;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import androidx.multidex.MultiDex;
|
||||
import androidx.multidex.MultiDexApplication;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import net.gotev.uploadservice.UploadServiceConfig;
|
||||
import net.gotev.uploadservice.observer.request.GlobalRequestObserver;
|
||||
import com.jaredrummler.cyanea.Cyanea;
|
||||
import com.jaredrummler.cyanea.prefs.CyaneaTheme;
|
||||
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportField;
|
||||
|
@ -37,52 +33,49 @@ import org.acra.config.DialogConfigurationBuilder;
|
|||
import org.acra.config.MailSenderConfigurationBuilder;
|
||||
import org.acra.data.StringFormat;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.List;
|
||||
|
||||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||
import app.fedilab.android.peertube.services.GlobalUploadObserver;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import io.noties.prism4j.annotations.PrismBundle;
|
||||
|
||||
@PrismBundle(includeAll = true, grammarLocatorClassName = ".MySuperGrammerLocator")
|
||||
|
||||
public class MainApplication extends MultiDexApplication {
|
||||
|
||||
public static String UPLOAD_CHANNEL_ID = "upload_info_peertube";
|
||||
private WebView webView;
|
||||
|
||||
private static MainApplication app;
|
||||
|
||||
public static MainApplication getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
try {
|
||||
webView = new WebView(this);
|
||||
} catch (Exception ignored) {
|
||||
app = this;
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(MainApplication.this);
|
||||
|
||||
|
||||
Cyanea.init(this, super.getResources());
|
||||
List<CyaneaTheme> list = CyaneaTheme.Companion.from(getAssets(), "themes/cyanea_themes.json");
|
||||
boolean custom_theme = sharedpreferences.getBoolean("use_custom_theme", false);
|
||||
boolean no_theme_set = sharedpreferences.getBoolean("no_theme_set", true);
|
||||
if (no_theme_set && !custom_theme) {
|
||||
list.get(0).apply(Cyanea.getInstance());
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putBoolean("no_theme_set", false);
|
||||
editor.apply();
|
||||
}
|
||||
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
|
||||
StrictMode.setVmPolicy(builder.build());
|
||||
|
||||
Toasty.Config.getInstance().apply();
|
||||
if (webView != null) {
|
||||
try {
|
||||
webView.destroy();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
createNotificationChannel();
|
||||
UploadServiceConfig.initialize(MainApplication.this, UPLOAD_CHANNEL_ID, true);
|
||||
|
||||
new GlobalRequestObserver(this, new GlobalUploadObserver());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void attachBaseContext(Context base) {
|
||||
super.attachBaseContext(base);
|
||||
MultiDex.install(MainApplication.this);
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(MainApplication.this);
|
||||
boolean send_crash_reports = sharedpreferences.getBoolean(getString(R.string.SET_SEND_CRASH_REPORTS), false);
|
||||
String currentTheme = sharedpreferences.getString(getString(R.string.SET_THEME_BASE), getString(R.string.SET_DEFAULT_THEME));
|
||||
ThemeHelper.switchTo(currentTheme);
|
||||
if (send_crash_reports) {
|
||||
ACRA.init(this, new CoreConfigurationBuilder()
|
||||
//core configuration:
|
||||
|
@ -99,6 +92,7 @@ public class MainApplication extends MultiDexApplication {
|
|||
.withResIcon(R.mipmap.ic_launcher)
|
||||
.withText(getString(R.string.crash_title))
|
||||
.withCommentPrompt(getString(R.string.crash_message))
|
||||
.withResTheme(R.style.DialogDark)
|
||||
.withPositiveButtonText(getString(R.string.send_email))
|
||||
.withNegativeButtonText(getString(R.string.cancel))
|
||||
.build()
|
||||
|
@ -114,15 +108,4 @@ public class MainApplication extends MultiDexApplication {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void createNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
NotificationChannel channel = new NotificationChannel(UPLOAD_CHANNEL_ID,
|
||||
getString(R.string.notification_channel_name),
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
channel.setSound(null, null);
|
||||
((NotificationManager) Objects.requireNonNull(getSystemService(Context.NOTIFICATION_SERVICE))).createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,17 +15,16 @@ package app.fedilab.android.activities;
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.app.ActivityOptionsCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -34,20 +33,17 @@ import java.util.List;
|
|||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.BuildConfig;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Account;
|
||||
import app.fedilab.android.client.entities.api.Status;
|
||||
import app.fedilab.android.databinding.ActivityAboutBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseBarActivity;
|
||||
import app.fedilab.android.mastodon.activities.ProfileActivity;
|
||||
import app.fedilab.android.mastodon.client.entities.api.Account;
|
||||
import app.fedilab.android.mastodon.client.entities.api.Status;
|
||||
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
||||
import app.fedilab.android.mastodon.helper.CrossActionHelper;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
||||
import app.fedilab.android.mastodon.viewmodel.mastodon.AccountsVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import app.fedilab.android.helper.CrossActionHelper;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
||||
|
||||
|
||||
public class AboutActivity extends BaseBarActivity {
|
||||
public class AboutActivity extends BaseActivity {
|
||||
|
||||
|
||||
private ActivityAboutBinding binding;
|
||||
|
@ -56,17 +52,18 @@ public class AboutActivity extends BaseBarActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyThemeBar(this);
|
||||
binding = ActivityAboutBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
String version = "";
|
||||
|
||||
try {
|
||||
PackageInfo pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
|
||||
version = pInfo.versionName;
|
||||
String version = pInfo.versionName;
|
||||
binding.aboutVersion.setText(getResources().getString(R.string.about_vesrion, version));
|
||||
} catch (PackageManager.NameNotFoundException ignored) {
|
||||
}
|
||||
|
@ -82,26 +79,13 @@ public class AboutActivity extends BaseBarActivity {
|
|||
}
|
||||
binding.aboutSupportPaypal.setOnClickListener(v -> Helper.openBrowser(AboutActivity.this, "https://www.paypal.me/Mastalab"));
|
||||
|
||||
|
||||
String finalVersion = version;
|
||||
binding.aboutVersionCopy.setOnClickListener(v -> {
|
||||
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
String content = "Fedilab v" + finalVersion + " for " + (BuildConfig.DONATIONS ? "FDroid" : "Google");
|
||||
|
||||
ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, content);
|
||||
if (clipboard != null) {
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toasty.info(AboutActivity.this, getString(R.string.clipboard_version), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
});
|
||||
binding.accountFollow.setBackgroundTintList(ThemeHelper.getButtonActionColorStateList(AboutActivity.this));
|
||||
if (BuildConfig.DONATIONS) {
|
||||
binding.aboutSupportPaypal.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.aboutSupportPaypal.setVisibility(View.GONE);
|
||||
}
|
||||
binding.accountFollow.setIconResource(R.drawable.ic_baseline_person_add_24);
|
||||
binding.accountFollow.setImageResource(R.drawable.ic_baseline_person_add_24);
|
||||
binding.aboutWebsite.setOnClickListener(v -> Helper.openBrowser(AboutActivity.this, "https://fedilab.app"));
|
||||
CrossActionHelper.fetchRemoteAccount(AboutActivity.this, "@apps@toot.fedilab.app", new CrossActionHelper.Callback() {
|
||||
@Override
|
||||
|
@ -119,14 +103,12 @@ public class AboutActivity extends BaseBarActivity {
|
|||
binding.accountUn.setText(account.acct);
|
||||
binding.accountPp.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(AboutActivity.this, ProfileActivity.class);
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(Helper.ARG_ACCOUNT, account);
|
||||
new CachedBundle(AboutActivity.this).insertBundle(args, Helper.getCurrentAccount(AboutActivity.this), bundleId -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
||||
intent.putExtras(bundle);
|
||||
startActivity(intent);
|
||||
});
|
||||
Bundle b = new Bundle();
|
||||
b.putSerializable(Helper.ARG_ACCOUNT, account);
|
||||
intent.putExtras(b);
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeSceneTransitionAnimation(AboutActivity.this, binding.accountPp, getString(R.string.activity_porfile_pp));
|
||||
startActivity(intent, options.toBundle());
|
||||
});
|
||||
AccountsVM accountsVM = new ViewModelProvider(AboutActivity.this).get(AccountsVM.class);
|
||||
List<String> ids = new ArrayList<>();
|
||||
|
@ -136,7 +118,7 @@ public class AboutActivity extends BaseBarActivity {
|
|||
if (relationShips != null && relationShips.size() > 0) {
|
||||
if (!relationShips.get(0).following) {
|
||||
binding.accountFollow.setVisibility(View.VISIBLE);
|
||||
binding.accountFollow.setOnClickListener(v -> accountsVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, true, false, null)
|
||||
binding.accountFollow.setOnClickListener(v -> accountsVM.follow(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, true, false)
|
||||
.observe(AboutActivity.this, relationShip -> binding.accountFollow.setVisibility(View.GONE)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.app.Timeline;
|
||||
import app.fedilab.android.databinding.ActivityActionsBinding;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAccount;
|
||||
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonTimeline;
|
||||
|
||||
public class ActionActivity extends BaseActivity {
|
||||
|
||||
private ActivityActionsBinding binding;
|
||||
private boolean canGoBack;
|
||||
private FragmentMastodonTimeline fragmentMastodonTimeline;
|
||||
private FragmentMastodonAccount fragmentMastodonAccount;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ThemeHelper.applyThemeBar(this);
|
||||
binding = ActivityActionsBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
canGoBack = false;
|
||||
binding.favourites.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.FAVOURITE_TIMELINE));
|
||||
binding.bookmarks.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.BOOKMARK_TIMELINE));
|
||||
binding.muted.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.MUTED_TIMELINE));
|
||||
binding.blocked.setOnClickListener(v -> displayTimeline(Timeline.TimeLineEnum.BLOCKED_TIMELINE));
|
||||
}
|
||||
|
||||
private void displayTimeline(Timeline.TimeLineEnum type) {
|
||||
canGoBack = true;
|
||||
if (type == Timeline.TimeLineEnum.MUTED_TIMELINE || type == Timeline.TimeLineEnum.BLOCKED_TIMELINE) {
|
||||
|
||||
ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> {
|
||||
fragmentMastodonAccount = new FragmentMastodonAccount();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentMastodonAccount.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentMastodonAccount);
|
||||
fragmentTransaction.commit();
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> {
|
||||
fragmentMastodonTimeline = new FragmentMastodonTimeline();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentMastodonTimeline.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentMastodonTimeline);
|
||||
fragmentTransaction.commit();
|
||||
});
|
||||
|
||||
}
|
||||
switch (type) {
|
||||
case MUTED_TIMELINE:
|
||||
setTitle(R.string.muted_menu);
|
||||
break;
|
||||
case FAVOURITE_TIMELINE:
|
||||
setTitle(R.string.favourite);
|
||||
break;
|
||||
case BLOCKED_TIMELINE:
|
||||
setTitle(R.string.blocked_menu);
|
||||
break;
|
||||
case BOOKMARK_TIMELINE:
|
||||
setTitle(R.string.bookmarks);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (canGoBack) {
|
||||
canGoBack = false;
|
||||
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.buttonContainer, () -> {
|
||||
if (fragmentMastodonTimeline != null) {
|
||||
fragmentMastodonTimeline.onDestroyView();
|
||||
}
|
||||
if (fragmentMastodonAccount != null) {
|
||||
fragmentMastodonAccount.onDestroyView();
|
||||
}
|
||||
});
|
||||
setTitle(R.string.interactions);
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
onBackPressed();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.activities.admin;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -19,6 +19,7 @@ import android.content.ClipData;
|
|||
import android.content.ClipboardManager;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
|
@ -26,7 +27,6 @@ import android.text.Spanned;
|
|||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
@ -46,6 +46,7 @@ import com.bumptech.glide.request.transition.Transition;
|
|||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -53,153 +54,71 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
import app.fedilab.android.client.entities.api.Account;
|
||||
import app.fedilab.android.client.entities.api.AdminAccount;
|
||||
import app.fedilab.android.client.entities.api.Attachment;
|
||||
import app.fedilab.android.databinding.ActivityAdminAccountBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseActivity;
|
||||
import app.fedilab.android.mastodon.activities.InstanceProfileActivity;
|
||||
import app.fedilab.android.mastodon.activities.MediaActivity;
|
||||
import app.fedilab.android.mastodon.client.entities.api.Attachment;
|
||||
import app.fedilab.android.mastodon.client.entities.api.admin.AdminAccount;
|
||||
import app.fedilab.android.mastodon.client.entities.api.admin.AdminIp;
|
||||
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
||||
import app.fedilab.android.mastodon.helper.SpannableHelper;
|
||||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||
import app.fedilab.android.mastodon.viewmodel.mastodon.AdminVM;
|
||||
import app.fedilab.android.mastodon.viewmodel.mastodon.NodeInfoVM;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.SpannableHelper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.viewmodel.mastodon.AdminVM;
|
||||
import app.fedilab.android.viewmodel.mastodon.NodeInfoVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
|
||||
public class AdminAccountActivity extends BaseActivity {
|
||||
|
||||
|
||||
private AdminAccount adminAccount;
|
||||
private Account account;
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
private ActivityAdminAccountBinding binding;
|
||||
private String account_id;
|
||||
private AdminVM adminVM;
|
||||
private AdminAccount adminAccount;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyTheme(this);
|
||||
binding = ActivityAdminAccountBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
Bundle args = getIntent().getExtras();
|
||||
adminAccount = null;
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
adminAccount = (AdminAccount) b.getSerializable(Helper.ARG_ACCOUNT);
|
||||
if (adminAccount != null) {
|
||||
account = adminAccount.account;
|
||||
}
|
||||
}
|
||||
postponeEnterTransition();
|
||||
|
||||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
|
||||
if (args != null) {
|
||||
long bundleId = args.getLong(Helper.ARG_INTENT_ID, -1);
|
||||
new CachedBundle(AdminAccountActivity.this).getBundle(bundleId, Helper.getCurrentAccount(AdminAccountActivity.this), this::initializeAfterBundle);
|
||||
} else {
|
||||
initializeAfterBundle(null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void initializeAfterBundle(Bundle bundle) {
|
||||
|
||||
if (bundle != null) {
|
||||
adminAccount = (AdminAccount) bundle.getSerializable(Helper.ARG_ACCOUNT);
|
||||
account_id = bundle.getString(Helper.ARG_ACCOUNT_ID, null);
|
||||
}
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
float scale = sharedpreferences.getFloat(getString(R.string.SET_FONT_SCALE), 1.1f);
|
||||
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18 * 1.1f / scale);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
adminVM = new ViewModelProvider(AdminAccountActivity.this).get(AdminVM.class);
|
||||
if (account_id != null) {
|
||||
adminVM.getAccount(MainActivity.currentInstance, MainActivity.currentToken, account_id).observe(this, this::initializeView);
|
||||
return;
|
||||
}
|
||||
if (adminAccount != null && adminAccount.account != null) {
|
||||
initializeView(adminAccount);
|
||||
binding.toolbar.setPopupTheme(Helper.popupStyle());
|
||||
if (account != null) {
|
||||
initializeView(account);
|
||||
} else {
|
||||
Toasty.error(AdminAccountActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
Toasty.error(AdminAccountActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
binding.disableAction.setOnClickListener(v -> {
|
||||
if (adminAccount.disabled) {
|
||||
adminVM.enable(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount.disabled = false;
|
||||
binding.disableAction.setText(R.string.disable);
|
||||
binding.disabled.setText(R.string.no);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id, "disable ", null, null, null, null);
|
||||
adminAccount.disabled = true;
|
||||
binding.disableAction.setText(R.string.undisable);
|
||||
binding.disabled.setText(R.string.yes);
|
||||
}
|
||||
});
|
||||
|
||||
binding.approveAction.setOnClickListener(v -> {
|
||||
if (adminAccount.approved) {
|
||||
adminVM.reject(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount = adminAccountResult;
|
||||
initializeView(adminAccount);
|
||||
});
|
||||
} else {
|
||||
adminVM.approve(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id);
|
||||
adminAccount.approved = true;
|
||||
initializeView(adminAccount);
|
||||
}
|
||||
});
|
||||
|
||||
binding.silenceAction.setOnClickListener(v -> {
|
||||
if (adminAccount.silenced) {
|
||||
adminVM.unsilence(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount = adminAccountResult;
|
||||
initializeView(adminAccount);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id, "silence", null, null, null, null);
|
||||
adminAccount.silenced = true;
|
||||
initializeView(adminAccount);
|
||||
}
|
||||
});
|
||||
|
||||
binding.suspendAction.setOnClickListener(v -> {
|
||||
if (adminAccount.suspended) {
|
||||
adminVM.unsuspend(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount = adminAccountResult;
|
||||
initializeView(adminAccount);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, adminAccount.id, "suspend", null, null, null, null);
|
||||
adminAccount.suspended = true;
|
||||
initializeView(adminAccount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeView(AdminAccount adminAccount) {
|
||||
private void initializeView(Account account) {
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(AdminAccountActivity.this);
|
||||
if (adminAccount == null) {
|
||||
Toasty.error(AdminAccountActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
if (account == null) {
|
||||
Toasty.error(AdminAccountActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
binding.title.setText(String.format(Locale.getDefault(), "@%s", adminAccount.account.acct));
|
||||
binding.title.setText(String.format(Locale.getDefault(), "@%s", account.acct));
|
||||
|
||||
// MastodonHelper.loadPPMastodon(binding.profilePicture, account);
|
||||
binding.appBar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
|
||||
|
@ -213,18 +132,14 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
binding.username.setText(String.format(Locale.getDefault(), "@%s", adminAccount.username));
|
||||
binding.domain.setText(adminAccount.domain);
|
||||
binding.email.setText(adminAccount.email);
|
||||
StringBuilder lastActive = new StringBuilder();
|
||||
if (adminAccount.ips != null) {
|
||||
int count = 0;
|
||||
for (AdminIp ip : adminAccount.ips) {
|
||||
for (AdminAccount.IP ip : adminAccount.ips) {
|
||||
lastActive.append(Helper.shortDateToString(ip.used_at)).append(" - ").append(ip.ip).append("\r\n");
|
||||
count++;
|
||||
if (count > 4) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastActive.toString().trim().length() == 0) {
|
||||
|
@ -244,9 +159,78 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
binding.silenceAction.setText(adminAccount.silenced ? R.string.unsilence : R.string.silence);
|
||||
binding.suspendAction.setText(adminAccount.suspended ? R.string.unsuspend : R.string.suspend);
|
||||
|
||||
AdminVM adminVM = new ViewModelProvider(AdminAccountActivity.this).get(AdminVM.class);
|
||||
|
||||
binding.disableAction.setOnClickListener(v -> {
|
||||
if (adminAccount.disabled) {
|
||||
adminVM.enable(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount.disabled = false;
|
||||
binding.disableAction.setText(R.string.disable);
|
||||
binding.disabled.setText(R.string.no);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, "disable ", null, null, null, null);
|
||||
adminAccount.disabled = true;
|
||||
binding.disableAction.setText(R.string.undisable);
|
||||
binding.disabled.setText(R.string.yes);
|
||||
}
|
||||
});
|
||||
|
||||
binding.approveAction.setOnClickListener(v -> {
|
||||
if (adminAccount.approved) {
|
||||
adminVM.reject(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount.approved = false;
|
||||
binding.approveAction.setText(R.string.approve);
|
||||
binding.approved.setText(R.string.no);
|
||||
});
|
||||
} else {
|
||||
adminVM.approve(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id);
|
||||
adminAccount.approved = true;
|
||||
binding.approveAction.setText(R.string.reject);
|
||||
binding.approved.setText(R.string.yes);
|
||||
}
|
||||
});
|
||||
|
||||
binding.silenceAction.setOnClickListener(v -> {
|
||||
if (adminAccount.disabled) {
|
||||
adminVM.unsilence(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount.silenced = false;
|
||||
binding.silenceAction.setText(R.string.silence);
|
||||
binding.disabled.setText(R.string.no);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, "silence", null, null, null, null);
|
||||
adminAccount.silenced = true;
|
||||
binding.disableAction.setText(R.string.unsilence);
|
||||
binding.disabled.setText(R.string.yes);
|
||||
}
|
||||
});
|
||||
|
||||
binding.suspendAction.setOnClickListener(v -> {
|
||||
if (adminAccount.disabled) {
|
||||
adminVM.unsuspend(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id)
|
||||
.observe(AdminAccountActivity.this, adminAccountResult -> {
|
||||
adminAccount.suspended = false;
|
||||
binding.suspendAction.setText(R.string.suspend);
|
||||
binding.suspended.setText(R.string.no);
|
||||
});
|
||||
} else {
|
||||
adminVM.performAction(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, account.id, "suspend", null, null, null, null);
|
||||
adminAccount.suspended = true;
|
||||
binding.disableAction.setText(R.string.unsuspend);
|
||||
binding.suspended.setText(R.string.yes);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//Retrieve relationship with the connected account
|
||||
List<String> accountListToCheck = new ArrayList<>();
|
||||
accountListToCheck.add(account.id);
|
||||
//Animate emojis
|
||||
if (adminAccount.account.emojis != null && adminAccount.account.emojis.size() > 0) {
|
||||
if (account.emojis != null && account.emojis.size() > 0) {
|
||||
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
|
||||
if (!disableAnimatedEmoji) {
|
||||
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
@ -257,35 +241,35 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
//Tablayout for timelines/following/followers
|
||||
|
||||
boolean disableGif = sharedpreferences.getBoolean(getString(R.string.SET_DISABLE_GIF), false);
|
||||
String targetedUrl = disableGif ? adminAccount.account.avatar_static : adminAccount.account.avatar;
|
||||
String targetedUrl = disableGif ? account.avatar_static : account.avatar;
|
||||
Glide.with(AdminAccountActivity.this)
|
||||
.asDrawable()
|
||||
.dontTransform()
|
||||
.load(targetedUrl).into(
|
||||
new CustomTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
|
||||
binding.profilePicture.setImageDrawable(resource);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
new CustomTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
|
||||
binding.profilePicture.setImageDrawable(resource);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
binding.profilePicture.setImageResource(R.drawable.ic_person);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
binding.profilePicture.setImageResource(R.drawable.ic_person);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
//Load header
|
||||
MastodonHelper.loadProfileMediaMastodon(AdminAccountActivity.this, binding.bannerPp, adminAccount.account, MastodonHelper.MediaAccountType.HEADER);
|
||||
MastodonHelper.loadProfileMediaMastodon(binding.bannerPp, account, MastodonHelper.MediaAccountType.HEADER);
|
||||
//Redraws icon for locked accounts
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
if (adminAccount.account.locked) {
|
||||
if (account.locked) {
|
||||
Drawable img = ContextCompat.getDrawable(AdminAccountActivity.this, R.drawable.ic_baseline_lock_24);
|
||||
assert img != null;
|
||||
img.setBounds(0, 0, (int) (16 * scale + 0.5f), (int) (16 * scale + 0.5f));
|
||||
|
@ -295,41 +279,41 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
}
|
||||
//Peertube account watched by a Mastodon account
|
||||
//Bot account
|
||||
if (adminAccount.account.bot) {
|
||||
if (account.bot) {
|
||||
binding.accountBot.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (adminAccount.account.acct != null) {
|
||||
setTitle(adminAccount.account.acct);
|
||||
if (account.acct != null) {
|
||||
setTitle(account.acct);
|
||||
}
|
||||
|
||||
|
||||
final SpannableString content = new SpannableString(getString(R.string.disclaimer_full));
|
||||
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
|
||||
content.setSpan(new ForegroundColorSpan(ThemeHelper.getAttColor(this, R.attr.colorPrimary)), 0, content.length(),
|
||||
content.setSpan(new ForegroundColorSpan(ContextCompat.getColor(AdminAccountActivity.this, R.color.cyanea_accent_reference)), 0, content.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
//This account was moved to another one
|
||||
if (adminAccount.account.moved != null) {
|
||||
if (account.moved != null) {
|
||||
binding.accountMoved.setVisibility(View.VISIBLE);
|
||||
Drawable imgTravel = ContextCompat.getDrawable(AdminAccountActivity.this, R.drawable.ic_baseline_card_travel_24);
|
||||
assert imgTravel != null;
|
||||
imgTravel.setBounds(0, 0, (int) (20 * scale + 0.5f), (int) (20 * scale + 0.5f));
|
||||
binding.accountMoved.setCompoundDrawables(imgTravel, null, null, null);
|
||||
//Retrieves content and make account names clickable
|
||||
SpannableString spannableString = SpannableHelper.moveToText(AdminAccountActivity.this, adminAccount.account);
|
||||
SpannableString spannableString = SpannableHelper.moveToText(AdminAccountActivity.this, account);
|
||||
binding.accountMoved.setText(spannableString, TextView.BufferType.SPANNABLE);
|
||||
binding.accountMoved.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
|
||||
binding.accountDn.setText(
|
||||
adminAccount.account.getSpanDisplayNameEmoji(AdminAccountActivity.this,
|
||||
account.getSpanDisplayName(AdminAccountActivity.this,
|
||||
new WeakReference<>(binding.accountDn)),
|
||||
TextView.BufferType.SPANNABLE);
|
||||
binding.accountUn.setText(String.format("@%s", adminAccount.account.acct));
|
||||
binding.accountUn.setText(String.format("@%s", account.acct));
|
||||
binding.accountUn.setOnLongClickListener(v -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
String account_id = adminAccount.account.acct;
|
||||
String account_id = account.acct;
|
||||
if (account_id.split("@").length == 1)
|
||||
account_id += "@" + BaseMainActivity.currentInstance;
|
||||
ClipData clip = ClipData.newPlainText("mastodon_account_id", "@" + account_id);
|
||||
|
@ -339,36 +323,32 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
return false;
|
||||
});
|
||||
|
||||
MastodonHelper.loadPPMastodon(binding.accountPp, adminAccount.account);
|
||||
MastodonHelper.loadPPMastodon(binding.accountPp, account);
|
||||
binding.accountPp.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(AdminAccountActivity.this, MediaActivity.class);
|
||||
Bundle args = new Bundle();
|
||||
Bundle b = new Bundle();
|
||||
Attachment attachment = new Attachment();
|
||||
attachment.description = adminAccount.account.acct;
|
||||
attachment.preview_url = adminAccount.account.avatar;
|
||||
attachment.url = adminAccount.account.avatar;
|
||||
attachment.remote_url = adminAccount.account.avatar;
|
||||
attachment.description = account.acct;
|
||||
attachment.preview_url = account.avatar;
|
||||
attachment.url = account.avatar;
|
||||
attachment.remote_url = account.avatar;
|
||||
attachment.type = "image";
|
||||
ArrayList<Attachment> attachments = new ArrayList<>();
|
||||
attachments.add(attachment);
|
||||
args.putSerializable(Helper.ARG_MEDIA_ARRAY, attachments);
|
||||
args.putInt(Helper.ARG_MEDIA_POSITION, 1);
|
||||
new CachedBundle(AdminAccountActivity.this).insertBundle(args, Helper.getCurrentAccount(AdminAccountActivity.this), bundleId -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
||||
intent.putExtras(bundle);
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeSceneTransitionAnimation(AdminAccountActivity.this, binding.accountPp, attachment.url);
|
||||
// start the new activity
|
||||
startActivity(intent, options.toBundle());
|
||||
});
|
||||
b.putSerializable(Helper.ARG_MEDIA_ARRAY, attachments);
|
||||
b.putInt(Helper.ARG_MEDIA_POSITION, 1);
|
||||
intent.putExtras(b);
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeSceneTransitionAnimation(AdminAccountActivity.this, binding.accountPp, attachment.url);
|
||||
// start the new activity
|
||||
startActivity(intent, options.toBundle());
|
||||
});
|
||||
|
||||
|
||||
binding.accountDate.setText(Helper.shortDateToString(adminAccount.created_at));
|
||||
binding.accountDate.setText(Helper.shortDateToString(account.created_at));
|
||||
binding.accountDate.setVisibility(View.VISIBLE);
|
||||
|
||||
String[] accountInstanceArray = adminAccount.account.acct.split("@");
|
||||
String[] accountInstanceArray = account.acct.split("@");
|
||||
String accountInstance = BaseMainActivity.currentInstance;
|
||||
if (accountInstanceArray.length > 1) {
|
||||
accountInstance = accountInstanceArray[1];
|
||||
|
@ -382,11 +362,12 @@ public class AdminAccountActivity extends BaseActivity {
|
|||
binding.instanceInfo.setVisibility(View.VISIBLE);
|
||||
|
||||
binding.instanceInfo.setOnClickListener(v -> {
|
||||
InstanceProfileActivity instanceProfileActivity = new InstanceProfileActivity();
|
||||
Intent intent = new Intent(AdminAccountActivity.this, InstanceProfileActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
b.putString(Helper.ARG_INSTANCE, finalAccountInstance);
|
||||
instanceProfileActivity.setArguments(b);
|
||||
instanceProfileActivity.show(getSupportFragmentManager(), null);
|
||||
intent.putExtras(b);
|
||||
startActivity(intent);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.activities.admin;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -14,20 +14,13 @@ package app.fedilab.android.mastodon.activities.admin;
|
|||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import static app.fedilab.android.activities.AdminActionActivity.AdminEnum.REPORT;
|
||||
|
||||
import static app.fedilab.android.mastodon.activities.admin.AdminActionActivity.AdminEnum.ACCOUNT;
|
||||
import static app.fedilab.android.mastodon.activities.admin.AdminActionActivity.AdminEnum.DOMAIN;
|
||||
import static app.fedilab.android.mastodon.activities.admin.AdminActionActivity.AdminEnum.REPORT;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
@ -35,156 +28,89 @@ import androidx.core.content.ContextCompat;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentTransaction;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.databinding.ActivityAdminActionsBinding;
|
||||
import app.fedilab.android.databinding.PopupAdminFilterAccountsBinding;
|
||||
import app.fedilab.android.databinding.PopupAdminFilterReportsBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseBarActivity;
|
||||
import app.fedilab.android.mastodon.client.entities.api.admin.AdminDomainBlock;
|
||||
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||
import app.fedilab.android.mastodon.ui.fragment.admin.FragmentAdminAccount;
|
||||
import app.fedilab.android.mastodon.ui.fragment.admin.FragmentAdminDomain;
|
||||
import app.fedilab.android.mastodon.ui.fragment.admin.FragmentAdminReport;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.ui.fragment.admin.FragmentAdminAccount;
|
||||
import app.fedilab.android.ui.fragment.admin.FragmentAdminReport;
|
||||
|
||||
public class AdminActionActivity extends BaseBarActivity {
|
||||
public class AdminActionActivity extends BaseActivity {
|
||||
|
||||
public static Boolean local = true, remote = true, active = true, pending = true, disabled = true, silenced = true, suspended = true, staff = null, orderByMostRecent = true;
|
||||
public static Boolean resolved = null, reportLocal = true, reportRemote = true;
|
||||
public static Boolean resolved = false, reportLocal = true, reportRemote = true;
|
||||
private ActivityAdminActionsBinding binding;
|
||||
private boolean canGoBack;
|
||||
private FragmentAdminReport fragmentAdminReport;
|
||||
private FragmentAdminAccount fragmentAdminAccount;
|
||||
private FragmentAdminDomain fragmentAdminDomain;
|
||||
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Bundle args = intent.getExtras();
|
||||
if (args != null) {
|
||||
long bundleId = args.getLong(Helper.ARG_INTENT_ID, -1);
|
||||
new CachedBundle(AdminActionActivity.this).getBundle(bundleId, Helper.getCurrentAccount(AdminActionActivity.this), bundle -> {
|
||||
AdminDomainBlock adminDomainBlock = (AdminDomainBlock) bundle.getSerializable(Helper.ARG_ADMIN_DOMAINBLOCK);
|
||||
AdminDomainBlock adminDomainBlockDelete = (AdminDomainBlock) bundle.getSerializable(Helper.ARG_ADMIN_DOMAINBLOCK_DELETE);
|
||||
if (adminDomainBlock != null && adminDomainBlock.domain != null && fragmentAdminDomain != null) {
|
||||
fragmentAdminDomain.update(adminDomainBlock);
|
||||
}
|
||||
if (adminDomainBlockDelete != null && fragmentAdminDomain != null) {
|
||||
fragmentAdminDomain.delete(adminDomainBlockDelete);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyThemeBar(this);
|
||||
binding = ActivityAdminActionsBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
|
||||
ContextCompat.registerReceiver(AdminActionActivity.this, mReceiver, new IntentFilter(Helper.BROADCAST_DATA), ContextCompat.RECEIVER_NOT_EXPORTED);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
canGoBack = false;
|
||||
binding.reports.setOnClickListener(v -> displayTimeline(REPORT));
|
||||
binding.accounts.setOnClickListener(v -> displayTimeline(ACCOUNT));
|
||||
binding.domains.setOnClickListener(v -> displayTimeline(DOMAIN));
|
||||
|
||||
getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (canGoBack) {
|
||||
canGoBack = false;
|
||||
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.buttonContainer, () -> {
|
||||
if (fragmentAdminReport != null) {
|
||||
fragmentAdminReport.onDestroyView();
|
||||
fragmentAdminReport = null;
|
||||
}
|
||||
if (fragmentAdminAccount != null) {
|
||||
fragmentAdminAccount.onDestroyView();
|
||||
fragmentAdminAccount = null;
|
||||
}
|
||||
if (fragmentAdminDomain != null) {
|
||||
fragmentAdminDomain.onDestroyView();
|
||||
fragmentAdminDomain = null;
|
||||
}
|
||||
setTitle(R.string.administration);
|
||||
invalidateOptionsMenu();
|
||||
});
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
binding.accounts.setOnClickListener(v -> displayTimeline(AdminEnum.ACCOUNT));
|
||||
}
|
||||
|
||||
private void displayTimeline(AdminEnum type) {
|
||||
canGoBack = true;
|
||||
if (type == REPORT) {
|
||||
fragmentAdminReport = new FragmentAdminReport();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentAdminReport.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentAdminReport);
|
||||
fragmentTransaction.commit();
|
||||
ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> {
|
||||
|
||||
});
|
||||
} else if (type == ACCOUNT) {
|
||||
fragmentAdminAccount = new FragmentAdminAccount();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentAdminAccount.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentAdminAccount);
|
||||
fragmentTransaction.commit();
|
||||
ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> {
|
||||
|
||||
fragmentAdminReport = new FragmentAdminReport();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentAdminReport.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentAdminReport);
|
||||
fragmentTransaction.commit();
|
||||
});
|
||||
} else if (type == DOMAIN) {
|
||||
fragmentAdminDomain = new FragmentAdminDomain();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentAdminDomain.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentAdminDomain);
|
||||
fragmentTransaction.commit();
|
||||
|
||||
} else {
|
||||
|
||||
ThemeHelper.slideViewsToLeft(binding.buttonContainer, binding.fragmentContainer, () -> {
|
||||
|
||||
fragmentAdminAccount = new FragmentAdminAccount();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_TIMELINE_TYPE, type);
|
||||
bundle.putString(Helper.ARG_VIEW_MODEL_KEY, "FEDILAB_" + type.getValue());
|
||||
fragmentAdminAccount.setArguments(bundle);
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction =
|
||||
fragmentManager.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.fragment_container, fragmentAdminAccount);
|
||||
fragmentTransaction.commit();
|
||||
});
|
||||
|
||||
}
|
||||
switch (type) {
|
||||
case REPORT -> setTitle(R.string.reports);
|
||||
case ACCOUNT -> setTitle(R.string.accounts);
|
||||
case DOMAIN -> setTitle(R.string.domains);
|
||||
case REPORT:
|
||||
setTitle(R.string.reports);
|
||||
break;
|
||||
case ACCOUNT:
|
||||
setTitle(R.string.accounts);
|
||||
break;
|
||||
}
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
||||
if (canGoBack && fragmentAdminAccount != null) {
|
||||
if (canGoBack) {
|
||||
getMenuInflater().inflate(R.menu.menu_admin_account, menu);
|
||||
}
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
|
@ -193,11 +119,11 @@ public class AdminActionActivity extends BaseBarActivity {
|
|||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
getOnBackPressedDispatcher().onBackPressed();
|
||||
onBackPressed();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_filter) {
|
||||
if (getTitle().toString().equalsIgnoreCase(getString(R.string.accounts))) {
|
||||
AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(AdminActionActivity.this);
|
||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(AdminActionActivity.this, Helper.dialogStyle());
|
||||
PopupAdminFilterAccountsBinding binding = PopupAdminFilterAccountsBinding.inflate(getLayoutInflater());
|
||||
alertDialogBuilder.setView(binding.getRoot());
|
||||
if (local != null && remote == null) {
|
||||
|
@ -229,8 +155,6 @@ public class AdminActionActivity extends BaseBarActivity {
|
|||
binding.moderationAll.setChecked(true);
|
||||
}
|
||||
binding.moderation.setOnCheckedChangeListener((group, checkedId) -> {
|
||||
disabled = null;
|
||||
silenced = null;
|
||||
if (checkedId == R.id.moderation_all) {
|
||||
active = true;
|
||||
suspended = true;
|
||||
|
@ -291,7 +215,7 @@ public class AdminActionActivity extends BaseBarActivity {
|
|||
AlertDialog alert = alertDialogBuilder.create();
|
||||
alert.show();
|
||||
} else {
|
||||
AlertDialog.Builder alertDialogBuilder = new MaterialAlertDialogBuilder(AdminActionActivity.this);
|
||||
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(AdminActionActivity.this, Helper.dialogStyle());
|
||||
PopupAdminFilterReportsBinding binding = PopupAdminFilterReportsBinding.inflate(getLayoutInflater());
|
||||
alertDialogBuilder.setView(binding.getRoot());
|
||||
if (resolved == null) {
|
||||
|
@ -303,7 +227,7 @@ public class AdminActionActivity extends BaseBarActivity {
|
|||
if (checkedId == R.id.status_resolved) {
|
||||
resolved = true;
|
||||
} else if (checkedId == R.id.status_unresolved) {
|
||||
resolved = null;
|
||||
resolved = false;
|
||||
}
|
||||
});
|
||||
if (reportLocal != null && reportRemote == null) {
|
||||
|
@ -347,25 +271,31 @@ public class AdminActionActivity extends BaseBarActivity {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mReceiver != null) {
|
||||
try {
|
||||
unregisterReceiver(mReceiver);
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
public void onBackPressed() {
|
||||
if (canGoBack) {
|
||||
canGoBack = false;
|
||||
ThemeHelper.slideViewsToRight(binding.fragmentContainer, binding.buttonContainer, () -> {
|
||||
if (fragmentAdminReport != null) {
|
||||
fragmentAdminReport.onDestroyView();
|
||||
}
|
||||
if (fragmentAdminAccount != null) {
|
||||
fragmentAdminAccount.onDestroyView();
|
||||
}
|
||||
setTitle(R.string.administration);
|
||||
invalidateOptionsMenu();
|
||||
});
|
||||
} else {
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum AdminEnum {
|
||||
@SerializedName("REPORT")
|
||||
REPORT("REPORT"),
|
||||
@SerializedName("ACCOUNT")
|
||||
ACCOUNT("ACCOUNT"),
|
||||
@SerializedName("DOMAIN")
|
||||
DOMAIN("DOMAIN");
|
||||
ACCOUNT("ACCOUNT");
|
||||
|
||||
private final String value;
|
||||
|
||||
AdminEnum(String value) {
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.activities.admin;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -19,6 +19,7 @@ import android.content.ClipData;
|
|||
import android.content.ClipboardManager;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
|
@ -26,7 +27,6 @@ import android.text.Spanned;
|
|||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.text.style.UnderlineSpan;
|
||||
import android.util.TypedValue;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
@ -46,6 +46,7 @@ import com.bumptech.glide.request.transition.Transition;
|
|||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -53,25 +54,20 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Account;
|
||||
import app.fedilab.android.client.entities.api.AdminAccount;
|
||||
import app.fedilab.android.client.entities.api.Attachment;
|
||||
import app.fedilab.android.databinding.ActivityAdminAccountBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseBarActivity;
|
||||
import app.fedilab.android.mastodon.activities.InstanceProfileActivity;
|
||||
import app.fedilab.android.mastodon.activities.MediaActivity;
|
||||
import app.fedilab.android.mastodon.client.entities.api.Account;
|
||||
import app.fedilab.android.mastodon.client.entities.api.Attachment;
|
||||
import app.fedilab.android.mastodon.client.entities.api.admin.AdminAccount;
|
||||
import app.fedilab.android.mastodon.client.entities.api.admin.AdminIp;
|
||||
import app.fedilab.android.mastodon.client.entities.app.CachedBundle;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.helper.MastodonHelper;
|
||||
import app.fedilab.android.mastodon.helper.SpannableHelper;
|
||||
import app.fedilab.android.mastodon.helper.ThemeHelper;
|
||||
import app.fedilab.android.mastodon.viewmodel.mastodon.AdminVM;
|
||||
import app.fedilab.android.mastodon.viewmodel.mastodon.NodeInfoVM;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.SpannableHelper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.viewmodel.mastodon.AdminVM;
|
||||
import app.fedilab.android.viewmodel.mastodon.NodeInfoVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
|
||||
public class AdminReportActivity extends BaseBarActivity {
|
||||
public class AdminReportActivity extends BaseActivity {
|
||||
|
||||
private AdminAccount adminAccount;
|
||||
private Account account;
|
||||
|
@ -82,46 +78,35 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyTheme(this);
|
||||
binding = ActivityAdminAccountBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
Bundle args = getIntent().getExtras();
|
||||
postponeEnterTransition();
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
float scale = sharedpreferences.getFloat(getString(R.string.SET_FONT_SCALE), 1.1f);
|
||||
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18 * 1.1f / scale);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
|
||||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
}
|
||||
|
||||
if (args != null) {
|
||||
long bundleId = args.getLong(Helper.ARG_INTENT_ID, -1);
|
||||
new CachedBundle(AdminReportActivity.this).getBundle(bundleId, Helper.getCurrentAccount(AdminReportActivity.this), this::initializeAfterBundle);
|
||||
} else {
|
||||
initializeAfterBundle(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initializeAfterBundle(Bundle bundle) {
|
||||
if (bundle != null) {
|
||||
adminAccount = (AdminAccount) bundle.getSerializable(Helper.ARG_ACCOUNT);
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
adminAccount = (AdminAccount) b.getSerializable(Helper.ARG_ACCOUNT);
|
||||
if (adminAccount != null) {
|
||||
account = adminAccount.account;
|
||||
}
|
||||
}
|
||||
postponeEnterTransition();
|
||||
|
||||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
binding.toolbar.setPopupTheme(Helper.popupStyle());
|
||||
if (account != null) {
|
||||
initializeView(account);
|
||||
} else {
|
||||
Toasty.error(AdminReportActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
Toasty.error(AdminReportActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +114,7 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
private void initializeView(Account account) {
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(AdminReportActivity.this);
|
||||
if (account == null) {
|
||||
Toasty.error(AdminReportActivity.this, getString(R.string.toast_error), Toast.LENGTH_LONG).show();
|
||||
Toasty.error(AdminReportActivity.this, getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
@ -153,14 +138,14 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
binding.email.setText(adminAccount.email);
|
||||
StringBuilder lastActive = new StringBuilder();
|
||||
if (adminAccount.ips != null) {
|
||||
for (AdminIp ip : adminAccount.ips) {
|
||||
for (AdminAccount.IP ip : adminAccount.ips) {
|
||||
lastActive.append(Helper.shortDateToString(ip.used_at)).append(" - ").append(ip.ip).append("\r\n");
|
||||
}
|
||||
}
|
||||
if (lastActive.toString().trim().isEmpty()) {
|
||||
if (lastActive.toString().trim().length() == 0) {
|
||||
binding.lastActiveContainer.setVisibility(View.GONE);
|
||||
}
|
||||
if (adminAccount.email == null || adminAccount.email.trim().isEmpty()) {
|
||||
if (adminAccount.email == null || adminAccount.email.trim().length() == 0) {
|
||||
binding.emailContainer.setVisibility(View.GONE);
|
||||
}
|
||||
binding.lastActive.setText(lastActive.toString());
|
||||
|
@ -259,8 +244,11 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
});
|
||||
|
||||
|
||||
//Retrieve relationship with the connected account
|
||||
List<String> accountListToCheck = new ArrayList<>();
|
||||
accountListToCheck.add(account.id);
|
||||
//Animate emojis
|
||||
if (account.emojis != null && !account.emojis.isEmpty()) {
|
||||
if (account.emojis != null && account.emojis.size() > 0) {
|
||||
boolean disableAnimatedEmoji = sharedpreferences.getBoolean(getString(R.string.SET_DISABLE_ANIMATED_EMOJI), false);
|
||||
if (!disableAnimatedEmoji) {
|
||||
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
|
@ -276,27 +264,27 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
.asDrawable()
|
||||
.dontTransform()
|
||||
.load(targetedUrl).into(
|
||||
new CustomTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
|
||||
binding.profilePicture.setImageDrawable(resource);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
new CustomTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull final Drawable resource, Transition<? super Drawable> transition) {
|
||||
binding.profilePicture.setImageDrawable(resource);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
binding.profilePicture.setImageResource(R.drawable.ic_person);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
@Override
|
||||
public void onLoadFailed(@Nullable Drawable errorDrawable) {
|
||||
binding.profilePicture.setImageResource(R.drawable.ic_person);
|
||||
startPostponedEnterTransition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
@Override
|
||||
public void onLoadCleared(@Nullable Drawable placeholder) {
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
//Load header
|
||||
MastodonHelper.loadProfileMediaMastodon(AdminReportActivity.this, binding.bannerPp, account, MastodonHelper.MediaAccountType.HEADER);
|
||||
MastodonHelper.loadProfileMediaMastodon(binding.bannerPp, account, MastodonHelper.MediaAccountType.HEADER);
|
||||
//Redraws icon for locked accounts
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
if (account.locked) {
|
||||
|
@ -319,7 +307,7 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
|
||||
final SpannableString content = new SpannableString(getString(R.string.disclaimer_full));
|
||||
content.setSpan(new UnderlineSpan(), 0, content.length(), 0);
|
||||
content.setSpan(new ForegroundColorSpan(ThemeHelper.getAttColor(this, R.attr.colorPrimary)), 0, content.length(),
|
||||
content.setSpan(new ForegroundColorSpan(ContextCompat.getColor(AdminReportActivity.this, R.color.cyanea_accent_reference)), 0, content.length(),
|
||||
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
|
||||
//This account was moved to another one
|
||||
|
@ -336,7 +324,7 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
}
|
||||
|
||||
binding.accountDn.setText(
|
||||
account.getSpanDisplayNameEmoji(AdminReportActivity.this,
|
||||
account.getSpanDisplayName(AdminReportActivity.this,
|
||||
new WeakReference<>(binding.accountDn)),
|
||||
TextView.BufferType.SPANNABLE);
|
||||
binding.accountUn.setText(String.format("@%s", account.acct));
|
||||
|
@ -355,7 +343,7 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
MastodonHelper.loadPPMastodon(binding.accountPp, account);
|
||||
binding.accountPp.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(AdminReportActivity.this, MediaActivity.class);
|
||||
Bundle args = new Bundle();
|
||||
Bundle b = new Bundle();
|
||||
Attachment attachment = new Attachment();
|
||||
attachment.description = account.acct;
|
||||
attachment.preview_url = account.avatar;
|
||||
|
@ -364,16 +352,13 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
attachment.type = "image";
|
||||
ArrayList<Attachment> attachments = new ArrayList<>();
|
||||
attachments.add(attachment);
|
||||
args.putSerializable(Helper.ARG_MEDIA_ARRAY, attachments);
|
||||
args.putInt(Helper.ARG_MEDIA_POSITION, 1);
|
||||
new CachedBundle(AdminReportActivity.this).insertBundle(args, Helper.getCurrentAccount(AdminReportActivity.this), bundleId -> {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(Helper.ARG_INTENT_ID, bundleId);
|
||||
intent.putExtras(bundle);
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeSceneTransitionAnimation(AdminReportActivity.this, binding.accountPp, attachment.url);
|
||||
startActivity(intent, options.toBundle());
|
||||
});
|
||||
b.putSerializable(Helper.ARG_MEDIA_ARRAY, attachments);
|
||||
b.putInt(Helper.ARG_MEDIA_POSITION, 1);
|
||||
intent.putExtras(b);
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeSceneTransitionAnimation(AdminReportActivity.this, binding.accountPp, attachment.url);
|
||||
// start the new activity
|
||||
startActivity(intent, options.toBundle());
|
||||
});
|
||||
|
||||
|
||||
|
@ -394,11 +379,12 @@ public class AdminReportActivity extends BaseBarActivity {
|
|||
binding.instanceInfo.setVisibility(View.VISIBLE);
|
||||
|
||||
binding.instanceInfo.setOnClickListener(v -> {
|
||||
InstanceProfileActivity instanceProfileActivity = new InstanceProfileActivity();
|
||||
Intent intent = new Intent(AdminReportActivity.this, InstanceProfileActivity.class);
|
||||
Bundle b = new Bundle();
|
||||
b.putString(Helper.ARG_INSTANCE, finalAccountInstance);
|
||||
instanceProfileActivity.setArguments(b);
|
||||
instanceProfileActivity.show(getSupportFragmentManager(), null);
|
||||
intent.putExtras(b);
|
||||
startActivity(intent);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.activities;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -18,20 +18,20 @@ package app.fedilab.android.mastodon.activities;
|
|||
import static app.fedilab.android.BaseMainActivity.currentInstance;
|
||||
import static app.fedilab.android.BaseMainActivity.emojis;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.TypedValue;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.EmojiInstance;
|
||||
import app.fedilab.android.databinding.ActivityAnnouncementBinding;
|
||||
import app.fedilab.android.mastodon.client.entities.api.EmojiInstance;
|
||||
import app.fedilab.android.mastodon.exception.DBException;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.ui.fragment.timeline.FragmentMastodonAnnouncement;
|
||||
import app.fedilab.android.exception.DBException;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonAnnouncement;
|
||||
|
||||
|
||||
public class AnnouncementActivity extends BaseActivity {
|
||||
|
@ -40,7 +40,7 @@ public class AnnouncementActivity extends BaseActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyTheme(this);
|
||||
ActivityAnnouncementBinding binding = ActivityAnnouncementBinding.inflate(getLayoutInflater());
|
||||
|
||||
setContentView(binding.getRoot());
|
||||
|
@ -50,15 +50,14 @@ public class AnnouncementActivity extends BaseActivity {
|
|||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
binding.title.setText(R.string.action_announcements);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
float scale = sharedpreferences.getFloat(getString(R.string.SET_FONT_SCALE), 1.1f);
|
||||
binding.title.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18 * 1.1f / scale);
|
||||
|
||||
Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_tags, new FragmentMastodonAnnouncement(), null, null, null);
|
||||
if (emojis == null || !emojis.containsKey(currentInstance)) {
|
||||
new Thread(() -> {
|
|
@ -1,5 +1,5 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2023 Thomas Schneider
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
|
@ -15,28 +15,32 @@ package app.fedilab.android.activities;
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
import app.fedilab.android.databinding.ActivityMainPeertubeBinding;
|
||||
import app.fedilab.android.mastodon.activities.BaseActivity;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.jaredrummler.cyanea.app.CyaneaAppCompatActivity;
|
||||
import com.vanniktech.emoji.EmojiManager;
|
||||
import com.vanniktech.emoji.one.EmojiOneProvider;
|
||||
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
|
||||
|
||||
public class PeertubeBaseMainActivity extends BaseActivity {
|
||||
@SuppressLint("Registered")
|
||||
public class BaseActivity extends CyaneaAppCompatActivity {
|
||||
|
||||
protected ActivityMainPeertubeBinding parentBinding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
parentBinding = ActivityMainPeertubeBinding.inflate(getLayoutInflater());
|
||||
View view = parentBinding.getRoot();
|
||||
setContentView(view);
|
||||
static {
|
||||
Helper.installProvider();
|
||||
EmojiManager.install(new EmojiOneProvider());
|
||||
}
|
||||
|
||||
//Method for discovering cast devices
|
||||
public void discoverCast() {
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ThemeHelper.adjustFontScale(this, getResources().getConfiguration());
|
||||
Helper.setLocale(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.client.entities.app;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -14,21 +14,23 @@ package app.fedilab.android.mastodon.client.entities.app;
|
|||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import android.annotation.SuppressLint;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import com.jaredrummler.cyanea.app.CyaneaFragmentActivity;
|
||||
import com.vanniktech.emoji.EmojiManager;
|
||||
import com.vanniktech.emoji.one.EmojiOneProvider;
|
||||
|
||||
import app.fedilab.android.helper.Helper;
|
||||
|
||||
|
||||
public class Quotes implements Serializable {
|
||||
@SuppressLint("Registered")
|
||||
public class BaseFragmentActivity extends CyaneaFragmentActivity {
|
||||
|
||||
@SerializedName("quotes")
|
||||
public List<Quote> quotes;
|
||||
|
||||
public static class Quote implements Serializable {
|
||||
@SerializedName("author")
|
||||
public String author;
|
||||
@SerializedName("content")
|
||||
public String content;
|
||||
static {
|
||||
Helper.installProvider();
|
||||
EmojiManager.install(new EmojiOneProvider());
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package app.fedilab.android.mastodon.activities;
|
||||
package app.fedilab.android.activities;
|
||||
/* Copyright 2022 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
|
@ -15,6 +15,7 @@ package app.fedilab.android.mastodon.activities;
|
|||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
@ -24,27 +25,24 @@ import android.view.MenuItem;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.app.Account;
|
||||
import app.fedilab.android.client.entities.app.BaseAccount;
|
||||
import app.fedilab.android.client.entities.app.CacheAccount;
|
||||
import app.fedilab.android.databinding.ActivityCacheBinding;
|
||||
import app.fedilab.android.mastodon.client.entities.app.Account;
|
||||
import app.fedilab.android.mastodon.client.entities.app.BaseAccount;
|
||||
import app.fedilab.android.mastodon.client.entities.app.CacheAccount;
|
||||
import app.fedilab.android.mastodon.client.entities.app.StatusCache;
|
||||
import app.fedilab.android.mastodon.client.entities.app.StatusDraft;
|
||||
import app.fedilab.android.mastodon.exception.DBException;
|
||||
import app.fedilab.android.mastodon.helper.CacheHelper;
|
||||
import app.fedilab.android.mastodon.helper.Helper;
|
||||
import app.fedilab.android.mastodon.ui.drawer.CacheAdapter;
|
||||
import app.fedilab.android.helper.CacheHelper;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.ui.drawer.CacheAdapter;
|
||||
|
||||
public class CacheActivity extends BaseBarActivity {
|
||||
public class CacheActivity extends BaseActivity {
|
||||
|
||||
private ActivityCacheBinding binding;
|
||||
private List<CacheAccount> cacheAccounts;
|
||||
|
@ -53,11 +51,12 @@ public class CacheActivity extends BaseBarActivity {
|
|||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
ThemeHelper.applyThemeBar(this);
|
||||
binding = ActivityCacheBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
CacheHelper.getCacheValues(CacheActivity.this, size -> {
|
||||
if (size > 0) {
|
||||
|
@ -68,35 +67,13 @@ public class CacheActivity extends BaseBarActivity {
|
|||
|
||||
|
||||
new Thread(() -> {
|
||||
List<BaseAccount> accounts;
|
||||
List<BaseAccount> accounts = new Account(CacheActivity.this).getPushNotificationAccounts();
|
||||
cacheAccounts = new ArrayList<>();
|
||||
try {
|
||||
accounts = new Account(CacheActivity.this).getAll();
|
||||
for (BaseAccount baseAccount : accounts) {
|
||||
CacheAccount cacheAccount = new CacheAccount();
|
||||
cacheAccount.account = baseAccount;
|
||||
try {
|
||||
cacheAccount.home_cache_count = new StatusCache(CacheActivity.this).countHome(baseAccount);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
cacheAccount.other_cache_count = new StatusCache(CacheActivity.this).countOther(baseAccount);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
cacheAccount.draft_count = new StatusDraft(CacheActivity.this).count(baseAccount);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
cacheAccounts.add(cacheAccount);
|
||||
}
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
for (BaseAccount baseAccount : accounts) {
|
||||
CacheAccount cacheAccount = new CacheAccount();
|
||||
cacheAccount.account = baseAccount;
|
||||
cacheAccounts.add(cacheAccount);
|
||||
}
|
||||
|
||||
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
cacheAdapter = new CacheAdapter(cacheAccounts);
|
||||
|
@ -121,7 +98,7 @@ public class CacheActivity extends BaseBarActivity {
|
|||
finish();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_clear) {
|
||||
AlertDialog.Builder deleteConfirm = new MaterialAlertDialogBuilder(CacheActivity.this);
|
||||
AlertDialog.Builder deleteConfirm = new AlertDialog.Builder(CacheActivity.this, Helper.dialogStyle());
|
||||
deleteConfirm.setTitle(getString(R.string.delete_cache));
|
||||
deleteConfirm.setMessage(getString(R.string.delete_cache_message));
|
||||
deleteConfirm.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
|
||||
|
@ -131,21 +108,7 @@ public class CacheActivity extends BaseBarActivity {
|
|||
size = size / 1000000.0f;
|
||||
}
|
||||
binding.fileCacheSize.setText(String.format("%s %s", String.format(Locale.getDefault(), "%.2f", size), getString(R.string.cache_units)));
|
||||
AlertDialog.Builder restartBuilder = new MaterialAlertDialogBuilder(CacheActivity.this);
|
||||
restartBuilder.setMessage(getString(R.string.restart_the_app));
|
||||
restartBuilder.setNegativeButton(R.string.no, (dialogRestart, whichRestart) -> {
|
||||
recreate();
|
||||
dialogRestart.dismiss();
|
||||
});
|
||||
restartBuilder.setPositiveButton(R.string.restart, (dialogRestart, whichRestart) -> {
|
||||
dialogRestart.dismiss();
|
||||
Helper.restart(CacheActivity.this);
|
||||
});
|
||||
AlertDialog alertDialog = restartBuilder.create();
|
||||
if (!isFinishing()) {
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
cacheAdapter.notifyDataSetChanged();
|
||||
}));
|
||||
dialog.dismiss();
|
||||
});
|
|
@ -0,0 +1,841 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
||||
import static app.fedilab.android.BaseMainActivity.currentInstance;
|
||||
import static app.fedilab.android.BaseMainActivity.emojis;
|
||||
import static app.fedilab.android.ui.drawer.ComposeAdapter.prepareDraft;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ClipData;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.work.Data;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Attachment;
|
||||
import app.fedilab.android.client.entities.api.Context;
|
||||
import app.fedilab.android.client.entities.api.EmojiInstance;
|
||||
import app.fedilab.android.client.entities.api.Instance;
|
||||
import app.fedilab.android.client.entities.api.Mention;
|
||||
import app.fedilab.android.client.entities.api.ScheduledStatus;
|
||||
import app.fedilab.android.client.entities.api.Status;
|
||||
import app.fedilab.android.client.entities.app.BaseAccount;
|
||||
import app.fedilab.android.client.entities.app.Languages;
|
||||
import app.fedilab.android.client.entities.app.StatusDraft;
|
||||
import app.fedilab.android.databinding.ActivityPaginationBinding;
|
||||
import app.fedilab.android.databinding.PopupContactBinding;
|
||||
import app.fedilab.android.exception.DBException;
|
||||
import app.fedilab.android.helper.DividerDecorationSimple;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.MediaHelper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.interfaces.OnDownloadInterface;
|
||||
import app.fedilab.android.jobs.ScheduleThreadWorker;
|
||||
import app.fedilab.android.services.PostMessageService;
|
||||
import app.fedilab.android.services.ThreadMessageService;
|
||||
import app.fedilab.android.ui.drawer.AccountsReplyAdapter;
|
||||
import app.fedilab.android.ui.drawer.ComposeAdapter;
|
||||
import app.fedilab.android.viewmodel.mastodon.AccountsVM;
|
||||
import app.fedilab.android.viewmodel.mastodon.StatusesVM;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
|
||||
public class ComposeActivity extends BaseActivity implements ComposeAdapter.ManageDrafts, AccountsReplyAdapter.ActionDone {
|
||||
|
||||
|
||||
public static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 754;
|
||||
public static final int REQUEST_AUDIO_PERMISSION_RESULT = 1653;
|
||||
public static final int PICK_MEDIA = 5700;
|
||||
public static final int TAKE_PHOTO = 5600;
|
||||
private final Timer timer = new Timer();
|
||||
private List<Status> statusList;
|
||||
private Status statusReply, statusMention;
|
||||
private StatusDraft statusDraft;
|
||||
private ComposeAdapter composeAdapter;
|
||||
private final BroadcastReceiver imageReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(android.content.Context context, Intent intent) {
|
||||
String imgpath = intent.getStringExtra("imgpath");
|
||||
float focusX = intent.getFloatExtra("focusX", -2);
|
||||
float focusY = intent.getFloatExtra("focusY", -2);
|
||||
if (imgpath != null) {
|
||||
int position = 0;
|
||||
for (Status status : statusList) {
|
||||
if (status.media_attachments != null && status.media_attachments.size() > 0) {
|
||||
for (Attachment attachment : status.media_attachments) {
|
||||
if (attachment.local_path.equalsIgnoreCase(imgpath)) {
|
||||
if (focusX != -2) {
|
||||
attachment.focus = focusX + "," + focusY;
|
||||
}
|
||||
composeAdapter.notifyItemChanged(position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
private ActivityPaginationBinding binding;
|
||||
private BaseAccount account;
|
||||
private String instance, token;
|
||||
private Uri photoFileUri;
|
||||
private ScheduledStatus scheduledStatus;
|
||||
private String visibility;
|
||||
private app.fedilab.android.client.entities.api.Account accountMention;
|
||||
private String statusReplyId;
|
||||
private app.fedilab.android.client.entities.api.Account mentionBooster;
|
||||
private ArrayList<Uri> sharedUriList = new ArrayList<>();
|
||||
private Uri sharedUri;
|
||||
private String sharedSubject, sharedContent, sharedTitle, sharedDescription, shareURL, sharedUrlMedia;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ThemeHelper.applyTheme(this);
|
||||
binding = ActivityPaginationBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
statusList = new ArrayList<>();
|
||||
Bundle b = getIntent().getExtras();
|
||||
if (b != null) {
|
||||
statusReply = (Status) b.getSerializable(Helper.ARG_STATUS_REPLY);
|
||||
statusDraft = (StatusDraft) b.getSerializable(Helper.ARG_STATUS_DRAFT);
|
||||
scheduledStatus = (ScheduledStatus) b.getSerializable(Helper.ARG_STATUS_SCHEDULED);
|
||||
statusReplyId = b.getString(Helper.ARG_STATUS_REPLY_ID);
|
||||
statusMention = (Status) b.getSerializable(Helper.ARG_STATUS_MENTION);
|
||||
account = (BaseAccount) b.getSerializable(Helper.ARG_ACCOUNT);
|
||||
instance = b.getString(Helper.ARG_INSTANCE, null);
|
||||
token = b.getString(Helper.ARG_TOKEN, null);
|
||||
visibility = b.getString(Helper.ARG_VISIBILITY, null);
|
||||
mentionBooster = (app.fedilab.android.client.entities.api.Account) b.getSerializable(Helper.ARG_MENTION_BOOSTER);
|
||||
accountMention = (app.fedilab.android.client.entities.api.Account) b.getSerializable(Helper.ARG_ACCOUNT_MENTION);
|
||||
//Shared elements
|
||||
sharedUriList = b.getParcelableArrayList(Helper.ARG_SHARE_URI_LIST);
|
||||
sharedUri = b.getParcelable(Helper.ARG_SHARE_URI);
|
||||
sharedUrlMedia = b.getString(Helper.ARG_SHARE_URL_MEDIA);
|
||||
sharedSubject = b.getString(Helper.ARG_SHARE_SUBJECT, null);
|
||||
sharedContent = b.getString(Helper.ARG_SHARE_CONTENT, null);
|
||||
sharedTitle = b.getString(Helper.ARG_SHARE_TITLE, null);
|
||||
sharedDescription = b.getString(Helper.ARG_SHARE_DESCRIPTION, null);
|
||||
shareURL = b.getString(Helper.ARG_SHARE_URL, null);
|
||||
}
|
||||
|
||||
|
||||
binding.toolbar.setPopupTheme(Helper.popupStyle());
|
||||
//Edit a scheduled status from server
|
||||
if (scheduledStatus != null) {
|
||||
statusDraft = new StatusDraft();
|
||||
List<Status> statuses = new ArrayList<>();
|
||||
Status status = new Status();
|
||||
status.text = scheduledStatus.params.text;
|
||||
status.in_reply_to_id = scheduledStatus.params.in_reply_to_id;
|
||||
status.poll = scheduledStatus.params.poll;
|
||||
|
||||
if (scheduledStatus.params.media_ids != null && scheduledStatus.params.media_ids.size() > 0) {
|
||||
status.media_attachments = new ArrayList<>();
|
||||
new Thread(() -> {
|
||||
StatusesVM statusesVM = new ViewModelProvider(ComposeActivity.this).get(StatusesVM.class);
|
||||
for (String attachmentId : scheduledStatus.params.media_ids) {
|
||||
statusesVM.getAttachment(instance, token, attachmentId)
|
||||
.observe(ComposeActivity.this, attachment -> status.media_attachments.add(attachment));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
status.sensitive = scheduledStatus.params.sensitive;
|
||||
status.spoiler_text = scheduledStatus.params.spoiler_text;
|
||||
status.visibility = scheduledStatus.params.visibility;
|
||||
statusDraft.statusDraftList = statuses;
|
||||
}
|
||||
if (account == null) {
|
||||
account = currentAccount;
|
||||
}
|
||||
if (account == null) {
|
||||
Toasty.error(ComposeActivity.this, getString(R.string.toast_error), Toasty.LENGTH_SHORT).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (instance == null) {
|
||||
instance = account.instance;
|
||||
}
|
||||
if (token == null) {
|
||||
token = account.token;
|
||||
}
|
||||
if (emojis == null || !emojis.containsKey(currentInstance)) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
emojis.put(currentInstance, new EmojiInstance(ComposeActivity.this).getEmojiList(currentInstance));
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ComposeActivity.this);
|
||||
if (MainActivity.instanceInfo == null) {
|
||||
String instanceInfo = sharedpreferences.getString(getString(R.string.INSTANCE_INFO) + instance, null);
|
||||
if (instanceInfo != null) {
|
||||
MainActivity.instanceInfo = Instance.restore(instanceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
StatusesVM statusesVM = new ViewModelProvider(ComposeActivity.this).get(StatusesVM.class);
|
||||
//Empty compose
|
||||
List<Status> statusDraftList = new ArrayList<>();
|
||||
Status status = new Status();
|
||||
statusDraftList.add(status);
|
||||
|
||||
if (statusReplyId != null && statusDraft != null) {//Delete and redraft
|
||||
statusesVM.getStatus(currentInstance, BaseMainActivity.currentToken, statusReplyId)
|
||||
.observe(ComposeActivity.this, status1 -> {
|
||||
if (status1 != null) {
|
||||
statusesVM.getContext(currentInstance, BaseMainActivity.currentToken, statusReplyId)
|
||||
.observe(ComposeActivity.this, statusContext -> {
|
||||
if (statusContext != null) {
|
||||
initializeContextRedraftView(statusContext, status1);
|
||||
} else {
|
||||
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Helper.sendToastMessage(getApplication(), Helper.RECEIVE_TOAST_TYPE_ERROR, getString(R.string.toast_error));
|
||||
}
|
||||
});
|
||||
} else if (statusDraft != null) {//Restore a draft with all messages
|
||||
if (statusDraft.statusReplyList != null) {
|
||||
statusList.addAll(statusDraft.statusReplyList);
|
||||
binding.recyclerView.addItemDecoration(new DividerDecorationSimple(ComposeActivity.this, statusList));
|
||||
}
|
||||
int statusCount = statusList.size();
|
||||
statusList.addAll(statusDraft.statusDraftList);
|
||||
composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility);
|
||||
composeAdapter.manageDrafts = this;
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
|
||||
binding.recyclerView.setLayoutManager(mLayoutManager);
|
||||
binding.recyclerView.setAdapter(composeAdapter);
|
||||
binding.recyclerView.scrollToPosition(composeAdapter.getItemCount() - 1);
|
||||
|
||||
} else if (statusReply != null) {
|
||||
statusList.add(statusReply);
|
||||
int statusCount = statusList.size();
|
||||
statusDraftList.get(0).in_reply_to_id = statusReply.id;
|
||||
//We change order for mentions
|
||||
//At first place the account that has been mentioned if it's not our
|
||||
statusDraftList.get(0).mentions = new ArrayList<>();
|
||||
if (statusReply.account.acct != null && !statusReply.account.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
|
||||
Mention mention = new Mention();
|
||||
mention.acct = "@" + statusReply.account.acct;
|
||||
mention.url = statusReply.account.url;
|
||||
mention.username = statusReply.account.username;
|
||||
statusDraftList.get(0).mentions.add(mention);
|
||||
}
|
||||
|
||||
//There are other mentions to
|
||||
if (statusReply.mentions != null && statusReply.mentions.size() > 0) {
|
||||
for (Mention mentionTmp : statusReply.mentions) {
|
||||
if (statusReply.account.acct != null && !mentionTmp.acct.equalsIgnoreCase(statusReply.account.acct) && !mentionTmp.acct.equalsIgnoreCase(currentAccount.mastodon_account.acct)) {
|
||||
statusDraftList.get(0).mentions.add(mentionTmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mentionBooster != null) {
|
||||
Mention mention = new Mention();
|
||||
mention.acct = mentionBooster.acct;
|
||||
mention.url = mentionBooster.url;
|
||||
mention.username = mentionBooster.username;
|
||||
boolean present = false;
|
||||
for (Mention mentionTmp : statusDraftList.get(0).mentions) {
|
||||
if (mentionTmp.acct.equalsIgnoreCase(mentionBooster.acct)) {
|
||||
present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!present) {
|
||||
statusDraftList.get(0).mentions.add(mention);
|
||||
}
|
||||
}
|
||||
if (statusReply.spoiler_text != null) {
|
||||
statusDraftList.get(0).spoiler_text = statusReply.spoiler_text;
|
||||
}
|
||||
//StatusDraftList at this point should only have one element
|
||||
statusList.addAll(statusDraftList);
|
||||
composeAdapter = new ComposeAdapter(statusList, statusCount, account, accountMention, visibility);
|
||||
composeAdapter.manageDrafts = this;
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
|
||||
binding.recyclerView.setLayoutManager(mLayoutManager);
|
||||
binding.recyclerView.setAdapter(composeAdapter);
|
||||
statusesVM.getContext(currentInstance, BaseMainActivity.currentToken, statusReply.id)
|
||||
.observe(ComposeActivity.this, this::initializeContextView);
|
||||
} else {
|
||||
//Compose without replying
|
||||
statusList.addAll(statusDraftList);
|
||||
composeAdapter = new ComposeAdapter(statusList, 0, account, accountMention, visibility);
|
||||
composeAdapter.manageDrafts = this;
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
|
||||
binding.recyclerView.setLayoutManager(mLayoutManager);
|
||||
binding.recyclerView.setAdapter(composeAdapter);
|
||||
if (statusMention != null) {
|
||||
composeAdapter.loadMentions(statusMention);
|
||||
}
|
||||
}
|
||||
MastodonHelper.loadPPMastodon(binding.profilePicture, account.mastodon_account);
|
||||
LocalBroadcastManager.getInstance(this)
|
||||
.registerReceiver(imageReceiver,
|
||||
new IntentFilter(Helper.INTENT_SEND_MODIFIED_IMAGE));
|
||||
|
||||
if (timer != null) {
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
storeDraft(false);
|
||||
}
|
||||
}, 0, 10000);
|
||||
}
|
||||
|
||||
if (sharedUriList != null && sharedUriList.size() > 0) {
|
||||
|
||||
Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
List<Uri> uris = new ArrayList<>(sharedUriList);
|
||||
composeAdapter.addAttachment(-1, uris);
|
||||
}, 1000);
|
||||
} else if (sharedUri != null && !sharedUri.toString().startsWith("http")) {
|
||||
Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
List<Uri> uris = new ArrayList<>();
|
||||
uris.add(sharedUri);
|
||||
composeAdapter.addAttachment(-1, uris);
|
||||
}, 1000);
|
||||
} else if (shareURL != null) {
|
||||
Helper.download(ComposeActivity.this, sharedUrlMedia, new OnDownloadInterface() {
|
||||
@Override
|
||||
public void onDownloaded(String saveFilePath, String downloadUrl, Error error) {
|
||||
composeAdapter.addSharing(shareURL, sharedTitle, sharedDescription, sharedSubject, sharedContent, saveFilePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdateProgress(int progress) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
}
|
||||
LocalBroadcastManager.getInstance(this)
|
||||
.unregisterReceiver(imageReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
storeDraftWarning();
|
||||
}
|
||||
|
||||
private void storeDraftWarning() {
|
||||
if (statusDraft == null) {
|
||||
statusDraft = prepareDraft(statusList, composeAdapter, account.instance, account.user_id);
|
||||
}
|
||||
if (canBeSent(statusDraft)) {
|
||||
AlertDialog.Builder alt_bld = new AlertDialog.Builder(ComposeActivity.this, Helper.dialogStyle());
|
||||
alt_bld.setMessage(R.string.save_draft);
|
||||
alt_bld.setPositiveButton(R.string.save, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
storeDraft(false);
|
||||
finish();
|
||||
|
||||
});
|
||||
alt_bld.setNegativeButton(R.string.no, (dialog, id) -> {
|
||||
dialog.dismiss();
|
||||
finish();
|
||||
});
|
||||
AlertDialog alert = alt_bld.create();
|
||||
alert.show();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intialize the common view for the context
|
||||
*
|
||||
* @param context {@link Context}
|
||||
*/
|
||||
private void initializeContextView(final Context context) {
|
||||
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
//Build the array of statuses
|
||||
statusList.addAll(0, context.ancestors);
|
||||
composeAdapter.setStatusCount(context.ancestors.size() + 1);
|
||||
composeAdapter.notifyItemRangeInserted(0, context.ancestors.size());
|
||||
composeAdapter.notifyItemChanged(context.ancestors.size() + 1);
|
||||
if (binding.recyclerView.getItemDecorationCount() > 0) {
|
||||
for (int i = 0; i < binding.recyclerView.getItemDecorationCount(); i++) {
|
||||
binding.recyclerView.removeItemDecorationAt(i);
|
||||
}
|
||||
}
|
||||
binding.recyclerView.addItemDecoration(new DividerDecorationSimple(ComposeActivity.this, statusList));
|
||||
binding.recyclerView.scrollToPosition(composeAdapter.getItemCount() - 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Intialize the common view for the context
|
||||
*
|
||||
* @param context {@link Context}
|
||||
*/
|
||||
private void initializeContextRedraftView(final Context context, Status initialStatus) {
|
||||
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Build the array of statuses
|
||||
statusList.addAll(0, context.ancestors);
|
||||
statusList.add(initialStatus);
|
||||
statusList.add(statusDraft.statusDraftList.get(0));
|
||||
composeAdapter = new ComposeAdapter(statusList, context.ancestors.size(), account, accountMention, visibility);
|
||||
composeAdapter.manageDrafts = this;
|
||||
LinearLayoutManager mLayoutManager = new LinearLayoutManager(ComposeActivity.this);
|
||||
binding.recyclerView.setLayoutManager(mLayoutManager);
|
||||
binding.recyclerView.setAdapter(composeAdapter);
|
||||
composeAdapter.setStatusCount(context.ancestors.size() + 1);
|
||||
binding.recyclerView.addItemDecoration(new DividerDecorationSimple(ComposeActivity.this, statusList));
|
||||
binding.recyclerView.scrollToPosition(composeAdapter.getItemCount() - 1);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_compose, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
storeDraftWarning();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_photo_camera) {
|
||||
photoFileUri = MediaHelper.dispatchTakePictureIntent(ComposeActivity.this);
|
||||
} else if (item.getItemId() == R.id.action_contacts) {
|
||||
AlertDialog.Builder builderSingle = new AlertDialog.Builder(ComposeActivity.this, Helper.dialogStyle());
|
||||
|
||||
builderSingle.setTitle(getString(R.string.select_accounts));
|
||||
PopupContactBinding popupContactBinding = PopupContactBinding.inflate(getLayoutInflater(), new LinearLayout(ComposeActivity.this), false);
|
||||
popupContactBinding.loader.setVisibility(View.VISIBLE);
|
||||
AccountsVM accountsVM = new ViewModelProvider(ComposeActivity.this).get(AccountsVM.class);
|
||||
accountsVM.searchAccounts(instance, token, "", 10, false, true)
|
||||
.observe(ComposeActivity.this, accounts -> onRetrieveContact(popupContactBinding, accounts));
|
||||
|
||||
popupContactBinding.searchAccount.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
if (count > 0) {
|
||||
popupContactBinding.searchAccount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_baseline_close_24, 0);
|
||||
} else {
|
||||
popupContactBinding.searchAccount.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_baseline_search_24, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s != null && s.length() > 0) {
|
||||
accountsVM.searchAccounts(instance, token, s.toString().trim(), 10, false, true)
|
||||
.observe(ComposeActivity.this, accounts -> onRetrieveContact(popupContactBinding, accounts));
|
||||
}
|
||||
}
|
||||
});
|
||||
popupContactBinding.searchAccount.setOnTouchListener((v, event) -> {
|
||||
final int DRAWABLE_RIGHT = 2;
|
||||
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (popupContactBinding.searchAccount.length() > 0 && event.getRawX() >= (popupContactBinding.searchAccount.getRight() - popupContactBinding.searchAccount.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
|
||||
popupContactBinding.searchAccount.setText("");
|
||||
accountsVM.searchAccounts(instance, token, "", 10, false, true)
|
||||
.observe(ComposeActivity.this, accounts -> onRetrieveContact(popupContactBinding, accounts));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
builderSingle.setView(popupContactBinding.getRoot());
|
||||
builderSingle.setNegativeButton(R.string.validate, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
composeAdapter.putCursor();
|
||||
});
|
||||
builderSingle.show();
|
||||
} else if (item.getItemId() == R.id.action_microphone) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ==
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
MediaHelper.recordAudio(ComposeActivity.this, file -> {
|
||||
List<Uri> uris = new ArrayList<>();
|
||||
uris.add(Uri.fromFile(new File(file)));
|
||||
composeAdapter.addAttachment(-1, uris);
|
||||
});
|
||||
} else {
|
||||
if (shouldShowRequestPermissionRationale(Manifest.permission.RECORD_AUDIO)) {
|
||||
Toast.makeText(this,
|
||||
getString(R.string.audio), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO
|
||||
}, REQUEST_AUDIO_PERMISSION_RESULT);
|
||||
}
|
||||
|
||||
} else {
|
||||
MediaHelper.recordAudio(ComposeActivity.this, file -> {
|
||||
List<Uri> uris = new ArrayList<>();
|
||||
uris.add(Uri.fromFile(new File(file)));
|
||||
composeAdapter.addAttachment(-1, uris);
|
||||
});
|
||||
}
|
||||
} else if (item.getItemId() == R.id.action_schedule) {
|
||||
if (statusDraft == null) {
|
||||
statusDraft = prepareDraft(statusList, composeAdapter, account.instance, account.user_id);
|
||||
}
|
||||
if (canBeSent(statusDraft)) {
|
||||
MediaHelper.scheduleMessage(ComposeActivity.this, date -> storeDraft(true, date));
|
||||
} else {
|
||||
Toasty.info(ComposeActivity.this, getString(R.string.toot_error_no_content), Toasty.LENGTH_SHORT).show();
|
||||
}
|
||||
} else if (item.getItemId() == R.id.action_language) {
|
||||
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ComposeActivity.this);
|
||||
List<Languages.Language> languages = Languages.get(ComposeActivity.this);
|
||||
String[] codesArr = new String[0];
|
||||
String[] languagesArr = new String[0];
|
||||
|
||||
String currentCode = sharedpreferences.getString(getString(R.string.SET_COMPOSE_LANGUAGE) + account.user_id + account.instance, null);
|
||||
int selection = 0;
|
||||
|
||||
if (languages != null) {
|
||||
codesArr = new String[languages.size()];
|
||||
languagesArr = new String[languages.size()];
|
||||
int i = 0;
|
||||
for (Languages.Language language : languages) {
|
||||
codesArr[i] = language.code;
|
||||
languagesArr[i] = language.language;
|
||||
if (currentCode != null && currentCode.equalsIgnoreCase(language.code)) {
|
||||
selection = i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ComposeActivity.this, Helper.dialogStyle());
|
||||
builder.setTitle(getString(R.string.message_language));
|
||||
|
||||
builder.setSingleChoiceItems(languagesArr, selection, null);
|
||||
String[] finalCodesArr = codesArr;
|
||||
builder.setPositiveButton(R.string.validate, (dialog, which) -> {
|
||||
int selectedPosition = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
|
||||
editor.putString(getString(R.string.SET_COMPOSE_LANGUAGE) + account.user_id + account.instance, finalCodesArr[selectedPosition]);
|
||||
editor.apply();
|
||||
dialog.dismiss();
|
||||
});
|
||||
builder.setNegativeButton(R.string.reset, (dialog, which) -> {
|
||||
editor.putString(getString(R.string.SET_COMPOSE_LANGUAGE) + account.user_id + account.instance, null);
|
||||
editor.apply();
|
||||
dialog.dismiss();
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void onRetrieveContact(PopupContactBinding binding, List<app.fedilab.android.client.entities.api.Account> accounts) {
|
||||
binding.loader.setVisibility(View.GONE);
|
||||
if (accounts == null) {
|
||||
accounts = new ArrayList<>();
|
||||
}
|
||||
List<Boolean> checkedValues = new ArrayList<>();
|
||||
List<app.fedilab.android.client.entities.api.Account> contacts = new ArrayList<>(accounts);
|
||||
for (app.fedilab.android.client.entities.api.Account account : contacts) {
|
||||
checkedValues.add(composeAdapter.getLastComposeContent().contains("@" + account.acct));
|
||||
}
|
||||
AccountsReplyAdapter contactAdapter = new AccountsReplyAdapter(contacts, checkedValues);
|
||||
binding.lvAccountsSearch.setAdapter(contactAdapter);
|
||||
binding.lvAccountsSearch.setLayoutManager(new LinearLayoutManager(ComposeActivity.this));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
List<Uri> uris = new ArrayList<>();
|
||||
if (requestCode >= PICK_MEDIA && resultCode == RESULT_OK) {
|
||||
ClipData clipData = data.getClipData();
|
||||
int position = requestCode - PICK_MEDIA;
|
||||
if (clipData != null) {
|
||||
for (int i = 0; i < clipData.getItemCount(); i++) {
|
||||
ClipData.Item item = clipData.getItemAt(i);
|
||||
uris.add(item.getUri());
|
||||
}
|
||||
} else {
|
||||
uris.add(data.getData());
|
||||
}
|
||||
composeAdapter.addAttachment(position, uris);
|
||||
} else if (requestCode == TAKE_PHOTO && resultCode == RESULT_OK) {
|
||||
uris.add(photoFileUri);
|
||||
composeAdapter.addAttachment(-1, uris);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDraftAdded(int position) {
|
||||
Status status = new Status();
|
||||
status.mentions = statusList.get(position).mentions;
|
||||
status.visibility = statusList.get(position).visibility;
|
||||
status.spoiler_text = statusList.get(position).spoiler_text;
|
||||
status.sensitive = statusList.get(position).sensitive;
|
||||
statusList.add(status);
|
||||
composeAdapter.notifyItemInserted(position + 1);
|
||||
binding.recyclerView.smoothScrollToPosition(position + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemDraftDeleted(Status status, int position) {
|
||||
statusList.remove(status);
|
||||
composeAdapter.notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubmit(StatusDraft draft) {
|
||||
//Store in drafts
|
||||
if (statusDraft == null) {
|
||||
statusDraft = draft;
|
||||
} else {
|
||||
statusDraft.statusDraftList = draft.statusDraftList;
|
||||
}
|
||||
storeDraft(true);
|
||||
}
|
||||
|
||||
|
||||
private void storeDraft(boolean sendMessage) {
|
||||
storeDraft(sendMessage, null);
|
||||
}
|
||||
|
||||
private void storeDraft(boolean sendMessage, String scheduledDate) {
|
||||
new Thread(() -> {
|
||||
//Collect all statusCompose
|
||||
List<Status> statusDrafts = new ArrayList<>();
|
||||
List<Status> statusReplies = new ArrayList<>();
|
||||
for (Status status : statusList) {
|
||||
if (status.id == null) {
|
||||
statusDrafts.add(status);
|
||||
} else {
|
||||
statusReplies.add(status);
|
||||
}
|
||||
|
||||
}
|
||||
if (statusDraft == null) {
|
||||
statusDraft = new StatusDraft(ComposeActivity.this);
|
||||
} else {
|
||||
//Draft previously and date is changed
|
||||
if (statusDraft.scheduled_at != null && scheduledDate != null && statusDraft.workerUuid != null) {
|
||||
WorkManager.getInstance(ComposeActivity.this).cancelWorkById(statusDraft.workerUuid);
|
||||
}
|
||||
}
|
||||
if (statusReplies.size() > 0) {
|
||||
statusDraft.statusReplyList = new ArrayList<>();
|
||||
statusDraft.statusReplyList.addAll(statusReplies);
|
||||
}
|
||||
if (statusDrafts.size() > 0) {
|
||||
statusDraft.statusDraftList = new ArrayList<>();
|
||||
statusDraft.statusDraftList.addAll(statusDrafts);
|
||||
}
|
||||
if (statusDraft.instance == null) {
|
||||
statusDraft.instance = account.instance;
|
||||
}
|
||||
if (statusDraft.user_id == null) {
|
||||
statusDraft.user_id = account.user_id;
|
||||
}
|
||||
|
||||
if (!canBeSent(statusDraft)) {
|
||||
return;
|
||||
}
|
||||
if (statusDraft.id > 0) {
|
||||
try {
|
||||
new StatusDraft(ComposeActivity.this).updateStatusDraft(statusDraft);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
statusDraft.id = new StatusDraft(ComposeActivity.this).insertStatusDraft(statusDraft);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//Only one single message scheduled
|
||||
if (sendMessage && scheduledDate != null && statusDraft.statusDraftList.size() > 1) {
|
||||
//Schedule a thread
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(Helper.SCHEDULE_DATE_FORMAT, Locale.getDefault());
|
||||
Date date;
|
||||
try {
|
||||
date = sdf.parse(scheduledDate);
|
||||
long delayToPass = 0;
|
||||
if (date != null) {
|
||||
delayToPass = (date.getTime() - new Date().getTime());
|
||||
}
|
||||
Data inputData = new Data.Builder()
|
||||
.putString(Helper.ARG_INSTANCE, currentInstance)
|
||||
.putString(Helper.ARG_TOKEN, BaseMainActivity.currentToken)
|
||||
.putString(Helper.ARG_USER_ID, BaseMainActivity.currentUserID)
|
||||
.putLong(Helper.ARG_STATUS_DRAFT_ID, statusDraft.id)
|
||||
.build();
|
||||
|
||||
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(ScheduleThreadWorker.class)
|
||||
.setInputData(inputData)
|
||||
.addTag(Helper.WORKER_SCHEDULED_STATUSES)
|
||||
.setInitialDelay(delayToPass, TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
statusDraft.workerUuid = oneTimeWorkRequest.getId();
|
||||
statusDraft.scheduled_at = date;
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
Runnable myRunnable = () -> {
|
||||
Toasty.info(ComposeActivity.this, getString(R.string.toot_scheduled), Toasty.LENGTH_LONG).show();
|
||||
finish();
|
||||
};
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if (sendMessage) {
|
||||
int mediaCount = 0;
|
||||
for (Status status : statusDraft.statusDraftList) {
|
||||
mediaCount += status.media_attachments != null ? status.media_attachments.size() : 0;
|
||||
}
|
||||
if (mediaCount > 0) {
|
||||
Intent intent = new Intent(ComposeActivity.this, PostMessageService.class);
|
||||
intent.putExtra(Helper.ARG_STATUS_DRAFT, statusDraft);
|
||||
intent.putExtra(Helper.ARG_INSTANCE, instance);
|
||||
intent.putExtra(Helper.ARG_TOKEN, token);
|
||||
intent.putExtra(Helper.ARG_USER_ID, account.user_id);
|
||||
intent.putExtra(Helper.ARG_SCHEDULED_DATE, scheduledDate);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
startForegroundService(intent);
|
||||
} else {
|
||||
startService(intent);
|
||||
}
|
||||
} else {
|
||||
new ThreadMessageService(ComposeActivity.this, instance, account.user_id, token, statusDraft, scheduledDate);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
private boolean canBeSent(StatusDraft statusDraft) {
|
||||
if (statusDraft == null || statusDraft.statusDraftList == null || statusDraft.statusDraftList.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
Status statusCheck = statusDraft.statusDraftList.get(0);
|
||||
if (statusCheck == null) {
|
||||
return false;
|
||||
}
|
||||
return (statusCheck.text != null && statusCheck.text.trim().length() != 0)
|
||||
|| (statusCheck.media_attachments != null && statusCheck.media_attachments.size() != 0)
|
||||
|| statusCheck.poll != null
|
||||
|| (statusCheck.spoiler_text != null && statusCheck.spoiler_text.trim().length() != 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onContactClick(boolean isChecked, String acct) {
|
||||
composeAdapter.updateContent(isChecked, acct);
|
||||
}
|
||||
|
||||
|
||||
public enum mediaType {
|
||||
PHOTO,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
ALL
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package app.fedilab.android.activities;
|
||||
/* Copyright 2021 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
|
||||
import static app.fedilab.android.BaseMainActivity.currentAccount;
|
||||
import static app.fedilab.android.ui.drawer.StatusAdapter.sendAction;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import app.fedilab.android.BaseMainActivity;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.client.entities.api.Status;
|
||||
import app.fedilab.android.client.entities.app.QuickLoad;
|
||||
import app.fedilab.android.client.entities.app.StatusCache;
|
||||
import app.fedilab.android.databinding.ActivityConversationBinding;
|
||||
import app.fedilab.android.exception.DBException;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.helper.MastodonHelper;
|
||||
import app.fedilab.android.helper.ThemeHelper;
|
||||
import app.fedilab.android.ui.fragment.timeline.FragmentMastodonContext;
|
||||
import app.fedilab.android.viewmodel.mastodon.StatusesVM;
|
||||
|
||||
public class ContextActivity extends BaseActivity {
|
||||
|
||||
public static boolean expand;
|
||||
public static boolean displayCW;
|
||||
public static Resources.Theme theme;
|
||||
Fragment currentFragment;
|
||||
private Status focusedStatus;
|
||||
private ActivityConversationBinding binding;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ThemeHelper.applyTheme(this);
|
||||
binding = ActivityConversationBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
//Remove title
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
actionBar.setBackgroundDrawable(new ColorDrawable(ContextCompat.getColor(this, R.color.cyanea_primary)));
|
||||
}
|
||||
binding.title.setText(R.string.context_conversation);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
binding.toolbar.setPopupTheme(Helper.popupStyle());
|
||||
Bundle b = getIntent().getExtras();
|
||||
final SharedPreferences sharedpreferences = PreferenceManager.getDefaultSharedPreferences(ContextActivity.this);
|
||||
displayCW = sharedpreferences.getBoolean(getString(R.string.SET_EXPAND_CW), false);
|
||||
focusedStatus = null; // or other values
|
||||
if (b != null)
|
||||
focusedStatus = (Status) b.getSerializable(Helper.ARG_STATUS);
|
||||
if (focusedStatus == null || currentAccount == null || currentAccount.mastodon_account == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
MastodonHelper.loadPPMastodon(binding.profilePicture, currentAccount.mastodon_account);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(Helper.ARG_STATUS, focusedStatus);
|
||||
currentFragment = Helper.addFragment(getSupportFragmentManager(), R.id.nav_host_fragment_content_main, new FragmentMastodonContext(), bundle, null, null);
|
||||
StatusesVM timelinesVM = new ViewModelProvider(ContextActivity.this).get(StatusesVM.class);
|
||||
timelinesVM.getStatus(BaseMainActivity.currentInstance, BaseMainActivity.currentToken, focusedStatus.id).observe(ContextActivity.this, status -> {
|
||||
if (status != null) {
|
||||
StatusCache statusCache = new StatusCache();
|
||||
statusCache.instance = BaseMainActivity.currentInstance;
|
||||
statusCache.user_id = BaseMainActivity.currentUserID;
|
||||
statusCache.status = status;
|
||||
statusCache.status_id = status.id;
|
||||
//Update cache
|
||||
new Thread(() -> {
|
||||
try {
|
||||
new StatusCache(getApplication()).updateIfExists(statusCache);
|
||||
new QuickLoad(getApplication().getApplicationContext()).updateStatus(currentAccount, status);
|
||||
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||
//Update UI
|
||||
Runnable myRunnable = () -> sendAction(ContextActivity.this, Helper.ARG_STATUS_ACTION, status, null);
|
||||
mainHandler.post(myRunnable);
|
||||
} catch (DBException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.menu_context, menu);
|
||||
MenuItem itemExpand = menu.findItem(R.id.action_expand);
|
||||
if (expand) {
|
||||
itemExpand.setIcon(R.drawable.ic_baseline_expand_less_24);
|
||||
} else {
|
||||
itemExpand.setIcon(R.drawable.ic_baseline_expand_more_24);
|
||||
}
|
||||
MenuItem itemDisplayCW = menu.findItem(R.id.action_show_cw);
|
||||
if (displayCW) {
|
||||
itemDisplayCW.setIcon(R.drawable.ic_baseline_remove_red_eye_24);
|
||||
} else {
|
||||
itemDisplayCW.setIcon(R.drawable.ic_outline_remove_red_eye_24);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCurrentFragment(FragmentMastodonContext fragmentMastodonContext) {
|
||||
currentFragment = fragmentMastodonContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
finish();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_expand) {
|
||||
expand = !expand;
|
||||
if (currentFragment != null && currentFragment instanceof FragmentMastodonContext) {
|
||||
((FragmentMastodonContext) currentFragment).redraw();
|
||||
}
|
||||
invalidateOptionsMenu();
|
||||
} else if (item.getItemId() == R.id.action_show_cw) {
|
||||
displayCW = !displayCW;
|
||||
if (currentFragment != null && currentFragment instanceof FragmentMastodonContext) {
|
||||
((FragmentMastodonContext) currentFragment).refresh();
|
||||
}
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue