Compare commits
223 Commits
v1.1.4+for
...
v1.1.4+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9f4df3d4e | ||
|
|
9078667d51 | ||
|
|
7569e1aef6 | ||
|
|
723983dadf | ||
|
|
f87e020abd | ||
|
|
fb5729d5cc | ||
|
|
2ff6c53d6d | ||
|
|
cfc6895711 | ||
|
|
1c27fc68ee | ||
|
|
df0d578573 | ||
|
|
2fa3c69af1 | ||
|
|
095bf92fed | ||
|
|
debe017f12 | ||
|
|
f956e12167 | ||
|
|
2c50c38d82 | ||
|
|
b4980101ad | ||
|
|
8395fca60f | ||
|
|
b22e7d277f | ||
|
|
c0e67593ee | ||
|
|
5dc4235724 | ||
|
|
f77caeefae | ||
|
|
c1ef23bbe8 | ||
|
|
e7e80bcf7d | ||
|
|
c27f5aaf30 | ||
|
|
d52728f22e | ||
|
|
3c7c962320 | ||
|
|
abf570d177 | ||
|
|
46422cd62d | ||
|
|
f1ffa2629e | ||
|
|
2074f3c33b | ||
|
|
7c51803674 | ||
|
|
6d80c62f30 | ||
|
|
64907a7e1c | ||
|
|
17922ca1d5 | ||
|
|
01ac219854 | ||
|
|
9bbf8c4618 | ||
|
|
978beaec77 | ||
|
|
0950e2eb7f | ||
|
|
116328adb9 | ||
|
|
32a2c66c34 | ||
|
|
231ea46f9f | ||
|
|
661f545e35 | ||
|
|
600be455a3 | ||
|
|
a4df06726f | ||
|
|
e45e2c31d1 | ||
|
|
d1e0cd3c20 | ||
|
|
db16dde073 | ||
|
|
b3fe44bc08 | ||
|
|
e5fab4a555 | ||
|
|
abe28179ec | ||
|
|
60d4e4d396 | ||
|
|
435e73d718 | ||
|
|
17dc0850d5 | ||
|
|
9667a32e44 | ||
|
|
4e6ba84bb3 | ||
|
|
8714b24388 | ||
|
|
495db142d7 | ||
|
|
ac5d11159f | ||
|
|
d1479f142b | ||
|
|
ee6ec631e8 | ||
|
|
dee21222a7 | ||
|
|
cd8123ca34 | ||
|
|
ceb08ea78d | ||
|
|
b79ba71228 | ||
|
|
2903874dbc | ||
|
|
cac5b554e2 | ||
|
|
c4adbc8e45 | ||
|
|
bb01077c3b | ||
|
|
b370fcda6d | ||
|
|
d364ebbb2f | ||
|
|
5b28468efd | ||
|
|
6fd58c9682 | ||
|
|
b580743619 | ||
|
|
4a9cb9f2dc | ||
|
|
202a5f9581 | ||
|
|
145f55817f | ||
|
|
79025c2f36 | ||
|
|
2515a8d381 | ||
|
|
ede7ece25a | ||
|
|
2db39f8c66 | ||
|
|
5f0382456f | ||
|
|
63b1b58c4e | ||
|
|
06f2f67f0c | ||
|
|
05c33be3f4 | ||
|
|
e274b7e6d5 | ||
|
|
0806d0c5ea | ||
|
|
5c67dd0188 | ||
|
|
b4358f51cb | ||
|
|
622c6d503d | ||
|
|
b190480d77 | ||
|
|
9a085beea8 | ||
|
|
1a42a77e24 | ||
|
|
e35794ef7d | ||
|
|
1f9611fc3e | ||
|
|
563afd487c | ||
|
|
e10faeefc4 | ||
|
|
65dbbb3d61 | ||
|
|
fa69868ca1 | ||
|
|
9c18de7b90 | ||
|
|
61bd19f6ff | ||
|
|
ba0689aef7 | ||
|
|
ad54e6bb4b | ||
|
|
f15fcb43da | ||
|
|
66208f5694 | ||
|
|
68863f28eb | ||
|
|
7feaf093e2 | ||
|
|
4ab9e25fec | ||
|
|
e14dfda2fd | ||
|
|
c9aae828e2 | ||
|
|
f346c0af26 | ||
|
|
f2557b7815 | ||
|
|
a2726f5b61 | ||
|
|
834ec1575d | ||
|
|
a30f5bdee8 | ||
|
|
4cef005286 | ||
|
|
58a05681fe | ||
|
|
2589faf499 | ||
|
|
a5bdf34289 | ||
|
|
09fdd7f492 | ||
|
|
519d8b887d | ||
|
|
a2f2263bf7 | ||
|
|
5b73b10b34 | ||
|
|
b7a4364a28 | ||
|
|
3f075aff7b | ||
|
|
f4c33a5970 | ||
|
|
809af0ec18 | ||
|
|
4ee640e072 | ||
|
|
1cbf310555 | ||
|
|
f1fdc8aa43 | ||
|
|
d696daece3 | ||
|
|
967bb09282 | ||
|
|
136d910b3b | ||
|
|
51eb48a455 | ||
|
|
6ee8afcf96 | ||
|
|
a59f2d4609 | ||
|
|
b75d871837 | ||
|
|
c72f93b990 | ||
|
|
586d337ead | ||
|
|
d84e10a22e | ||
|
|
351ec89207 | ||
|
|
7db7bf0220 | ||
|
|
a9764c4f46 | ||
|
|
a430b6a280 | ||
|
|
6a01124d13 | ||
|
|
2843e445e2 | ||
|
|
5c947d14b2 | ||
|
|
590adba3e3 | ||
|
|
efee249173 | ||
|
|
6d2ed27364 | ||
|
|
55716d742f | ||
|
|
e4555da735 | ||
|
|
8b4b99bec7 | ||
|
|
5de4b19969 | ||
|
|
a9460f401e | ||
|
|
012cca550e | ||
|
|
0c743db412 | ||
|
|
b819ee7d6d | ||
|
|
e7e3a249b5 | ||
|
|
980c580b55 | ||
|
|
e23c530e74 | ||
|
|
a64caccca2 | ||
|
|
829bcafcf2 | ||
|
|
e2a935c647 | ||
|
|
2e7afdb49e | ||
|
|
cdc965e026 | ||
|
|
dd4faa005e | ||
|
|
726ec7159c | ||
|
|
e74256ef6f | ||
|
|
a18718ca81 | ||
|
|
5a9bc0e269 | ||
|
|
2d39c62ff0 | ||
|
|
0da4f79413 | ||
|
|
2bdef776a2 | ||
|
|
1819d6f042 | ||
|
|
2f6a707847 | ||
|
|
4aaf017824 | ||
|
|
fb05ed48d0 | ||
|
|
49203ae539 | ||
|
|
d17660d516 | ||
|
|
513ce34671 | ||
|
|
44ce48009b | ||
|
|
a57ad67308 | ||
|
|
e63d04cea9 | ||
|
|
cf48cb6f75 | ||
|
|
542e53cf6a | ||
|
|
bab1d40038 | ||
|
|
2f4a8247e8 | ||
|
|
18f605e5c5 | ||
|
|
cd8a80a6a1 | ||
|
|
3ce8aa7894 | ||
|
|
b356794da9 | ||
|
|
afe8f6cf6a | ||
|
|
ed0df82fe9 | ||
|
|
d3bc7a9790 | ||
|
|
633c0f870d | ||
|
|
f9fe7819f9 | ||
|
|
f3d13545e7 | ||
|
|
f6b77777b5 | ||
|
|
340990fbd9 | ||
|
|
a7687f8e35 | ||
|
|
52aa4a5289 | ||
|
|
268accea14 | ||
|
|
101cde4d84 | ||
|
|
8863446f6a | ||
|
|
28a0824f6b | ||
|
|
b1f9d0516d | ||
|
|
5b21747d5d | ||
|
|
9fda48cff0 | ||
|
|
0e6f3df212 | ||
|
|
a8c3f1555e | ||
|
|
cd797a637b | ||
|
|
53b2eb59d3 | ||
|
|
09e2224596 | ||
|
|
5999aad21b | ||
|
|
874ce07c3e | ||
|
|
1787d08718 | ||
|
|
9a12be88da | ||
|
|
8f6bb74e61 | ||
|
|
e67bd2972a | ||
|
|
de5929d8d2 | ||
|
|
d7699ef079 | ||
|
|
3ab04ebca8 | ||
|
|
78d2aa96d7 |
56
README.md
56
README.md
@@ -3,12 +3,15 @@
|
||||
# Megalodon
|
||||
|
||||
[](https://translate.codeberg.org/engage/megalodon/)
|
||||
|
||||
[](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
|
||||
|
||||
> A fork of the [official Mastodon Android app](https://github.com/mastodon/mastodon-android) adding important features that are missing in the official app and possibly won’t ever be implemented, such as the federated timeline, unlisted posting, bookmarks and an image description viewer.
|
||||
<a href="https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk"><img height="50" alt="Get it on Google Play" src="img/google-play-badge.png"></a>
|
||||
|
||||
<a href="https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk"><img height="50" alt="Get it on F-Droid" src="img/f-droid-badge.png"></a>
|
||||
|
||||
**Warning! [A previous version's integrated updater was broken](https://github.com/sk22/megalodon/issues/106) – I already published a fixed version! If you're not updating through Izzy's F-Droid repository (more sources to come, hopefully!), you'll have to download the current release manually. Sorry about that!**
|
||||
> A fork of the [official Mastodon Android app](https://github.com/mastodon/mastodon-android) adding important features that are missing in the official app and possibly won’t ever be implemented, such as the federated timeline, unlisted posting and an image description viewer.
|
||||
|
||||
[](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
|
||||
|
||||
---
|
||||
|
||||
@@ -43,26 +46,32 @@ This is important to **ensure the content you’re sharing is as accessible as p
|
||||
|
||||
On the Fediverse, it’s quite common for people to pin posts they want others to read before following them. You can pin/unpin posts yourself by clicking the `⋯` button in the top right corner of your posts.
|
||||
|
||||
### **Bookmarks**
|
||||
|
||||
**They allow for quickly saving posts and viewing them through the Bookmarks button on the top right of your profile.**
|
||||
|
||||
To bookmark a post, press the button between the Favorite and Share buttons on the bottom of the post. Bookmarks are saved privately, so the post authors won’t know you saved their post – the list of bookmarked posts is only visible to you.
|
||||
|
||||
## Installation
|
||||
|
||||
**In short: Press the download button to download the APK. Open the downloaded file on your Android device to install it. Megalodon will automatically notify you about new updates inside the app.**
|
||||
### From app stores
|
||||
|
||||
[](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
|
||||
* **[Izzy's F-Droid repository](https://apt.izzysoft.de/fdroid/repo)**: [apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk](https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk)
|
||||
|
||||
To install this app on your Android device, download the [latest release from GitHub](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk) and open it. You might have to accept installing APK files from your browser when trying to install it. You can also take a look at all releases on the [Releases](https://github.com/sk22/megalodon/releases) page.
|
||||
Note that you'll need to add Izzy's F-Droid repository to your F-Droid app first:
|
||||
|
||||
`https://apt.izzysoft.de/fdroid/repo`
|
||||
|
||||
* **[Google Play Store](https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk)**: [play.google.com/store/apps/details?id=org.joinmastodon.android.sk](https://play.google.com/store/apps/details?id=org.joinmastodon.android.sk)
|
||||
|
||||
* **[F-Droid.org](https://f-droid.org)?** Not yet, sorry!
|
||||
|
||||
If you want, you can help me figure out if something's missing in the [Issue #47: F-Droid.org](https://github.com/sk22/megalodon/issues/47)
|
||||
|
||||
### Directly from GitHub
|
||||
|
||||
Press the download button to download the APK. Open the downloaded file on your Android device to install it. Megalodon will automatically notify you about new updates inside the app.
|
||||
|
||||
[](https://github.com/sk22/megalodon/releases/latest/download/megalodon.apk)
|
||||
|
||||
You might have to accept installing APK files from your browser when trying to install it. You can also take a look at all releases on the [Releases](https://github.com/sk22/megalodon/releases) page.
|
||||
|
||||
Megalodon makes use of [Mastodon for Android](https://github.com/mastodon/mastodon-android)’s automatic update checker. Megalodon will check for new updates available on GitHub and offer to download and install them. You can also manually press “Check for updates” at the bottom of the settings page!
|
||||
|
||||
### Other sources
|
||||
|
||||
* **[Izzy's F-Droid repository](https://apt.izzysoft.de/fdroid/repo)**: https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -92,7 +101,7 @@ As with the source code, the translation is sourced from the official project, w
|
||||
|
||||
There's also a handful of custom strings exclusive to this projects that would need to be translated. You can help translate **Megalodon** on Weblate: https://translate.codeberg.org/projects/megalodon/
|
||||
|
||||
[](https://translate.codeberg.org/engage/megalodon/)
|
||||
[](https://translate.codeberg.org/engage/megalodon/)
|
||||
|
||||
|
||||
---
|
||||
@@ -122,6 +131,10 @@ There's also a handful of custom strings exclusive to this projects that would n
|
||||
* [Show visibility of original post when replying](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/display-reply-visibility)
|
||||
* [Clickable reply/boost line above posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:clickable-boost-reply-line)
|
||||
* [Clickable reply line while replying to open original post](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/clickable-reply-line-compose)
|
||||
* [Add push notification setting for post notifications](https://github.com/sk22/megalodon/commit/b190480d7739be47f23543d9e7644660f9b4b4ee)
|
||||
* [Add option to allow voting for multiple options on polls](https://github.com/sk22/megalodon/commit/5b28468efd49387b4f8b83f142f3adf3104ca60c)
|
||||
* [Add translate function](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/translate-button)
|
||||
* [Add language selector](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/language-selector)
|
||||
|
||||
|
||||
### Behavior
|
||||
@@ -133,6 +146,12 @@ There's also a handful of custom strings exclusive to this projects that would n
|
||||
* [Option to hide interaction numbers](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:settings/hide-interaction-numbers)
|
||||
* [Option to always reveal content warnings](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/cw-above-text)
|
||||
* [Option to disable scrolling title bars](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:settings/disable-marquee)
|
||||
* [No ellipsis for long poll answers](https://github.com/mastodon/mastodon-android/commit/c9aae828e2518adccdc092e41f8d1f0489636271)
|
||||
* [Show poll vote button for multiple and single answer polls](https://github.com/mastodon/mastodon-android/commit/e14dfda2fdf32f0fa3043504ac5831683a87559a)
|
||||
* [Show own vote after voting](https://github.com/mastodon/mastodon-android/commit/4ab9e25fec4fd9c10b7a8ddd1be522b3cc12cf28) ([Closes issue](https://github.com/mastodon/mastodon-android/commit/4ab9e25fec4fd9c10b7a8ddd1be522b3cc12cf28))
|
||||
* [Make inline emoji search case-insensitive and don't only search from start of emoji names](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:better-inline-emoji-search) ([Pull request](https://github.com/mastodon/mastodon-android/pull/445))
|
||||
* [Include subject line when sharing e.g. a website to Megalodon](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:external-share-include-subject)
|
||||
* [Improve semantics for voting on polls (radio buttons and checkboxes)](https://github.com/sk22/megalodon/commit/6fd58c96827cb1d2da329cebdc170a1425dd18d7)
|
||||
|
||||
|
||||
### Visual
|
||||
@@ -140,6 +159,9 @@ There's also a handful of custom strings exclusive to this projects that would n
|
||||
* [Custom extended footer redesign](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:compact-extended-footer)
|
||||
* [Improvements to the true black mode](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:true-black-improvements)
|
||||
* [Profile header tweaks](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:ui/profile-header-tweaks)
|
||||
* [Custom color themes](https://github.com/sk22/megalodon/pull/124) by [@LucasGGamerM](https://github.com/LucasGGamerM)
|
||||
* [Custom "megalodon" text logo](https://github.com/sk22/megalodon/commit/563afd487ca5c608cfbb00fa3909d3c27384acc0) by [@LucasGGamerM](https://github.com/LucasGGamerM)
|
||||
* [Custom login screen](https://github.com/sk22/megalodon/commit/9bbf8c4618dbe13accaeb3b5482bf3fe88cac4c0)
|
||||
|
||||
|
||||
## Building
|
||||
|
||||
BIN
img/f-droid-badge.png
Normal file
BIN
img/f-droid-badge.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -9,8 +9,8 @@ android {
|
||||
applicationId "org.joinmastodon.android.sk"
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
versionCode 55
|
||||
versionName "1.1.4+fork.55"
|
||||
versionCode 59
|
||||
versionName "1.1.4+fork.59"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
resConfigs "en", "ar-rSA", "bs-rBA", "ca-rES", "cs-rCZ", "de-rDE", "el-rGR", "es-rES",
|
||||
"eu-rES", "fi-rFI", "fr-rFR", "gl-rES", "hr-rHR", "hy-rAM", "it-rIT", "iw-rIL",
|
||||
|
||||
@@ -51,7 +51,10 @@ public class ExternalShareActivity extends FragmentStackActivity{
|
||||
getWindow().setBackgroundDrawable(null);
|
||||
|
||||
Intent intent=getIntent();
|
||||
String text=intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
StringBuilder builder=new StringBuilder();
|
||||
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) builder.append(intent.getStringExtra(Intent.EXTRA_SUBJECT)).append("\n");
|
||||
if (intent.hasExtra(Intent.EXTRA_TEXT)) builder.append(intent.getStringExtra(Intent.EXTRA_TEXT)).append("\n");
|
||||
String text=builder.toString();
|
||||
List<Uri> mediaUris;
|
||||
if(Intent.ACTION_SEND.equals(intent.getAction())){
|
||||
Uri singleUri=intent.getParcelableExtra(Intent.EXTRA_STREAM);
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
package org.joinmastodon.android;
|
||||
|
||||
import static org.joinmastodon.android.api.MastodonAPIController.gson;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GlobalUserPreferences{
|
||||
public static boolean playGifs;
|
||||
public static boolean useCustomTabs;
|
||||
@@ -14,12 +24,22 @@ public class GlobalUserPreferences{
|
||||
public static boolean showInteractionCounts;
|
||||
public static boolean alwaysExpandContentWarnings;
|
||||
public static boolean disableMarquee;
|
||||
public static boolean voteButtonForSingleChoice;
|
||||
public static ThemePreference theme;
|
||||
public static ColorPreference color;
|
||||
|
||||
private static SharedPreferences getPrefs(){
|
||||
private final static Type recentLanguagesType = new TypeToken<Map<String, List<String>>>() {}.getType();
|
||||
public static Map<String, List<String>> recentLanguages;
|
||||
|
||||
private static SharedPreferences getPrefs(){
|
||||
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
private static <T> T fromJson(String json, Type type, T orElse) {
|
||||
try { return gson.fromJson(json, type); }
|
||||
catch (JsonSyntaxException ignored) { return orElse; }
|
||||
}
|
||||
|
||||
public static void load(){
|
||||
SharedPreferences prefs=getPrefs();
|
||||
playGifs=prefs.getBoolean("playGifs", true);
|
||||
@@ -32,7 +52,10 @@ public class GlobalUserPreferences{
|
||||
showInteractionCounts=prefs.getBoolean("showInteractionCounts", false);
|
||||
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
|
||||
disableMarquee=prefs.getBoolean("disableMarquee", false);
|
||||
voteButtonForSingleChoice=prefs.getBoolean("voteButtonForSingleChoice", true);
|
||||
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
|
||||
color=ColorPreference.values()[prefs.getInt("color", 0)];
|
||||
recentLanguages=fromJson(prefs.getString("recentLanguages", "{}"), recentLanguagesType, new HashMap<>());
|
||||
}
|
||||
|
||||
public static void save(){
|
||||
@@ -48,12 +71,24 @@ public class GlobalUserPreferences{
|
||||
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
|
||||
.putBoolean("disableMarquee", disableMarquee)
|
||||
.putInt("theme", theme.ordinal())
|
||||
.putInt("color", color.ordinal())
|
||||
.putString("recentLanguages", gson.toJson(recentLanguages))
|
||||
.apply();
|
||||
}
|
||||
|
||||
public enum ColorPreference{
|
||||
PINK,
|
||||
PURPLE,
|
||||
GREEN,
|
||||
BLUE,
|
||||
BROWN,
|
||||
YELLOW
|
||||
}
|
||||
|
||||
public enum ThemePreference{
|
||||
AUTO,
|
||||
LIGHT,
|
||||
DARK
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.ComposeFragment;
|
||||
import org.joinmastodon.android.fragments.HomeFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.SplashFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.MegalodonLoginFragment;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||
@@ -33,7 +33,7 @@ public class MainActivity extends FragmentStackActivity{
|
||||
|
||||
if(savedInstanceState==null){
|
||||
if(AccountSessionManager.getInstance().getLoggedInAccounts().isEmpty()){
|
||||
showFragmentClearingBackStack(new SplashFragment());
|
||||
showFragmentClearingBackStack(new MegalodonLoginFragment());
|
||||
}else{
|
||||
AccountSessionManager.getInstance().maybeUpdateLocalInfo();
|
||||
AccountSession session;
|
||||
|
||||
@@ -370,7 +370,7 @@ public class PushSubscriptionManager{
|
||||
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
|
||||
if(session.pushSubscription==null || forceReRegister)
|
||||
session.getPushSubscriptionManager().registerAccountForPush(session.pushSubscription);
|
||||
else if(session.needUpdatePushSettings)
|
||||
else
|
||||
session.getPushSubscriptionManager().updatePushSettings(session.pushSubscription);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,15 @@ public class GetInstance extends MastodonAPIRequest<Instance>{
|
||||
public GetInstance(){
|
||||
super(HttpMethod.GET, "/instance", Instance.class);
|
||||
}
|
||||
|
||||
public static class V2 extends MastodonAPIRequest<Instance.V2>{
|
||||
public V2(){
|
||||
super(HttpMethod.GET, "/instance", Instance.V2.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPathPrefix() {
|
||||
return "/api/v2";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.joinmastodon.android.api.requests.statuses;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.TranslatedStatus;
|
||||
|
||||
public class TranslateStatus extends MastodonAPIRequest<TranslatedStatus> {
|
||||
public TranslateStatus(String id) {
|
||||
super(HttpMethod.POST, "/statuses/"+id+"/translate", TranslatedStatus.class);
|
||||
setRequestBody(new Object());
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import org.joinmastodon.android.api.StatusInteractionController;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Application;
|
||||
import org.joinmastodon.android.model.Filter;
|
||||
import org.joinmastodon.android.model.Preferences;
|
||||
import org.joinmastodon.android.model.PushSubscription;
|
||||
import org.joinmastodon.android.model.Token;
|
||||
|
||||
@@ -28,6 +29,7 @@ public class AccountSession{
|
||||
public long filtersLastUpdated;
|
||||
public List<Filter> wordFilters=new ArrayList<>();
|
||||
public String pushAccountID;
|
||||
public Preferences preferences;
|
||||
private transient MastodonAPIController apiController;
|
||||
private transient StatusInteractionController statusInteractionController;
|
||||
private transient CacheController cacheController;
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.MastodonAPIController;
|
||||
import org.joinmastodon.android.api.PushSubscriptionManager;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetPreferences;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetWordFilters;
|
||||
import org.joinmastodon.android.api.requests.instance.GetCustomEmojis;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetOwnAccount;
|
||||
@@ -34,6 +35,7 @@ import org.joinmastodon.android.model.Emoji;
|
||||
import org.joinmastodon.android.model.EmojiCategory;
|
||||
import org.joinmastodon.android.model.Filter;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.Preferences;
|
||||
import org.joinmastodon.android.model.Token;
|
||||
|
||||
import java.io.File;
|
||||
@@ -248,12 +250,13 @@ public class AccountSessionManager{
|
||||
HashSet<String> domains=new HashSet<>();
|
||||
for(AccountSession session:sessions.values()){
|
||||
domains.add(session.domain.toLowerCase());
|
||||
if(now-session.infoLastUpdated>24L*3600_000L){
|
||||
updateSessionLocalInfo(session);
|
||||
}
|
||||
if(now-session.filtersLastUpdated>3600_000L){
|
||||
updateSessionWordFilters(session);
|
||||
}
|
||||
// if(now-session.infoLastUpdated>24L*3600_000L){
|
||||
updateSessionPreferences(session);
|
||||
updateSessionLocalInfo(session);
|
||||
// }
|
||||
// if(now-session.filtersLastUpdated>3600_000L){
|
||||
updateSessionWordFilters(session);
|
||||
// }
|
||||
}
|
||||
if(loadedInstances){
|
||||
maybeUpdateCustomEmojis(domains);
|
||||
@@ -263,10 +266,10 @@ public class AccountSessionManager{
|
||||
private void maybeUpdateCustomEmojis(Set<String> domains){
|
||||
long now=System.currentTimeMillis();
|
||||
for(String domain:domains){
|
||||
Long lastUpdated=instancesLastUpdated.get(domain);
|
||||
if(lastUpdated==null || now-lastUpdated>24L*3600_000L){
|
||||
updateInstanceInfo(domain);
|
||||
}
|
||||
// Long lastUpdated=instancesLastUpdated.get(domain);
|
||||
// if(lastUpdated==null || now-lastUpdated>24L*3600_000L){
|
||||
updateInstanceInfo(domain);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,6 +291,18 @@ public class AccountSessionManager{
|
||||
.exec(session.getID());
|
||||
}
|
||||
|
||||
private void updateSessionPreferences(AccountSession session){
|
||||
new GetPreferences().setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Preferences preferences) {
|
||||
session.preferences=preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {}
|
||||
}).exec(session.getID());
|
||||
}
|
||||
|
||||
private void updateSessionWordFilters(AccountSession session){
|
||||
new GetWordFilters()
|
||||
.setCallback(new Callback<>(){
|
||||
@@ -313,6 +328,11 @@ public class AccountSessionManager{
|
||||
public void onSuccess(Instance instance){
|
||||
instances.put(domain, instance);
|
||||
updateInstanceEmojis(instance, domain);
|
||||
try {
|
||||
if (Integer.parseInt(instance.version.split("\\.")[0]) >= 4) {
|
||||
updateInstanceInfoV2(domain);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -323,6 +343,19 @@ public class AccountSessionManager{
|
||||
.execNoAuth(domain);
|
||||
}
|
||||
|
||||
public void updateInstanceInfoV2(String domain) {
|
||||
new GetInstance.V2().setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Instance.V2 v2) {
|
||||
Instance instanceInfo = instances.get(domain);
|
||||
if (instanceInfo != null) instanceInfo.v2 = v2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse errorResponse) {}
|
||||
}).execNoAuth(domain);
|
||||
}
|
||||
|
||||
private void updateInstanceEmojis(Instance instance, String domain){
|
||||
new GetCustomEmojis()
|
||||
.setCallback(new Callback<>(){
|
||||
@@ -398,6 +431,10 @@ public class AccountSessionManager{
|
||||
return instances.get(domain);
|
||||
}
|
||||
|
||||
public Instance getInstanceInfoForAccount(String account) {
|
||||
return AccountSessionManager.getInstance().getInstanceInfo(instance.getAccount(account).domain);
|
||||
}
|
||||
|
||||
public void updateAccountInfo(String id, Account account){
|
||||
AccountSession session=getAccount(id);
|
||||
session.self=account;
|
||||
|
||||
@@ -400,10 +400,12 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
public void onPollOptionClick(PollOptionStatusDisplayItem.Holder holder){
|
||||
Poll poll=holder.getItem().poll;
|
||||
Poll.Option option=holder.getItem().option;
|
||||
if(poll.multiple){
|
||||
if(poll.multiple || GlobalUserPreferences.voteButtonForSingleChoice){
|
||||
if(poll.selectedOptions==null)
|
||||
poll.selectedOptions=new ArrayList<>();
|
||||
if(poll.selectedOptions.contains(option)){
|
||||
boolean optionContained=poll.selectedOptions.contains(option);
|
||||
if(!poll.multiple) poll.selectedOptions.clear();
|
||||
if(optionContained){
|
||||
poll.selectedOptions.remove(option);
|
||||
holder.itemView.setSelected(false);
|
||||
}else{
|
||||
@@ -412,6 +414,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
}
|
||||
for(int i=0;i<list.getChildCount();i++){
|
||||
RecyclerView.ViewHolder vh=list.getChildViewHolder(list.getChildAt(i));
|
||||
if(!poll.multiple && vh instanceof PollOptionStatusDisplayItem.Holder item){
|
||||
if (item != holder) item.itemView.setSelected(false);
|
||||
}
|
||||
if(vh instanceof PollFooterStatusDisplayItem.Holder footer){
|
||||
if(footer.getItemID().equals(holder.getItemID())){
|
||||
footer.rebind();
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import static org.joinmastodon.android.GlobalUserPreferences.recentLanguages;
|
||||
import static org.joinmastodon.android.utils.MastodonLanguage.allLanguages;
|
||||
import static org.joinmastodon.android.utils.MastodonLanguage.defaultRecentLanguages;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
@@ -29,11 +33,13 @@ import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.SubMenu;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
@@ -41,6 +47,7 @@ import android.view.WindowManager;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
@@ -54,6 +61,7 @@ import android.widget.Toast;
|
||||
import com.twitter.twittertext.TwitterTextEmojiRegex;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.MastodonAPIController;
|
||||
@@ -94,6 +102,7 @@ import org.joinmastodon.android.ui.views.ComposeEditText;
|
||||
import org.joinmastodon.android.ui.views.ComposeMediaLayout;
|
||||
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
|
||||
import org.joinmastodon.android.ui.views.SizeListenerLinearLayout;
|
||||
import org.joinmastodon.android.utils.MastodonLanguage;
|
||||
import org.parceler.Parcel;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
@@ -104,6 +113,7 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -144,7 +154,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
private String accountID;
|
||||
private int charCount, charLimit, trimmedCharCount;
|
||||
|
||||
private Button publishButton;
|
||||
private Button publishButton, languageButton;
|
||||
private PopupMenu languagePopup;
|
||||
private ImageButton mediaBtn, pollBtn, emojiBtn, spoilerBtn, visibilityBtn;
|
||||
private ImageView sensitiveIcon;
|
||||
private ComposeMediaLayout attachmentsView;
|
||||
@@ -153,6 +164,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
private View pollWrap;
|
||||
private View addPollOptionBtn;
|
||||
private View sensitiveItem;
|
||||
private View pollAllowMultipleItem;
|
||||
private CheckBox pollAllowMultipleCheckbox;
|
||||
private TextView pollDurationView;
|
||||
|
||||
private ArrayList<DraftPollOption> pollOptions=new ArrayList<>();
|
||||
@@ -187,6 +200,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
private boolean ignoreSelectionChanges=false;
|
||||
private Runnable updateUploadEtaRunnable;
|
||||
|
||||
private String language;
|
||||
private MastodonLanguage.LanguageResolver languageResolver;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -198,6 +214,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
instanceDomain=session.domain;
|
||||
customEmojis=AccountSessionManager.getInstance().getCustomEmojis(instanceDomain);
|
||||
instance=AccountSessionManager.getInstance().getInstanceInfo(instanceDomain);
|
||||
languageResolver=new MastodonLanguage.LanguageResolver(instance);
|
||||
if(getArguments().containsKey("editStatus")){
|
||||
editingStatus=Parcels.unwrap(getArguments().getParcelable("editStatus"));
|
||||
redraftStatus=getArguments().getBoolean("redraftStatus");
|
||||
@@ -216,8 +233,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
charLimit=instance.configuration.statuses.maxCharacters;
|
||||
else
|
||||
charLimit=500;
|
||||
|
||||
loadDefaultStatusVisibility(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -297,6 +312,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
pollOptionsView=view.findViewById(R.id.poll_options);
|
||||
pollWrap=view.findViewById(R.id.poll_wrap);
|
||||
addPollOptionBtn=view.findViewById(R.id.add_poll_option);
|
||||
pollAllowMultipleItem=view.findViewById(R.id.poll_allow_multiple);
|
||||
pollAllowMultipleCheckbox=view.findViewById(R.id.poll_allow_multiple_checkbox);
|
||||
pollAllowMultipleItem.setOnClickListener(v->this.togglePollAllowMultiple());
|
||||
|
||||
addPollOptionBtn.setOnClickListener(v->{
|
||||
createDraftPollOption().edit.requestFocus();
|
||||
@@ -311,6 +329,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
pollBtn.setSelected(true);
|
||||
mediaBtn.setEnabled(false);
|
||||
pollWrap.setVisibility(View.VISIBLE);
|
||||
updatePollAllowMultiple(savedInstanceState.getBoolean("pollAllowMultiple", false));
|
||||
for(String oldText:savedInstanceState.getStringArrayList("pollOptions")){
|
||||
DraftPollOption opt=createDraftPollOption();
|
||||
opt.edit.setText(oldText);
|
||||
@@ -321,6 +340,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
pollBtn.setSelected(true);
|
||||
mediaBtn.setEnabled(false);
|
||||
pollWrap.setVisibility(View.VISIBLE);
|
||||
updatePollAllowMultiple(editingStatus.poll.multiple);
|
||||
for(Poll.Option eopt:editingStatus.poll.options){
|
||||
DraftPollOption opt=createDraftPollOption();
|
||||
opt.edit.setText(eopt.title);
|
||||
@@ -367,6 +387,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
statusVisibility=editingStatus.visibility;
|
||||
}
|
||||
|
||||
loadDefaultStatusVisibility(savedInstanceState);
|
||||
updateVisibilityIcon();
|
||||
|
||||
autocompleteViewController=new ComposeAutocompleteViewController(getActivity(), accountID);
|
||||
@@ -391,9 +412,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
outState.putStringArrayList("pollOptions", opts);
|
||||
outState.putInt("pollDuration", pollDuration);
|
||||
outState.putString("pollDurationStr", pollDurationStr);
|
||||
outState.putBoolean("pollAllowMultiple", pollAllowMultipleItem.isSelected());
|
||||
}
|
||||
outState.putBoolean("sensitive", sensitive);
|
||||
outState.putBoolean("hasSpoiler", hasSpoiler);
|
||||
outState.putString("language", language);
|
||||
if(!attachments.isEmpty()){
|
||||
ArrayList<Parcelable> serializedAttachments=new ArrayList<>(attachments.size());
|
||||
for(DraftMediaAttachment att:attachments){
|
||||
@@ -485,14 +508,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
spoilerEdit.addTextChangedListener(new SimpleTextWatcher(e->updateCharCounter()));
|
||||
if(replyTo!=null){
|
||||
replyText.setText(getString(R.string.in_reply_to, replyTo.account.displayName));
|
||||
int visibilityNameRes = switch (statusVisibility) {
|
||||
int visibilityNameRes = switch (replyTo.visibility) {
|
||||
case PUBLIC -> R.string.visibility_public;
|
||||
case UNLISTED -> R.string.sk_visibility_unlisted;
|
||||
case PRIVATE -> R.string.visibility_followers_only;
|
||||
case DIRECT -> R.string.visibility_private;
|
||||
};
|
||||
replyText.setContentDescription(getString(R.string.in_reply_to, replyTo.account.displayName) + ". " + getString(R.string.post_visibility) + ": " + getString(visibilityNameRes));
|
||||
Drawable visibilityIcon = getActivity().getDrawable(switch(statusVisibility){
|
||||
Drawable visibilityIcon = getActivity().getDrawable(switch(replyTo.visibility){
|
||||
case PUBLIC -> R.drawable.ic_fluent_earth_20_regular;
|
||||
case UNLISTED -> R.drawable.ic_fluent_people_community_20_regular;
|
||||
case PRIVATE -> R.drawable.ic_fluent_people_checkmark_20_regular;
|
||||
@@ -533,6 +556,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
spoilerEdit.setText(replyTo.spoilerText);
|
||||
spoilerBtn.setSelected(true);
|
||||
}
|
||||
if (replyTo.language != null && !replyTo.language.isEmpty()) updateLanguage(replyTo.language);
|
||||
}
|
||||
}else if (editingStatus==null || editingStatus.inReplyToId==null){
|
||||
// TODO: remove workaround after https://github.com/mastodon/mastodon-android/issues/341 gets fixed
|
||||
@@ -545,6 +569,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
ignoreSelectionChanges=true;
|
||||
mainEditText.setSelection(mainEditText.length());
|
||||
ignoreSelectionChanges=false;
|
||||
updateLanguage(editingStatus.language);
|
||||
if(!editingStatus.mediaAttachments.isEmpty()){
|
||||
attachmentsView.setVisibility(View.VISIBLE);
|
||||
for(Attachment att:editingStatus.mediaAttachments){
|
||||
@@ -607,6 +632,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
sendError.setVisibility(View.GONE);
|
||||
sendProgress.setVisibility(View.GONE);
|
||||
|
||||
LinearLayout.LayoutParams langParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
langParams.setMarginEnd(V.dp(8));
|
||||
wrap.addView(buildLanguageSelector(), langParams);
|
||||
|
||||
wrap.addView(publishButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
wrap.setPadding(V.dp(16), V.dp(4), V.dp(16), V.dp(8));
|
||||
wrap.setClipToPadding(false);
|
||||
@@ -616,6 +645,56 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
updatePublishButtonState();
|
||||
}
|
||||
|
||||
private void updateLanguage(String lang) {
|
||||
updateLanguage(languageResolver.from(lang));
|
||||
}
|
||||
|
||||
private void updateLanguage(MastodonLanguage loc) {
|
||||
language = loc.getLanguage();
|
||||
languageButton.setText(loc.getLanguageName());
|
||||
languageButton.setContentDescription(getActivity().getString(R.string.sk_post_language, loc.getDefaultName()));
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private Button buildLanguageSelector() {
|
||||
TypedValue typedValue = new TypedValue();
|
||||
getActivity().getTheme().resolveAttribute(android.R.attr.textColorSecondary, typedValue, true);
|
||||
|
||||
languageButton=new Button(getActivity());
|
||||
languageButton.setTextColor(typedValue.data);
|
||||
languageButton.setBackground(getActivity().getDrawable(R.drawable.bg_text_button));
|
||||
languageButton.setPadding(V.dp(8), 0, V.dp(8), 0);
|
||||
languageButton.setCompoundDrawablesRelativeWithIntrinsicBounds(getActivity().getDrawable(R.drawable.ic_fluent_local_language_16_regular), null, null, null);
|
||||
languageButton.setCompoundDrawableTintList(languageButton.getTextColors());
|
||||
languageButton.setCompoundDrawablePadding(V.dp(6));
|
||||
|
||||
languagePopup=new PopupMenu(getActivity(), languageButton);
|
||||
languageButton.setOnTouchListener(languagePopup.getDragToOpenListener());
|
||||
languageButton.setOnClickListener(v->languagePopup.show());
|
||||
|
||||
updateLanguage(languageResolver.getDefault());
|
||||
|
||||
Menu languageMenu = languagePopup.getMenu();
|
||||
for (String recentLanguage : Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages)) {
|
||||
MastodonLanguage l = languageResolver.from(recentLanguage);
|
||||
languageMenu.add(0, allLanguages.indexOf(l), Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
||||
}
|
||||
|
||||
SubMenu allLanguagesMenu = languageMenu.addSubMenu(R.string.sk_available_languages);
|
||||
for (int i = 0; i < allLanguages.size(); i++) {
|
||||
MastodonLanguage l = allLanguages.get(i);
|
||||
allLanguagesMenu.add(0, i, Menu.NONE, getActivity().getString(R.string.sk_language_name, l.getDefaultName(), l.getLanguageName()));
|
||||
}
|
||||
|
||||
languagePopup.setOnMenuItemClickListener(i->{
|
||||
if (i.hasSubMenu()) return false;
|
||||
updateLanguage(allLanguages.get(i.getItemId()));
|
||||
return true;
|
||||
});
|
||||
|
||||
return languageButton;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item){
|
||||
return true;
|
||||
@@ -689,6 +768,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
req.status=text;
|
||||
req.visibility=statusVisibility;
|
||||
req.sensitive=sensitive;
|
||||
req.language=language;
|
||||
if(!attachments.isEmpty()){
|
||||
req.mediaIds=attachments.stream().map(a->a.serverAttachment.id).collect(Collectors.toList());
|
||||
}
|
||||
@@ -698,6 +778,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
if(!pollOptions.isEmpty()){
|
||||
req.poll=new CreateStatus.Request.Poll();
|
||||
req.poll.expiresIn=pollDuration;
|
||||
req.poll.multiple=pollAllowMultipleItem.isSelected();
|
||||
for(DraftPollOption opt:pollOptions)
|
||||
req.poll.options.add(opt.edit.getText().toString());
|
||||
}
|
||||
@@ -765,6 +846,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
.setCallback(resCallback)
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
if (replyTo == null) {
|
||||
List<String> newRecentLanguages = new ArrayList<>(Optional.ofNullable(recentLanguages.get(accountID)).orElse(defaultRecentLanguages));
|
||||
newRecentLanguages.remove(language);
|
||||
newRecentLanguages.add(0, language);
|
||||
recentLanguages.put(accountID, newRecentLanguages.stream().limit(4).collect(Collectors.toList()));
|
||||
GlobalUserPreferences.save();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasDraft(){
|
||||
@@ -1208,6 +1297,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
option.view=LayoutInflater.from(getActivity()).inflate(R.layout.compose_poll_option, pollOptionsView, false);
|
||||
option.edit=option.view.findViewById(R.id.edit);
|
||||
option.dragger=option.view.findViewById(R.id.dragger_thingy);
|
||||
ImageView icon = option.view.findViewById(R.id.icon);
|
||||
icon.setImageDrawable(getContext().getDrawable(pollAllowMultipleItem.isSelected() ?
|
||||
R.drawable.ic_poll_checkbox_regular_selector :
|
||||
R.drawable.ic_poll_option_button
|
||||
));
|
||||
|
||||
option.dragger.setOnLongClickListener(v->{
|
||||
pollOptionsView.startDragging(option.view);
|
||||
@@ -1343,34 +1437,23 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
statusVisibility = (StatusPrivacy) savedInstanceState.getSerializable("visibility");
|
||||
}
|
||||
|
||||
new GetPreferences()
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Preferences result){
|
||||
// Only override the reply visibility if our preference is more private
|
||||
if (result.postingDefaultVisibility.isLessVisibleThan(statusVisibility)) {
|
||||
statusVisibility = switch (result.postingDefaultVisibility) {
|
||||
case PUBLIC -> StatusPrivacy.PUBLIC;
|
||||
case UNLISTED -> StatusPrivacy.UNLISTED;
|
||||
case PRIVATE -> StatusPrivacy.PRIVATE;
|
||||
case DIRECT -> StatusPrivacy.DIRECT;
|
||||
};
|
||||
}
|
||||
Preferences prefs = AccountSessionManager.getInstance().getAccount(accountID).preferences;
|
||||
if (prefs != null) {
|
||||
// Only override the reply visibility if our preference is more private
|
||||
if (prefs.postingDefaultVisibility.isLessVisibleThan(statusVisibility)) {
|
||||
statusVisibility = switch (prefs.postingDefaultVisibility) {
|
||||
case PUBLIC -> StatusPrivacy.PUBLIC;
|
||||
case UNLISTED -> StatusPrivacy.UNLISTED;
|
||||
case PRIVATE -> StatusPrivacy.PRIVATE;
|
||||
case DIRECT -> StatusPrivacy.DIRECT;
|
||||
};
|
||||
}
|
||||
|
||||
// A saved privacy setting from a previous compose session wins over all
|
||||
if(savedInstanceState !=null){
|
||||
statusVisibility = (StatusPrivacy) savedInstanceState.getSerializable("visibility");
|
||||
}
|
||||
|
||||
updateVisibilityIcon ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
Log.w(TAG, "Unable to get user preferences to set default post privacy");
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
// A saved privacy setting from a previous compose session wins over all
|
||||
if(savedInstanceState !=null){
|
||||
statusVisibility = (StatusPrivacy) savedInstanceState.getSerializable("visibility");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateVisibilityIcon(){
|
||||
@@ -1385,6 +1468,27 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
});
|
||||
}
|
||||
|
||||
private void togglePollAllowMultiple() {
|
||||
updatePollAllowMultiple(!pollAllowMultipleItem.isSelected());
|
||||
}
|
||||
|
||||
private void updatePollAllowMultiple(boolean multiple){
|
||||
pollAllowMultipleItem.setSelected(multiple);
|
||||
pollAllowMultipleCheckbox.setChecked(multiple);
|
||||
ImageView btn = addPollOptionBtn.findViewById(R.id.add_poll_option_icon);
|
||||
btn.setImageDrawable(getContext().getDrawable(multiple ?
|
||||
R.drawable.ic_fluent_add_square_24_regular :
|
||||
R.drawable.ic_fluent_add_circle_24_regular
|
||||
));
|
||||
for (DraftPollOption opt:pollOptions) {
|
||||
ImageView icon = opt.view.findViewById(R.id.icon);
|
||||
icon.setImageDrawable(getContext().getDrawable(multiple ?
|
||||
R.drawable.ic_poll_checkbox_regular_selector :
|
||||
R.drawable.ic_poll_option_button
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSelectionChanged(int start, int end){
|
||||
if(ignoreSelectionChanges)
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Activity;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -17,6 +18,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
@@ -56,7 +58,7 @@ import me.grishka.appkit.utils.V;
|
||||
|
||||
public class HomeTimelineFragment extends StatusListFragment{
|
||||
private ImageButton fab;
|
||||
private TextView toolbarLogo;
|
||||
private ImageView toolbarLogo;
|
||||
private Button toolbarShowNewPostsBtn;
|
||||
private boolean newPostsBtnShown;
|
||||
private AnimatorSet currentNewPostsAnim;
|
||||
@@ -315,9 +317,10 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||
}
|
||||
|
||||
private void updateToolbarLogo(){
|
||||
toolbarLogo =new TextView(getActivity());
|
||||
toolbarLogo.setText(getString(R.string.sk_app_name).toLowerCase(Locale.getDefault()));
|
||||
toolbarLogo.setTextAppearance(R.style.app_title);
|
||||
toolbarLogo=new ImageView(getActivity());
|
||||
toolbarLogo.setScaleType(ImageView.ScaleType.CENTER);
|
||||
toolbarLogo.setImageResource(R.drawable.logo);
|
||||
toolbarLogo.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary)));
|
||||
|
||||
toolbarShowNewPostsBtn=new Button(getActivity());
|
||||
toolbarShowNewPostsBtn.setTextAppearance(R.style.m3_title_medium);
|
||||
@@ -345,7 +348,9 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||
}
|
||||
|
||||
FrameLayout logoWrap=new FrameLayout(getActivity());
|
||||
logoWrap.addView(toolbarLogo, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
|
||||
FrameLayout.LayoutParams logoParams=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
|
||||
logoParams.setMargins(0, V.dp(2), 0, 0);
|
||||
logoWrap.addView(toolbarLogo, logoParams);
|
||||
logoWrap.addView(toolbarShowNewPostsBtn, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, V.dp(32), Gravity.CENTER));
|
||||
|
||||
Toolbar toolbar=getToolbar();
|
||||
|
||||
@@ -555,11 +555,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
menu.findItem(R.id.mute).setTitle(getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.block).setTitle(getString(relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.report).setTitle(getString(R.string.report_user, account.getDisplayUsername()));
|
||||
MenuItem manageUserLists=menu.findItem(R.id.manage_user_lists);
|
||||
if(relationship.following) {
|
||||
menu.findItem(R.id.hide_boosts).setTitle(getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getDisplayUsername()));
|
||||
manageUserLists.setTitle(getString(R.string.sk_lists_with_user, account.getDisplayUsername()));
|
||||
manageUserLists.setVisible(true);
|
||||
}else {
|
||||
menu.findItem(R.id.hide_boosts).setVisible(false);
|
||||
menu.findItem(R.id.manage_user_lists).setVisible(false);
|
||||
manageUserLists.setVisible(false);
|
||||
}
|
||||
if(!account.isLocal())
|
||||
menu.findItem(R.id.block_domain).setTitle(getString(relationship.domainBlocking ? R.string.unblock_domain : R.string.block_domain, account.getDomain()));
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
@@ -99,6 +100,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
GlobalUserPreferences.disableMarquee=i.checked;
|
||||
GlobalUserPreferences.save();
|
||||
}));
|
||||
items.add(new ColorPicker());
|
||||
|
||||
items.add(new HeaderItem(R.string.settings_behavior));
|
||||
items.add(new SwitchItem(R.string.settings_gif, R.drawable.ic_fluent_gif_24_regular, GlobalUserPreferences.playGifs, i->{
|
||||
@@ -144,6 +146,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
items.add(new SwitchItem(R.string.notify_follow, R.drawable.ic_fluent_person_add_24_regular, pushSubscription.alerts.follow, i->onNotificationsChanged(PushNotification.Type.FOLLOW, i.checked)));
|
||||
items.add(new SwitchItem(R.string.notify_reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, pushSubscription.alerts.reblog, i->onNotificationsChanged(PushNotification.Type.REBLOG, i.checked)));
|
||||
items.add(new SwitchItem(R.string.notify_mention, R.drawable.ic_at_symbol, pushSubscription.alerts.mention, i->onNotificationsChanged(PushNotification.Type.MENTION, i.checked)));
|
||||
items.add(new SwitchItem(R.string.sk_notify_posts, R.drawable.ic_fluent_alert_24_regular, pushSubscription.alerts.status, i->onNotificationsChanged(PushNotification.Type.STATUS, i.checked)));
|
||||
|
||||
items.add(new HeaderItem(R.string.settings_boring));
|
||||
items.add(new TextItem(R.string.settings_account, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/auth/edit")));
|
||||
@@ -157,6 +160,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
}
|
||||
items.add(new TextItem(R.string.sk_settings_contribute, ()->UiUtils.launchWebBrowser(getActivity(), "https://github.com/sk22/megalodon")));
|
||||
items.add(new TextItem(R.string.settings_clear_cache, this::clearImageCache));
|
||||
items.add(new TextItem(R.string.sk_clear_recent_languages, ()->UiUtils.showConfirmationAlert(getActivity(), R.string.sk_clear_recent_languages, R.string.sk_confirm_clear_recent_languages, R.string.clear, ()->{
|
||||
GlobalUserPreferences.recentLanguages.remove(accountID);
|
||||
GlobalUserPreferences.save();
|
||||
})));
|
||||
items.add(new TextItem(R.string.log_out, this::confirmLogOut));
|
||||
|
||||
items.add(new FooterItem(getString(R.string.sk_settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)));
|
||||
@@ -234,6 +241,12 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
restartActivityToApplyNewTheme();
|
||||
}
|
||||
|
||||
private void onColorPreferenceClick(GlobalUserPreferences.ColorPreference color){
|
||||
GlobalUserPreferences.color=color;
|
||||
GlobalUserPreferences.save();
|
||||
restartActivityToApplyNewTheme();
|
||||
}
|
||||
|
||||
private void onTrueBlackThemeChanged(SwitchItem item){
|
||||
GlobalUserPreferences.trueBlackTheme=item.checked;
|
||||
GlobalUserPreferences.save();
|
||||
@@ -293,6 +306,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
case FOLLOW -> subscription.alerts.follow=enabled;
|
||||
case REBLOG -> subscription.alerts.reblog=enabled;
|
||||
case MENTION -> subscription.alerts.mention=subscription.alerts.poll=enabled;
|
||||
case STATUS -> subscription.alerts.status=enabled;
|
||||
}
|
||||
needUpdateNotificationSettings=true;
|
||||
}
|
||||
@@ -436,6 +450,13 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
}
|
||||
}
|
||||
|
||||
public class ColorPicker extends Item{
|
||||
@Override
|
||||
public int getViewType(){
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ThemeItem extends Item{
|
||||
|
||||
@Override
|
||||
@@ -520,6 +541,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
case 5 -> new HeaderViewHolder(true);
|
||||
case 6 -> new FooterViewHolder();
|
||||
case 7 -> new UpdateViewHolder();
|
||||
case 8 -> new ColorPickerViewHolder();
|
||||
default -> throw new IllegalStateException("Unexpected value: "+viewType);
|
||||
};
|
||||
}
|
||||
@@ -648,6 +670,68 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
}
|
||||
}
|
||||
}
|
||||
private class ColorPickerViewHolder extends BindableViewHolder<ColorPicker>{
|
||||
private final Button button;
|
||||
private final PopupMenu popupMenu;
|
||||
private final ImageView icon;
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public ColorPickerViewHolder(){
|
||||
super(getActivity(), R.layout.item_settings_color_picker, list);
|
||||
icon=findViewById(R.id.icon);
|
||||
button=findViewById(R.id.color_picker_button);
|
||||
popupMenu=new PopupMenu(getActivity(), button, Gravity.CENTER_HORIZONTAL);
|
||||
popupMenu.inflate(R.menu.color_picker);
|
||||
popupMenu.setOnMenuItemClickListener(item->{
|
||||
GlobalUserPreferences.ColorPreference pref;
|
||||
int id=item.getItemId();
|
||||
if(id==R.id.pink_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.PINK;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else if(id==R.id.purple_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.PURPLE;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else if(id==R.id.green_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.GREEN;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else if(id==R.id.blue_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.BLUE;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else if(id==R.id.brown_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.BROWN;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else if(id==R.id.yellow_color) {
|
||||
pref = GlobalUserPreferences.ColorPreference.YELLOW;
|
||||
onColorPreferenceClick(pref);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
// UiUtils.enablePopupMenuIcons(getActivity(), popupMenu);
|
||||
button.setOnTouchListener(popupMenu.getDragToOpenListener());
|
||||
button.setOnClickListener(v->popupMenu.show());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(ColorPicker item){
|
||||
icon.setImageResource(R.drawable.ic_fluent_color_24_regular);
|
||||
button.setText(switch(GlobalUserPreferences.color){
|
||||
case PINK -> R.string.sk_color_theme_pink;
|
||||
case PURPLE -> R.string.sk_color_theme_purple;
|
||||
case GREEN -> R.string.sk_color_theme_green;
|
||||
case BLUE -> R.string.sk_color_theme_blue;
|
||||
case BROWN -> R.string.sk_color_theme_brown;
|
||||
case YELLOW -> R.string.sk_color_theme_yellow;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class NotificationPolicyViewHolder extends BindableViewHolder<NotificationPolicyItem>{
|
||||
private final Button button;
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ImageSpan;
|
||||
import android.text.style.ReplacementSpan;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.onboarding.InstanceCatalogFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.InstanceCatalogSignupFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.InstanceChooserLoginFragment;
|
||||
import org.joinmastodon.android.ui.InterpolatingMotionEffect;
|
||||
import org.joinmastodon.android.ui.views.SizeListenerFrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager2.widget.ViewPager2;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.fragments.AppKitFragment;
|
||||
import me.grishka.appkit.utils.V;
|
||||
@@ -23,12 +35,13 @@ public class SplashFragment extends AppKitFragment{
|
||||
|
||||
private SizeListenerFrameLayout contentView;
|
||||
private View artContainer, blueFill, greenFill;
|
||||
private InterpolatingMotionEffect motionEffect;
|
||||
private ViewPager2 pager;
|
||||
private ViewGroup pagerDots;
|
||||
private View artClouds, artPlaneElephant, artRightHill, artLeftHill, artCenterHill;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
motionEffect=new InterpolatingMotionEffect(MastodonApp.context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -37,15 +50,44 @@ public class SplashFragment extends AppKitFragment{
|
||||
contentView=(SizeListenerFrameLayout) inflater.inflate(R.layout.fragment_splash, container, false);
|
||||
contentView.findViewById(R.id.btn_get_started).setOnClickListener(this::onButtonClick);
|
||||
contentView.findViewById(R.id.btn_log_in).setOnClickListener(this::onButtonClick);
|
||||
artClouds=contentView.findViewById(R.id.art_clouds);
|
||||
artPlaneElephant=contentView.findViewById(R.id.art_plane_elephant);
|
||||
artRightHill=contentView.findViewById(R.id.art_right_hill);
|
||||
artLeftHill=contentView.findViewById(R.id.art_left_hill);
|
||||
artCenterHill=contentView.findViewById(R.id.art_center_hill);
|
||||
pager=contentView.findViewById(R.id.pager);
|
||||
pagerDots=contentView.findViewById(R.id.pager_dots);
|
||||
pager.setAdapter(new PagerAdapter());
|
||||
pager.setOffscreenPageLimit(3);
|
||||
pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
|
||||
for(int i=0;i<pagerDots.getChildCount();i++){
|
||||
float alpha;
|
||||
if(i==position){
|
||||
alpha=0.3f+0.7f*(1f-positionOffset);
|
||||
}else if(i==position+1){
|
||||
alpha=0.3f+0.7f*positionOffset;
|
||||
}else{
|
||||
alpha=0.3f;
|
||||
}
|
||||
pagerDots.getChildAt(i).setAlpha(alpha);
|
||||
}
|
||||
|
||||
float parallaxProgress=(position+positionOffset)/2f;
|
||||
artClouds.setTranslationX(V.dp(-27)*(position>=1 ? 1f : positionOffset));
|
||||
artPlaneElephant.setTranslationX(V.dp(101.55f)*parallaxProgress);
|
||||
artLeftHill.setTranslationX(V.dp(-88)*parallaxProgress);
|
||||
artLeftHill.setTranslationY(V.dp(24)*parallaxProgress);
|
||||
artRightHill.setTranslationX(V.dp(-88)*parallaxProgress);
|
||||
artRightHill.setTranslationY(V.dp(-24)*parallaxProgress);
|
||||
artCenterHill.setTranslationX(V.dp(-40)*parallaxProgress);
|
||||
}
|
||||
});
|
||||
|
||||
artContainer=contentView.findViewById(R.id.art_container);
|
||||
blueFill=contentView.findViewById(R.id.blue_fill);
|
||||
greenFill=contentView.findViewById(R.id.green_fill);
|
||||
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_clouds), V.dp(-5), V.dp(5), V.dp(-5), V.dp(5)));
|
||||
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_right_hill), V.dp(-15), V.dp(25), V.dp(-10), V.dp(10)));
|
||||
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_left_hill), V.dp(-25), V.dp(15), V.dp(-15), V.dp(15)));
|
||||
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_center_hill), V.dp(-14), V.dp(14), V.dp(-5), V.dp(25)));
|
||||
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(contentView.findViewById(R.id.art_plane_elephant), V.dp(-20), V.dp(12), V.dp(-20), V.dp(12)));
|
||||
|
||||
contentView.setSizeListener(new SizeListenerFrameLayout.OnSizeChangedListener(){
|
||||
@Override
|
||||
@@ -66,15 +108,16 @@ public class SplashFragment extends AppKitFragment{
|
||||
|
||||
private void onButtonClick(View v){
|
||||
Bundle extras=new Bundle();
|
||||
extras.putBoolean("signup", v.getId()==R.id.btn_get_started);
|
||||
Nav.go(getActivity(), InstanceCatalogFragment.class, extras);
|
||||
boolean isSignup=v.getId()==R.id.btn_get_started;
|
||||
extras.putBoolean("signup", isSignup);
|
||||
Nav.go(getActivity(), isSignup ? InstanceCatalogSignupFragment.class : InstanceChooserLoginFragment.class, extras);
|
||||
}
|
||||
|
||||
private void updateArtSize(int w, int h){
|
||||
float scale=w/(float)V.dp(412);
|
||||
float scale=w/(float)V.dp(360);
|
||||
artContainer.setScaleX(scale);
|
||||
artContainer.setScaleY(scale);
|
||||
blueFill.setScaleY(h/2f);
|
||||
blueFill.setScaleY(artContainer.getBottom()-V.dp(90));
|
||||
greenFill.setScaleY(h-artContainer.getBottom()+V.dp(90));
|
||||
}
|
||||
|
||||
@@ -100,15 +143,91 @@ public class SplashFragment extends AppKitFragment{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShown(){
|
||||
super.onShown();
|
||||
motionEffect.activate();
|
||||
private class PagerAdapter extends RecyclerView.Adapter<PagerViewHolder>{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new PagerViewHolder(viewType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PagerViewHolder holder, int position){}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHidden(){
|
||||
super.onHidden();
|
||||
motionEffect.deactivate();
|
||||
private class PagerViewHolder extends RecyclerView.ViewHolder{
|
||||
public PagerViewHolder(int page){
|
||||
super(new LinearLayout(getActivity()));
|
||||
LinearLayout ll=(LinearLayout) itemView;
|
||||
ll.setOrientation(LinearLayout.VERTICAL);
|
||||
int pad=V.dp(16);
|
||||
ll.setPadding(pad, pad, pad, pad);
|
||||
ll.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
|
||||
TextView title=new TextView(getActivity());
|
||||
title.setTextAppearance(R.style.m3_headline_medium);
|
||||
title.setText(switch(page){
|
||||
case 0 -> {
|
||||
String src=getString(R.string.welcome_page1_title);
|
||||
SpannableString ss=new SpannableString(src);
|
||||
int start=src.indexOf("{logo}");
|
||||
if(start!=-1){
|
||||
LogoSpan span=new LogoSpan(getResources().getDrawable(R.drawable.splash_logo, getActivity().getTheme()));
|
||||
ss.setSpan(span, start, start+6, 0);
|
||||
}
|
||||
yield ss;
|
||||
}
|
||||
case 1 -> getString(R.string.welcome_page2_title);
|
||||
case 2 -> getString(R.string.welcome_page3_title);
|
||||
default -> throw new IllegalStateException("Unexpected value: "+page);
|
||||
});
|
||||
title.setTextColor(0xFF17063B);
|
||||
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(page==0 ? 46 : 36));
|
||||
lp.bottomMargin=V.dp(page==0 ? 4 : 14);
|
||||
ll.addView(title, lp);
|
||||
|
||||
TextView text=new TextView(getActivity());
|
||||
text.setTextAppearance(R.style.m3_body_medium);
|
||||
text.setText(switch(page){
|
||||
case 0 -> R.string.welcome_page1_text;
|
||||
case 1 -> R.string.welcome_page2_text;
|
||||
case 2 -> R.string.welcome_page3_text;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+page);
|
||||
});
|
||||
text.setTextColor(0xFF17063B);
|
||||
ll.addView(text, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
}
|
||||
|
||||
private class LogoSpan extends ReplacementSpan{
|
||||
private final Drawable drawable;
|
||||
|
||||
private LogoSpan(Drawable drawable){
|
||||
this.drawable=drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm){
|
||||
return drawable.getIntrinsicWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint){
|
||||
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
|
||||
canvas.save();
|
||||
canvas.translate(x, y-V.dp(20));
|
||||
drawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,13 +286,16 @@ public abstract class BaseAccountListFragment extends BaseRecyclerFragment<BaseA
|
||||
menu.findItem(R.id.mute).setTitle(getString(relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.block).setTitle(getString(relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.report).setTitle(getString(R.string.report_user, account.getDisplayUsername()));
|
||||
menu.findItem(R.id.manage_user_lists).setTitle(getString(R.string.sk_lists_with_user, account.getDisplayUsername()));
|
||||
MenuItem hideBoosts=menu.findItem(R.id.hide_boosts);
|
||||
MenuItem manageUserLists=menu.findItem(R.id.manage_user_lists);
|
||||
if(relationship.following){
|
||||
hideBoosts.setTitle(getString(relationship.showingReblogs ? R.string.hide_boosts_from_user : R.string.show_boosts_from_user, account.getDisplayUsername()));
|
||||
hideBoosts.setVisible(true);
|
||||
manageUserLists.setTitle(getString(R.string.sk_lists_with_user, account.getDisplayUsername()));
|
||||
manageUserLists.setVisible(true);
|
||||
}else{
|
||||
hideBoosts.setVisible(false);
|
||||
manageUserLists.setVisible(true);
|
||||
}
|
||||
MenuItem blockDomain=menu.findItem(R.id.block_domain);
|
||||
if(!account.isLocal()){
|
||||
|
||||
@@ -2,46 +2,30 @@ package org.joinmastodon.android.fragments.onboarding;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.LocaleList;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.MastodonAPIController;
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.api.MastodonErrorResponse;
|
||||
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
||||
import org.joinmastodon.android.api.requests.catalog.GetCatalogCategories;
|
||||
import org.joinmastodon.android.api.requests.catalog.GetCatalogInstances;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.catalog.CatalogCategory;
|
||||
import org.joinmastodon.android.model.catalog.CatalogInstance;
|
||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.tabs.TabLayout;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.parceler.Parcels;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
@@ -59,317 +43,53 @@ import java.util.stream.Collectors;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.fragments.BaseRecyclerFragment;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.V;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstance>{
|
||||
private InstancesAdapter adapter;
|
||||
private MergeRecyclerAdapter mergeAdapter;
|
||||
private View headerView;
|
||||
private CatalogInstance chosenInstance;
|
||||
private List<CatalogInstance> filteredData=new ArrayList<>();
|
||||
private Button nextButton;
|
||||
private MastodonAPIRequest<?> getCategoriesRequest;
|
||||
private EditText searchEdit;
|
||||
private TabLayout categoriesList;
|
||||
private Runnable searchDebouncer=this::onSearchChangedDebounced;
|
||||
private String currentSearchQuery;
|
||||
private String currentCategory="all";
|
||||
private List<CatalogCategory> categories=new ArrayList<>();
|
||||
private String loadingInstanceDomain;
|
||||
private GetInstance loadingInstanceRequest;
|
||||
private Call loadingInstanceRedirectRequest;
|
||||
private HashMap<String, Instance> instancesCache=new HashMap<>();
|
||||
private ProgressDialog instanceProgressDialog;
|
||||
private View buttonBar;
|
||||
private HashMap<String, String> redirects=new HashMap<>(), redirectsInverse=new HashMap<>();
|
||||
|
||||
private boolean isSignup;
|
||||
abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstance>{
|
||||
protected RecyclerView.Adapter adapter;
|
||||
protected MergeRecyclerAdapter mergeAdapter;
|
||||
protected CatalogInstance chosenInstance;
|
||||
protected Button nextButton;
|
||||
protected EditText searchEdit;
|
||||
protected Runnable searchDebouncer=this::onSearchChangedDebounced;
|
||||
protected String currentSearchQuery;
|
||||
protected String loadingInstanceDomain;
|
||||
protected HashMap<String, Instance> instancesCache=new HashMap<>();
|
||||
protected View buttonBar;
|
||||
protected List<CatalogInstance> filteredData=new ArrayList<>();
|
||||
protected GetInstance loadingInstanceRequest;
|
||||
protected Call loadingInstanceRedirectRequest;
|
||||
protected ProgressDialog instanceProgressDialog;
|
||||
protected HashMap<String, String> redirects=new HashMap<>();
|
||||
protected HashMap<String, String> redirectsInverse=new HashMap<>();
|
||||
protected boolean isSignup;
|
||||
protected CatalogInstance fakeInstance=new CatalogInstance();
|
||||
|
||||
private static final double DUNBAR=Math.log(800);
|
||||
|
||||
public InstanceCatalogFragment(){
|
||||
super(R.layout.fragment_onboarding_common, 10);
|
||||
public InstanceCatalogFragment(int layout, int perPage){
|
||||
super(layout, perPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
isSignup=getArguments().getBoolean("signup");
|
||||
isSignup=getArguments() != null && getArguments().getBoolean("signup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context){
|
||||
super.onAttach(context);
|
||||
setRefreshEnabled(false);
|
||||
loadData();
|
||||
}
|
||||
protected abstract void proceedWithAuthOrSignup(Instance instance);
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
currentRequest=new GetCatalogInstances(null, null)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<CatalogInstance> result){
|
||||
if(getActivity()==null)
|
||||
return;
|
||||
Map<String, List<CatalogInstance>> byLang=result.stream().collect(Collectors.groupingBy(ci->ci.language));
|
||||
for(List<CatalogInstance> group:byLang.values()){
|
||||
Collections.sort(group, (a, b)->{
|
||||
double aa=Math.abs(DUNBAR-Math.log(a.lastWeekUsers));
|
||||
double bb=Math.abs(DUNBAR-Math.log(b.lastWeekUsers));
|
||||
return Double.compare(aa, bb);
|
||||
});
|
||||
}
|
||||
// get the list of user-configured system languages
|
||||
List<String> userLangs;
|
||||
if(Build.VERSION.SDK_INT<24){
|
||||
userLangs=Collections.singletonList(getResources().getConfiguration().locale.getLanguage());
|
||||
}else{
|
||||
LocaleList ll=getResources().getConfiguration().getLocales();
|
||||
userLangs=new ArrayList<>(ll.size());
|
||||
for(int i=0;i<ll.size();i++){
|
||||
userLangs.add(ll.get(i).getLanguage());
|
||||
}
|
||||
}
|
||||
// add instances in preferred languages to the top of the list, in the order of preference
|
||||
ArrayList<CatalogInstance> sortedList=new ArrayList<>();
|
||||
for(String lang:userLangs){
|
||||
List<CatalogInstance> langInstances=byLang.remove(lang);
|
||||
if(langInstances!=null){
|
||||
sortedList.addAll(langInstances);
|
||||
}
|
||||
}
|
||||
// sort the remaining language groups by aggregate lastWeekUsers
|
||||
class InstanceGroup{
|
||||
public int activeUsers;
|
||||
public List<CatalogInstance> instances;
|
||||
}
|
||||
byLang.values().stream().map(il->{
|
||||
InstanceGroup group=new InstanceGroup();
|
||||
group.instances=il;
|
||||
for(CatalogInstance instance:il){
|
||||
group.activeUsers+=instance.lastWeekUsers;
|
||||
}
|
||||
return group;
|
||||
}).sorted(Comparator.comparingInt((InstanceGroup g)->g.activeUsers).reversed()).forEachOrdered(ig->sortedList.addAll(ig.instances));
|
||||
onDataLoaded(sortedList, false);
|
||||
updateFilteredList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
error.showToast(getActivity());
|
||||
onDataLoaded(Collections.emptyList(), false);
|
||||
}
|
||||
})
|
||||
.execNoAuth("");
|
||||
getCategoriesRequest=new GetCatalogCategories(null)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<CatalogCategory> result){
|
||||
getCategoriesRequest=null;
|
||||
CatalogCategory all=new CatalogCategory();
|
||||
all.category="all";
|
||||
categories.add(all);
|
||||
result.stream().sorted(Comparator.comparingInt((CatalogCategory cc)->cc.serversCount).reversed()).forEach(categories::add);
|
||||
updateCategories();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
getCategoriesRequest=null;
|
||||
error.showToast(getActivity());
|
||||
CatalogCategory all=new CatalogCategory();
|
||||
all.category="all";
|
||||
categories.add(all);
|
||||
updateCategories();
|
||||
}
|
||||
})
|
||||
.execNoAuth("");
|
||||
}
|
||||
|
||||
private void updateCategories(){
|
||||
categoriesList.removeAllTabs();
|
||||
for(CatalogCategory cat:categories){
|
||||
int titleRes=getTitleForCategory(cat.category);
|
||||
TabLayout.Tab tab=categoriesList.newTab().setText(titleRes!=0 ? getString(titleRes) : cat.category).setCustomView(R.layout.item_instance_category);
|
||||
ImageView emoji=tab.getCustomView().findViewById(R.id.emoji);
|
||||
emoji.setImageResource(getEmojiForCategory(cat.category));
|
||||
categoriesList.addTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(){
|
||||
super.onDestroy();
|
||||
if(getCategoriesRequest!=null)
|
||||
getCategoriesRequest.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter getAdapter(){
|
||||
headerView=getActivity().getLayoutInflater().inflate(R.layout.header_onboarding_instance_catalog, list, false);
|
||||
searchEdit=headerView.findViewById(R.id.search_edit);
|
||||
categoriesList=headerView.findViewById(R.id.categories_list);
|
||||
categoriesList.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab){
|
||||
CatalogCategory category=categories.get(tab.getPosition());
|
||||
currentCategory=category.category;
|
||||
updateFilteredList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab){
|
||||
|
||||
}
|
||||
});
|
||||
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
||||
searchEdit.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){
|
||||
searchEdit.removeCallbacks(searchDebouncer);
|
||||
searchEdit.postDelayed(searchDebouncer, 300);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s){
|
||||
}
|
||||
});
|
||||
|
||||
mergeAdapter=new MergeRecyclerAdapter();
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||
mergeAdapter.addAdapter(adapter=new InstancesAdapter());
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
nextButton=view.findViewById(R.id.btn_next);
|
||||
nextButton.setOnClickListener(this::onNextClick);
|
||||
nextButton.setEnabled(chosenInstance!=null);
|
||||
view.findViewById(R.id.btn_back).setOnClickListener(v->Nav.finish(this));
|
||||
list.setItemAnimator(new BetterItemAnimator());
|
||||
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 1, 16, 16, DividerItemDecoration.NOT_FIRST));
|
||||
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLight));
|
||||
buttonBar=view.findViewById(R.id.button_bar);
|
||||
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLight));
|
||||
}
|
||||
|
||||
private void onNextClick(View v){
|
||||
String domain=chosenInstance.domain;
|
||||
Instance instance=instancesCache.get(domain);
|
||||
if(instance!=null){
|
||||
proceedWithAuthOrSignup(instance);
|
||||
}else{
|
||||
showProgressDialog();
|
||||
if(!domain.equals(loadingInstanceDomain)){
|
||||
loadInstanceInfo(domain, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void proceedWithAuthOrSignup(Instance instance){
|
||||
getActivity().getSystemService(InputMethodManager.class).hideSoftInputFromWindow(contentView.getWindowToken(), 0);
|
||||
if(isSignup){
|
||||
if(!instance.registrations){
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.instance_signup_closed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
Bundle args=new Bundle();
|
||||
args.putParcelable("instance", Parcels.wrap(instance));
|
||||
Nav.go(getActivity(), InstanceRulesFragment.class, args);
|
||||
}else{
|
||||
AccountSessionManager.getInstance().authenticate(getActivity(), instance);
|
||||
}
|
||||
}
|
||||
|
||||
// private String getEmojiForCategory(String category){
|
||||
// return switch(category){
|
||||
// case "all" -> "💬";
|
||||
// case "academia" -> "📚";
|
||||
// case "activism" -> "✊";
|
||||
// case "food" -> "🍕";
|
||||
// case "furry" -> "🦁";
|
||||
// case "games" -> "🕹";
|
||||
// case "general" -> "🐘";
|
||||
// case "journalism" -> "📰";
|
||||
// case "lgbt" -> "🏳️🌈";
|
||||
// case "regional" -> "📍";
|
||||
// case "art" -> "🎨";
|
||||
// case "music" -> "🎼";
|
||||
// case "tech" -> "📱";
|
||||
// default -> "❓";
|
||||
// };
|
||||
// }
|
||||
|
||||
private int getEmojiForCategory(String category){
|
||||
return switch(category){
|
||||
case "all" -> R.drawable.ic_category_all;
|
||||
case "academia" -> R.drawable.ic_category_academia;
|
||||
case "activism" -> R.drawable.ic_category_activism;
|
||||
case "food" -> R.drawable.ic_category_food;
|
||||
case "furry" -> R.drawable.ic_category_furry;
|
||||
case "games" -> R.drawable.ic_category_games;
|
||||
case "general" -> R.drawable.ic_category_general;
|
||||
case "journalism" -> R.drawable.ic_category_journalism;
|
||||
case "lgbt" -> R.drawable.ic_category_lgbt;
|
||||
case "regional" -> R.drawable.ic_category_regional;
|
||||
case "art" -> R.drawable.ic_category_art;
|
||||
case "music" -> R.drawable.ic_category_music;
|
||||
case "tech" -> R.drawable.ic_category_tech;
|
||||
default -> R.drawable.ic_category_unknown;
|
||||
};
|
||||
}
|
||||
|
||||
private int getTitleForCategory(String category){
|
||||
return switch(category){
|
||||
case "all" -> R.string.category_all;
|
||||
case "academia" -> R.string.category_academia;
|
||||
case "activism" -> R.string.category_activism;
|
||||
case "food" -> R.string.category_food;
|
||||
case "furry" -> R.string.category_furry;
|
||||
case "games" -> R.string.category_games;
|
||||
case "general" -> R.string.category_general;
|
||||
case "journalism" -> R.string.category_journalism;
|
||||
case "lgbt" -> R.string.category_lgbt;
|
||||
case "regional" -> R.string.category_regional;
|
||||
case "art" -> R.string.category_art;
|
||||
case "music" -> R.string.category_music;
|
||||
case "tech" -> R.string.category_tech;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
private boolean onSearchEnterPressed(TextView v, int actionId, KeyEvent event){
|
||||
protected boolean onSearchEnterPressed(TextView v, int actionId, KeyEvent event){
|
||||
if(event!=null && event.getAction()!=KeyEvent.ACTION_DOWN)
|
||||
return true;
|
||||
currentSearchQuery=searchEdit.getText().toString().toLowerCase();
|
||||
@@ -385,60 +105,73 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onSearchChangedDebounced(){
|
||||
protected void onSearchChangedDebounced(){
|
||||
currentSearchQuery=searchEdit.getText().toString().toLowerCase();
|
||||
updateFilteredList();
|
||||
loadInstanceInfo(currentSearchQuery, false);
|
||||
}
|
||||
|
||||
private void updateFilteredList(){
|
||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||
filteredData.clear();
|
||||
for(CatalogInstance instance:data){
|
||||
if(currentCategory.equals("all") || instance.categories.contains(currentCategory)){
|
||||
if(TextUtils.isEmpty(currentSearchQuery) || instance.domain.contains(currentSearchQuery)){
|
||||
if(instance.domain.equals(currentSearchQuery) || !isSignup || !instance.approvalRequired)
|
||||
filteredData.add(instance);
|
||||
}
|
||||
protected List<CatalogInstance> sortInstances(List<CatalogInstance> result){
|
||||
Map<String, List<CatalogInstance>> byLang=result.stream().collect(Collectors.groupingBy(ci->ci.language));
|
||||
for(List<CatalogInstance> group:byLang.values()){
|
||||
Collections.sort(group, (a, b)->{
|
||||
double aa=Math.abs(DUNBAR-Math.log(a.lastWeekUsers));
|
||||
double bb=Math.abs(DUNBAR-Math.log(b.lastWeekUsers));
|
||||
return Double.compare(aa, bb);
|
||||
});
|
||||
}
|
||||
// get the list of user-configured system languages
|
||||
List<String> userLangs;
|
||||
if(Build.VERSION.SDK_INT<24){
|
||||
userLangs=Collections.singletonList(getResources().getConfiguration().locale.getLanguage());
|
||||
}else{
|
||||
LocaleList ll=getResources().getConfiguration().getLocales();
|
||||
userLangs=new ArrayList<>(ll.size());
|
||||
for(int i=0;i<ll.size();i++){
|
||||
userLangs.add(ll.get(i).getLanguage());
|
||||
}
|
||||
}
|
||||
DiffUtil.calculateDiff(new DiffUtil.Callback(){
|
||||
@Override
|
||||
public int getOldListSize(){
|
||||
return prevData.size();
|
||||
// add instances in preferred languages to the top of the list, in the order of preference
|
||||
ArrayList<CatalogInstance> sortedList=new ArrayList<>();
|
||||
for(String lang:userLangs){
|
||||
List<CatalogInstance> langInstances=byLang.remove(lang);
|
||||
if(langInstances!=null){
|
||||
sortedList.addAll(langInstances);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize(){
|
||||
return filteredData.size();
|
||||
}
|
||||
// sort the remaining language groups by aggregate lastWeekUsers
|
||||
class InstanceGroup{
|
||||
public int activeUsers;
|
||||
public List<CatalogInstance> instances;
|
||||
}
|
||||
byLang.values().stream().map(il->{
|
||||
InstanceGroup group=new InstanceGroup();
|
||||
group.instances=il;
|
||||
for(CatalogInstance instance:il){
|
||||
group.activeUsers+=instance.lastWeekUsers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition){
|
||||
return prevData.get(oldItemPosition)==filteredData.get(newItemPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition){
|
||||
return prevData.get(oldItemPosition)==filteredData.get(newItemPosition);
|
||||
}
|
||||
}).dispatchUpdatesTo(adapter);
|
||||
return group;
|
||||
}).sorted(Comparator.comparingInt((InstanceGroup g)->g.activeUsers).reversed()).forEachOrdered(ig->sortedList.addAll(ig.instances));
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
private void showProgressDialog(){
|
||||
protected abstract void updateFilteredList();
|
||||
|
||||
protected void showProgressDialog(){
|
||||
instanceProgressDialog=new ProgressDialog(getActivity());
|
||||
instanceProgressDialog.setMessage(getString(R.string.loading_instance));
|
||||
instanceProgressDialog.setOnCancelListener(dialog->cancelLoadingInstanceInfo());
|
||||
instanceProgressDialog.show();
|
||||
}
|
||||
|
||||
private String normalizeInstanceDomain(String _domain){
|
||||
protected String normalizeInstanceDomain(String _domain){
|
||||
if(TextUtils.isEmpty(_domain))
|
||||
return null;
|
||||
if(_domain.contains(":")){
|
||||
try{
|
||||
_domain=Uri.parse(_domain).getAuthority();
|
||||
}catch(Exception ignore){}
|
||||
}catch(Exception ignore){
|
||||
}
|
||||
if(TextUtils.isEmpty(_domain))
|
||||
return null;
|
||||
}
|
||||
@@ -453,12 +186,12 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
return domain;
|
||||
}
|
||||
|
||||
private void loadInstanceInfo(String _domain, boolean isFromRedirect){
|
||||
protected void loadInstanceInfo(String _domain, boolean isFromRedirect){
|
||||
String domain=normalizeInstanceDomain(_domain);
|
||||
Instance cachedInstance=instancesCache.get(domain);
|
||||
if(cachedInstance!=null){
|
||||
for(CatalogInstance ci:filteredData){
|
||||
if(ci.domain.equals(domain))
|
||||
for(CatalogInstance ci : filteredData){
|
||||
if(ci.domain.equals(domain) && ci!=fakeInstance)
|
||||
return;
|
||||
}
|
||||
CatalogInstance ci=cachedInstance.toCatalogInstance();
|
||||
@@ -476,44 +209,57 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
loadingInstanceDomain=domain;
|
||||
loadingInstanceRequest=new GetInstance();
|
||||
loadingInstanceRequest.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Instance result){
|
||||
loadingInstanceRequest=null;
|
||||
loadingInstanceDomain=null;
|
||||
result.uri=domain; // needed for instances that use domain redirection
|
||||
instancesCache.put(domain, result);
|
||||
if(instanceProgressDialog!=null){
|
||||
instanceProgressDialog.dismiss();
|
||||
instanceProgressDialog=null;
|
||||
proceedWithAuthOrSignup(result);
|
||||
}
|
||||
if(Objects.equals(domain, currentSearchQuery) || Objects.equals(currentSearchQuery, redirects.get(domain)) || Objects.equals(currentSearchQuery, redirectsInverse.get(domain))){
|
||||
boolean found=false;
|
||||
for(CatalogInstance ci:filteredData){
|
||||
if(ci.domain.equals(domain)){
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
CatalogInstance ci=result.toCatalogInstance();
|
||||
filteredData.add(0, ci);
|
||||
adapter.notifyItemInserted(0);
|
||||
}
|
||||
@Override
|
||||
public void onSuccess(Instance result){
|
||||
loadingInstanceRequest=null;
|
||||
loadingInstanceDomain=null;
|
||||
result.uri=domain; // needed for instances that use domain redirection
|
||||
instancesCache.put(domain, result);
|
||||
if(instanceProgressDialog!=null){
|
||||
instanceProgressDialog.dismiss();
|
||||
instanceProgressDialog=null;
|
||||
proceedWithAuthOrSignup(result);
|
||||
}
|
||||
if(Objects.equals(domain, currentSearchQuery) || Objects.equals(currentSearchQuery, redirects.get(domain)) || Objects.equals(currentSearchQuery, redirectsInverse.get(domain))){
|
||||
boolean found=false;
|
||||
for(CatalogInstance ci : filteredData){
|
||||
if(ci.domain.equals(domain) && ci!=fakeInstance){
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
CatalogInstance ci=result.toCatalogInstance();
|
||||
if(filteredData.size()==1 && filteredData.get(0)==fakeInstance){
|
||||
filteredData.set(0, ci);
|
||||
adapter.notifyItemChanged(0);
|
||||
}else{
|
||||
filteredData.add(0, ci);
|
||||
adapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
loadingInstanceRequest=null;
|
||||
if(!isFromRedirect && error instanceof MastodonErrorResponse me && me.httpStatus==404){
|
||||
fetchDomainFromHostMetaAndMaybeRetry(domain, error);
|
||||
return;
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
loadingInstanceRequest=null;
|
||||
if(!isFromRedirect && error instanceof MastodonErrorResponse me && me.httpStatus==404){
|
||||
fetchDomainFromHostMetaAndMaybeRetry(domain, error);
|
||||
return;
|
||||
}
|
||||
loadingInstanceDomain=null;
|
||||
showInstanceInfoLoadError(domain, error);
|
||||
if(fakeInstance!=null){
|
||||
fakeInstance.description=getString(R.string.error);
|
||||
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
|
||||
if(list.findViewHolderForAdapterPosition(1) instanceof BindableViewHolder<?> ivh){
|
||||
ivh.rebind();
|
||||
}
|
||||
loadingInstanceDomain=null;
|
||||
showInstanceInfoLoadError(domain, error);
|
||||
}
|
||||
}).execNoAuth(domain);
|
||||
}
|
||||
}
|
||||
}).execNoAuth(domain);
|
||||
}
|
||||
|
||||
private void cancelLoadingInstanceInfo(){
|
||||
@@ -584,7 +330,7 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
InputSource source=new InputSource(response.body().charStream());
|
||||
Document doc=DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(source);
|
||||
NodeList list=doc.getElementsByTagName("Link");
|
||||
for(int i=0;i<list.getLength();i++){
|
||||
for(int i=0; i<list.getLength(); i++){
|
||||
if(list.item(i) instanceof Element el){
|
||||
String template=el.getAttribute("template");
|
||||
if("lrdd".equals(el.getAttribute("rel")) && !TextUtils.isEmpty(template) && template.contains("{uri}")){
|
||||
@@ -616,78 +362,26 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
}
|
||||
}
|
||||
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceViewHolder>{
|
||||
public InstancesAdapter(){
|
||||
super(imgLoader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InstanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new InstanceViewHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(InstanceViewHolder holder, int position){
|
||||
holder.bind(filteredData.get(position));
|
||||
super.onBindViewHolder(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return filteredData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
return -1;
|
||||
}
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
nextButton=view.findViewById(R.id.btn_next);
|
||||
nextButton.setOnClickListener(this::onNextClick);
|
||||
nextButton.setEnabled(chosenInstance!=null);
|
||||
buttonBar=view.findViewById(R.id.button_bar);
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
||||
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.Clickable{
|
||||
private final TextView title, description, userCount, lang;
|
||||
private final RadioButton radioButton;
|
||||
|
||||
public InstanceViewHolder(){
|
||||
super(getActivity(), R.layout.item_instance_catalog, list);
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
userCount=findViewById(R.id.user_count);
|
||||
lang=findViewById(R.id.lang);
|
||||
radioButton=findViewById(R.id.radiobtn);
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(userCount);
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(lang);
|
||||
protected void onNextClick(View v){
|
||||
String domain=chosenInstance.domain;
|
||||
Instance instance=instancesCache.get(domain);
|
||||
if(instance!=null){
|
||||
proceedWithAuthOrSignup(instance);
|
||||
}else{
|
||||
showProgressDialog();
|
||||
if(!domain.equals(loadingInstanceDomain)){
|
||||
loadInstanceInfo(domain, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(CatalogInstance item){
|
||||
title.setText(item.normalizedDomain);
|
||||
description.setText(item.description);
|
||||
userCount.setText(UiUtils.abbreviateNumber(item.totalUsers));
|
||||
lang.setText(item.language.toUpperCase());
|
||||
radioButton.setChecked(chosenInstance==item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
if(chosenInstance==item)
|
||||
return;
|
||||
if(chosenInstance!=null){
|
||||
int idx=filteredData.indexOf(chosenInstance);
|
||||
if(idx!=-1){
|
||||
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(mergeAdapter.getPositionForAdapter(adapter)+idx);
|
||||
if(holder instanceof InstanceViewHolder ivh){
|
||||
ivh.radioButton.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
radioButton.setChecked(true);
|
||||
if(chosenInstance==null)
|
||||
nextButton.setEnabled(true);
|
||||
chosenInstance=item;
|
||||
loadInstanceInfo(chosenInstance.domain, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,374 @@
|
||||
package org.joinmastodon.android.fragments.onboarding;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.LocaleList;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.api.requests.catalog.GetCatalogCategories;
|
||||
import org.joinmastodon.android.api.requests.catalog.GetCatalogInstances;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.catalog.CatalogCategory;
|
||||
import org.joinmastodon.android.model.catalog.CatalogInstance;
|
||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.tabs.TabLayout;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
|
||||
public class InstanceCatalogSignupFragment extends InstanceCatalogFragment{
|
||||
private View headerView;
|
||||
private MastodonAPIRequest<?> getCategoriesRequest;
|
||||
private TabLayout categoriesList;
|
||||
private String currentCategory="all";
|
||||
private List<CatalogCategory> categories=new ArrayList<>();
|
||||
|
||||
|
||||
public InstanceCatalogSignupFragment(){
|
||||
super(R.layout.fragment_onboarding_common, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context){
|
||||
super.onAttach(context);
|
||||
setRefreshEnabled(false);
|
||||
loadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
currentRequest=new GetCatalogInstances(null, null)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<CatalogInstance> result){
|
||||
if(getActivity()==null)
|
||||
return;
|
||||
onDataLoaded(sortInstances(result), false);
|
||||
updateFilteredList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
error.showToast(getActivity());
|
||||
onDataLoaded(Collections.emptyList(), false);
|
||||
}
|
||||
})
|
||||
.execNoAuth("");
|
||||
getCategoriesRequest=new GetCatalogCategories(null)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<CatalogCategory> result){
|
||||
getCategoriesRequest=null;
|
||||
CatalogCategory all=new CatalogCategory();
|
||||
all.category="all";
|
||||
categories.add(all);
|
||||
result.stream().sorted(Comparator.comparingInt((CatalogCategory cc)->cc.serversCount).reversed()).forEach(categories::add);
|
||||
updateCategories();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
getCategoriesRequest=null;
|
||||
error.showToast(getActivity());
|
||||
CatalogCategory all=new CatalogCategory();
|
||||
all.category="all";
|
||||
categories.add(all);
|
||||
updateCategories();
|
||||
}
|
||||
})
|
||||
.execNoAuth("");
|
||||
}
|
||||
|
||||
private void updateCategories(){
|
||||
categoriesList.removeAllTabs();
|
||||
for(CatalogCategory cat:categories){
|
||||
int titleRes=getTitleForCategory(cat.category);
|
||||
TabLayout.Tab tab=categoriesList.newTab().setText(titleRes!=0 ? getString(titleRes) : cat.category).setCustomView(R.layout.item_instance_category);
|
||||
ImageView emoji=tab.getCustomView().findViewById(R.id.emoji);
|
||||
emoji.setImageResource(getEmojiForCategory(cat.category));
|
||||
categoriesList.addTab(tab);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(){
|
||||
super.onDestroy();
|
||||
if(getCategoriesRequest!=null)
|
||||
getCategoriesRequest.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter getAdapter(){
|
||||
headerView=getActivity().getLayoutInflater().inflate(R.layout.header_onboarding_instance_catalog, list, false);
|
||||
searchEdit=headerView.findViewById(R.id.search_edit);
|
||||
categoriesList=headerView.findViewById(R.id.categories_list);
|
||||
categoriesList.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){
|
||||
@Override
|
||||
public void onTabSelected(TabLayout.Tab tab){
|
||||
CatalogCategory category=categories.get(tab.getPosition());
|
||||
currentCategory=category.category;
|
||||
updateFilteredList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(TabLayout.Tab tab){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(TabLayout.Tab tab){
|
||||
|
||||
}
|
||||
});
|
||||
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
||||
searchEdit.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){
|
||||
searchEdit.removeCallbacks(searchDebouncer);
|
||||
searchEdit.postDelayed(searchDebouncer, 300);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s){
|
||||
}
|
||||
});
|
||||
|
||||
mergeAdapter=new MergeRecyclerAdapter();
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||
mergeAdapter.addAdapter(adapter=new InstancesAdapter());
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
view.findViewById(R.id.btn_back).setOnClickListener(v->Nav.finish(this));
|
||||
list.setItemAnimator(new BetterItemAnimator());
|
||||
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorPollVoted, 1, 16, 16, DividerItemDecoration.NOT_FIRST));
|
||||
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLight));
|
||||
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorBackgroundLight));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void proceedWithAuthOrSignup(Instance instance){
|
||||
getActivity().getSystemService(InputMethodManager.class).hideSoftInputFromWindow(contentView.getWindowToken(), 0);
|
||||
if(isSignup){
|
||||
if(!instance.registrations){
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.instance_signup_closed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
Bundle args=new Bundle();
|
||||
args.putParcelable("instance", Parcels.wrap(instance));
|
||||
Nav.go(getActivity(), InstanceRulesFragment.class, args);
|
||||
}else{
|
||||
}
|
||||
}
|
||||
|
||||
// private String getEmojiForCategory(String category){
|
||||
// return switch(category){
|
||||
// case "all" -> "💬";
|
||||
// case "academia" -> "📚";
|
||||
// case "activism" -> "✊";
|
||||
// case "food" -> "🍕";
|
||||
// case "furry" -> "🦁";
|
||||
// case "games" -> "🕹";
|
||||
// case "general" -> "🐘";
|
||||
// case "journalism" -> "📰";
|
||||
// case "lgbt" -> "🏳️🌈";
|
||||
// case "regional" -> "📍";
|
||||
// case "art" -> "🎨";
|
||||
// case "music" -> "🎼";
|
||||
// case "tech" -> "📱";
|
||||
// default -> "❓";
|
||||
// };
|
||||
// }
|
||||
|
||||
private int getEmojiForCategory(String category){
|
||||
return switch(category){
|
||||
case "all" -> R.drawable.ic_category_all;
|
||||
case "academia" -> R.drawable.ic_category_academia;
|
||||
case "activism" -> R.drawable.ic_category_activism;
|
||||
case "food" -> R.drawable.ic_category_food;
|
||||
case "furry" -> R.drawable.ic_category_furry;
|
||||
case "games" -> R.drawable.ic_category_games;
|
||||
case "general" -> R.drawable.ic_category_general;
|
||||
case "journalism" -> R.drawable.ic_category_journalism;
|
||||
case "lgbt" -> R.drawable.ic_category_lgbt;
|
||||
case "regional" -> R.drawable.ic_category_regional;
|
||||
case "art" -> R.drawable.ic_category_art;
|
||||
case "music" -> R.drawable.ic_category_music;
|
||||
case "tech" -> R.drawable.ic_category_tech;
|
||||
default -> R.drawable.ic_category_unknown;
|
||||
};
|
||||
}
|
||||
|
||||
private int getTitleForCategory(String category){
|
||||
return switch(category){
|
||||
case "all" -> R.string.category_all;
|
||||
case "academia" -> R.string.category_academia;
|
||||
case "activism" -> R.string.category_activism;
|
||||
case "food" -> R.string.category_food;
|
||||
case "furry" -> R.string.category_furry;
|
||||
case "games" -> R.string.category_games;
|
||||
case "general" -> R.string.category_general;
|
||||
case "journalism" -> R.string.category_journalism;
|
||||
case "lgbt" -> R.string.category_lgbt;
|
||||
case "regional" -> R.string.category_regional;
|
||||
case "art" -> R.string.category_art;
|
||||
case "music" -> R.string.category_music;
|
||||
case "tech" -> R.string.category_tech;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFilteredList(){
|
||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||
filteredData.clear();
|
||||
for(CatalogInstance instance:data){
|
||||
if(currentCategory.equals("all") || instance.categories.contains(currentCategory)){
|
||||
if(TextUtils.isEmpty(currentSearchQuery) || instance.domain.contains(currentSearchQuery)){
|
||||
if(instance.domain.equals(currentSearchQuery) || !isSignup || !instance.approvalRequired)
|
||||
filteredData.add(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
DiffUtil.calculateDiff(new DiffUtil.Callback(){
|
||||
@Override
|
||||
public int getOldListSize(){
|
||||
return prevData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewListSize(){
|
||||
return filteredData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition){
|
||||
return prevData.get(oldItemPosition)==filteredData.get(newItemPosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition){
|
||||
return prevData.get(oldItemPosition)==filteredData.get(newItemPosition);
|
||||
}
|
||||
}).dispatchUpdatesTo(adapter);
|
||||
}
|
||||
|
||||
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceCatalogSignupFragment.InstanceViewHolder>{
|
||||
public InstancesAdapter(){
|
||||
super(imgLoader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InstanceCatalogSignupFragment.InstanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new InstanceCatalogSignupFragment.InstanceViewHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(InstanceCatalogSignupFragment.InstanceViewHolder holder, int position){
|
||||
holder.bind(filteredData.get(position));
|
||||
super.onBindViewHolder(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return filteredData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.Clickable{
|
||||
private final TextView title, description, userCount, lang;
|
||||
private final RadioButton radioButton;
|
||||
|
||||
public InstanceViewHolder(){
|
||||
super(getActivity(), R.layout.item_instance_catalog, list);
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
userCount=findViewById(R.id.user_count);
|
||||
lang=findViewById(R.id.lang);
|
||||
radioButton=findViewById(R.id.radiobtn);
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(userCount);
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(lang);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(CatalogInstance item){
|
||||
title.setText(item.normalizedDomain);
|
||||
description.setText(item.description);
|
||||
userCount.setText(UiUtils.abbreviateNumber(item.totalUsers));
|
||||
lang.setText(item.language.toUpperCase());
|
||||
radioButton.setChecked(chosenInstance==item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
if(chosenInstance==item)
|
||||
return;
|
||||
if(chosenInstance!=null){
|
||||
int idx=filteredData.indexOf(chosenInstance);
|
||||
if(idx!=-1){
|
||||
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(mergeAdapter.getPositionForAdapter(adapter)+idx);
|
||||
if(holder instanceof InstanceCatalogSignupFragment.InstanceViewHolder ivh){
|
||||
ivh.radioButton.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
radioButton.setChecked(true);
|
||||
if(chosenInstance==null)
|
||||
nextButton.setEnabled(true);
|
||||
chosenInstance=item;
|
||||
loadInstanceInfo(chosenInstance.domain, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package org.joinmastodon.android.fragments.onboarding;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.catalog.GetCatalogInstances;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.catalog.CatalogInstance;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.V;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
|
||||
public class InstanceChooserLoginFragment extends InstanceCatalogFragment{
|
||||
private View headerView;
|
||||
private boolean loadedAutocomplete;
|
||||
private ImageButton clearBtn;
|
||||
|
||||
public InstanceChooserLoginFragment(){
|
||||
super(R.layout.fragment_login, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
dataLoaded();
|
||||
setTitle(R.string.login_title);
|
||||
if(!loadedAutocomplete){
|
||||
loadAutocompleteServers();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void proceedWithAuthOrSignup(Instance instance){
|
||||
AccountSessionManager.getInstance().authenticate(getActivity(), instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFilteredList(){
|
||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||
filteredData.clear();
|
||||
if(currentSearchQuery.length()>0){
|
||||
boolean foundExactMatch=false;
|
||||
for(CatalogInstance inst:data){
|
||||
if(inst.normalizedDomain.contains(currentSearchQuery)){
|
||||
filteredData.add(inst);
|
||||
if(inst.normalizedDomain.equals(currentSearchQuery))
|
||||
foundExactMatch=true;
|
||||
}
|
||||
}
|
||||
if(!foundExactMatch)
|
||||
filteredData.add(0, fakeInstance);
|
||||
}
|
||||
UiUtils.updateList(prevData, filteredData, list, adapter, Objects::equals);
|
||||
for(int i=0;i<list.getChildCount();i++){
|
||||
list.getChildAt(i).invalidateOutline();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
|
||||
}
|
||||
|
||||
private void loadAutocompleteServers(){
|
||||
loadedAutocomplete=true;
|
||||
new GetCatalogInstances(null, null)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<CatalogInstance> result){
|
||||
data.clear();
|
||||
data.addAll(sortInstances(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
|
||||
}
|
||||
})
|
||||
.execNoAuth("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateToolbar(){
|
||||
super.onUpdateToolbar();
|
||||
Toolbar toolbar=getToolbar();
|
||||
toolbar.setElevation(0);
|
||||
toolbar.setBackground(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter getAdapter(){
|
||||
headerView=getActivity().getLayoutInflater().inflate(R.layout.header_onboarding_login, list, false);
|
||||
clearBtn=headerView.findViewById(R.id.search_clear);
|
||||
searchEdit=headerView.findViewById(R.id.search_edit);
|
||||
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
||||
searchEdit.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){
|
||||
searchEdit.removeCallbacks(searchDebouncer);
|
||||
searchEdit.postDelayed(searchDebouncer, 300);
|
||||
|
||||
if(s.length()>0){
|
||||
fakeInstance.domain=fakeInstance.normalizedDomain=s.toString();
|
||||
fakeInstance.description=getString(R.string.loading_instance);
|
||||
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
|
||||
if(list.findViewHolderForAdapterPosition(1) instanceof InstanceViewHolder ivh){
|
||||
ivh.rebind();
|
||||
}
|
||||
}
|
||||
if(filteredData.isEmpty()){
|
||||
filteredData.add(fakeInstance);
|
||||
adapter.notifyItemInserted(0);
|
||||
}
|
||||
clearBtn.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
clearBtn.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s){
|
||||
}
|
||||
});
|
||||
clearBtn.setOnClickListener(v->searchEdit.setText(""));
|
||||
|
||||
mergeAdapter=new MergeRecyclerAdapter();
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||
mergeAdapter.addAdapter(adapter=new InstancesAdapter());
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
|
||||
|
||||
list.addItemDecoration(new RecyclerView.ItemDecoration(){
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
|
||||
if(parent.getChildViewHolder(view) instanceof InstanceViewHolder){
|
||||
outRect.left=outRect.right=V.dp(16);
|
||||
}
|
||||
}
|
||||
});
|
||||
((UsableRecyclerView)list).setDrawSelectorOnTop(true);
|
||||
}
|
||||
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceViewHolder>{
|
||||
public InstancesAdapter(){
|
||||
super(imgLoader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InstanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new InstanceViewHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(InstanceViewHolder holder, int position){
|
||||
holder.bind(filteredData.get(position));
|
||||
super.onBindViewHolder(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return filteredData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.Clickable{
|
||||
private final TextView title, description;
|
||||
private final RadioButton radioButton;
|
||||
|
||||
public InstanceViewHolder(){
|
||||
super(getActivity(), R.layout.item_instance_login, list);
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
radioButton=findViewById(R.id.radiobtn);
|
||||
radioButton.setMinWidth(0);
|
||||
radioButton.setMinHeight(0);
|
||||
|
||||
itemView.setOutlineProvider(new ViewOutlineProvider(){
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline){
|
||||
outline.setRoundRect(0, getAbsoluteAdapterPosition()==1 ? 0 : V.dp(-4), view.getWidth(), view.getHeight()+(getAbsoluteAdapterPosition()==filteredData.size() ? 0 : V.dp(4)), V.dp(4));
|
||||
}
|
||||
});
|
||||
itemView.setClipToOutline(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(CatalogInstance item){
|
||||
title.setText(item.normalizedDomain);
|
||||
description.setText(item.description);
|
||||
radioButton.setChecked(chosenInstance==item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
if(chosenInstance==item)
|
||||
return;
|
||||
if(chosenInstance!=null){
|
||||
int idx=filteredData.indexOf(chosenInstance);
|
||||
if(idx!=-1){
|
||||
boolean found=false;
|
||||
for(int i=0;i<list.getChildCount();i++){
|
||||
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
|
||||
if(holder.getAbsoluteAdapterPosition()==mergeAdapter.getPositionForAdapter(adapter)+idx && holder instanceof InstanceViewHolder ivh){
|
||||
ivh.radioButton.setChecked(false);
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
adapter.notifyItemChanged(idx);
|
||||
}
|
||||
}
|
||||
radioButton.setChecked(true);
|
||||
if(chosenInstance==null)
|
||||
nextButton.setEnabled(true);
|
||||
chosenInstance=item;
|
||||
loadInstanceInfo(chosenInstance.domain, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
package org.joinmastodon.android.fragments.onboarding;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DiffUtil;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.catalog.CatalogInstance;
|
||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||
import org.joinmastodon.android.ui.DividerItemDecoration;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import me.grishka.appkit.FragmentStackActivity;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.PaginatedList;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.V;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
|
||||
public class MegalodonLoginFragment extends InstanceCatalogFragment {
|
||||
private View headerView;
|
||||
|
||||
public MegalodonLoginFragment() {
|
||||
super(R.layout.fragment_megalodon_welcome, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context){
|
||||
super.onAttach(context);
|
||||
setRefreshEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
dataLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onUpdateToolbar(){
|
||||
super.onUpdateToolbar();
|
||||
|
||||
if (!canGoBack()) {
|
||||
ImageView toolbarLogo=new ImageView(getActivity());
|
||||
toolbarLogo.setScaleType(ImageView.ScaleType.CENTER);
|
||||
toolbarLogo.setImageResource(R.drawable.logo);
|
||||
toolbarLogo.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary)));
|
||||
|
||||
FrameLayout logoWrap=new FrameLayout(getActivity());
|
||||
FrameLayout.LayoutParams logoParams=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
|
||||
logoParams.setMargins(0, V.dp(2), 0, 0);
|
||||
logoWrap.addView(toolbarLogo, logoParams);
|
||||
|
||||
getToolbar().addView(logoWrap, new Toolbar.LayoutParams(Gravity.CENTER));
|
||||
} else {
|
||||
setTitle(R.string.add_account);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void proceedWithAuthOrSignup(Instance instance) {
|
||||
AccountSessionManager.getInstance().authenticate(getActivity(), instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFilteredList(){
|
||||
boolean addFakeInstance = currentSearchQuery.length()>0 && currentSearchQuery.matches("^\\S+\\.[^\\.]+$");
|
||||
if(addFakeInstance){
|
||||
fakeInstance.domain=fakeInstance.normalizedDomain=currentSearchQuery;
|
||||
fakeInstance.description=getString(R.string.loading_instance);
|
||||
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
|
||||
if(list.findViewHolderForAdapterPosition(1) instanceof InstanceViewHolder ivh){
|
||||
ivh.rebind();
|
||||
}
|
||||
}
|
||||
if(filteredData.isEmpty()){
|
||||
filteredData.add(fakeInstance);
|
||||
adapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||
filteredData.clear();
|
||||
if(currentSearchQuery.length()>0){
|
||||
boolean foundExactMatch=false;
|
||||
for(CatalogInstance inst:data){
|
||||
if(inst.normalizedDomain.contains(currentSearchQuery)){
|
||||
filteredData.add(inst);
|
||||
if(inst.normalizedDomain.equals(currentSearchQuery))
|
||||
foundExactMatch=true;
|
||||
}
|
||||
}
|
||||
if(!foundExactMatch && addFakeInstance) {
|
||||
filteredData.add(0, fakeInstance);
|
||||
adapter.notifyItemChanged(0);
|
||||
}
|
||||
}
|
||||
UiUtils.updateList(prevData, filteredData, list, adapter, Objects::equals);
|
||||
for(int i=0;i<list.getChildCount();i++){
|
||||
list.getChildAt(i).invalidateOutline();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorWindowBackground));
|
||||
list.setItemAnimator(new BetterItemAnimator());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count) {}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.Adapter getAdapter(){
|
||||
headerView=getActivity().getLayoutInflater().inflate(R.layout.header_megalodon_welcome, list, false);
|
||||
searchEdit=headerView.findViewById(R.id.search_edit);
|
||||
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
|
||||
|
||||
headerView.findViewById(R.id.more).setVisibility(View.GONE);
|
||||
headerView.findViewById(R.id.visibility).setVisibility(View.GONE);
|
||||
((TextView) headerView.findViewById(R.id.username)).setText("@megalodon");
|
||||
((TextView) headerView.findViewById(R.id.name)).setText(R.string.sk_app_name);
|
||||
((TextView) headerView.findViewById(R.id.timestamp)).setText(R.string.time_now);
|
||||
((ImageView) headerView.findViewById(R.id.avatar)).setImageDrawable(getActivity().getDrawable(R.mipmap.ic_launcher));
|
||||
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(this);
|
||||
|
||||
searchEdit.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){
|
||||
nextButton.setEnabled(false);
|
||||
chosenInstance = null;
|
||||
searchEdit.removeCallbacks(searchDebouncer);
|
||||
searchEdit.postDelayed(searchDebouncer, 300);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s){}
|
||||
});
|
||||
|
||||
mergeAdapter=new MergeRecyclerAdapter();
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||
mergeAdapter.addAdapter(adapter=new InstancesAdapter());
|
||||
View spacer = new Space(getActivity());
|
||||
spacer.setMinimumHeight(V.dp(8));
|
||||
mergeAdapter.addAdapter(new SingleViewRecyclerAdapter(spacer));
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceViewHolder>{
|
||||
public InstancesAdapter(){
|
||||
super(imgLoader);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InstanceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new InstanceViewHolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(InstanceViewHolder holder, int position){
|
||||
holder.bind(filteredData.get(position));
|
||||
chosenInstance = filteredData.get(position);
|
||||
if (chosenInstance != fakeInstance) nextButton.setEnabled(true);
|
||||
super.onBindViewHolder(holder, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return filteredData.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.Clickable{
|
||||
private final TextView title, description, userCount, lang;
|
||||
private final RadioButton radioButton;
|
||||
|
||||
public InstanceViewHolder(){
|
||||
super(getActivity(), R.layout.item_megalodon_instance, list);
|
||||
|
||||
// itemView.setPadding(V.dp(16), V.dp(16), V.dp(16), V.dp(16));
|
||||
// TypedValue value = new TypedValue();
|
||||
// getActivity().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
|
||||
// itemView.setBackground(getActivity().getTheme().getDrawable(R.drawable.bg_search_field));
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
userCount=findViewById(R.id.user_count);
|
||||
lang=findViewById(R.id.lang);
|
||||
radioButton=findViewById(R.id.radiobtn);
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N){
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(userCount);
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(lang);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(CatalogInstance item){
|
||||
title.setText(item.normalizedDomain);
|
||||
description.setText(item.description);
|
||||
if (item == fakeInstance) {
|
||||
userCount.setVisibility(View.GONE);
|
||||
lang.setVisibility(View.GONE);
|
||||
} else {
|
||||
userCount.setVisibility(View.VISIBLE);
|
||||
lang.setVisibility(View.VISIBLE);
|
||||
userCount.setText(UiUtils.abbreviateNumber(item.totalUsers));
|
||||
lang.setText(item.language.toUpperCase());
|
||||
}
|
||||
radioButton.setChecked(chosenInstance==item);
|
||||
radioButton.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
if(chosenInstance!=null){
|
||||
int idx=filteredData.indexOf(chosenInstance);
|
||||
if(idx!=-1){
|
||||
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(mergeAdapter.getPositionForAdapter(adapter)+idx);
|
||||
if(holder instanceof InstanceViewHolder ivh){
|
||||
ivh.radioButton.setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
radioButton.setChecked(true);
|
||||
if(chosenInstance==null)
|
||||
nextButton.setEnabled(true);
|
||||
chosenInstance=item;
|
||||
loadInstanceInfo(chosenInstance.domain, false);
|
||||
onNextClick(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,8 @@ public class Instance extends BaseModel{
|
||||
// non-standard field in some Mastodon forks
|
||||
public int maxTootChars;
|
||||
|
||||
public V2 v2;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
super.postprocess();
|
||||
@@ -176,4 +178,19 @@ public class Instance extends BaseModel{
|
||||
public int minExpiration;
|
||||
public int maxExpiration;
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public static class V2 extends BaseModel {
|
||||
public V2.Configuration configuration;
|
||||
|
||||
@Parcel
|
||||
public static class Configuration {
|
||||
public TranslationConfiguration translation;
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public static class TranslationConfiguration{
|
||||
public boolean enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,9 @@ public class PushNotification extends BaseModel{
|
||||
@SerializedName("follow")
|
||||
FOLLOW(R.string.notification_type_follow),
|
||||
@SerializedName("poll")
|
||||
POLL(R.string.notification_type_poll);
|
||||
POLL(R.string.notification_type_poll),
|
||||
@SerializedName("status")
|
||||
STATUS(R.string.sk_notification_type_status);
|
||||
|
||||
@StringRes
|
||||
public final int localizedName;
|
||||
|
||||
@@ -43,10 +43,11 @@ public class PushSubscription extends BaseModel implements Cloneable{
|
||||
public boolean reblog;
|
||||
public boolean mention;
|
||||
public boolean poll;
|
||||
public boolean status;
|
||||
|
||||
public static Alerts ofAll(){
|
||||
Alerts alerts=new Alerts();
|
||||
alerts.follow=alerts.favourite=alerts.reblog=alerts.mention=alerts.poll=true;
|
||||
alerts.follow=alerts.favourite=alerts.reblog=alerts.mention=alerts.poll=alerts.status=true;
|
||||
return alerts;
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ public class PushSubscription extends BaseModel implements Cloneable{
|
||||
", reblog="+reblog+
|
||||
", mention="+mention+
|
||||
", poll="+poll+
|
||||
", status="+status+
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
public class TranslatedStatus extends BaseModel {
|
||||
public String content;
|
||||
public String detectedSourceLanguage;
|
||||
public String provider;
|
||||
}
|
||||
@@ -2,14 +2,12 @@ package org.joinmastodon.android.ui;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
@@ -25,8 +23,7 @@ import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.SplashFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.fragments.onboarding.MegalodonLoginFragment;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.List;
|
||||
@@ -80,7 +77,7 @@ public class AccountSwitcherSheet extends BottomSheet{
|
||||
holder.avatar.setImageResource(R.drawable.ic_fluent_add_circle_24_filled);
|
||||
holder.avatar.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(activity, android.R.attr.textColorPrimary)));
|
||||
adapter.addAdapter(new ClickableSingleViewRecyclerAdapter(holder.itemView, ()->{
|
||||
Nav.go(activity, SplashFragment.class, null);
|
||||
Nav.go(activity, MegalodonLoginFragment.class, null);
|
||||
dismiss();
|
||||
}));
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
@@ -154,11 +155,16 @@ public class ComposeAutocompleteViewController{
|
||||
}else if(mode==Mode.EMOJIS){
|
||||
String _text=text.substring(1); // remove ':'
|
||||
List<WrappedEmoji> oldList=emojis;
|
||||
emojis=AccountSessionManager.getInstance()
|
||||
List<Emoji> allEmojis = AccountSessionManager.getInstance()
|
||||
.getCustomEmojis(AccountSessionManager.getInstance().getAccount(accountID).domain)
|
||||
.stream()
|
||||
.flatMap(ec->ec.emojis.stream())
|
||||
.filter(e->e.visibleInPicker && e.shortcode.startsWith(_text))
|
||||
.filter(e->e.visibleInPicker)
|
||||
.collect(Collectors.toList());
|
||||
List<Emoji> startsWithSearch = allEmojis.stream().filter(e -> e.shortcode.toLowerCase().startsWith(_text.toLowerCase())).collect(Collectors.toList());
|
||||
emojis=Stream.concat(startsWithSearch.stream(), allEmojis.stream()
|
||||
.filter(e -> !startsWithSearch.contains(e))
|
||||
.filter(e -> e.shortcode.toLowerCase().contains(_text.toLowerCase())))
|
||||
.map(WrappedEmoji::new)
|
||||
.collect(Collectors.toList());
|
||||
UiUtils.updateList(oldList, emojis, list, emojisAdapter, (e1, e2)->e1.emoji.shortcode.equals(e2.emoji.shortcode));
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Poll;
|
||||
@@ -44,7 +45,7 @@ public class PollFooterStatusDisplayItem extends StatusDisplayItem{
|
||||
text+=" · "+item.parentFragment.getString(R.string.poll_closed);
|
||||
}
|
||||
this.text.setText(text);
|
||||
button.setVisibility(item.poll.isExpired() || item.poll.voted || !item.poll.multiple ? View.GONE : View.VISIBLE);
|
||||
button.setVisibility(item.poll.isExpired() || item.poll.voted || (!item.poll.multiple && !GlobalUserPreferences.voteButtonForSingleChoice) ? View.GONE : View.VISIBLE);
|
||||
button.setEnabled(item.poll.selectedOptions!=null && !item.poll.selectedOptions.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
@@ -60,7 +61,8 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<PollOptionStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView text, percent;
|
||||
private final View icon, button;
|
||||
private final View button;
|
||||
private final ImageView icon;
|
||||
private final Drawable progressBg;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
@@ -76,17 +78,23 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||
@Override
|
||||
public void onBind(PollOptionStatusDisplayItem item){
|
||||
text.setText(item.text);
|
||||
icon.setVisibility(item.showResults ? View.GONE : View.VISIBLE);
|
||||
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
||||
itemView.setClickable(!item.showResults);
|
||||
icon.setImageDrawable(itemView.getContext().getDrawable(item.poll.multiple ?
|
||||
item.showResults ? R.drawable.ic_poll_checkbox_regular_selector : R.drawable.ic_poll_checkbox_filled_selector :
|
||||
item.showResults ? R.drawable.ic_poll_option_button : R.drawable.ic_fluent_radio_button_24_selector
|
||||
));
|
||||
if(item.showResults){
|
||||
progressBg.setLevel(Math.round(10000f*item.votesFraction));
|
||||
button.setBackground(progressBg);
|
||||
itemView.setSelected(item.isMostVoted);
|
||||
icon.setSelected(item.poll.ownVotes.contains(item.poll.options.indexOf(item.option)));
|
||||
icon.setVisibility(item.poll.voted && item.poll.ownVotes.isEmpty() ? View.GONE : View.VISIBLE);
|
||||
percent.setText(String.format(Locale.getDefault(), "%d%%", Math.round(item.votesFraction*100f)));
|
||||
}else{
|
||||
itemView.setSelected(item.poll.selectedOptions!=null && item.poll.selectedOptions.contains(item.option));
|
||||
button.setBackgroundResource(R.drawable.bg_poll_option_clickable);
|
||||
icon.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import static org.joinmastodon.android.MastodonApp.context;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
@@ -38,6 +41,8 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
emojiHelper.setText(ssb);
|
||||
this.icon=icon;
|
||||
this.handleClick=handleClick;
|
||||
TypedValue outValue = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,6 +72,8 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
text.setText(item.text);
|
||||
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, 0, 0);
|
||||
if(item.handleClick!=null) text.setOnClickListener(item.handleClick);
|
||||
text.setEnabled(!item.inset);
|
||||
text.setClickable(!item.inset);
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N)
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(text);
|
||||
}
|
||||
|
||||
@@ -9,16 +9,25 @@ import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
||||
import org.joinmastodon.android.model.StatusPrivacy;
|
||||
import org.joinmastodon.android.model.TranslatedStatus;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.views.LinkedTextView;
|
||||
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.MovieDrawable;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
@@ -30,6 +39,12 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
private CharSequence parsedSpoilerText;
|
||||
public boolean textSelectable;
|
||||
public final Status status;
|
||||
public boolean translated = false;
|
||||
public TranslatedStatus translation = null;
|
||||
|
||||
private AccountSession session;
|
||||
private Instance instanceInfo;
|
||||
private boolean translateEnabled;
|
||||
|
||||
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status){
|
||||
super(parentID, parentFragment);
|
||||
@@ -41,6 +56,9 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
spoilerEmojiHelper=new CustomEmojiHelper();
|
||||
spoilerEmojiHelper.setText(parsedSpoilerText);
|
||||
}
|
||||
session = AccountSessionManager.getInstance().getAccount(parentFragment.getAccountID());
|
||||
instanceInfo = AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
||||
translateEnabled = instanceInfo.v2 != null && instanceInfo.v2.configuration.translation != null && instanceInfo.v2.configuration.translation.enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,9 +83,10 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
public static class Holder extends StatusDisplayItem.Holder<TextStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final LinkedTextView text;
|
||||
private final LinearLayout spoilerHeader;
|
||||
private final TextView spoilerTitle, spoilerTitleInline;
|
||||
private final View spoilerOverlay, borderTop, borderBottom;
|
||||
private final TextView spoilerTitle, spoilerTitleInline, translateInfo;
|
||||
private final View spoilerOverlay, borderTop, borderBottom, textWrap, translateWrap, translateProgress;
|
||||
private final Drawable backgroundColor, borderColor;
|
||||
private final Button translateButton;
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_text, parent);
|
||||
@@ -78,6 +97,11 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
spoilerOverlay=findViewById(R.id.spoiler_overlay);
|
||||
borderTop=findViewById(R.id.border_top);
|
||||
borderBottom=findViewById(R.id.border_bottom);
|
||||
textWrap=findViewById(R.id.text_wrap);
|
||||
translateWrap=findViewById(R.id.translate_wrap);
|
||||
translateButton=findViewById(R.id.translate_btn);
|
||||
translateInfo=findViewById(R.id.translate_info);
|
||||
translateProgress=findViewById(R.id.translate_progress);
|
||||
itemView.setOnClickListener(v->item.parentFragment.onRevealSpoilerClick(this));
|
||||
|
||||
TypedValue outValue=new TypedValue();
|
||||
@@ -91,7 +115,9 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public void onBind(TextStatusDisplayItem item){
|
||||
text.setText(item.text);
|
||||
text.setText(item.translated
|
||||
? HtmlParser.parse(item.translation.content, item.status.emojis, item.status.mentions, item.status.tags, item.parentFragment.getAccountID())
|
||||
: item.text);
|
||||
text.setTextIsSelectable(item.textSelectable);
|
||||
spoilerTitleInline.setTextIsSelectable(item.textSelectable);
|
||||
text.setInvalidateOnEveryFrame(false);
|
||||
@@ -105,20 +131,53 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
if(item.status.spoilerRevealed){
|
||||
spoilerOverlay.setVisibility(View.GONE);
|
||||
spoilerHeader.setVisibility(View.VISIBLE);
|
||||
text.setVisibility(View.VISIBLE);
|
||||
textWrap.setVisibility(View.VISIBLE);
|
||||
itemView.setClickable(false);
|
||||
}else{
|
||||
spoilerOverlay.setVisibility(View.VISIBLE);
|
||||
spoilerHeader.setVisibility(View.GONE);
|
||||
text.setVisibility(View.GONE);
|
||||
textWrap.setVisibility(View.GONE);
|
||||
itemView.setClickable(true);
|
||||
}
|
||||
}else{
|
||||
spoilerOverlay.setVisibility(View.GONE);
|
||||
spoilerHeader.setVisibility(View.GONE);
|
||||
text.setVisibility(View.VISIBLE);
|
||||
textWrap.setVisibility(View.VISIBLE);
|
||||
itemView.setClickable(false);
|
||||
}
|
||||
|
||||
translateWrap.setVisibility(item.textSelectable && item.translateEnabled &&
|
||||
!item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) &&
|
||||
(item.session.preferences == null || !item.status.language.equalsIgnoreCase(item.session.preferences.postingDefaultLanguage))
|
||||
? View.VISIBLE : View.GONE);
|
||||
translateButton.setText(item.translated ? R.string.sk_translate_show_original : R.string.sk_translate_post);
|
||||
translateInfo.setText(item.translated ? itemView.getResources().getString(R.string.sk_translated_using, item.translation.provider) : "");
|
||||
translateButton.setOnClickListener(v->{
|
||||
if (item.translation == null) {
|
||||
translateProgress.setVisibility(View.VISIBLE);
|
||||
translateButton.setClickable(false);
|
||||
new TranslateStatus(item.status.id).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(TranslatedStatus translatedStatus) {
|
||||
item.translation = translatedStatus;
|
||||
item.translated = true;
|
||||
translateProgress.setVisibility(View.GONE);
|
||||
translateButton.setClickable(true);
|
||||
rebind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
translateProgress.setVisibility(View.GONE);
|
||||
translateButton.setClickable(true);
|
||||
error.showToast(itemView.getContext());
|
||||
}
|
||||
}).exec(item.parentFragment.getAccountID());
|
||||
} else {
|
||||
item.translated = !item.translated;
|
||||
rebind();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.provider.Settings;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.view.Menu;
|
||||
@@ -655,13 +656,71 @@ public class UiUtils{
|
||||
}
|
||||
|
||||
public static void setUserPreferredTheme(Context context){
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO -> GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack : R.style.Theme_Mastodon_AutoLightDark;
|
||||
case LIGHT -> R.style.Theme_Mastodon_Light;
|
||||
case DARK -> GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack : R.style.Theme_Mastodon_Dark;
|
||||
});
|
||||
}
|
||||
// boolean isDarkTheme = isDarkTheme();
|
||||
switch(GlobalUserPreferences.color){
|
||||
case PINK:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack : R.style.Theme_Mastodon_AutoLightDark;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack : R.style.Theme_Mastodon_Dark;
|
||||
});
|
||||
break;
|
||||
case PURPLE:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack_Original : R.style.Theme_Mastodon_AutoLightDark_Original;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light_Original;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack_Original : R.style.Theme_Mastodon_Dark_Original;
|
||||
});
|
||||
break;
|
||||
case GREEN:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack_Green : R.style.Theme_Mastodon_AutoLightDark_Green;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light_Green;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack_Green : R.style.Theme_Mastodon_Dark_Green;
|
||||
});
|
||||
break;
|
||||
case BLUE:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack_Blue : R.style.Theme_Mastodon_AutoLightDark_Blue;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light_Blue;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack_Blue : R.style.Theme_Mastodon_Dark_Blue;
|
||||
});
|
||||
break;
|
||||
case BROWN:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack_Brown : R.style.Theme_Mastodon_AutoLightDark_Brown;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light_Brown;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack_Brown : R.style.Theme_Mastodon_Dark_Brown;
|
||||
});
|
||||
break;
|
||||
case YELLOW:
|
||||
context.setTheme(switch(GlobalUserPreferences.theme){
|
||||
case AUTO ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_AutoLightDark_TrueBlack_Yellow : R.style.Theme_Mastodon_AutoLightDark_Yellow;
|
||||
case LIGHT ->
|
||||
R.style.Theme_Mastodon_Light_Yellow;
|
||||
case DARK ->
|
||||
GlobalUserPreferences.trueBlackTheme ? R.style.Theme_Mastodon_Dark_TrueBlack_Yellow : R.style.Theme_Mastodon_Dark_Yellow;
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
public static boolean isDarkTheme(){
|
||||
if(GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO)
|
||||
return (MastodonApp.context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK)==Configuration.UI_MODE_NIGHT_YES;
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
package org.joinmastodon.android.ui.views;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.Editable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
|
||||
|
||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class FloatingHintEditTextLayout extends FrameLayout{
|
||||
private EditText edit;
|
||||
private TextView label;
|
||||
private int labelTextSize;
|
||||
private int offsetY;
|
||||
private boolean hintVisible;
|
||||
private Animator currentAnim;
|
||||
|
||||
public FloatingHintEditTextLayout(Context context){
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public FloatingHintEditTextLayout(Context context, AttributeSet attrs){
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public FloatingHintEditTextLayout(Context context, AttributeSet attrs, int defStyle){
|
||||
super(context, attrs, defStyle);
|
||||
if(isInEditMode())
|
||||
V.setApplicationContext(context);
|
||||
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.FloatingHintEditTextLayout);
|
||||
labelTextSize=ta.getDimensionPixelSize(R.styleable.FloatingHintEditTextLayout_android_labelTextSize, V.dp(12));
|
||||
offsetY=ta.getDimensionPixelOffset(R.styleable.FloatingHintEditTextLayout_editTextOffsetY, 0);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate(){
|
||||
super.onFinishInflate();
|
||||
if(getChildCount()>0 && getChildAt(0) instanceof EditText et){
|
||||
edit=et;
|
||||
}else{
|
||||
throw new IllegalStateException("First child must be an EditText");
|
||||
}
|
||||
|
||||
label=new TextView(getContext());
|
||||
label.setTextSize(TypedValue.COMPLEX_UNIT_PX, labelTextSize);
|
||||
label.setTextColor(edit.getHintTextColors());
|
||||
label.setText(edit.getHint());
|
||||
label.setSingleLine();
|
||||
label.setPivotX(0f);
|
||||
label.setPivotY(0f);
|
||||
LayoutParams lp=new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.START | Gravity.TOP);
|
||||
lp.setMarginStart(edit.getPaddingStart());
|
||||
addView(label, lp);
|
||||
|
||||
hintVisible=edit.getText().length()==0;
|
||||
if(hintVisible)
|
||||
label.setAlpha(0f);
|
||||
|
||||
edit.addTextChangedListener(new SimpleTextWatcher(this::onTextChanged));
|
||||
}
|
||||
|
||||
private void onTextChanged(Editable text){
|
||||
boolean newHintVisible=text.length()==0;
|
||||
if(newHintVisible==hintVisible)
|
||||
return;
|
||||
if(currentAnim!=null)
|
||||
currentAnim.cancel();
|
||||
hintVisible=newHintVisible;
|
||||
|
||||
label.setAlpha(1);
|
||||
float scale=edit.getLineHeight()/(float)label.getLineHeight();
|
||||
float transY=edit.getHeight()/2f-edit.getLineHeight()/2f+(edit.getTop()-label.getTop())-(label.getHeight()/2f-label.getLineHeight()/2f);
|
||||
|
||||
AnimatorSet anim=new AnimatorSet();
|
||||
if(hintVisible){
|
||||
anim.playTogether(
|
||||
ObjectAnimator.ofFloat(edit, TRANSLATION_Y, 0),
|
||||
ObjectAnimator.ofFloat(label, SCALE_X, scale),
|
||||
ObjectAnimator.ofFloat(label, SCALE_Y, scale),
|
||||
ObjectAnimator.ofFloat(label, TRANSLATION_Y, transY)
|
||||
);
|
||||
edit.setHintTextColor(0);
|
||||
}else{
|
||||
label.setScaleX(scale);
|
||||
label.setScaleY(scale);
|
||||
label.setTranslationY(transY);
|
||||
anim.playTogether(
|
||||
ObjectAnimator.ofFloat(edit, TRANSLATION_Y, offsetY),
|
||||
ObjectAnimator.ofFloat(label, SCALE_X, 1f),
|
||||
ObjectAnimator.ofFloat(label, SCALE_Y, 1f),
|
||||
ObjectAnimator.ofFloat(label, TRANSLATION_Y, 0f)
|
||||
);
|
||||
}
|
||||
anim.setDuration(150);
|
||||
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||
anim.start();
|
||||
anim.addListener(new AnimatorListenerAdapter(){
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation){
|
||||
currentAnim=null;
|
||||
if(hintVisible){
|
||||
label.setAlpha(0);
|
||||
edit.setHintTextColor(label.getTextColors());
|
||||
}
|
||||
}
|
||||
});
|
||||
currentAnim=anim;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/boost_selected" android:state_selected="true"/>
|
||||
<item android:color="?android:colorAccent" android:state_selected="true"/>
|
||||
<item android:color="?android:textColorSecondary" android:state_enabled="true"/>
|
||||
<item android:color="?android:textColorSecondary" android:alpha="0.3"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_800" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_300"/>
|
||||
<item android:color="?android:colorPrimary" android:state_enabled="true"/>
|
||||
<item android:color="?colorPollVoted"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_100" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_500"/>
|
||||
<item android:color="?colorSecondary" android:state_enabled="true"/>
|
||||
<item android:color="?colorPollVoted"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_600" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_300"/>
|
||||
<item android:color="?colorPollVoted" android:state_enabled="true"/>
|
||||
<item android:color="?colorSearchHint"/>
|
||||
</selector>
|
||||
5
mastodon/src/main/res/color/button_text_m3_filled.xml
Normal file
5
mastodon/src/main/res/color/button_text_m3_filled.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?colorM3OnPrimary" android:state_enabled="true"/>
|
||||
<item android:color="?colorM3OnSurface" android:alpha="0.38"/>
|
||||
</selector>
|
||||
5
mastodon/src/main/res/color/button_text_m3_text.xml
Normal file
5
mastodon/src/main/res/color/button_text_m3_text.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?colorM3Primary" android:state_enabled="true"/>
|
||||
<item android:color="?colorM3OnSurface" android:alpha="0.38"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_50" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_400"/>
|
||||
<item android:color="?colorTabInactive"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_800" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_400"/>
|
||||
<item android:color="?colorTabInactive"/>
|
||||
</selector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_800" android:state_enabled="true"/>
|
||||
<item android:color="@color/gray_400"/>
|
||||
<item android:color="?android:colorPrimary" android:state_enabled="true"/>
|
||||
<item android:color="?colorTabInactive"/>
|
||||
</selector>
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@color/gray_50"/>
|
||||
<item android:color="?colorSecondary"/>
|
||||
</selector>
|
||||
4
mastodon/src/main/res/color/m3_pressed_overlay.xml
Normal file
4
mastodon/src/main/res/color/m3_pressed_overlay.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?colorM3PressedOverlay" android:alpha="0.12"/>
|
||||
</selector>
|
||||
4
mastodon/src/main/res/color/m3_primary_overlay.xml
Normal file
4
mastodon/src/main/res/color/m3_primary_overlay.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?colorM3Primary" android:alpha="0.12"/>
|
||||
</selector>
|
||||
5
mastodon/src/main/res/color/m3_radiobutton_tint.xml
Normal file
5
mastodon/src/main/res/color/m3_radiobutton_tint.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="?colorM3Primary" android:state_checked="true"/>
|
||||
<item android:color="?colorM3OnSurfaceVariant"/>
|
||||
</selector>
|
||||
19
mastodon/src/main/res/drawable/bg_button_m3_filled.xml
Normal file
19
mastodon/src/main/res/drawable/bg_button_m3_filled.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="true">
|
||||
<ripple android:color="@color/m3_pressed_overlay">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?colorM3Primary"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
</item>
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?colorM3DisabledBackground"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
9
mastodon/src/main/res/drawable/bg_button_m3_text.xml
Normal file
9
mastodon/src/main/res/drawable/bg_button_m3_text.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple android:color="@color/m3_primary_overlay" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/mask">
|
||||
<shape>
|
||||
<solid android:color="#000"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -2,7 +2,7 @@
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/highlight_over_dark">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/gray_600"/>
|
||||
<solid android:color="?colorSearchHint"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M12 7c0.414 0 0.75 0.336 0.75 0.75v3.5h3.5c0.414 0 0.75 0.336 0.75 0.75s-0.336 0.75-0.75 0.75h-3.5v3.5c0 0.414-0.336 0.75-0.75 0.75s-0.75-0.336-0.75-0.75v-3.5h-3.5C7.336 12.75 7 12.414 7 12s0.336-0.75 0.75-0.75h3.5v-3.5C11.25 7.336 11.586 7 12 7zM3 6.25C3 4.455 4.455 3 6.25 3h11.5C19.545 3 21 4.455 21 6.25v11.5c0 1.795-1.455 3.25-3.25 3.25H6.25C4.455 21 3 19.545 3 17.75V6.25zM6.25 4.5C5.284 4.5 4.5 5.284 4.5 6.25v11.5c0 0.966 0.784 1.75 1.75 1.75h11.5c0.966 0 1.75-0.784 1.75-1.75V6.25c0-0.966-0.784-1.75-1.75-1.75H6.25z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M6.25 3C4.455 3 3 4.455 3 6.25v11.5C3 19.545 4.455 21 6.25 21h11.5c1.795 0 3.25-1.455 3.25-3.25V6.25C21 4.455 19.545 3 17.75 3H6.25zm11.03 6.28l-6.754 6.747c-0.293 0.292-0.767 0.292-1.06 0L6.72 13.28c-0.293-0.293-0.293-0.768 0-1.06 0.293-0.293 0.768-0.293 1.06 0l2.217 2.216 6.223-6.217c0.293-0.292 0.768-0.292 1.06 0.001 0.293 0.293 0.293 0.768 0 1.06z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M6.25 3C4.455 3 3 4.455 3 6.25v11.5C3 19.545 4.455 21 6.25 21h11.5c1.795 0 3.25-1.455 3.25-3.25V6.25C21 4.455 19.545 3 17.75 3H6.25zM4.5 6.25c0-0.966 0.784-1.75 1.75-1.75h11.5c0.966 0 1.75 0.784 1.75 1.75v11.5c0 0.966-0.784 1.75-1.75 1.75H6.25c-0.966 0-1.75-0.784-1.75-1.75V6.25zm12.78 3.03c0.293-0.292 0.293-0.767 0-1.06-0.292-0.293-0.767-0.293-1.06 0l-6.223 6.216L7.78 12.22c-0.293-0.293-0.768-0.293-1.06 0-0.294 0.292-0.294 0.767 0 1.06l2.745 2.746c0.293 0.293 0.767 0.293 1.06 0l6.754-6.745z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M3 6.25C3 4.455 4.455 3 6.25 3h11.5C19.545 3 21 4.455 21 6.25v11.5c0 1.795-1.455 3.25-3.25 3.25H6.25C4.455 21 3 19.545 3 17.75V6.25zM6.25 5C5.56 5 5 5.56 5 6.25v11.5C5 18.44 5.56 19 6.25 19h11.5c0.69 0 1.25-0.56 1.25-1.25V6.25C19 5.56 18.44 5 17.75 5H6.25z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M3 6.25C3 4.455 4.455 3 6.25 3h11.5C19.545 3 21 4.455 21 6.25v11.5c0 1.795-1.455 3.25-3.25 3.25H6.25C4.455 21 3 19.545 3 17.75V6.25zM6.25 4.5C5.284 4.5 4.5 5.284 4.5 6.25v11.5c0 0.966 0.784 1.75 1.75 1.75h11.5c0.966 0 1.75-0.784 1.75-1.75V6.25c0-0.966-0.784-1.75-1.75-1.75H6.25z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M3.839 5.858c2.94-3.916 9.03-5.055 13.364-2.36 4.28 2.66 5.854 7.777 4.1 12.577-1.655 4.533-6.016 6.328-9.159 4.048-1.177-0.854-1.634-1.925-1.854-3.664l-0.106-0.987-0.045-0.398c-0.123-0.934-0.311-1.352-0.705-1.572C8.9 13.204 8.542 13.197 7.84 13.47l-0.351 0.146-0.179 0.078c-1.014 0.44-1.688 0.595-2.541 0.416l-0.2-0.047-0.164-0.047c-2.79-0.865-3.203-4.648-0.565-8.158zm0.984 6.716l0.123 0.037 0.134 0.03c0.439 0.087 0.814 0.015 1.437-0.242l0.602-0.257c1.202-0.493 1.985-0.54 3.046 0.05 0.917 0.512 1.275 1.298 1.457 2.66l0.053 0.459 0.055 0.532 0.047 0.422c0.172 1.361 0.485 2.09 1.248 2.644 2.275 1.65 5.534 0.309 6.87-3.349 1.516-4.152 0.174-8.514-3.484-10.789-3.675-2.284-8.899-1.306-11.373 1.987-2.075 2.763-1.82 5.28-0.215 5.816zm11.225-1.994c-0.18-0.667 0.217-1.353 0.883-1.531 0.667-0.179 1.353 0.217 1.531 0.884 0.18 0.667-0.217 1.352-0.884 1.53-0.666 0.18-1.352-0.216-1.53-0.883zm0.494 3.488c-0.179-0.666 0.217-1.352 0.884-1.53 0.667-0.18 1.352 0.216 1.531 0.883 0.179 0.667-0.217 1.353-0.884 1.531-0.667 0.179-1.352-0.217-1.53-0.884zM14.07 7.577c-0.179-0.667 0.217-1.352 0.884-1.53 0.667-0.18 1.352 0.216 1.53 0.883 0.18 0.667-0.216 1.352-0.883 1.53-0.667 0.18-1.352-0.216-1.53-0.883zm-0.028 8.998c-0.18-0.666 0.217-1.352 0.883-1.53 0.667-0.18 1.353 0.216 1.531 0.883 0.18 0.667-0.217 1.353-0.883 1.531-0.667 0.179-1.353-0.217-1.531-0.884zm-3.497-9.97c-0.179-0.666 0.217-1.352 0.883-1.53 0.667-0.18 1.353 0.217 1.532 0.883 0.178 0.667-0.218 1.353-0.884 1.531-0.667 0.179-1.353-0.217-1.531-0.884z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
|
||||
<path android:pathData="M10 18c4.418 0 8-3.582 8-8s-3.582-8-8-8-8 3.582-8 8 3.582 8 8 8zm0-15c0.657 0 1.407 0.59 2.022 1.908 0.217 0.466 0.406 1.002 0.559 1.592H7.419c0.153-0.59 0.342-1.126 0.56-1.592C8.592 3.59 9.342 3 10 3zM7.072 4.485C6.796 5.077 6.565 5.757 6.389 6.5H3.936c0.837-1.446 2.176-2.565 3.778-3.118-0.241 0.33-0.456 0.704-0.642 1.103zM6.192 7.5C6.068 8.288 6 9.13 6 10c0 0.87 0.067 1.712 0.193 2.5H3.46C3.163 11.724 3 10.88 3 10c0-0.88 0.163-1.724 0.46-2.5h2.733zm0.197 6c0.176 0.743 0.407 1.422 0.683 2.015 0.186 0.399 0.401 0.773 0.642 1.103-1.602-0.553-2.941-1.672-3.778-3.118H6.39zm1.03 0h5.162c-0.153 0.59-0.342 1.126-0.56 1.592C11.408 16.41 10.658 17 10 17c-0.657 0-1.407-0.59-2.022-1.908C7.761 14.626 7.572 14.09 7.42 13.5zm5.375-1H7.206C7.073 11.725 7 10.883 7 10s0.074-1.725 0.206-2.5h5.588C12.927 8.275 13 9.117 13 10s-0.073 1.725-0.206 2.5zm0.817 1h2.453c-0.837 1.446-2.176 2.565-3.778 3.118 0.241-0.33 0.456-0.704 0.642-1.103 0.276-0.593 0.507-1.272 0.683-2.015zm2.93-1h-2.734C13.933 11.712 14 10.87 14 10c0-0.87-0.067-1.712-0.193-2.5h2.733C16.837 8.276 17 9.12 17 10c0 0.88-0.163 1.724-0.46 2.5zm-4.255-9.118c1.602 0.553 2.941 1.672 3.778 3.118H13.61c-0.176-0.743-0.407-1.423-0.683-2.015-0.186-0.399-0.401-0.773-0.642-1.103z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M12 1.999c5.524 0 10.002 4.478 10.002 10.002 0 5.523-4.478 10.001-10.002 10.001-5.524 0-10.002-4.478-10.002-10.001C1.998 6.477 6.476 1.999 12 1.999zm0 1.5c-4.695 0-8.502 3.806-8.502 8.502 0 4.695 3.807 8.501 8.502 8.501s8.502-3.806 8.502-8.501c0-4.696-3.807-8.502-8.502-8.502zm-0.003 2.5c3.312 0 5.998 2.686 5.998 5.998 0 3.313-2.686 5.998-5.998 5.998-3.313 0-5.999-2.685-5.999-5.998S8.684 6 11.997 6z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--~ Copyright (c) 2022. ~ Microsoft Corporation. All rights reserved.-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_fluent_radio_button_24_filled" android:state_activated="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_radio_button_24_filled" android:state_checked="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_radio_button_24_filled" android:state_selected="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_radio_button_24_regular"/>
|
||||
</selector>
|
||||
@@ -4,7 +4,7 @@
|
||||
<item android:width="14dp" android:height="14dp" android:gravity="top|right">
|
||||
<shape android:shape="oval">
|
||||
<stroke android:color="?android:colorPrimary" android:width="2dp"/>
|
||||
<solid android:color="@color/primary_600"/>
|
||||
<solid android:color="?android:colorAccent"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
9
mastodon/src/main/res/drawable/ic_m3_cancel.xml
Normal file
9
mastodon/src/main/res/drawable/ic_m3_cancel.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2ZM12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20ZM12,10.59L15.59,7L17,8.41L13.41,12L17,15.59L15.59,17L12,13.41L8.41,17L7,15.59L10.59,12L7,8.41L8.41,7L12,10.59Z"
|
||||
android:fillColor="#49454F"/>
|
||||
</vector>
|
||||
9
mastodon/src/main/res/drawable/ic_m3_search.xml
Normal file
9
mastodon/src/main/res/drawable/ic_m3_search.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M12.3,11.058L17.075,15.833L15.833,17.075L11.058,12.3C10.167,12.942 9.092,13.333 7.917,13.333C4.925,13.333 2.5,10.908 2.5,7.917C2.5,4.925 4.925,2.5 7.917,2.5C10.908,2.5 13.333,4.925 13.333,7.917C13.333,9.092 12.942,10.167 12.3,11.058ZM7.917,4.167C5.842,4.167 4.167,5.842 4.167,7.917C4.167,9.992 5.842,11.667 7.917,11.667C9.992,11.667 11.667,9.992 11.667,7.917C11.667,5.842 9.992,4.167 7.917,4.167Z"
|
||||
android:fillColor="#49454F"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_filled" android:state_activated="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_filled" android:state_checked="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_filled" android:state_selected="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_unchecked_24_filled"/>
|
||||
</selector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_regular" android:state_activated="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_regular" android:state_checked="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_checked_24_regular" android:state_selected="true"/>
|
||||
<item android:drawable="@drawable/ic_fluent_checkbox_unchecked_24_regular"/>
|
||||
</selector>
|
||||
@@ -4,7 +4,7 @@
|
||||
<item android:width="14dp" android:height="14dp" android:gravity="top|right">
|
||||
<shape android:shape="oval">
|
||||
<stroke android:color="?android:colorPrimary" android:width="2dp"/>
|
||||
<solid android:color="@color/primary_600"/>
|
||||
<solid android:color="?android:colorAccent"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -1,9 +1,34 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="110dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="110"
|
||||
android:viewportHeight="18">
|
||||
android:width="124.78dp"
|
||||
android:height="22.75dp"
|
||||
android:viewportWidth="124.78"
|
||||
android:viewportHeight="22.75">
|
||||
<path
|
||||
android:pathData="M18.406,9.999V17.878H15.287V10.231C15.287,8.618 14.609,7.8 13.254,7.8C11.755,7.8 11.004,8.771 11.004,10.69V14.876H7.903V10.69C7.903,8.771 7.151,7.8 5.653,7.8C4.297,7.8 3.619,8.618 3.619,10.231V17.878H0.5V9.999C0.5,8.389 0.91,7.109 1.733,6.162C2.581,5.215 3.693,4.73 5.072,4.73C6.668,4.73 7.877,5.344 8.676,6.572L9.453,7.876L10.23,6.572C11.029,5.344 12.238,4.73 13.834,4.73C15.214,4.73 16.325,5.215 17.174,6.162C17.997,7.109 18.406,8.389 18.406,9.999ZM29.152,13.916C29.795,13.235 30.105,12.378 30.105,11.345C30.105,10.311 29.795,9.454 29.152,8.798C28.532,8.118 27.745,7.79 26.791,7.79C25.838,7.79 25.051,8.118 24.431,8.798C23.811,9.454 23.501,10.311 23.501,11.345C23.501,12.378 23.811,13.235 24.431,13.916C25.051,14.571 25.838,14.899 26.791,14.899C27.745,14.899 28.532,14.571 29.152,13.916ZM30.105,5.042H33.181V17.647H30.105V16.16C29.176,17.395 27.888,18 26.219,18C24.622,18 23.263,17.37 22.118,16.084C20.998,14.798 20.426,13.21 20.426,11.345C20.426,9.504 20.998,7.916 22.118,6.63C23.263,5.345 24.622,4.689 26.219,4.689C27.888,4.689 29.176,5.294 30.105,6.529V5.042ZM43.528,11.118C44.434,11.798 44.888,12.756 44.864,13.966C44.864,15.252 44.41,16.26 43.481,16.966C42.551,17.647 41.431,18 40.072,18C37.616,18 35.947,16.992 35.065,15L37.735,13.412C38.093,14.496 38.879,15.05 40.072,15.05C41.168,15.05 41.717,14.697 41.717,13.966C41.717,13.437 41.001,12.958 39.547,12.58C38.999,12.429 38.546,12.277 38.188,12.151C37.688,11.95 37.258,11.723 36.901,11.445C36.019,10.765 35.566,9.857 35.566,8.698C35.566,7.462 35.995,6.479 36.853,5.773C37.735,5.042 38.808,4.689 40.095,4.689C42.146,4.689 43.648,5.571 44.625,7.361L42.003,8.874C41.621,8.017 40.978,7.588 40.095,7.588C39.166,7.588 38.713,7.941 38.713,8.622C38.713,9.151 39.428,9.63 40.882,10.008C42.003,10.26 42.885,10.639 43.528,11.118ZM53.304,8.168H50.61V13.412C50.61,14.042 50.848,14.42 51.301,14.597C51.635,14.723 52.303,14.748 53.304,14.697V17.647C51.23,17.899 49.728,17.698 48.846,17.017C47.964,16.361 47.534,15.151 47.534,13.412V8.168H45.46V5.042H47.534V2.496L50.61,1.513V5.042H53.304V8.168ZM63.103,13.84C63.723,13.185 64.033,12.353 64.033,11.344C64.033,10.336 63.723,9.504 63.103,8.849C62.483,8.193 61.721,7.866 60.791,7.866C59.861,7.866 59.098,8.193 58.478,8.849C57.882,9.529 57.572,10.361 57.572,11.344C57.572,12.328 57.882,13.16 58.478,13.84C59.098,14.496 59.861,14.823 60.791,14.823C61.721,14.823 62.483,14.496 63.103,13.84ZM56.308,16.084C55.093,14.798 54.497,13.235 54.497,11.344C54.497,9.479 55.093,7.916 56.308,6.63C57.524,5.345 59.026,4.689 60.791,4.689C62.555,4.689 64.057,5.345 65.273,6.63C66.489,7.916 67.109,9.504 67.109,11.344C67.109,13.21 66.489,14.798 65.273,16.084C64.057,17.37 62.579,18 60.791,18C59.002,18 57.524,17.37 56.308,16.084ZM77.385,13.916C78.005,13.235 78.314,12.378 78.314,11.345C78.314,10.311 78.005,9.454 77.385,8.798C76.765,8.118 75.978,7.79 75.024,7.79C74.071,7.79 73.284,8.118 72.64,8.798C72.021,9.454 71.71,10.311 71.71,11.345C71.71,12.378 72.021,13.235 72.64,13.916C73.284,14.571 74.094,14.899 75.024,14.899C75.978,14.899 76.765,14.571 77.385,13.916ZM78.314,0H81.39V17.647H78.314V16.16C77.409,17.395 76.121,18 74.452,18C72.855,18 71.472,17.37 70.328,16.084C69.207,14.798 68.635,13.21 68.635,11.345C68.635,9.504 69.207,7.916 70.328,6.63C71.472,5.345 72.855,4.689 74.452,4.689C76.121,4.689 77.409,5.294 78.314,6.529V0ZM92.191,13.84C92.811,13.185 93.12,12.353 93.12,11.344C93.12,10.336 92.811,9.504 92.191,8.849C91.571,8.193 90.808,7.866 89.878,7.866C88.948,7.866 88.185,8.193 87.565,8.849C86.969,9.529 86.659,10.361 86.659,11.344C86.659,12.328 86.969,13.16 87.565,13.84C88.185,14.496 88.948,14.823 89.878,14.823C90.808,14.823 91.571,14.496 92.191,13.84ZM85.396,16.084C84.18,14.798 83.584,13.235 83.584,11.344C83.584,9.479 84.18,7.916 85.396,6.63C86.612,5.345 88.114,4.689 89.878,4.689C91.642,4.689 93.144,5.345 94.36,6.63C95.576,7.916 96.196,9.504 96.196,11.344C96.196,13.21 95.576,14.798 94.36,16.084C93.144,17.37 91.666,18 89.878,18C88.09,18 86.612,17.37 85.396,16.084ZM109.5,9.908V17.647H106.424V10.311C106.424,9.479 106.21,8.849 105.781,8.37C105.375,7.941 104.803,7.714 104.064,7.714C102.324,7.714 101.442,8.748 101.442,10.84V17.647H98.366V5.042H101.442V6.454C102.181,5.269 103.349,4.689 104.994,4.689C106.305,4.689 107.378,5.143 108.213,6.076C109.071,7.009 109.5,8.269 109.5,9.908Z"
|
||||
android:fillColor="#282C37"/>
|
||||
android:pathData="m26.16,17.57q-1.82,0 -3.29,-0.84 -1.46,-0.84 -2.3,-2.3 -0.82,-1.49 -0.82,-3.34 0,-1.75 0.82,-3.24 0.82,-1.51 2.26,-2.4 1.44,-0.89 3.22,-0.89 1.9,0 3.26,0.82 1.37,0.82 2.06,2.23 0.72,1.42 0.72,3.14 0,0.55 -0.07,1.06h-9.19q0.24,1.46 1.15,2.23 0.94,0.74 2.23,0.74 1.08,0 1.85,-0.46 0.79,-0.48 1.25,-1.27l2.54,1.25q-1.87,3.26 -5.69,3.26zM29.07,9.58q-0.05,-0.58 -0.43,-1.13 -0.36,-0.58 -1.03,-0.94 -0.65,-0.38 -1.54,-0.38 -1.13,0 -1.94,0.67 -0.79,0.65 -1.15,1.78z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m40.27,22.75q-2.33,0 -3.86,-1.06 -1.54,-1.03 -2.06,-2.5l2.95,-1.2q0.38,0.91 1.18,1.44 0.79,0.53 1.8,0.53 1.49,0 2.35,-0.91 0.89,-0.91 0.89,-2.59v-0.96h-0.19q-0.58,0.82 -1.51,1.25 -0.94,0.43 -2.14,0.43 -1.51,0 -2.83,-0.77 -1.3,-0.79 -2.09,-2.21 -0.79,-1.44 -0.79,-3.34 0,-1.9 0.79,-3.31 0.79,-1.44 2.09,-2.21 1.32,-0.79 2.83,-0.79 1.2,0 2.14,0.43 0.94,0.43 1.51,1.25h0.19v-1.3h3.02L46.54,16.34q0,1.97 -0.77,3.41 -0.77,1.44 -2.18,2.21 -1.42,0.79 -3.31,0.79zM40.32,14.33q1.32,0 2.26,-0.91 0.94,-0.94 0.94,-2.54 0,-1.66 -0.94,-2.54 -0.91,-0.91 -2.26,-0.91 -1.34,0 -2.28,0.91 -0.94,0.91 -0.94,2.54 0,1.63 0.94,2.54 0.94,0.91 2.28,0.91z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m53.23,17.57q-1.94,0 -3.19,-1.13 -1.25,-1.15 -1.25,-3 0,-1.22 0.65,-2.16 0.65,-0.94 1.78,-1.44 1.13,-0.5 2.5,-0.5 1.9,0 3.24,0.55L56.95,9.36q0,-1.01 -0.77,-1.63 -0.74,-0.62 -2.02,-0.62 -0.86,0 -1.68,0.41 -0.79,0.38 -1.32,1.03l-2.02,-1.58q0.89,-1.15 2.23,-1.78 1.34,-0.62 2.93,-0.62 2.81,0 4.27,1.3 1.46,1.3 1.46,3.79v7.54h-3.1v-1.25h-0.19q-0.55,0.72 -1.46,1.18 -0.89,0.46 -2.06,0.46zM53.98,15.12q1.37,0 2.16,-0.86 0.82,-0.89 0.82,-2.06 -1.22,-0.58 -2.57,-0.58 -2.45,0 -2.45,1.82 0,0.74 0.53,1.22 0.53,0.46 1.51,0.46z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m62.95,0h3.14L66.1,17.18h-3.14z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m74.93,17.57q-1.9,0 -3.38,-0.84 -1.49,-0.86 -2.33,-2.33 -0.82,-1.49 -0.82,-3.34 0,-1.82 0.82,-3.31 0.84,-1.49 2.33,-2.33 1.49,-0.86 3.38,-0.86 1.87,0 3.36,0.86 1.49,0.84 2.3,2.33 0.84,1.49 0.84,3.31 0,1.85 -0.84,3.34 -0.82,1.46 -2.3,2.33 -1.49,0.84 -3.36,0.84zM74.93,14.66q0.91,0 1.68,-0.43 0.77,-0.43 1.22,-1.25 0.46,-0.82 0.46,-1.92 0,-1.08 -0.46,-1.9 -0.46,-0.82 -1.22,-1.25 -0.77,-0.43 -1.68,-0.43 -0.91,0 -1.68,0.43 -0.77,0.43 -1.25,1.25 -0.46,0.82 -0.46,1.9 0,1.08 0.46,1.92 0.48,0.82 1.25,1.25 0.77,0.43 1.68,0.43z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m89.09,17.57q-1.66,0 -3.02,-0.82 -1.34,-0.84 -2.14,-2.3 -0.77,-1.49 -0.77,-3.38 0,-1.87 0.77,-3.36 0.79,-1.49 2.14,-2.3 1.37,-0.84 3.02,-0.84 1.25,0 2.21,0.55 0.96,0.53 1.46,1.32h0.19l-0.19,-1.73L92.76,0h3.12L95.88,17.18h-2.93v-1.46h-0.19q-0.48,0.79 -1.46,1.32 -0.96,0.53 -2.21,0.53zM89.62,14.66q0.89,0 1.66,-0.46 0.77,-0.46 1.22,-1.27 0.46,-0.82 0.46,-1.87 0,-1.06 -0.46,-1.87 -0.46,-0.82 -1.22,-1.25 -0.77,-0.46 -1.66,-0.46 -0.86,0 -1.63,0.46 -0.77,0.43 -1.22,1.25 -0.46,0.82 -0.46,1.87 0,1.06 0.46,1.87 0.46,0.82 1.22,1.27 0.77,0.46 1.63,0.46z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m104.72,17.57q-1.9,0 -3.38,-0.84 -1.49,-0.86 -2.33,-2.33 -0.82,-1.49 -0.82,-3.34 0,-1.82 0.82,-3.31 0.84,-1.49 2.33,-2.33 1.49,-0.86 3.38,-0.86 1.87,0 3.36,0.86 1.49,0.84 2.3,2.33 0.84,1.49 0.84,3.31 0,1.85 -0.84,3.34 -0.82,1.46 -2.3,2.33 -1.49,0.84 -3.36,0.84zM104.72,14.66q0.91,0 1.68,-0.43 0.77,-0.43 1.22,-1.25 0.46,-0.82 0.46,-1.92 0,-1.08 -0.46,-1.9 -0.46,-0.82 -1.22,-1.25 -0.77,-0.43 -1.68,-0.43 -0.91,0 -1.68,0.43 -0.77,0.43 -1.25,1.25 -0.46,0.82 -0.46,1.9 0,1.08 0.46,1.92 0.48,0.82 1.25,1.25 0.77,0.43 1.68,0.43z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m113.38,4.94h2.95v1.54h0.19q0.55,-0.89 1.56,-1.39 1.01,-0.53 2.18,-0.53 2.21,0 3.36,1.34 1.15,1.34 1.15,3.67v7.61h-3.14v-7.22q0,-1.18 -0.6,-1.82 -0.6,-0.65 -1.68,-0.65 -1.27,0 -2.06,0.98 -0.77,0.98 -0.77,2.47v6.24h-3.14z"
|
||||
android:fillColor="#282c37"/>
|
||||
<path
|
||||
android:pathData="m4.53,4.54c-1.37,0 -2.47,0.48 -3.31,1.42C0.41,6.9 0,8.16 0,9.76v7.8h3.09v-7.57c0,-1.6 0.67,-2.41 2.01,-2.41 1.48,0 2.23,0.96 2.23,2.86v4.14h3.07v-4.14c0,-1.9 0.74,-2.86 2.23,-2.86 1.34,0 2.01,0.81 2.01,2.41v7.57h3.09v-7.8c0,-1.59 -0.41,-2.86 -1.22,-3.8 -0.84,-0.94 -1.94,-1.42 -3.31,-1.42 -1.58,0 -2.78,0.61 -3.57,1.82l-0.77,1.29 -0.77,-1.29C7.3,5.15 6.11,4.54 4.53,4.54Z"
|
||||
android:strokeWidth="0.990258"
|
||||
android:fillColor="#282c37"/>
|
||||
</vector>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<stroke android:color="@color/gray_50" android:width="4dp"/>
|
||||
<stroke android:color="?colorSecondary" android:width="4dp"/>
|
||||
<solid android:color="#80000000"/>
|
||||
<size android:width="52dp" android:height="52dp"/>
|
||||
</shape>
|
||||
|
||||
5
mastodon/src/main/res/drawable/rect_4dp.xml
Normal file
5
mastodon/src/main/res/drawable/rect_4dp.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#000"/>
|
||||
<corners android:radius="4dp"/>
|
||||
</shape>
|
||||
@@ -1,7 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="257dp"
|
||||
android:height="67dp"
|
||||
android:width="134dp"
|
||||
android:height="34dp"
|
||||
android:viewportWidth="313"
|
||||
android:viewportHeight="81">
|
||||
<path
|
||||
@@ -20,8 +20,8 @@
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M14.81,23.2C14.81,20.72 16.77,18.72 19.2,18.72C21.62,18.72 23.58,20.73 23.58,23.2C23.58,25.67 21.62,27.68 19.2,27.68C16.77,27.68 14.81,25.67 14.81,23.2Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
android:fillColor="#000"/>
|
||||
<path
|
||||
android:pathData="M80.02,27.06V47.66H72.03V27.67C72.03,23.45 70.3,21.32 66.83,21.32C63,21.32 61.07,23.87 61.07,28.87V39.82H53.14V28.87C53.14,23.84 51.24,21.32 47.38,21.32C43.92,21.32 42.18,23.45 42.18,27.67V47.65H34.21V27.06C34.21,22.86 35.25,19.51 37.35,17.03C39.53,14.54 42.37,13.29 45.89,13.29C49.97,13.29 53.07,14.9 55.11,18.11L57.11,21.52L59.1,18.11C61.14,14.91 64.23,13.29 68.32,13.29C71.84,13.29 74.69,14.55 76.86,17.03C78.96,19.51 80.01,22.83 80.01,27.06H80.02ZM107.49,37.3C109.15,35.51 109.93,33.29 109.93,30.59C109.93,27.89 109.14,25.65 107.49,23.94C105.91,22.15 103.89,21.3 101.45,21.3C99.02,21.3 97.01,22.15 95.41,23.94C93.83,25.65 93.04,27.89 93.04,30.59C93.04,33.29 93.83,35.53 95.41,37.3C97,39 99.02,39.87 101.45,39.87C103.89,39.87 105.9,39.02 107.49,37.3ZM109.93,14.12H117.8V47.06H109.93V43.18C107.55,46.41 104.26,48 99.99,48C95.71,48 92.42,46.36 89.5,43C86.64,39.64 85.18,35.48 85.18,30.61C85.18,25.74 86.65,21.65 89.5,18.29C92.43,14.93 95.92,13.23 99.99,13.23C104.06,13.23 107.55,14.81 109.93,18.02V14.14V14.12ZM144.26,29.97C146.58,31.76 147.73,34.25 147.67,37.41C147.67,40.77 146.52,43.41 144.14,45.24C141.76,47.03 138.89,47.94 135.41,47.94C129.13,47.94 124.87,45.3 122.61,40.11L129.43,35.96C130.34,38.78 132.35,40.25 135.41,40.25C138.22,40.25 139.62,39.33 139.62,37.42C139.62,36.03 137.79,34.78 134.07,33.8C132.66,33.41 131.5,33.01 130.6,32.68C129.31,32.16 128.22,31.56 127.31,30.83C125.05,29.04 123.9,26.68 123.9,23.65C123.9,20.42 124.99,17.85 127.19,16C129.45,14.09 132.19,13.18 135.48,13.18C140.73,13.18 144.56,15.48 147.07,20.16L140.37,24.1C139.4,21.86 137.74,20.74 135.48,20.74C133.11,20.74 131.95,21.65 131.95,23.44C131.95,24.83 133.78,26.08 137.5,27.06C140.37,27.72 142.63,28.7 144.26,29.97H144.27H144.26ZM169.26,22.27H162.37V35.98C162.37,37.63 162.98,38.63 164.15,39.08C165,39.4 166.71,39.47 169.27,39.34V47.05C163.98,47.71 160.14,47.17 157.88,45.41C155.62,43.7 154.53,40.53 154.53,36V22.27H149.23V14.1H154.53V7.46L162.39,4.89V14.12H169.29V22.29H169.27L169.26,22.27ZM194.34,37.1C195.92,35.4 196.71,33.22 196.71,30.58C196.71,27.94 195.92,25.78 194.34,24.05C192.74,22.35 190.79,21.48 188.42,21.48C186.04,21.48 184.09,22.33 182.49,24.05C180.97,25.84 180.18,28 180.18,30.58C180.18,33.16 180.97,35.31 182.49,37.1C184.08,38.81 186.04,39.67 188.42,39.67C190.79,39.67 192.74,38.82 194.34,37.1ZM176.96,42.96C173.85,39.6 172.32,35.52 172.32,30.58C172.32,25.63 173.85,21.62 176.96,18.26C180.07,14.9 183.91,13.19 188.42,13.19C192.92,13.19 196.77,14.9 199.87,18.26C202.97,21.62 204.57,25.77 204.57,30.58C204.57,35.39 202.97,39.6 199.87,42.96C196.76,46.32 192.98,47.96 188.42,47.96C183.85,47.96 180.06,46.32 176.96,42.96ZM230.86,37.29C232.45,35.5 233.24,33.28 233.24,30.58C233.24,27.87 232.45,25.63 230.86,23.93C229.28,22.14 227.26,21.29 224.82,21.29C222.39,21.29 220.37,22.14 218.73,23.93C217.14,25.63 216.35,27.87 216.35,30.58C216.35,33.28 217.14,35.52 218.73,37.29C220.38,38.99 222.45,39.86 224.82,39.86C227.2,39.86 229.27,39 230.86,37.29ZM233.24,0.92H241.11V47.05H233.24V43.17C230.93,46.39 227.63,47.99 223.36,47.99C219.09,47.99 215.75,46.35 212.8,42.98C209.93,39.62 208.48,35.47 208.48,30.6C208.48,25.73 209.95,21.64 212.8,18.28C215.72,14.92 219.26,13.22 223.36,13.22C227.45,13.22 230.93,14.8 233.24,18.01V0.93V0.92ZM268.74,37.07C270.32,35.36 271.12,33.18 271.12,30.54C271.12,27.9 270.32,25.74 268.74,24.01C267.15,22.31 265.21,21.45 262.82,21.45C260.43,21.45 258.5,22.3 256.9,24.01C255.37,25.8 254.58,27.96 254.58,30.54C254.58,33.12 255.37,35.28 256.9,37.07C258.48,38.77 260.44,39.64 262.82,39.64C265.2,39.64 267.14,38.78 268.74,37.07ZM251.36,42.92C248.26,39.56 246.73,35.48 246.73,30.54C246.73,25.6 248.25,21.58 251.36,18.22C254.47,14.86 258.32,13.15 262.82,13.15C267.32,13.15 271.18,14.86 274.27,18.22C277.38,21.58 278.97,25.73 278.97,30.54C278.97,35.35 277.38,39.56 274.27,42.92C271.16,46.28 267.38,47.93 262.82,47.93C258.26,47.93 254.46,46.28 251.36,42.92ZM313,26.78V47.01H305.14V27.84C305.14,25.66 304.59,24.01 303.48,22.77C302.45,21.65 300.98,21.07 299.09,21.07C294.65,21.07 292.39,23.77 292.39,29.24V47.03H284.53V14.1H292.39V17.81C294.28,14.71 297.28,13.19 301.47,13.19C304.82,13.19 307.57,14.37 309.71,16.81C311.91,19.24 313,22.54 313,26.82"
|
||||
android:fillColor="#ffffff"/>
|
||||
android:fillColor="#000"/>
|
||||
</vector>
|
||||
|
||||
4
mastodon/src/main/res/drawable/white_circle.xml
Normal file
4
mastodon/src/main/res/drawable/white_circle.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<solid android:color="#fff"/>
|
||||
</shape>
|
||||
@@ -15,6 +15,7 @@
|
||||
android:outlineProvider="background"
|
||||
android:elevation="2dp">
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="16dp"
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
<LinearLayout
|
||||
android:id="@+id/button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="12dp"
|
||||
android:outlineProvider="background"
|
||||
android:elevation="2dp"
|
||||
android:background="@drawable/bg_poll_option_clickable"
|
||||
@@ -25,7 +26,6 @@
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:duplicateParentState="true"
|
||||
android:tint="?colorDarkIcon"
|
||||
android:src="@drawable/ic_poll_option_button"/>
|
||||
|
||||
@@ -48,9 +48,7 @@
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
tools:text="scream into void"/>
|
||||
tools:text="scream into void. like this: aaaaaaaaaaaaaaaaaaaa"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
android:paddingBottom="12dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/text_wrap"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
@@ -17,7 +18,8 @@
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone">
|
||||
<View
|
||||
android:id="@+id/border_top"
|
||||
android:layout_width="match_parent"
|
||||
@@ -47,10 +49,57 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:textSize="16sp"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
tools:text="setting up my mstdn"/>
|
||||
</LinearLayout>
|
||||
android:textAppearance="@style/m3_body_large"/>
|
||||
|
||||
<org.joinmastodon.android.ui.views.AutoOrientationLinearLayout
|
||||
android:id="@+id/translate_wrap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/action_btn_wrap"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:clipToPadding="false">
|
||||
<org.joinmastodon.android.ui.views.ProgressBarButton
|
||||
android:id="@+id/translate_btn"
|
||||
style="?secondaryButtonStyle"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="8dp"
|
||||
tools:text="@string/translate_post"/>
|
||||
<ProgressBar
|
||||
android:id="@+id/translate_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"
|
||||
style="?android:progressBarStyleSmall"
|
||||
android:elevation="10dp"
|
||||
android:outlineProvider="none"
|
||||
android:indeterminateTint="?android:textColorPrimary"
|
||||
android:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/translate_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:layout_weight="1"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textAlignment="textEnd"
|
||||
tools:text="Translated using TranslateEngine" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.AutoOrientationLinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:visibility="gone"
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
android:outlineProvider="background"
|
||||
android:elevation="2dp">
|
||||
<ImageView
|
||||
android:id="@+id/add_poll_option_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="16dp"
|
||||
@@ -148,6 +149,39 @@
|
||||
android:textAppearance="@style/m3_label_large"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="Duration: 7 days"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/poll_allow_multiple"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layoutDirection="locale"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:background="?android:selectableItemBackground">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/poll_allow_multiple_checkbox"
|
||||
android:clickable="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:duplicateParentState="true"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:textSize="16sp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/sk_poll_allow_multiple" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<org.joinmastodon.android.ui.views.ComposeMediaLayout
|
||||
@@ -162,6 +196,7 @@
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layoutDirection="locale"
|
||||
|
||||
52
mastodon/src/main/res/layout/fragment_login.xml
Normal file
52
mastodon/src/main/res/layout/fragment_login.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<me.grishka.appkit.views.FragmentRootLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/appkit_loader_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:background="?colorM3Background">
|
||||
|
||||
<include layout="@layout/appkit_toolbar"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/appkit_loader_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1">
|
||||
|
||||
<include layout="@layout/loading"
|
||||
android:id="@+id/loading"/>
|
||||
|
||||
<ViewStub android:layout="?errorViewLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/error"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/content_stub"/>
|
||||
|
||||
</FrameLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button
|
||||
android:id="@+id/btn_next"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:minWidth="145dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Filled"
|
||||
android:text="@string/next" />
|
||||
|
||||
</LinearLayout>
|
||||
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
||||
60
mastodon/src/main/res/layout/fragment_megalodon_welcome.xml
Normal file
60
mastodon/src/main/res/layout/fragment_megalodon_welcome.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<me.grishka.appkit.views.FragmentRootLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/appkit_loader_root"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:background="?colorBackgroundLight">
|
||||
|
||||
<include layout="@layout/appkit_toolbar"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/appkit_loader_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<include layout="@layout/loading"
|
||||
android:id="@+id/loading"/>
|
||||
|
||||
<ViewStub android:layout="?errorViewLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/error"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/content_stub"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="?attr/colorPollVoted"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorBackgroundLight"
|
||||
android:outlineProvider="bounds"
|
||||
android:orientation="horizontal"
|
||||
android:elevation="0dp">
|
||||
|
||||
<Button
|
||||
style="?primaryLargeButtonStyle"
|
||||
android:id="@+id/btn_next"
|
||||
android:minWidth="145dp"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/next" />
|
||||
|
||||
</LinearLayout>
|
||||
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
||||
@@ -1,12 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.joinmastodon.android.ui.views.SizeListenerFrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<org.joinmastodon.android.ui.views.SizeListenerFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:clipToPadding="false"
|
||||
android:clipChildren="false">
|
||||
android:clipToPadding="false">
|
||||
|
||||
<View
|
||||
android:id="@+id/blue_fill"
|
||||
@@ -18,51 +17,60 @@
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/art_container"
|
||||
android:layout_width="450dp"
|
||||
android:layout_height="631dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_gravity="center">
|
||||
android:layout_width="360dp"
|
||||
android:layout_height="640dp"
|
||||
android:layout_gravity="center"
|
||||
tools:ignore="rtlHardcoded">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_clouds"
|
||||
android:layout_width="450dp"
|
||||
android:layout_height="589dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_width="414dp"
|
||||
android:layout_height="541dp"
|
||||
android:layout_marginTop="91dp"
|
||||
android:layout_gravity="top|left"
|
||||
android:alpha="0.3"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_art_layer0"/>
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_plane_elephant"
|
||||
android:layout_width="245.64dp"
|
||||
android:layout_height="72.65dp"
|
||||
android:layout_marginLeft="-101.55dp"
|
||||
android:layout_marginTop="238.12dp"
|
||||
android:layout_gravity="left|top"
|
||||
android:alpha="0.3"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_art_layer4"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_right_hill"
|
||||
android:layout_width="218dp"
|
||||
android:layout_height="255dp"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginBottom="156dp"
|
||||
android:layout_marginRight="11dp"
|
||||
android:layout_width="150.84dp"
|
||||
android:layout_height="176.44dp"
|
||||
android:layout_gravity="top|left"
|
||||
android:layout_marginLeft="322dp"
|
||||
android:layout_marginTop="310dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_art_layer1"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_left_hill"
|
||||
android:layout_width="285dp"
|
||||
android:layout_height="222dp"
|
||||
android:layout_gravity="bottom|left"
|
||||
android:layout_marginLeft="-6dp"
|
||||
android:layout_marginBottom="243dp"
|
||||
android:layout_width="197.2dp"
|
||||
android:layout_height="153.61dp"
|
||||
android:layout_gravity="top|left"
|
||||
android:layout_marginTop="294dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_art_layer2"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_center_hill"
|
||||
android:layout_width="457dp"
|
||||
android:layout_height="397dp"
|
||||
android:layout_gravity="bottom|center_horizontal"
|
||||
android:layout_marginBottom="51dp"
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="346dp"
|
||||
android:layout_gravity="top|left"
|
||||
android:layout_marginTop="294dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_art_layer3"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/art_plane_elephant"
|
||||
android:layout_width="355dp"
|
||||
android:layout_height="105dp"
|
||||
android:layout_gravity="left|top"
|
||||
android:src="@drawable/splash_art_layer4"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
@@ -73,36 +81,65 @@
|
||||
android:transformPivotY="1px"
|
||||
android:background="#478E6A"/>
|
||||
|
||||
<org.joinmastodon.android.ui.views.SplashLogoView
|
||||
android:layout_width="261dp"
|
||||
android:layout_height="71dp"
|
||||
android:layout_gravity="center_horizontal|top"
|
||||
android:layout_marginTop="24dp"
|
||||
android:scaleType="center"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/splash_logo"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:padding="16dp"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
<Button
|
||||
android:id="@+id/btn_get_started"
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pager_dots"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="13dp"
|
||||
style="@style/Widget.Mastodon.Button.Large.Primary_LightOnDark"
|
||||
android:text="@string/get_started"/>
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:background="@drawable/white_circle"/>
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:alpha="0.3"
|
||||
android:background="@drawable/white_circle"/>
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="8dp"
|
||||
android:alpha="0.3"
|
||||
android:background="@drawable/white_circle"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_log_in"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/Widget.Mastodon.Button.Large.Primary_DarkOnLight"
|
||||
android:background="@drawable/bg_button_green"
|
||||
android:text="@string/log_in"/>
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Text"
|
||||
android:textColor="#fff"
|
||||
android:text="@string/already_have_account"/>
|
||||
<Button
|
||||
android:id="@+id/btn_get_started"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Filled"
|
||||
android:text="@string/get_started"/>
|
||||
</LinearLayout>
|
||||
|
||||
</org.joinmastodon.android.ui.views.SizeListenerFrameLayout>
|
||||
59
mastodon/src/main/res/layout/header_megalodon_welcome.xml
Normal file
59
mastodon/src/main/res/layout/header_megalodon_welcome.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/display_item_header" />
|
||||
|
||||
<TextView
|
||||
style="@style/m3_headline_small"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:text="@string/sk_welcome_title"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
style="@style/m3_body_large"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:text="@string/sk_welcome_text" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="?attr/colorPollVoted"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:inputType="textFilter|textNoSuggestions"
|
||||
android:singleLine="true"
|
||||
android:imeOptions="actionGo"
|
||||
android:drawableStart="@drawable/ic_fluent_globe_20_regular"
|
||||
android:drawablePadding="12dp"
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
android:background="@drawable/bg_search_field"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:elevation="0dp"
|
||||
android:hint="@string/sk_example_domain"/>
|
||||
|
||||
|
||||
<ViewStub
|
||||
android:layout="?errorViewLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/error"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
71
mastodon/src/main/res/layout/header_onboarding_login.xml
Normal file
71
mastodon/src/main/res/layout/header_onboarding_login.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:paddingStart="56dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:text="@string/login_subtitle"/>
|
||||
|
||||
<org.joinmastodon.android.ui.views.FloatingHintEditTextLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:editTextOffsetY="8dp"
|
||||
android:background="@drawable/rect_4dp"
|
||||
android:backgroundTint="?colorM3SurfaceVariant">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/search_edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@null"
|
||||
android:stateListAnimator="@null"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:textColorHint="?colorM3OnSurfaceVariant"
|
||||
android:inputType="textUri"
|
||||
android:importantForAutofill="no"
|
||||
android:paddingStart="48dp"
|
||||
android:layout_marginEnd="52dp"
|
||||
android:drawablePadding="16dp"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:hint="@string/server_url"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:scaleType="center"
|
||||
android:importantForAccessibility="no"
|
||||
android:tint="?colorM3OnSurfaceVariant"
|
||||
android:src="@drawable/ic_m3_search"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/search_clear"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:contentDescription="@string/clear"
|
||||
android:stateListAnimator="@null"
|
||||
android:elevation="0dp"
|
||||
android:src="@drawable/ic_m3_cancel"/>
|
||||
|
||||
</org.joinmastodon.android.ui.views.FloatingHintEditTextLayout>
|
||||
|
||||
</LinearLayout>
|
||||
53
mastodon/src/main/res/layout/item_instance_login.xml
Normal file
53
mastodon/src/main/res/layout/item_instance_login.xml
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:background="?colorM3SurfaceVariant">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/radiobtn"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="23dp"
|
||||
android:layout_marginStart="-3dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:buttonTint="@color/m3_radiobutton_tint"
|
||||
android:background="@null"
|
||||
android:focusable="false"
|
||||
android:clickable="false"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/radiobtn"
|
||||
android:layout_alignParentTop="true"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="16sp"
|
||||
android:minHeight="24dp"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="mastodon.social"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/radiobtn"
|
||||
android:layout_below="@id/title"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textColor="?colorM3OnSurfaceVariant"
|
||||
android:textSize="14sp"
|
||||
android:lineSpacingExtra="4sp"
|
||||
tools:text="General-purpose server run by the lead developer of Mastodon"/>
|
||||
|
||||
</RelativeLayout>
|
||||
14
mastodon/src/main/res/layout/item_megalodon_instance.xml
Normal file
14
mastodon/src/main/res/layout/item_megalodon_instance.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingVertical="8dp">
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_search_field">
|
||||
<include layout="@layout/item_instance_catalog" />
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
46
mastodon/src/main/res/layout/item_settings_color_picker.xml
Normal file
46
mastodon/src/main/res/layout/item_settings_color_picker.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.joinmastodon.android.ui.views.AutoOrientationLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center_vertical"
|
||||
android:layoutDirection="locale">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:tint="?android:textColorPrimary"
|
||||
tools:src="@drawable/ic_color_theme_preference"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:text="@string/sk_settings_color_picker"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/color_picker_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/bg_inline_button"
|
||||
android:elevation="0dp"
|
||||
android:ellipsize="middle"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:singleLine="true"
|
||||
android:stateListAnimator="@null"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
tools:text="@string/sk_color_theme_pink" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.AutoOrientationLinearLayout>
|
||||
9
mastodon/src/main/res/menu/color_picker.xml
Normal file
9
mastodon/src/main/res/menu/color_picker.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/pink_color" android:title="@string/sk_color_theme_pink"/>
|
||||
<item android:id="@+id/purple_color" android:title="@string/sk_color_theme_purple"/>
|
||||
<item android:id="@+id/green_color" android:title="@string/sk_color_theme_green"/>
|
||||
<item android:id="@+id/blue_color" android:title="@string/sk_color_theme_blue"/>
|
||||
<item android:id="@+id/brown_color" android:title="@string/sk_color_theme_brown"/>
|
||||
<item android:id="@+id/yellow_color" android:title="@string/sk_color_theme_yellow"/>
|
||||
</menu>
|
||||
@@ -4,5 +4,6 @@
|
||||
android:id="@+id/follow_requests"
|
||||
android:icon="@drawable/ic_follow_requests_24_badged"
|
||||
android:showAsAction="always"
|
||||
android:visible="false"
|
||||
android:title="@string/sk_follow_requests" />
|
||||
</menu>
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">الخطوات الأولى</string>
|
||||
<string name="log_in">تسجيلُ الدخول</string>
|
||||
<string name="next">التالي</string>
|
||||
<string name="loading_instance">يَجري الحُصُول على معلومات المَثيل…</string>
|
||||
<string name="error">خطأ</string>
|
||||
<string name="not_a_mastodon_instance">%s لا يبدو كمثيل ماستدون.</string>
|
||||
<string name="ok">حسنًا</string>
|
||||
<string name="preparing_auth">جَارٍ الإعدَادُ لِلمُصادَقَة…</string>
|
||||
<string name="finishing_auth">يُنهي المصادقة…</string>
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">Kreni</string>
|
||||
<string name="log_in">Loguj se</string>
|
||||
<string name="next">Dalje</string>
|
||||
<string name="loading_instance">Čekamo potrebne informacije…</string>
|
||||
<string name="error">Greška</string>
|
||||
<string name="not_a_mastodon_instance">%s ne izgleda kao Mastodon platforma.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Pripremamo autorizaciju…</string>
|
||||
<string name="finishing_auth">Završavamo autorizaciju…</string>
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">Comença</string>
|
||||
<string name="log_in">Inicia sessió</string>
|
||||
<string name="next">Següent</string>
|
||||
<string name="loading_instance">Obtenint informació sobre la instància…</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="not_a_mastodon_instance">Sembla que %s no és una instància de Mastodon.</string>
|
||||
<string name="ok">D\'acord</string>
|
||||
<string name="preparing_auth">Preparant l\'autenticació…</string>
|
||||
<string name="finishing_auth">Finalitzant l\'autenticació…</string>
|
||||
@@ -382,5 +380,8 @@
|
||||
<string name="i_agree">D’acord</string>
|
||||
<string name="empty_list">Aquesta llista està buida</string>
|
||||
<string name="instance_signup_closed">Aquest servidor no accepta nous registres.</string>
|
||||
<string name="text_copied">Copiat al porta-retalls</string>
|
||||
<string name="add_bookmark">Marca</string>
|
||||
<string name="remove_bookmark">Elimina el marcador</string>
|
||||
<string name="bookmarks">Marcadors</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="sk_pinned_posts">Fixat</string>
|
||||
</resources>
|
||||
<string name="sk_pinned_posts">Fixat</string>
|
||||
<string name="sk_delete_and_redraft">Elimina i torna a escriure</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Eliminar i tornar a escriure</string>
|
||||
<string name="sk_confirm_pin_post">Vols fixar aquesta publicació al teu perfil\?</string>
|
||||
<string name="sk_pinning">S\'està fixant…</string>
|
||||
<string name="sk_unpin_post">Deixa de fixar</string>
|
||||
<string name="sk_confirm_unpin_post_title">Deixar de fixar al perfil</string>
|
||||
<string name="sk_settings_show_replies">Mostra les respostes</string>
|
||||
<string name="sk_settings_load_new_posts">Carrega automàticament les publicacions noves</string>
|
||||
<string name="sk_federated_timeline">Federació</string>
|
||||
<string name="sk_federated_timeline_info_banner">Aquestes són les publicacions més recents de gent de la teua federació.</string>
|
||||
<string name="sk_update_ready">Megalodon %s s\'ha baixat i està preparat per a instal·lar-se.</string>
|
||||
<string name="sk_accept_follow_request">Accepta la sol·licitud</string>
|
||||
<string name="sk_disable_marquee">Desactiva el desplaçament de text a les barres de títol</string>
|
||||
<string name="sk_user_post_notifications_on">Notificacions activades per a publicacions de: %s</string>
|
||||
<string name="sk_app_name">Megalodon</string>
|
||||
<string name="sk_pin_post">Fixa al perfil</string>
|
||||
<string name="sk_confirm_pin_post_title">Fixar al perfil</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Segur que vols eliminar i tornar a escriure aquesta publicació\?</string>
|
||||
<string name="sk_confirm_unpin_post">Segur que vols deixar de fixar aquesta publicació\?</string>
|
||||
<string name="sk_unpinning">S\'està deixant de fixar…</string>
|
||||
<string name="sk_image_description">Descripció de la imatge</string>
|
||||
<string name="sk_visibility_unlisted">No llistat</string>
|
||||
<string name="sk_settings_show_boosts">Mostra els impulsos</string>
|
||||
<string name="sk_settings_show_interaction_counts">Mostra el recompte d\'interaccions</string>
|
||||
<string name="sk_settings_app_version">Megalodon v. %1$s (%2$d)</string>
|
||||
<string name="sk_user_post_notifications_off">Notificacions desactivades per a publicacions de: %s</string>
|
||||
<string name="sk_mark_media_as_sensitive">Marca el contingut com a sensible</string>
|
||||
<string name="sk_update_available">Megalodon %s està preparat per a baixar-se.</string>
|
||||
<string name="sk_check_for_update">Comprova actualitzacions</string>
|
||||
<string name="sk_no_update_available">No hi ha cap actualització disponible</string>
|
||||
<string name="sk_list_timelines">Llistes</string>
|
||||
<string name="sk_follow_requests">Sol·licituds de seguiment</string>
|
||||
<string name="sk_reject_follow_request">Rebutja la sol·licitud</string>
|
||||
<string name="sk_lists_with_user">Llistes amb %s</string>
|
||||
<string name="sk_settings_always_reveal_content_warnings">Mostra sempre els avisos de contingut</string>
|
||||
<string name="sk_settings_contribute">Contribueix a Megalodon</string>
|
||||
<string name="sk_settings_show_federated_timeline">Mostra la línia de temps federada</string>
|
||||
<string name="sk_notification_type_status">Publicacions</string>
|
||||
<string name="sk_notify_posts">Notificacions de publicacions</string>
|
||||
<string name="sk_settings_color_picker">Color de tema</string>
|
||||
<string name="sk_color_theme_pink">Rosa</string>
|
||||
<string name="sk_color_theme_purple">Lila</string>
|
||||
<string name="sk_color_theme_green">Verd</string>
|
||||
<string name="sk_color_theme_blue">Blau</string>
|
||||
<string name="sk_color_theme_brown">Marró</string>
|
||||
<string name="sk_color_theme_yellow">Groc</string>
|
||||
</resources>
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">Začínáme</string>
|
||||
<string name="log_in">Přihlásit se</string>
|
||||
<string name="next">Další</string>
|
||||
<string name="loading_instance">Získávání informací o instanci…</string>
|
||||
<string name="error">Chyba</string>
|
||||
<string name="not_a_mastodon_instance">Zdá se, že %s není instancí Mastodonu.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Příprava na autentizaci…</string>
|
||||
<string name="finishing_auth">Dokončení autentizace…</string>
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<string name="get_started">Loslegen</string>
|
||||
<string name="log_in">Anmelden</string>
|
||||
<string name="next">Weiter</string>
|
||||
<string name="loading_instance">Instanzinformationen werden geladen …</string>
|
||||
<string name="loading_instance">Server-Informationen werden abgerufen …</string>
|
||||
<string name="error">Fehler</string>
|
||||
<string name="not_a_mastodon_instance">%s scheint keine Mastodon-Instanz zu sein.</string>
|
||||
<string name="not_a_mastodon_instance">%s scheint kein Mastodon-Server zu sein.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Authentifizierung wird vorbereitet …</string>
|
||||
<string name="finishing_auth">Authentifizierung wird abgeschlossen …</string>
|
||||
@@ -13,7 +13,7 @@
|
||||
<string name="in_reply_to">Als Antwort auf %s</string>
|
||||
<string name="notifications">Benachrichtigungen</string>
|
||||
<string name="user_followed_you">folgt dir jetzt</string>
|
||||
<string name="user_sent_follow_request">hat dir eine Folgeanfrage gesendet</string>
|
||||
<string name="user_sent_follow_request">hat dir eine Follower-Anfrage gesendet</string>
|
||||
<string name="user_favorited">favorisierte</string>
|
||||
<string name="notification_boosted">teilte</string>
|
||||
<string name="poll_ended">Abstimmung beendet</string>
|
||||
@@ -47,11 +47,11 @@
|
||||
<string name="button_following">Folge ich</string>
|
||||
<string name="edit_profile">Profil bearbeiten</string>
|
||||
<string name="mention_user">%s erwähnen</string>
|
||||
<string name="share_user">%s teilen</string>
|
||||
<string name="share_user">Profil %s teilen</string>
|
||||
<string name="mute_user">%s stummschalten</string>
|
||||
<string name="unmute_user">%s nicht mehr stummschalten</string>
|
||||
<string name="block_user">%s sperren</string>
|
||||
<string name="unblock_user">%s nicht mehr sperren</string>
|
||||
<string name="unblock_user">%s entsperren</string>
|
||||
<string name="report_user">%s melden</string>
|
||||
<string name="block_domain">%s sperren</string>
|
||||
<string name="unblock_domain">%s nicht mehr sperren</string>
|
||||
@@ -61,10 +61,10 @@
|
||||
</plurals>
|
||||
<string name="profile_joined">Beigetreten</string>
|
||||
<string name="done">Fertig</string>
|
||||
<string name="loading">wird geladen …</string>
|
||||
<string name="loading">Wird geladen …</string>
|
||||
<string name="field_label">Beschriftung</string>
|
||||
<string name="field_content">Inhalt</string>
|
||||
<string name="saving">Speichern …</string>
|
||||
<string name="saving">wird gespeichert …</string>
|
||||
<string name="post_from_user">Beitrag von %s</string>
|
||||
<string name="poll_option_hint">%d. Auswahl</string>
|
||||
<plurals name="x_minutes">
|
||||
@@ -81,20 +81,20 @@
|
||||
</plurals>
|
||||
<string name="compose_poll_duration">Dauer: %s</string>
|
||||
<plurals name="x_seconds_left">
|
||||
<item quantity="one">%d Sekunde verbleibend</item>
|
||||
<item quantity="other">%d Sekunden verbleibend</item>
|
||||
<item quantity="one">noch %d Sekunde</item>
|
||||
<item quantity="other">noch %d Sekunden</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_left">
|
||||
<item quantity="one">%d Minute verbleibend</item>
|
||||
<item quantity="other">%d Minuten verbleibend</item>
|
||||
<item quantity="one">noch %d Minute</item>
|
||||
<item quantity="other">noch %d Minuten</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_left">
|
||||
<item quantity="one">%d Stunde verbleibend</item>
|
||||
<item quantity="other">%d Stunden verbleibend</item>
|
||||
<item quantity="one">noch %d Stunde</item>
|
||||
<item quantity="other">noch %d Stunden</item>
|
||||
</plurals>
|
||||
<plurals name="x_days_left">
|
||||
<item quantity="one">%d Tag verbleibend</item>
|
||||
<item quantity="other">%d Tage verbleibend</item>
|
||||
<item quantity="one">noch %d Tag</item>
|
||||
<item quantity="other">noch %d Tage</item>
|
||||
</plurals>
|
||||
<plurals name="x_voters">
|
||||
<item quantity="one">%,d Stimme</item>
|
||||
@@ -109,12 +109,12 @@
|
||||
<string name="do_unmute">Nicht mehr stummschalten</string>
|
||||
<string name="confirm_block_title">Konto sperren</string>
|
||||
<string name="confirm_block_domain_title">Domain sperren</string>
|
||||
<string name="confirm_block">Bestätigen, um %s zu blockieren</string>
|
||||
<string name="do_block">Ja, blockieren</string>
|
||||
<string name="confirm_block">Bestätigen, um %s zu sperren</string>
|
||||
<string name="do_block">Sperren</string>
|
||||
<string name="confirm_unblock_title">Konto nicht mehr sperren</string>
|
||||
<string name="confirm_unblock_domain_title">Domain nicht mehr blockieren</string>
|
||||
<string name="confirm_unblock">Bestätigen, um %s nicht mehr zu blockieren</string>
|
||||
<string name="do_unblock">Nicht mehr blockieren</string>
|
||||
<string name="confirm_unblock">Bestätigen, um Sperre von %s aufzuheben</string>
|
||||
<string name="do_unblock">Sperre aufheben</string>
|
||||
<string name="button_muted">Stummgeschaltet</string>
|
||||
<string name="button_blocked">Blockiert</string>
|
||||
<string name="action_vote">Abstimmen</string>
|
||||
@@ -147,63 +147,63 @@
|
||||
<string name="report_choose_reason_account">Was stimmt mit %s nicht?</string>
|
||||
<string name="report_choose_reason_subtitle">Bitte das Bestmögliche auswählen</string>
|
||||
<string name="report_reason_personal">Das gefällt mir nicht</string>
|
||||
<string name="report_reason_personal_subtitle">Den Inhalt kann man nicht allen zumuten</string>
|
||||
<string name="report_reason_personal_subtitle">Das ist nichts, was du sehen möchtest</string>
|
||||
<string name="report_reason_spam">Das ist Spam</string>
|
||||
<string name="report_reason_spam_subtitle">Bösartige Links, vorgetäuschtes Verhalten oder wiederholtes Antworten</string>
|
||||
<string name="report_reason_violation">Es verstößt gegen Serverregeln</string>
|
||||
<string name="report_reason_violation_subtitle">Du weißt, welche Regeln verletzt werden</string>
|
||||
<string name="report_reason_violation_subtitle">Du bist dir bewusst, dass dies gegen die Serverregeln verstößt</string>
|
||||
<string name="report_reason_other">Es ist etwas anderes</string>
|
||||
<string name="report_reason_other_subtitle">Das Problem passt nicht in eine der Kategorien</string>
|
||||
<string name="report_choose_rule">Welche Regeln werden verletzt?</string>
|
||||
<string name="report_reason_other_subtitle">Der Vorfall passt zu keiner dieser Kategorien</string>
|
||||
<string name="report_choose_rule">Gegen welche Regeln wird verstoßen?</string>
|
||||
<string name="report_choose_rule_subtitle">Alles Zutreffende auswählen</string>
|
||||
<string name="report_choose_posts">Gibt es Beiträge, die diesen Bericht unterstützen?</string>
|
||||
<string name="report_choose_posts">Gibt es Beiträge, die diese Meldung untermauern?</string>
|
||||
<string name="report_choose_posts_subtitle">Alles Zutreffende auswählen</string>
|
||||
<string name="report_comment_title">Gibt es etwas anderes, was wir wissen sollten?</string>
|
||||
<string name="report_comment_hint">Zusätzliche Kommentare</string>
|
||||
<string name="sending_report">Bericht wird gesendet…</string>
|
||||
<string name="report_comment_title">Gibt es weitere Anmerkungen, von denen wir wissen sollten?</string>
|
||||
<string name="report_comment_hint">Ergänzende Hinweise</string>
|
||||
<string name="sending_report">Meldung wird verschickt …</string>
|
||||
<string name="report_sent_title">Vielen Dank für die Meldung, wir werden uns damit befassen.</string>
|
||||
<string name="report_sent_subtitle">Während wir dies überprüfen, kannst du gegen %s vorgehen.</string>
|
||||
<string name="report_sent_subtitle">Während wir den Vorfall überprüfen, kannst du gegen %s weitere Maßnahmen ergreifen.</string>
|
||||
<string name="unfollow_user">%s entfolgen</string>
|
||||
<string name="unfollow">Entfolgen</string>
|
||||
<string name="mute_user_explain">Du wirst die eigenen und geteilten Beiträge des Kontos nicht mehr sehen können. Dass du das Profil stummgeschaltet hast, erfährt die Person nicht.</string>
|
||||
<string name="block_user_explain">Du wirst die Beiträge von diesem Konto nicht sehen. Das Konto wird nicht in der Lage sein, deine Beiträge zu sehen oder dir zu folgen. Die Person hinter dem Konto wird wissen, dass du das Konto blockiert hast.</string>
|
||||
<string name="report_personal_title">Du willst das nicht mehr sehen?</string>
|
||||
<string name="report_personal_subtitle">Wenn du etwas auf Mastodon nicht sehen willst, kannst du den Nutzer aus deiner Erfahrung streichen.</string>
|
||||
<string name="block_user_explain">Dir wird es nicht länger möglich sein, die Beiträge dieses Konto zu sehen. Das blockierte Profil wird nicht mehr in der Lage sein, deine Beiträge zu sehen oder dir zu folgen. Die Person hinter dem Konto wird mitbekommen, dass du ihr Konto gesperrt hast.</string>
|
||||
<string name="report_personal_title">Möchtest du das nicht mehr sehen?</string>
|
||||
<string name="report_personal_subtitle">Wenn du etwas auf Mastodon siehst, das dir nicht gefällt, kannst du die Person aus deinem Umfeld entfernen.</string>
|
||||
<string name="back">Zurück</string>
|
||||
<string name="instance_catalog_title">Mastodon wird von Benutzer*innen auf verschiedenen Servern gestaltet.</string>
|
||||
<string name="instance_catalog_subtitle">Wähle einen Server basierend auf deinen Interessen oder deiner Region – oder einfach einen allgemeinen. Du kannst trotzdem mit jedem interagieren, egal auf welchem Server.</string>
|
||||
<string name="search_communities">Server suchen oder Adresse eingeben</string>
|
||||
<string name="instance_rules_title">Einige Grundregeln</string>
|
||||
<string name="instance_rules_subtitle">Nimm dir eine Minute Zeit, und gehe kurz alle Regeln von %s durch.</string>
|
||||
<string name="search_communities">Server suchen oder Link eingeben</string>
|
||||
<string name="instance_rules_title">Serverregeln</string>
|
||||
<string name="instance_rules_subtitle">Nimm dir eine Minute Zeit und lies die Serverregeln von %s durch.</string>
|
||||
<string name="signup_title">Okay, lass uns mit %s anfangen</string>
|
||||
<string name="edit_photo">bearbeiten</string>
|
||||
<string name="display_name">Anzeigename</string>
|
||||
<string name="username">Kontoname</string>
|
||||
<string name="username">Profilname</string>
|
||||
<string name="email">E-Mail</string>
|
||||
<string name="password">Passwort</string>
|
||||
<string name="password_note">Verwende Großbuchstaben, Sonderzeichen und Zahlen, um deine Passwortstärke zu erhöhen.</string>
|
||||
<string name="category_academia">Bildung</string>
|
||||
<string name="category_activism">Aktivismus</string>
|
||||
<string name="category_activism">Bürgerbeteiligung</string>
|
||||
<string name="category_all">Alle</string>
|
||||
<string name="category_art">Kunst</string>
|
||||
<string name="category_food">Essen</string>
|
||||
<string name="category_furry">Flausch</string>
|
||||
<string name="category_furry">Furries</string>
|
||||
<string name="category_games">Spiele</string>
|
||||
<string name="category_general">Allgemein</string>
|
||||
<string name="category_journalism">Journalismus</string>
|
||||
<string name="category_lgbt">LGBT</string>
|
||||
<string name="category_music">Musik</string>
|
||||
<string name="category_regional">Regional</string>
|
||||
<string name="category_tech">Technologie</string>
|
||||
<string name="category_tech">Technik</string>
|
||||
<string name="confirm_email_title">Eine letzte Sache noch</string>
|
||||
<string name="confirm_email_subtitle">Schaue kurz in dein E-Mail-Postfach und tippe den Link an, den wir dir gesendet haben.</string>
|
||||
<string name="resend">Erneut senden</string>
|
||||
<string name="confirm_email_subtitle">Tippe auf den Link, den wir dir per E-Mail geschickt haben, um dein Konto zu verifizieren.</string>
|
||||
<string name="resend">Erneut abschicken</string>
|
||||
<string name="open_email_app">E-Mail-App öffnen</string>
|
||||
<string name="resent_email">Bestätigungs-E-Mail gesendet</string>
|
||||
<string name="compose_hint">Eintippen oder einfügen, was dir am Herzen liegt</string>
|
||||
<string name="content_warning">Inhaltwarnung</string>
|
||||
<string name="resent_email">Bestätigung per E-Mail zugeschickt</string>
|
||||
<string name="compose_hint">Was gibt\'s Neues? Was geht dir durch den Kopf? Was liegt dir am Herzen?</string>
|
||||
<string name="content_warning">Inhaltswarnung</string>
|
||||
<string name="add_image_description">Bildbeschreibung hinzufügen …</string>
|
||||
<string name="retry_upload">Hochladen erneut versuchen</string>
|
||||
<string name="retry_upload">Erneut hochladen</string>
|
||||
<string name="edit_image">Bild bearbeiten</string>
|
||||
<string name="save">Speichern</string>
|
||||
<string name="add_alt_text">Bildbeschreibung hinzufügen</string>
|
||||
@@ -212,9 +212,9 @@
|
||||
<string name="visibility_public">Öffentlich</string>
|
||||
<string name="visibility_followers_only">Nur Follower</string>
|
||||
<string name="visibility_private">Nur erwähnte Profile</string>
|
||||
<string name="search_all">Alle</string>
|
||||
<string name="search_people">Personen</string>
|
||||
<string name="recent_searches">Letzte Suchanfragen</string>
|
||||
<string name="search_all">Alles</string>
|
||||
<string name="search_people">Profile</string>
|
||||
<string name="recent_searches">Frühere Suchen</string>
|
||||
<string name="step_x_of_n">Schritt %1$d von %2$d</string>
|
||||
<string name="skip">Überspringen</string>
|
||||
<string name="notification_type_follow">Neue Follower</string>
|
||||
@@ -228,9 +228,9 @@
|
||||
<item quantity="one">Du kannst nicht mehr als %d Mediendatei anhängen</item>
|
||||
<item quantity="other">Du kannst nicht mehr als %d Mediendateien anhängen</item>
|
||||
</plurals>
|
||||
<string name="media_attachment_unsupported_type">Datei %s wird nicht unterstützt</string>
|
||||
<string name="media_attachment_too_big">Datei %1$s übersteigt die Größengrenze von %2$s MB</string>
|
||||
<string name="settings_theme">Design</string>
|
||||
<string name="media_attachment_unsupported_type">Dateityp von %s wird nicht unterstützt</string>
|
||||
<string name="media_attachment_too_big">Datei %1$s überschreitet die maximale Größe von %2$s MB</string>
|
||||
<string name="settings_theme">Erscheinungsbild</string>
|
||||
<string name="theme_auto">Systembedingt</string>
|
||||
<string name="theme_light">Hell</string>
|
||||
<string name="theme_dark">Dunkel</string>
|
||||
@@ -254,15 +254,15 @@
|
||||
<string name="settings_tos">Nutzungsbedingungen</string>
|
||||
<string name="settings_privacy_policy">Datenschutzbestimmungen</string>
|
||||
<string name="settings_spicy">Gefährliches</string>
|
||||
<string name="settings_clear_cache">Medienpuffer leeren</string>
|
||||
<string name="settings_clear_cache">Medien-Cache leeren</string>
|
||||
<string name="settings_app_version">Mastodon für Android v%1$s (%2$d)</string>
|
||||
<string name="media_cache_cleared">Medienpuffer geleert</string>
|
||||
<string name="media_cache_cleared">Medien-Cache geleert</string>
|
||||
<string name="confirm_log_out">Bist du dir sicher, dass du dich abmelden möchtest?</string>
|
||||
<string name="sensitive_content">Inhaltswarnung</string>
|
||||
<string name="sensitive_content_explain">Autor*in hat den Inhalt mit einer Inhaltswarnung versehen. Tippen zum Anzeigen.</string>
|
||||
<string name="media_hidden">Tippen zum Anzeigen</string>
|
||||
<string name="avatar_description">Das Profil von %s öffnen</string>
|
||||
<string name="more_options">Mehr Optionen</string>
|
||||
<string name="avatar_description">Profil von %s aufrufen</string>
|
||||
<string name="more_options">Weitere Einstellungen</string>
|
||||
<string name="reveal_content">Inhalt anzeigen</string>
|
||||
<string name="hide_content">Inhalt ausblenden</string>
|
||||
<string name="new_post">Neuer Beitrag</string>
|
||||
@@ -287,12 +287,12 @@
|
||||
<string name="signup_reason">Weshalb möchtest du beitreten?</string>
|
||||
<string name="signup_reason_note">Das erleichtert uns die Prüfung deiner Anmeldung.</string>
|
||||
<string name="clear">Leeren</string>
|
||||
<string name="profile_header">Kopfbild</string>
|
||||
<string name="profile_header">Titelbild</string>
|
||||
<string name="profile_picture">Profilbild</string>
|
||||
<string name="reorder">Neu sortieren</string>
|
||||
<string name="download">Herunterladen</string>
|
||||
<string name="permission_required">Berechtigung erforderlich</string>
|
||||
<string name="storage_permission_to_download">Die App benötigt Zugriff auf den Speicher deines Geräts, um diese Datei zu speichern.</string>
|
||||
<string name="storage_permission_to_download">Die App benötigt Zugriff auf den Speicher deines Gerätes, um diese Datei zu speichern.</string>
|
||||
<string name="open_settings">Einstellungen öffnen</string>
|
||||
<string name="error_saving_file">Fehler beim Speichern der Datei</string>
|
||||
<string name="file_saved">Datei gespeichert</string>
|
||||
@@ -302,7 +302,7 @@
|
||||
<string name="trending_posts_info_banner">Dies sind Beiträge, die auf deinem Mastodon-Server gerade angesagt sind.</string>
|
||||
<string name="trending_hashtags_info_banner">Diese Hashtags sind auf deinem Mastodon-Server gerade angesagt.</string>
|
||||
<string name="trending_links_info_banner">Diese journalistischen Nachrichten werden auf deinem Mastodon-Server gerade am häufigsten geteilt.</string>
|
||||
<string name="local_timeline_info_banner">Das sind die neuesten Beiträge von Personen, die denselben Mastodon-Server benutzen.</string>
|
||||
<string name="local_timeline_info_banner">Das sind die neuesten Beiträge von Personen, die denselben Mastodon-Server wie du benutzen.</string>
|
||||
<string name="dismiss">Verwerfen</string>
|
||||
<string name="see_new_posts">Neue Beiträge anzeigen</string>
|
||||
<string name="load_missing_posts">Weitere Beiträge laden</string>
|
||||
@@ -334,7 +334,7 @@
|
||||
<string name="post_info_reblogs">Geteilte Beiträge</string>
|
||||
<string name="post_info_favorites">Favoriten</string>
|
||||
<string name="edit_history">Verlauf bearbeiten</string>
|
||||
<string name="last_edit_at_x">Letzte Bearbeitung: %s</string>
|
||||
<string name="last_edit_at_x">Zuletzt bearbeitet: %s</string>
|
||||
<string name="time_just_now">gerade jetzt</string>
|
||||
<plurals name="x_seconds_ago">
|
||||
<item quantity="one">vor %d Sekunde</item>
|
||||
@@ -347,9 +347,9 @@
|
||||
<string name="edited_timestamp">bearbeitet %s</string>
|
||||
<string name="edit_original_post">Ursprünglicher Beitrag</string>
|
||||
<string name="edit_text_edited">Text bearbeitet</string>
|
||||
<string name="edit_spoiler_added">Inhaltwarnung hinzugefügt</string>
|
||||
<string name="edit_spoiler_edited">Inhaltwarnung bearbeitet</string>
|
||||
<string name="edit_spoiler_removed">Inhaltwarnung entfernt</string>
|
||||
<string name="edit_spoiler_added">Inhaltswarnung hinzugefügt</string>
|
||||
<string name="edit_spoiler_edited">Inhaltswarnung bearbeitet</string>
|
||||
<string name="edit_spoiler_removed">Inhaltswarnung entfernt</string>
|
||||
<string name="edit_poll_added">Umfrage hinzugefügt</string>
|
||||
<string name="edit_poll_edited">Umfrage bearbeitet</string>
|
||||
<string name="edit_poll_removed">Umfrage entfernt</string>
|
||||
@@ -363,13 +363,13 @@
|
||||
<string name="discard_changes">Änderungen verwerfen?</string>
|
||||
<string name="upload_failed">Hochladen fehlgeschlagen</string>
|
||||
<string name="file_size_bytes">%d Bytes</string>
|
||||
<string name="file_size_kb">%.2f KB</string>
|
||||
<string name="file_size_kb">%.2f kB</string>
|
||||
<string name="file_size_mb">%.2f MB</string>
|
||||
<string name="file_size_gb">%.2f GB</string>
|
||||
<string name="file_upload_progress">%1$s von %2$s</string>
|
||||
<string name="file_upload_time_remaining">%s verbleibend</string>
|
||||
<string name="upload_error_connection_lost">Dein Gerät hat gerade keinen Zugang zum Internet</string>
|
||||
<string name="upload_processing">wird verarbeitet …</string>
|
||||
<string name="upload_processing">Wird verarbeitet …</string>
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<string name="update_available">Mastodon für Android %s ist zum Herunterladen bereit.</string>
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
@@ -377,10 +377,17 @@
|
||||
<!-- %s is file size -->
|
||||
<string name="download_update">(%s) herunterladen</string>
|
||||
<string name="install_update">Installieren</string>
|
||||
<string name="privacy_policy_title">Mastodon und Ihre Privatsphäre</string>
|
||||
<string name="privacy_policy_subtitle">Obwohl die Mastodon-App keine Daten sammelt, kann der Server, über den Sie sich anmelden, eine andere Richtlinie haben. Nehmen Sie sich eine Minute Zeit, um die Mastodon-Datenschutzrichtlinien und die Datenschutzrichtlinien Ihres Servers zu lesen und zu akzeptieren.</string>
|
||||
<string name="privacy_policy_title">Mastodon und der Schutz deiner Daten</string>
|
||||
<string name="privacy_policy_subtitle">Obwohl die Mastodon-App keinerlei Daten sammelt, könnte der Server, über den du dich registriert hast, eine abweichende Datenschutzerklärung haben. Nimm dir einen Moment Zeit, um die Datenschutzbestimmungen sowohl der App als auch deiner Mastodon-Instanz durchzulesen und sie zu akzeptieren.</string>
|
||||
<string name="i_agree">Ich stimme zu</string>
|
||||
<string name="empty_list">Diese Liste ist leer</string>
|
||||
<string name="instance_signup_closed">Dieser Server akzeptiert keine neuen Registrierungen.</string>
|
||||
<string name="text_copied">In die Zwischenablage kopiert</string>
|
||||
<string name="add_bookmark">Lesezeichen setzen</string>
|
||||
<string name="remove_bookmark">Lesezeichen entfernen</string>
|
||||
<string name="bookmarks">Lesezeichen</string>
|
||||
<string name="your_favorites">Deine Favoriten</string>
|
||||
<string name="login_title">Willkommen zurück</string>
|
||||
<string name="login_subtitle">Melde dich mit dem Server an, auf dem du dein Konto erstellt hast.</string>
|
||||
<string name="server_url">Serveradresse</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,41 +1,62 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="sk_app_name">Megalodon</string>
|
||||
<string name="sk_pinned_posts">Angeheftet</string>
|
||||
<string name="sk_delete_and_redraft">Löschen und neu erstellen</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Beitrag löschen und neu erstellen</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Bist du dir sicher, dass du diesen Beitrag löschen und neu erstellen möchtest?</string>
|
||||
<string name="sk_pin_post">An Profil anheften</string>
|
||||
<string name="sk_confirm_pin_post_title">Beitrag an Profil anheften</string>
|
||||
<string name="sk_confirm_pin_post">Möchtest du den Beitrag an dein Profil anheften?</string>
|
||||
<string name="sk_pinning">Wird angeheftet…</string>
|
||||
<string name="sk_unpin_post">Von Profil lösen</string>
|
||||
<string name="sk_confirm_unpin_post_title">Angehefteten Beitrag von Profil lösen</string>
|
||||
<string name="sk_confirm_unpin_post">Bist du dir sicher, dass du den angehefteten Beitrag von deinem Profil lösen möchtest?</string>
|
||||
<string name="sk_unpinning">Wird vom Profil gelöst…</string>
|
||||
<string name="sk_image_description">Bildbeschreibung</string>
|
||||
<string name="sk_visibility_unlisted">Nicht gelistet</string>
|
||||
<string name="sk_settings_show_replies">Antworten anzeigen</string>
|
||||
<string name="sk_settings_show_boosts">Geteilte Beiträge anzeigen</string>
|
||||
<string name="sk_settings_load_new_posts">Automatisch neue Beiträge laden</string>
|
||||
<string name="sk_settings_show_interaction_counts">Interaktions-Anzahlen anzeigen</string>
|
||||
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
|
||||
<string name="sk_mark_media_as_sensitive">Medien als sensibel markieren</string>
|
||||
<string name="sk_user_post_notifications_on">Benachrichtigungen über Beiträge von %s aktiviert</string>
|
||||
<string name="sk_user_post_notifications_off">Benachrichtigungen über Beiträge von %s deaktiviert</string>
|
||||
<string name="sk_federated_timeline">Föderation</string>
|
||||
<string name="sk_federated_timeline_info_banner">Das sind die neuesten Beiträge von Personen, die in der Föderation deines Servers sind.</string>
|
||||
<string name="sk_update_available">Megalodon %s ist zum Herunterladen bereit.</string>
|
||||
<string name="sk_update_ready">Megalodon %s wurde heruntergeladen und kann jetzt installiert werden.</string>
|
||||
<string name="sk_check_for_update">Auf Update prüfen</string>
|
||||
<string name="sk_no_update_available">Kein Update verfügbar</string>
|
||||
<string name="sk_list_timelines">Listen</string>
|
||||
<string name="sk_follow_requests">Folgeanfragen</string>
|
||||
<string name="sk_accept_follow_request">Folgeanfrage akzeptieren</string>
|
||||
<string name="sk_reject_follow_request">Folgeanfrage ablehnen</string>
|
||||
<string name="sk_lists_with_user">Listen mit %s</string>
|
||||
<string name="sk_settings_always_reveal_content_warnings">Inhaltswarnungen immer ausklappen</string>
|
||||
<string name="sk_disable_marquee">Laufschrift in Titelleisten deaktivieren</string>
|
||||
<string name="sk_settings_contribute">Zu Megalodon beitragen</string>
|
||||
<string name="sk_settings_show_federated_timeline">Föderierte Timeline anzeigen</string>
|
||||
</resources>
|
||||
<string name="sk_app_name">Megalodon</string>
|
||||
<string name="sk_pinned_posts">Angeheftet</string>
|
||||
<string name="sk_delete_and_redraft">Löschen und neu erstellen</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Beitrag löschen und neu erstellen</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Bist du dir sicher, dass du diesen Beitrag löschen und neu erstellen möchtest?</string>
|
||||
<string name="sk_pin_post">An Profil anheften</string>
|
||||
<string name="sk_confirm_pin_post_title">Beitrag an Profil anheften</string>
|
||||
<string name="sk_confirm_pin_post">Möchtest du den Beitrag an dein Profil anheften?</string>
|
||||
<string name="sk_pinning">Wird angeheftet…</string>
|
||||
<string name="sk_unpin_post">Von Profil lösen</string>
|
||||
<string name="sk_confirm_unpin_post_title">Angehefteten Beitrag von Profil lösen</string>
|
||||
<string name="sk_confirm_unpin_post">Bist du dir sicher, dass du den angehefteten Beitrag von deinem Profil lösen möchtest?</string>
|
||||
<string name="sk_unpinning">Wird vom Profil gelöst…</string>
|
||||
<string name="sk_image_description">Bildbeschreibung</string>
|
||||
<string name="sk_visibility_unlisted">Nicht gelistet</string>
|
||||
<string name="sk_settings_show_replies">Antworten anzeigen</string>
|
||||
<string name="sk_settings_show_boosts">Geteilte Beiträge anzeigen</string>
|
||||
<string name="sk_settings_load_new_posts">Automatisch neue Beiträge laden</string>
|
||||
<string name="sk_settings_show_interaction_counts">Interaktions-Anzahlen anzeigen</string>
|
||||
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
|
||||
<string name="sk_mark_media_as_sensitive">Medien als sensibel markieren</string>
|
||||
<string name="sk_user_post_notifications_on">Benachrichtigungen über Beiträge von %s aktiviert</string>
|
||||
<string name="sk_user_post_notifications_off">Benachrichtigungen über Beiträge von %s deaktiviert</string>
|
||||
<string name="sk_federated_timeline">Föderation</string>
|
||||
<string name="sk_federated_timeline_info_banner">Das sind die neuesten Beiträge von Personen, die in der Föderation deines Servers sind.</string>
|
||||
<string name="sk_update_available">Megalodon %s ist zum Herunterladen bereit.</string>
|
||||
<string name="sk_update_ready">Megalodon %s wurde heruntergeladen und kann jetzt installiert werden.</string>
|
||||
<string name="sk_check_for_update">Auf Update prüfen</string>
|
||||
<string name="sk_no_update_available">Kein Update verfügbar</string>
|
||||
<string name="sk_list_timelines">Listen</string>
|
||||
<string name="sk_follow_requests">Folgeanfragen</string>
|
||||
<string name="sk_accept_follow_request">Folgeanfrage akzeptieren</string>
|
||||
<string name="sk_reject_follow_request">Folgeanfrage ablehnen</string>
|
||||
<string name="sk_lists_with_user">Listen mit %s</string>
|
||||
<string name="sk_settings_always_reveal_content_warnings">Inhaltswarnungen immer ausklappen</string>
|
||||
<string name="sk_disable_marquee">Laufschrift in Titelleisten deaktivieren</string>
|
||||
<string name="sk_settings_contribute">Zu Megalodon beitragen</string>
|
||||
<string name="sk_settings_show_federated_timeline">Föderierte Timeline anzeigen</string>
|
||||
<string name="sk_notify_posts">Beitrags-Benachrichtigungen</string>
|
||||
<string name="sk_settings_color_picker">Farbschema</string>
|
||||
<string name="sk_color_theme_pink">Pink</string>
|
||||
<string name="sk_color_theme_purple">Violett</string>
|
||||
<string name="sk_color_theme_green">Grün</string>
|
||||
<string name="sk_color_theme_brown">Braun</string>
|
||||
<string name="sk_color_theme_yellow">Gelb</string>
|
||||
<string name="sk_notification_type_status">Beiträge</string>
|
||||
<string name="sk_color_theme_blue">Blau</string>
|
||||
<string name="sk_poll_allow_multiple">Mehrfachantworten erlauben</string>
|
||||
<string name="sk_translated_using">Übersetzt mit %s</string>
|
||||
<string name="sk_post_language">Sprache: %s</string>
|
||||
<string name="sk_language_name">%s (%s)</string>
|
||||
<string name="sk_confirm_clear_recent_languages">Sicher, dass du die Liste der zuletzt verwendeten Sprachen leeren willst\?</string>
|
||||
<string name="sk_translate_post">Übersetzen</string>
|
||||
<string name="sk_translate_show_original">Original anzeigen</string>
|
||||
<string name="sk_available_languages">Verfügbare Sprachen</string>
|
||||
<string name="sk_clear_recent_languages">Zuletzt verwendete Sprachen leeren</string>
|
||||
<string name="sk_welcome_title">Willkommen!</string>
|
||||
<string name="sk_example_domain">beispiel.social</string>
|
||||
<string name="sk_welcome_text">Der Hai sagt Hi! Um anzufangen, bitte gib den Domain-Namen deiner Heim-Instanz unten ein.</string>
|
||||
</resources>
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">Empezar</string>
|
||||
<string name="log_in">Iniciar sesión</string>
|
||||
<string name="next">Siguiente</string>
|
||||
<string name="loading_instance">Obteniendo información de la instancia…</string>
|
||||
<string name="error">Error</string>
|
||||
<string name="not_a_mastodon_instance">%s no parece ser una instancia de Mastodon.</string>
|
||||
<string name="ok">Aceptar</string>
|
||||
<string name="preparing_auth">Preparando para autenticación…</string>
|
||||
<string name="finishing_auth">Terminando autenticación…</string>
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
<resources>
|
||||
<string name="sk_pinned_posts">Anclado</string>
|
||||
<string name="sk_delete_and_redraft">Eliminar y editar</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Eliminar y editar post</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Seguro que quiere eliminar y volver a editar este post\?</string>
|
||||
<string name="sk_pin_post">Fijar en perfil</string>
|
||||
<string name="sk_confirm_pin_post_title">Fijar post en perfil</string>
|
||||
<string name="sk_confirm_pin_post">Desea fijar el post en su perfil\?</string>
|
||||
<string name="sk_pinning">Fijando post…</string>
|
||||
<string name="sk_unpin_post">Quitar del perfil</string>
|
||||
<string name="sk_confirm_unpin_post_title">Quitar post del perfil</string>
|
||||
<string name="sk_confirm_unpin_post">Está seguro que quiere quitar el post\?</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Eliminar y editar publicación</string>
|
||||
<string name="sk_confirm_delete_and_redraft">¿Confirma que quiere eliminar y volver a editar esta publicación\?</string>
|
||||
<string name="sk_pin_post">Anclar en perfil</string>
|
||||
<string name="sk_confirm_pin_post_title">Anclar publicación en perfil</string>
|
||||
<string name="sk_confirm_pin_post">¿Quiere anclar la publicación en su perfil\?</string>
|
||||
<string name="sk_pinning">Anclando publicación…</string>
|
||||
<string name="sk_unpin_post">Desanclar del perfil</string>
|
||||
<string name="sk_confirm_unpin_post_title">Desanclar publicación del perfil</string>
|
||||
<string name="sk_confirm_unpin_post">¿Confirma que quiere desanclar esta publicación\?</string>
|
||||
<string name="sk_app_name">Megalodon</string>
|
||||
<string name="sk_unpinning">Quitando post…</string>
|
||||
<string name="sk_unpinning">Desanclando publicación…</string>
|
||||
<string name="sk_image_description">Descripción de la imagen</string>
|
||||
<string name="sk_visibility_unlisted">Sin listar</string>
|
||||
<string name="sk_visibility_unlisted">Descatalogada</string>
|
||||
<string name="sk_settings_show_replies">Mostrar respuestas</string>
|
||||
<string name="sk_settings_show_boosts">Mostrar boosts</string>
|
||||
<string name="sk_settings_load_new_posts">Cargar nuevos posts automáticamente</string>
|
||||
<string name="sk_settings_show_interaction_counts">Mostrar contadores de interacciones</string>
|
||||
<string name="sk_mark_media_as_sensitive">Marcar medio como sensible</string>
|
||||
<string name="sk_settings_show_boosts">Mostrar impulsos</string>
|
||||
<string name="sk_settings_load_new_posts">Cargar publicaciones nuevas automáticamente</string>
|
||||
<string name="sk_settings_show_interaction_counts">Mostrar recuentos de interacciones</string>
|
||||
<string name="sk_mark_media_as_sensitive">Marcar medio como delicado</string>
|
||||
<string name="sk_user_post_notifications_on">Activadas las notificaciones de posts para %s</string>
|
||||
<string name="sk_user_post_notifications_off">Desactivadas las notificaciones de posts para %s</string>
|
||||
<string name="sk_federated_timeline">Federación</string>
|
||||
<string name="sk_federated_timeline_info_banner">Estos son los posts más recientes de las personas de tu federación.</string>
|
||||
<string name="sk_federated_timeline_info_banner">Estas son las publicaciones más recientes de las personas de su federación.</string>
|
||||
<string name="sk_update_available">Megalodon %s está listo para descargar.</string>
|
||||
<string name="sk_update_ready">Megalodon %s se ha descargado y está listo para instalarse.</string>
|
||||
<string name="sk_check_for_update">Buscar actualizaciones</string>
|
||||
@@ -36,6 +36,24 @@
|
||||
<string name="sk_settings_always_reveal_content_warnings">Mostrar siempre advertencias de contenido</string>
|
||||
<string name="sk_disable_marquee">Desactivar desplazamiento de texto en barras del título</string>
|
||||
<string name="sk_settings_contribute">Contribuir a Megalodon</string>
|
||||
<string name="sk_settings_show_federated_timeline">Mostrar el timeline federado</string>
|
||||
<string name="sk_settings_show_federated_timeline">Mostrar cronología federada</string>
|
||||
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
|
||||
<string name="sk_notification_type_status">Publicaciones</string>
|
||||
<string name="sk_notify_posts">Publicar notificaciones</string>
|
||||
<string name="sk_settings_color_picker">Colores para los temas</string>
|
||||
<string name="sk_color_theme_pink">Rosa</string>
|
||||
<string name="sk_color_theme_purple">Violeta</string>
|
||||
<string name="sk_color_theme_green">Verde</string>
|
||||
<string name="sk_color_theme_blue">Azul</string>
|
||||
<string name="sk_color_theme_brown">Marrón</string>
|
||||
<string name="sk_color_theme_yellow">Amarillo</string>
|
||||
<string name="sk_poll_allow_multiple">Permitir respuesta múltiple</string>
|
||||
<string name="sk_translate_post">Traducir</string>
|
||||
<string name="sk_translate_show_original">Mostrar original</string>
|
||||
<string name="sk_translated_using">Traducido mediante %s</string>
|
||||
<string name="sk_post_language">Idioma: %s</string>
|
||||
<string name="sk_available_languages">Idiomas disponibles</string>
|
||||
<string name="sk_language_name">%s (%s)</string>
|
||||
<string name="sk_confirm_clear_recent_languages">¿Confirma que quiere vaciar sus idiomas usados recientemente\?</string>
|
||||
<string name="sk_clear_recent_languages">Vaciar idiomas usados recientemente</string>
|
||||
</resources>
|
||||
@@ -3,13 +3,11 @@
|
||||
<string name="get_started">Nola hasi</string>
|
||||
<string name="log_in">Hasi saioa</string>
|
||||
<string name="next">Hurrengoa</string>
|
||||
<string name="loading_instance">Instantziaren informazioa eskuratzen…</string>
|
||||
<string name="error">Errorea</string>
|
||||
<string name="not_a_mastodon_instance">%s(e)k ez dirudi Mastodon instantzia bat denik.</string>
|
||||
<string name="ok">Ados</string>
|
||||
<string name="preparing_auth">Autentifikaziorako prestatzen…</string>
|
||||
<string name="finishing_auth">Autentikazioa bukatzen…</string>
|
||||
<string name="user_boosted">%s(e)k zure bidalketa bultzatu du</string>
|
||||
<string name="user_boosted">%s(e)k bultzatu du</string>
|
||||
<string name="in_reply_to">%s-(r)i erantzunez</string>
|
||||
<string name="notifications">Jakinarazpenak</string>
|
||||
<string name="user_followed_you">jarraitu zaitu</string>
|
||||
@@ -96,6 +94,10 @@
|
||||
<item quantity="one">%d egun falta da</item>
|
||||
<item quantity="other">%d egun falta dira</item>
|
||||
</plurals>
|
||||
<plurals name="x_voters">
|
||||
<item quantity="one">Boto-emaile %,d</item>
|
||||
<item quantity="other">%,d boto-emaile</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">Itxita</string>
|
||||
<string name="confirm_mute_title">Mututu kontua</string>
|
||||
<string name="confirm_mute">Berretsi %s mututzea</string>
|
||||
@@ -134,6 +136,10 @@
|
||||
<item quantity="one">Pertsona %d hizketan</item>
|
||||
<item quantity="other">%d pertsona hizketan</item>
|
||||
</plurals>
|
||||
<plurals name="discussed_x_times">
|
||||
<item quantity="one">%d aldiz eztabaidatua</item>
|
||||
<item quantity="other">%d aldiz eztabaidatua</item>
|
||||
</plurals>
|
||||
<string name="report_title">Salatu %s</string>
|
||||
<string name="report_choose_reason">Zer du txarra argitalpen honek?</string>
|
||||
<string name="report_choose_reason_account">Zer du txarra %s?</string>
|
||||
@@ -166,6 +172,8 @@
|
||||
<string name="instance_catalog_subtitle">Aukeratu zerbitzari bat zure interesen, eskualdearen edo helburuen arabera. Pertsona guztiekin konektatu ahal izango duzu, zerbitzaria zein den kontuan hartu gabe.</string>
|
||||
<string name="search_communities">Bilatu zerbitzariak edo idatzi URL-a</string>
|
||||
<string name="instance_rules_title">Oinarrizko arau batzuk</string>
|
||||
<string name="instance_rules_subtitle">Hartu minutu bat %s-en administratzaileek ezarri eta aplikatutako arauak berrikusteko.</string>
|
||||
<string name="signup_title">%s zerbitzariko kontua prestatuko dizugu</string>
|
||||
<string name="edit_photo">editatu</string>
|
||||
<string name="display_name">pantaila-izena</string>
|
||||
<string name="username">erabiltzaile-izena</string>
|
||||
@@ -214,6 +222,12 @@
|
||||
<string name="notification_type_poll">Inkestak</string>
|
||||
<string name="choose_account">Aukeratu kontua</string>
|
||||
<string name="err_not_logged_in">Mesedez, hasi saioa lehenengo Mastodonen</string>
|
||||
<plurals name="cant_add_more_than_x_attachments">
|
||||
<item quantity="one">Ezin duzu multimedia fitxategi %d baino gehiago gehitu</item>
|
||||
<item quantity="other">Ezin dituzu %d baino multimedia fitxategi gehiago gehitu</item>
|
||||
</plurals>
|
||||
<string name="media_attachment_unsupported_type">%s fitxategi mota ez da bateragarria</string>
|
||||
<string name="media_attachment_too_big">%1$s fitxategiak %2$s MB-eko tamainaren muga gainditzen du</string>
|
||||
<string name="settings_theme">Itxura bisuala</string>
|
||||
<string name="theme_auto">Automatikoa</string>
|
||||
<string name="theme_light">Argia</string>
|
||||
@@ -297,6 +311,22 @@
|
||||
<string name="current_account">Oraingo kontua</string>
|
||||
<string name="log_out_account">Itxi saioa %s</string>
|
||||
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
|
||||
<plurals name="x_followers">
|
||||
<item quantity="one">Jarraitzaile %,d</item>
|
||||
<item quantity="other">%,d jarraitzaile</item>
|
||||
</plurals>
|
||||
<plurals name="x_following">
|
||||
<item quantity="one">%,d jarraitzen</item>
|
||||
<item quantity="other">%,d jarraitzen</item>
|
||||
</plurals>
|
||||
<plurals name="x_favorites">
|
||||
<item quantity="one">Gogoko bat</item>
|
||||
<item quantity="other">%,d gogoko</item>
|
||||
</plurals>
|
||||
<plurals name="x_reblogs">
|
||||
<item quantity="one">Bultzada %,d</item>
|
||||
<item quantity="other">%,d bultzada</item>
|
||||
</plurals>
|
||||
<string name="timestamp_via_app">%1$s %2$s -en bidez</string>
|
||||
<string name="time_now">orain</string>
|
||||
<string name="post_info_reblogs">Bultzadak</string>
|
||||
@@ -304,6 +334,14 @@
|
||||
<string name="edit_history">Editatu historia</string>
|
||||
<string name="last_edit_at_x">Azken edizioa %s</string>
|
||||
<string name="time_just_now">oraintxe</string>
|
||||
<plurals name="x_seconds_ago">
|
||||
<item quantity="one">Duela segundo %d</item>
|
||||
<item quantity="other">Duela %d segundo</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_ago">
|
||||
<item quantity="one">Duela minutu %d</item>
|
||||
<item quantity="other">Duela %d minutu</item>
|
||||
</plurals>
|
||||
<string name="edited_timestamp">editatua %s</string>
|
||||
<string name="edit_original_post">Jatorrizko bidalketa</string>
|
||||
<string name="edit_text_edited">Editatutako testua</string>
|
||||
@@ -326,12 +364,14 @@
|
||||
<string name="file_size_kb">%.2f KB</string>
|
||||
<string name="file_size_mb">%.2f MB</string>
|
||||
<string name="file_size_gb">%.2f GB</string>
|
||||
<string name="file_upload_progress">%2$s-tik %1$s</string>
|
||||
<string name="file_upload_time_remaining">%s geratzen da</string>
|
||||
<string name="upload_error_connection_lost">Zure gailuak interneterako konexioa galdu du</string>
|
||||
<string name="upload_processing">Prozesatzen…</string>
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<string name="update_available">Androiderako Mastodon %s prest dago jeisteko.</string>
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<string name="update_ready">%s Androiderako Mastodon deskargatu da eta instalatzeko prest dago.</string>
|
||||
<!-- %s is file size -->
|
||||
<string name="download_update">(%s) deskargatu</string>
|
||||
<string name="install_update">Instalatu</string>
|
||||
@@ -340,4 +380,9 @@
|
||||
<string name="i_agree">Ados nago</string>
|
||||
<string name="empty_list">Zerrenda hau hutsik dago</string>
|
||||
<string name="instance_signup_closed">Zerbitzari honek ez ditu izen-emate berriak onartzen.</string>
|
||||
<string name="text_copied">Arbelean kopiatuta</string>
|
||||
<string name="add_bookmark">Laster-marka</string>
|
||||
<string name="remove_bookmark">Kendu laster-marka</string>
|
||||
<string name="bookmarks">Laster-markak</string>
|
||||
<string name="your_favorites">Zure gogokoak</string>
|
||||
</resources>
|
||||
|
||||
165
mastodon/src/main/res/values-fil-rPH/strings.xml
Normal file
165
mastodon/src/main/res/values-fil-rPH/strings.xml
Normal file
@@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="get_started">Magsimula</string>
|
||||
<string name="log_in">Mag-log in</string>
|
||||
<string name="next">Sunod</string>
|
||||
<string name="error">Nag-Error</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Paghahanda para sa pagpapatunay…</string>
|
||||
<string name="finishing_auth">Natapos na ang pagpapatunay…</string>
|
||||
<string name="user_boosted">%s reblogged</string>
|
||||
<string name="in_reply_to">Sa sumagot sa %s</string>
|
||||
<string name="notifications">Mga abiso</string>
|
||||
<string name="user_followed_you">sinundan ka</string>
|
||||
<string name="user_sent_follow_request">may nagpadala sa iyo ng follow request</string>
|
||||
<string name="user_favorited">paborito ang iyong post</string>
|
||||
<string name="notification_boosted">na reblogged ang iyong post</string>
|
||||
<string name="poll_ended">natapos na ang poll</string>
|
||||
<string name="time_seconds">%ds</string>
|
||||
<string name="time_minutes">%dm</string>
|
||||
<string name="time_hours">%dh</string>
|
||||
<string name="time_days">%dd</string>
|
||||
<string name="share_toot_title">Ibahagi</string>
|
||||
<string name="settings">Mga setting</string>
|
||||
<string name="publish">I-publish</string>
|
||||
<string name="discard_draft">Ipagliban ang draft?</string>
|
||||
<string name="discard">Ipagliban</string>
|
||||
<string name="cancel">Kanselahin</string>
|
||||
<plurals name="followers">
|
||||
<item quantity="one">tagasunod</item>
|
||||
<item quantity="other">mga tagasunod</item>
|
||||
</plurals>
|
||||
<plurals name="following">
|
||||
<item quantity="one">sumusunod</item>
|
||||
<item quantity="other">sumusunod</item>
|
||||
</plurals>
|
||||
<plurals name="posts">
|
||||
<item quantity="one">post</item>
|
||||
<item quantity="other">mga post</item>
|
||||
</plurals>
|
||||
<string name="posts">Mga Post</string>
|
||||
<string name="posts_and_replies">Mga post at Mga tugon</string>
|
||||
<string name="media">Medya</string>
|
||||
<string name="profile_about">Tungkol</string>
|
||||
<string name="button_follow">Sundan</string>
|
||||
<string name="button_following">Sumusunod</string>
|
||||
<string name="edit_profile">I-edit ang profile</string>
|
||||
<string name="mention_user">Binanggit %s</string>
|
||||
<string name="share_user">Ibahagi %s</string>
|
||||
<string name="mute_user">I-mute %s</string>
|
||||
<string name="unmute_user">I-unmute %s</string>
|
||||
<string name="block_user">Na-Block %s</string>
|
||||
<string name="unblock_user">Na-Unblock %s</string>
|
||||
<string name="report_user">Na-report %s</string>
|
||||
<string name="block_domain">Na-Block %s</string>
|
||||
<string name="unblock_domain">Na-Unblock %s</string>
|
||||
<plurals name="x_posts">
|
||||
<item quantity="one">%,d post</item>
|
||||
<item quantity="other">%,d mga post</item>
|
||||
</plurals>
|
||||
<string name="profile_joined">Sumali</string>
|
||||
<string name="done">Tapos na</string>
|
||||
<string name="loading">Naglo-load…</string>
|
||||
<string name="field_label">Label</string>
|
||||
<string name="field_content">Nilalaman</string>
|
||||
<string name="saving">Pag-save…</string>
|
||||
<string name="post_from_user">Post galing %s</string>
|
||||
<string name="poll_option_hint">Pagpipilian %d</string>
|
||||
<plurals name="x_minutes">
|
||||
<item quantity="one">%d minuto</item>
|
||||
<item quantity="other">%d minuto</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours">
|
||||
<item quantity="one">%d oras</item>
|
||||
<item quantity="other">%d oras</item>
|
||||
</plurals>
|
||||
<plurals name="x_days">
|
||||
<item quantity="one">%d araw</item>
|
||||
<item quantity="other">%d araw</item>
|
||||
</plurals>
|
||||
<string name="compose_poll_duration">Tagal: %s</string>
|
||||
<plurals name="x_seconds_left">
|
||||
<item quantity="one">%d segundong natitira</item>
|
||||
<item quantity="other">%d segundong natitira</item>
|
||||
</plurals>
|
||||
<plurals name="x_minutes_left">
|
||||
<item quantity="one">%d minutong natitira</item>
|
||||
<item quantity="other">%d minutong natitira</item>
|
||||
</plurals>
|
||||
<plurals name="x_hours_left">
|
||||
<item quantity="one">%d natitirang oras</item>
|
||||
<item quantity="other">%d natitirang oras</item>
|
||||
</plurals>
|
||||
<plurals name="x_days_left">
|
||||
<item quantity="one">%d natitirang araw</item>
|
||||
<item quantity="other">%d natitirang araw</item>
|
||||
</plurals>
|
||||
<plurals name="x_voters">
|
||||
<item quantity="one">%, d botante</item>
|
||||
<item quantity="other">%,d botante</item>
|
||||
</plurals>
|
||||
<string name="poll_closed">Sarado</string>
|
||||
<string name="confirm_mute_title">I-Mute Ang Account</string>
|
||||
<string name="confirm_mute">Kumpirmahin ang pag-mute %s</string>
|
||||
<string name="do_mute">I-Mute</string>
|
||||
<string name="confirm_unmute_title">I-Unmute Ang Account</string>
|
||||
<string name="confirm_unmute">Kumpirmahin ang pag-unmute %s</string>
|
||||
<string name="do_unmute">I-unmute</string>
|
||||
<string name="confirm_block_title">I-Block Ang Account</string>
|
||||
<string name="confirm_block_domain_title">I-Block Ang Domain</string>
|
||||
<string name="confirm_block">Kumpirmahin ang pag-block %s</string>
|
||||
<string name="do_block">Block</string>
|
||||
<string name="confirm_unblock_title">I-Unblock ang Account</string>
|
||||
<string name="confirm_unblock_domain_title">I-Unblock ang Domain</string>
|
||||
<string name="confirm_unblock">Kumpirmahin ang pag-unblock%s</string>
|
||||
<string name="do_unblock">Unblock</string>
|
||||
<string name="button_muted">Naka-mute</string>
|
||||
<string name="button_blocked">Na-block</string>
|
||||
<string name="action_vote">Bumoto</string>
|
||||
<string name="tap_to_reveal">I-Tap para ipakita</string>
|
||||
<string name="delete">Tanggalin</string>
|
||||
<string name="confirm_delete_title">Burahin ang Post</string>
|
||||
<string name="confirm_delete">Sigurado ka bang gusto mong burahin ang post na ito?</string>
|
||||
<string name="notification_channel_audio_player">Pag-playback ng Audio</string>
|
||||
<string name="play">I-play</string>
|
||||
<string name="log_out">Mag-Sign out</string>
|
||||
<string name="add_account">Magdagdag ng account</string>
|
||||
<string name="search_hint">Maghanap</string>
|
||||
<string name="hashtags">Mga hashtag</string>
|
||||
<string name="news">Balita</string>
|
||||
<string name="for_you">Para sa\'yo</string>
|
||||
<string name="all_notifications">Lahat</string>
|
||||
<string name="mentions">Mga binangit</string>
|
||||
<plurals name="x_people_talking">
|
||||
<item quantity="one">%d tao ay nagsasalita</item>
|
||||
<item quantity="other">%d tao ay nagsasalita</item>
|
||||
</plurals>
|
||||
<plurals name="discussed_x_times">
|
||||
<item quantity="one">Tinalakay %d oras</item>
|
||||
<item quantity="other">Tinalakay %d oras</item>
|
||||
</plurals>
|
||||
<string name="report_title">Na-report %s</string>
|
||||
<string name="report_choose_reason">Ano ang mali sa post na ito?</string>
|
||||
<string name="report_choose_reason_account">Ano ang mali sa %s?</string>
|
||||
<string name="report_choose_reason_subtitle">Piliin ang pinakamahusay na tugma</string>
|
||||
<string name="report_reason_personal">Hindi ko gusto ito</string>
|
||||
<string name="report_reason_personal_subtitle">Hindi ito isang bagay na nais mong makita</string>
|
||||
<string name="report_reason_spam">Ito ay spam</string>
|
||||
<string name="report_reason_spam_subtitle">Nakakahamak na mga link, pekeng pakikipag-ugnayan, o paulit-ulit na mga tugon</string>
|
||||
<string name="report_reason_violation">Lumalabag ito sa mga patakaran ng server</string>
|
||||
<string name="report_reason_violation_subtitle">Alam mo na nilalabag nito ang mga tiyak na patakaran</string>
|
||||
<string name="report_reason_other">Ito may iba pa</string>
|
||||
<string name="report_reason_other_subtitle">Ang isyu ay hindi umaangkop sa iba pang mga kategorya</string>
|
||||
<string name="report_choose_rule">Aling mga patakaran ang nilabag?</string>
|
||||
<string name="report_choose_rule_subtitle">Piliin ang lahat na-iapply</string>
|
||||
<string name="report_choose_posts">Mayroon bang anumang mga post na nai-back up ang ulat na ito?</string>
|
||||
<string name="report_choose_posts_subtitle">Piliin ang lahat na aaply</string>
|
||||
<string name="report_comment_title">Mayroon pa bang dapat nating malaman?</string>
|
||||
<string name="report_comment_hint">Mga Karagdagang Komento</string>
|
||||
<string name="report_sent_title">Salamat sa pag-uulat, titingnan namin ito.</string>
|
||||
<string name="report_sent_subtitle">Habang sinusuri namin ito, maaari kang gumawa ng aksyon laban sa %s.</string>
|
||||
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<!-- %s is version like 1.2.3 -->
|
||||
<!-- %s is file size -->
|
||||
</resources>
|
||||
3
mastodon/src/main/res/values-fil-rPH/strings_sk.xml
Normal file
3
mastodon/src/main/res/values-fil-rPH/strings_sk.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
</resources>
|
||||
@@ -3,9 +3,9 @@
|
||||
<string name="get_started">Premiers pas</string>
|
||||
<string name="log_in">Se connecter</string>
|
||||
<string name="next">Suivant</string>
|
||||
<string name="loading_instance">Chargement des informations de l’instance…</string>
|
||||
<string name="loading_instance">Récupération des informations serveur…</string>
|
||||
<string name="error">Erreur</string>
|
||||
<string name="not_a_mastodon_instance">%s ne semble pas être une instance Mastodon.</string>
|
||||
<string name="not_a_mastodon_instance">%s ne semble pas être un serveur Mastodon.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="preparing_auth">Préparation à l’authentification…</string>
|
||||
<string name="finishing_auth">Fin de l’authentification…</string>
|
||||
@@ -387,4 +387,7 @@
|
||||
<string name="remove_bookmark">Retirer des favoris</string>
|
||||
<string name="bookmarks">Favoris</string>
|
||||
<string name="your_favorites">Vos favoris</string>
|
||||
<string name="login_title">Content de vous revoir</string>
|
||||
<string name="login_subtitle">Connectez-vous avec le serveur sur lequel vous avez créé votre compte.</string>
|
||||
<string name="server_url">URL du serveur</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="sk_pinned_posts">Épinglé</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Supprimer et reformuler le message</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Voulez-vous vraiment supprimer et reformuler ce message \?</string>
|
||||
<string name="sk_confirm_delete_and_redraft_title">Supprimer et rééditer le message</string>
|
||||
<string name="sk_confirm_delete_and_redraft">Voulez-vous vraiment supprimer et rééditer ce message \?</string>
|
||||
<string name="sk_confirm_pin_post">Voulez-vous épingler ce message à votre profil \?</string>
|
||||
<string name="sk_pinning">Épinglage de la publication…</string>
|
||||
<string name="sk_pinning">Épinglage du message…</string>
|
||||
<string name="sk_unpin_post">Détacher du profil</string>
|
||||
<string name="sk_confirm_unpin_post_title">Détacher la publication du profil</string>
|
||||
<string name="sk_unpinning">Détachement de la publication…</string>
|
||||
<string name="sk_confirm_unpin_post_title">Détacher le message du profil</string>
|
||||
<string name="sk_unpinning">Détachement du message…</string>
|
||||
<string name="sk_image_description">Description de l\'image</string>
|
||||
<string name="sk_visibility_unlisted">Non répertorié</string>
|
||||
<string name="sk_settings_show_replies">Afficher les réponses</string>
|
||||
<string name="sk_settings_show_boosts">Afficher les boosts</string>
|
||||
<string name="sk_settings_load_new_posts">Charger automatiquement les nouvelles publications</string>
|
||||
<string name="sk_settings_load_new_posts">Charger automatiquement les nouveaux messages</string>
|
||||
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
|
||||
<string name="sk_mark_media_as_sensitive">Marquer le média comme sensible</string>
|
||||
<string name="sk_user_post_notifications_on">Notifications de publication activées pour %s</string>
|
||||
<string name="sk_user_post_notifications_off">Désactivation des notifications de publication pour %s</string>
|
||||
<string name="sk_update_available">Megalodon %s est prêt à être téléchargé.</string>
|
||||
<string name="sk_update_ready">Megalodon %s est téléchargé et prêt à être installé.</string>
|
||||
<string name="sk_user_post_notifications_on">Notifications de message activées pour %s</string>
|
||||
<string name="sk_user_post_notifications_off">Désactivation des notifications de message pour %s</string>
|
||||
<string name="sk_update_available">Megalodon %s est prête à être téléchargée.</string>
|
||||
<string name="sk_update_ready">Megalodon %s est téléchargée et prête à être installée.</string>
|
||||
<string name="sk_check_for_update">Vérifier les mises à jour</string>
|
||||
<string name="sk_no_update_available">Pas de mise a jour disponible</string>
|
||||
<string name="sk_list_timelines">Listes</string>
|
||||
@@ -31,11 +31,29 @@
|
||||
<string name="sk_settings_contribute">Contribuez à Megalodon</string>
|
||||
<string name="sk_settings_show_federated_timeline">Afficher la timeline fédérée</string>
|
||||
<string name="sk_app_name">Megalodon</string>
|
||||
<string name="sk_delete_and_redraft">Supprimer et reformuler</string>
|
||||
<string name="sk_delete_and_redraft">Supprimer et rééditer</string>
|
||||
<string name="sk_pin_post">Épingler au profil</string>
|
||||
<string name="sk_confirm_pin_post_title">Épingler la publication au profil</string>
|
||||
<string name="sk_confirm_unpin_post">Êtes-vous sûr de vouloir détacher cette publication \?</string>
|
||||
<string name="sk_confirm_pin_post_title">Épingler le message au profil</string>
|
||||
<string name="sk_confirm_unpin_post">Êtes-vous sûr de vouloir détacher ce message \?</string>
|
||||
<string name="sk_settings_show_interaction_counts">Afficher le nombre d\'interactions</string>
|
||||
<string name="sk_federated_timeline">Fédération</string>
|
||||
<string name="sk_federated_timeline_info_banner">Ce sont les publications les plus récentes des membres de votre fédération.</string>
|
||||
<string name="sk_federated_timeline_info_banner">Ce sont les messages les plus récents des membres de votre fédération.</string>
|
||||
<string name="sk_notification_type_status">Messages</string>
|
||||
<string name="sk_notify_posts">Notifications des messages</string>
|
||||
<string name="sk_color_theme_pink">Rose</string>
|
||||
<string name="sk_color_theme_purple">Violet</string>
|
||||
<string name="sk_color_theme_green">Vert</string>
|
||||
<string name="sk_color_theme_blue">Bleu</string>
|
||||
<string name="sk_color_theme_brown">Marron</string>
|
||||
<string name="sk_color_theme_yellow">Jaune</string>
|
||||
<string name="sk_settings_color_picker">Couleur d\'accentuation</string>
|
||||
<string name="sk_poll_allow_multiple">Autoriser plusieurs choix</string>
|
||||
<string name="sk_translate_post">Traduire</string>
|
||||
<string name="sk_translate_show_original">Afficher l\'original</string>
|
||||
<string name="sk_translated_using">Traduit en utilisant %s</string>
|
||||
<string name="sk_post_language">Langue : %s</string>
|
||||
<string name="sk_available_languages">Langues disponibles</string>
|
||||
<string name="sk_language_name">%s (%s)</string>
|
||||
<string name="sk_confirm_clear_recent_languages">Êtes-vous sûr de vouloir effacer vos langues récemment utilisées \?</string>
|
||||
<string name="sk_clear_recent_languages">Effacer les langues récemment utilisées</string>
|
||||
</resources>
|
||||
@@ -3,9 +3,7 @@
|
||||
<string name="get_started">Dèan toiseach-tòiseachaidh</string>
|
||||
<string name="log_in">Clàraich a-steach</string>
|
||||
<string name="next">Air adhart</string>
|
||||
<string name="loading_instance">A’ faighinn fiosrachadh an ionstans…</string>
|
||||
<string name="error">Mearachd</string>
|
||||
<string name="not_a_mastodon_instance">Chan eil coltas ionstans Mhastodon air %s.</string>
|
||||
<string name="ok">Ceart ma-thà</string>
|
||||
<string name="preparing_auth">Ag ullachadh an dearbhaidh…</string>
|
||||
<string name="finishing_auth">A’ crìochnachadh an dearbhaidh…</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user