Compare commits
254 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
957bc76dbb | ||
|
|
1f5a28fb33 | ||
|
|
045c58ce66 | ||
|
|
e2dde7239f | ||
|
|
512ad93eea | ||
|
|
19759023a4 | ||
|
|
714d3399ce | ||
|
|
e1850e5282 | ||
|
|
a05c917b2c | ||
|
|
8f3a9c265c | ||
|
|
6f1a33b76e | ||
|
|
8f0451175f | ||
|
|
37a3a4f1c0 | ||
|
|
bd85746726 | ||
|
|
96265010bf | ||
|
|
4209951ce3 | ||
|
|
f1cbd95439 | ||
|
|
d63382c6d9 | ||
|
|
20697fb334 | ||
|
|
1090d1ca42 | ||
|
|
bec4acdf51 | ||
|
|
800b78bfd8 | ||
|
|
52b01b7bbe | ||
|
|
8b71764207 | ||
|
|
a5d7a75f32 | ||
|
|
8839bcb7aa | ||
|
|
bcaf71760d | ||
|
|
1d95204648 | ||
|
|
83bf2a808f | ||
|
|
7ffb0a01c6 | ||
|
|
0710113148 | ||
|
|
7c43e9a1af | ||
|
|
f9e768c378 | ||
|
|
2063dbd0b0 | ||
|
|
057683c72f | ||
|
|
4963a0e722 | ||
|
|
1d66d288bd | ||
|
|
b8f49157c3 | ||
|
|
d77a62ef6f | ||
|
|
c531150483 | ||
|
|
991f41c531 | ||
|
|
b5fb7dd2ec | ||
|
|
4fe8532971 | ||
|
|
4ae1e7d33e | ||
|
|
43fa4526a4 | ||
|
|
fc4b1da323 | ||
|
|
843755f4e4 | ||
|
|
80e02f7520 | ||
|
|
af8f52e589 | ||
|
|
bc3f48dec9 | ||
|
|
74ee832507 | ||
|
|
da1b2d09b1 | ||
|
|
99f8607211 | ||
|
|
ef293088e1 | ||
|
|
e08e72ccb0 | ||
|
|
b692440bab | ||
|
|
7061abc64b | ||
|
|
0dd5064abb | ||
|
|
a1aafff6ce | ||
|
|
1f88f154af | ||
|
|
3d1e0364c6 | ||
|
|
0f1b5431bb | ||
|
|
0369d3fa62 | ||
|
|
154e3a732a | ||
|
|
9c979db043 | ||
|
|
0af089db89 | ||
|
|
1335613860 | ||
|
|
cb86bfd8dc | ||
|
|
a0d32ae493 | ||
|
|
f7e56a6c40 | ||
|
|
56613c75f7 | ||
|
|
fb3c35c0a0 | ||
|
|
4b3dc0a59f | ||
|
|
7855615a7b | ||
|
|
ff6576f4da | ||
|
|
931fa9a9b0 | ||
|
|
77a70967f2 | ||
|
|
e5506d952c | ||
|
|
2c2dbd0761 | ||
|
|
e6f5ecd496 | ||
|
|
73cea2d83c | ||
|
|
835a576f44 | ||
|
|
0a090341cc | ||
|
|
453671abfb | ||
|
|
cfa7daa984 | ||
|
|
88f913f586 | ||
|
|
5b4aeb4923 | ||
|
|
19133a2913 | ||
|
|
293035b7c8 | ||
|
|
d06723de5c | ||
|
|
bc45d0c499 | ||
|
|
c320cccf6f | ||
|
|
e3aebbd145 | ||
|
|
e15d378e46 | ||
|
|
b6720d10fb | ||
|
|
83a2dbe8a1 | ||
|
|
5b8592a99d | ||
|
|
18a094c06c | ||
|
|
a319ff3dc0 | ||
|
|
0cb46eca1a | ||
|
|
d85c814cba | ||
|
|
f49e660f29 | ||
|
|
afa407e7d1 | ||
|
|
37e0f5ecea | ||
|
|
5000fdcfea | ||
|
|
2ec7489dbf | ||
|
|
05965cea6e | ||
|
|
279e22ccb3 | ||
|
|
6a6fc1ca8b | ||
|
|
b6b5426297 | ||
|
|
e332ddda74 | ||
|
|
2cd4cfb883 | ||
|
|
ef12d09d35 | ||
|
|
1e365a8a7c | ||
|
|
e9363b41fd | ||
|
|
5e99df137a | ||
|
|
c0d0b45e24 | ||
|
|
3340b4cdfa | ||
|
|
d4afcc3383 | ||
|
|
dad423eb04 | ||
|
|
7b275d7e3d | ||
|
|
5274ecb721 | ||
|
|
e45367a482 | ||
|
|
83532edaab | ||
|
|
793d28da6a | ||
|
|
a8e575f680 | ||
|
|
98b0b3f9dd | ||
|
|
2e6d9c296a | ||
|
|
a07dc96ef9 | ||
|
|
8ba097a68a | ||
|
|
b1dd990fea | ||
|
|
ba7864b910 | ||
|
|
5d8fa343cd | ||
|
|
3fc49c431b | ||
|
|
79b6e65ce3 | ||
|
|
9f457d0d76 | ||
|
|
aa2ff62db4 | ||
|
|
73fffca569 | ||
|
|
45589fc033 | ||
|
|
79b81ed932 | ||
|
|
d1242870df | ||
|
|
e0dbbc4bc0 | ||
|
|
bf89791817 | ||
|
|
e3197f6dc1 | ||
|
|
e6317aa898 | ||
|
|
c73dc326fd | ||
|
|
287e250357 | ||
|
|
9673a14420 | ||
|
|
3333fdc8d7 | ||
|
|
9fb4b8bb6e | ||
|
|
7b10ed13f4 | ||
|
|
c528bd797d | ||
|
|
264529705c | ||
|
|
4669e3dfc7 | ||
|
|
eff3798964 | ||
|
|
78c526c25b | ||
|
|
ec13415d1f | ||
|
|
96622184ae | ||
|
|
3742c1c862 | ||
|
|
a0c7757428 | ||
|
|
15f9f4906a | ||
|
|
d577cd9b21 | ||
|
|
cf610cbb87 | ||
|
|
1e1095204d | ||
|
|
3fb6a13a3a | ||
|
|
2826655fe2 | ||
|
|
0ccf450b28 | ||
|
|
d28b9460af | ||
|
|
3e1bdf98c2 | ||
|
|
3f87764230 | ||
|
|
25e8e2e9e1 | ||
|
|
3faf2ce9b9 | ||
|
|
cbe243fc9e | ||
|
|
a438f633be | ||
|
|
37ef67d7ac | ||
|
|
67d631b0f0 | ||
|
|
fc302ffa5f | ||
|
|
8c28556a94 | ||
|
|
45cc531eec | ||
|
|
5c9ad9286d | ||
|
|
ad1c9486d7 | ||
|
|
ad6a03b712 | ||
|
|
36bb8010bc | ||
|
|
2200da7a16 | ||
|
|
688c0e2e85 | ||
|
|
714345a65d | ||
|
|
34a1c7e408 | ||
|
|
6255221d6a | ||
|
|
58364de72a | ||
|
|
6d64df4ee4 | ||
|
|
7bac2f206b | ||
|
|
75e1a17a2c | ||
|
|
47b13384a8 | ||
|
|
77b9efa7d1 | ||
|
|
be5f3b18af | ||
|
|
d5d12a7ce5 | ||
|
|
d7726d7755 | ||
|
|
0cd0d37eff | ||
|
|
4521def103 | ||
|
|
5c70f0a758 | ||
|
|
c12c2c0416 | ||
|
|
db45c422e7 | ||
|
|
affd9a95c5 | ||
|
|
7baf25869a | ||
|
|
12096fb427 | ||
|
|
ef7136cb81 | ||
|
|
3c4baf0126 | ||
|
|
f0b87c62a5 | ||
|
|
a319435e91 | ||
|
|
5bd0e988e3 | ||
|
|
b2be669b9e | ||
|
|
51952b0485 | ||
|
|
2b0c5e7fac | ||
|
|
3e6cea1a6a | ||
|
|
1aec7c0999 | ||
|
|
5da98809a5 | ||
|
|
49695614b7 | ||
|
|
3fbbc104b7 | ||
|
|
2fe7c0b85e | ||
|
|
09d0e82216 | ||
|
|
d208fcea7d | ||
|
|
cc0674db34 | ||
|
|
1d5b84943d | ||
|
|
14fe992ca5 | ||
|
|
15232bddaf | ||
|
|
160ef25621 | ||
|
|
2afb8688a3 | ||
|
|
9d1af035ea | ||
|
|
fb7574d814 | ||
|
|
201a3cb9e3 | ||
|
|
cc735ee6a1 | ||
|
|
0165e14ea0 | ||
|
|
97d19605d5 | ||
|
|
bc490218f9 | ||
|
|
6dac05a21d | ||
|
|
fd3fff6322 | ||
|
|
edb64fff2e | ||
|
|
fe0e854e72 | ||
|
|
06c85fb203 | ||
|
|
69926c4ae1 | ||
|
|
ef44b0a412 | ||
|
|
8577ac1027 | ||
|
|
32da050106 | ||
|
|
526b74b3ef | ||
|
|
97ab328a9c | ||
|
|
21603eedcf | ||
|
|
7fbef273a1 | ||
|
|
9e19716504 | ||
|
|
b473642ab4 | ||
|
|
fba55f01a0 | ||
|
|
015e63ba66 | ||
|
|
d92e2407f3 | ||
|
|
a4f84fb8cd | ||
|
|
bfe88745ca |
@@ -1 +1 @@
|
|||||||
Decentralizált szociális hálózat
|
Decentralizált közösségi hálózat
|
||||||
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "org.joinmastodon.android"
|
applicationId "org.joinmastodon.android"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 33
|
targetSdk 33
|
||||||
versionCode 75
|
versionCode 80
|
||||||
versionName "2.2.0"
|
versionName "2.2.4"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "da-rDK", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fa-rIR", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "ig-rNG", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "my-rMM", "nl-rNL", "no-rNO", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "ur-rIN", "vi-rVN", "zh-rCN", "zh-rTW"
|
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "da-rDK", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fa-rIR", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "ig-rNG", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "my-rMM", "nl-rNL", "no-rNO", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "ur-rIN", "vi-rVN", "zh-rCN", "zh-rTW"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package org.joinmastodon.android;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
|
||||||
public class GlobalUserPreferences{
|
public class GlobalUserPreferences{
|
||||||
public static boolean playGifs;
|
public static boolean playGifs;
|
||||||
public static boolean useCustomTabs;
|
public static boolean useCustomTabs;
|
||||||
@@ -13,6 +16,10 @@ public class GlobalUserPreferences{
|
|||||||
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
|
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SharedPreferences getPreReplyPrefs(){
|
||||||
|
return MastodonApp.context.getSharedPreferences("pre_reply_sheets", Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
public static void load(){
|
public static void load(){
|
||||||
SharedPreferences prefs=getPrefs();
|
SharedPreferences prefs=getPrefs();
|
||||||
playGifs=prefs.getBoolean("playGifs", true);
|
playGifs=prefs.getBoolean("playGifs", true);
|
||||||
@@ -36,9 +43,42 @@ public class GlobalUserPreferences{
|
|||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOptedOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
|
||||||
|
if(getPreReplyPrefs().getBoolean("opt_out_"+type, false))
|
||||||
|
return true;
|
||||||
|
if(account==null)
|
||||||
|
return false;
|
||||||
|
String accountKey=account.acct;
|
||||||
|
if(!accountKey.contains("@"))
|
||||||
|
accountKey+="@"+AccountSessionManager.get(accountID).domain;
|
||||||
|
return getPreReplyPrefs().getBoolean("opt_out_"+type+"_"+accountKey.toLowerCase(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void optOutOfPreReplySheet(PreReplySheetType type, Account account, String accountID){
|
||||||
|
String key;
|
||||||
|
if(account==null){
|
||||||
|
key="opt_out_"+type;
|
||||||
|
}else{
|
||||||
|
String accountKey=account.acct;
|
||||||
|
if(!accountKey.contains("@"))
|
||||||
|
accountKey+="@"+AccountSessionManager.get(accountID).domain;
|
||||||
|
key="opt_out_"+type+"_"+accountKey.toLowerCase();
|
||||||
|
}
|
||||||
|
getPreReplyPrefs().edit().putBoolean(key, true).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetPreReplySheets(){
|
||||||
|
getPreReplyPrefs().edit().clear().apply();
|
||||||
|
}
|
||||||
|
|
||||||
public enum ThemePreference{
|
public enum ThemePreference{
|
||||||
AUTO,
|
AUTO,
|
||||||
LIGHT,
|
LIGHT,
|
||||||
DARK
|
DARK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum PreReplySheetType{
|
||||||
|
OLD_POST,
|
||||||
|
NON_MUTUAL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.app.Fragment;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.BadParcelableException;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -36,6 +37,8 @@ import me.grishka.appkit.api.Callback;
|
|||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
|
||||||
public class MainActivity extends FragmentStackActivity{
|
public class MainActivity extends FragmentStackActivity{
|
||||||
|
private static final String TAG="MainActivity";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState){
|
protected void onCreate(@Nullable Bundle savedInstanceState){
|
||||||
UiUtils.setUserPreferredTheme(this);
|
UiUtils.setUserPreferredTheme(this);
|
||||||
@@ -193,8 +196,14 @@ public class MainActivity extends FragmentStackActivity{
|
|||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
showFragmentClearingBackStack(fragment);
|
showFragmentClearingBackStack(fragment);
|
||||||
if(intent.getBooleanExtra("fromNotification", false) && intent.hasExtra("notification")){
|
if(intent.getBooleanExtra("fromNotification", false) && intent.hasExtra("notification")){
|
||||||
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
|
// Parcelables might not be compatible across app versions so this protects against possible crashes
|
||||||
showFragmentForNotification(notification, session.getID());
|
// when a notification was received, then the app was updated, and then the user opened the notification
|
||||||
|
try{
|
||||||
|
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
|
||||||
|
showFragmentForNotification(notification, session.getID());
|
||||||
|
}catch(BadParcelableException x){
|
||||||
|
Log.w(TAG, x);
|
||||||
|
}
|
||||||
}else if(intent.getBooleanExtra("compose", false)){
|
}else if(intent.getBooleanExtra("compose", false)){
|
||||||
showCompose();
|
showCompose();
|
||||||
}else if(Intent.ACTION_VIEW.equals(intent.getAction())){
|
}else if(Intent.ACTION_VIEW.equals(intent.getAction())){
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
|
|||||||
private Uri avatar, cover;
|
private Uri avatar, cover;
|
||||||
private File avatarFile, coverFile;
|
private File avatarFile, coverFile;
|
||||||
private List<AccountField> fields;
|
private List<AccountField> fields;
|
||||||
|
private Boolean discoverable, indexable;
|
||||||
|
|
||||||
public UpdateAccountCredentials(String displayName, String bio, Uri avatar, Uri cover, List<AccountField> fields){
|
public UpdateAccountCredentials(String displayName, String bio, Uri avatar, Uri cover, List<AccountField> fields){
|
||||||
super(HttpMethod.PATCH, "/accounts/update_credentials", Account.class);
|
super(HttpMethod.PATCH, "/accounts/update_credentials", Account.class);
|
||||||
@@ -41,6 +42,12 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
|
|||||||
this.fields=fields;
|
this.fields=fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UpdateAccountCredentials setDiscoverableIndexable(boolean discoverable, boolean indexable){
|
||||||
|
this.discoverable=discoverable;
|
||||||
|
this.indexable=indexable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RequestBody getRequestBody() throws IOException{
|
public RequestBody getRequestBody() throws IOException{
|
||||||
MultipartBody.Builder bldr=new MultipartBody.Builder()
|
MultipartBody.Builder bldr=new MultipartBody.Builder()
|
||||||
@@ -58,15 +65,21 @@ public class UpdateAccountCredentials extends MastodonAPIRequest<Account>{
|
|||||||
}else if(coverFile!=null){
|
}else if(coverFile!=null){
|
||||||
bldr.addFormDataPart("header", coverFile.getName(), new ResizedImageRequestBody(Uri.fromFile(coverFile), 1500*500, null));
|
bldr.addFormDataPart("header", coverFile.getName(), new ResizedImageRequestBody(Uri.fromFile(coverFile), 1500*500, null));
|
||||||
}
|
}
|
||||||
if(fields.isEmpty()){
|
if(fields!=null){
|
||||||
bldr.addFormDataPart("fields_attributes[0][name]", "").addFormDataPart("fields_attributes[0][value]", "");
|
if(fields.isEmpty()){
|
||||||
}else{
|
bldr.addFormDataPart("fields_attributes[0][name]", "").addFormDataPart("fields_attributes[0][value]", "");
|
||||||
int i=0;
|
}else{
|
||||||
for(AccountField field:fields){
|
int i=0;
|
||||||
bldr.addFormDataPart("fields_attributes["+i+"][name]", field.name).addFormDataPart("fields_attributes["+i+"][value]", field.value);
|
for(AccountField field:fields){
|
||||||
i++;
|
bldr.addFormDataPart("fields_attributes["+i+"][name]", field.name).addFormDataPart("fields_attributes["+i+"][value]", field.value);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(discoverable!=null)
|
||||||
|
bldr.addFormDataPart("discoverable", discoverable.toString());
|
||||||
|
if(indexable!=null)
|
||||||
|
bldr.addFormDataPart("indexable", indexable.toString());
|
||||||
|
|
||||||
return bldr.build();
|
return bldr.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ public class GetStatusEditHistory extends MastodonAPIRequest<List<Status>>{
|
|||||||
s.visibility=StatusPrivacy.PUBLIC;
|
s.visibility=StatusPrivacy.PUBLIC;
|
||||||
s.mentions=Collections.emptyList();
|
s.mentions=Collections.emptyList();
|
||||||
s.tags=Collections.emptyList();
|
s.tags=Collections.emptyList();
|
||||||
|
if(s.poll!=null){
|
||||||
|
s.poll.id="fakeID"+i;
|
||||||
|
s.poll.emojis=Collections.emptyList();
|
||||||
|
s.poll.ownVotes=Collections.emptyList();
|
||||||
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
super.validateAndPostprocessResponse(respObj, httpResponse);
|
super.validateAndPostprocessResponse(respObj, httpResponse);
|
||||||
|
|||||||
@@ -181,7 +181,11 @@ public class AccountSessionManager{
|
|||||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
||||||
MastodonApp.context.deleteSharedPreferences(id);
|
MastodonApp.context.deleteSharedPreferences(id);
|
||||||
}else{
|
}else{
|
||||||
new File(MastodonApp.context.getDir("shared_prefs", Context.MODE_PRIVATE), id+".xml").delete();
|
String dataDir=MastodonApp.context.getApplicationInfo().dataDir;
|
||||||
|
if(dataDir!=null){
|
||||||
|
File prefsDir=new File(dataDir, "shared_prefs");
|
||||||
|
new File(prefsDir, id+".xml").delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sessions.remove(id);
|
sessions.remove(id);
|
||||||
if(lastActiveAccountID.equals(id)){
|
if(lastActiveAccountID.equals(id)){
|
||||||
|
|||||||
@@ -14,10 +14,12 @@ import android.view.WindowInsets;
|
|||||||
import android.widget.Toolbar;
|
import android.widget.Toolbar;
|
||||||
|
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||||
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
||||||
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
import org.joinmastodon.android.api.requests.statuses.TranslateStatus;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.events.PollUpdatedEvent;
|
import org.joinmastodon.android.events.PollUpdatedEvent;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||||
@@ -27,6 +29,8 @@ import org.joinmastodon.android.model.Status;
|
|||||||
import org.joinmastodon.android.model.Translation;
|
import org.joinmastodon.android.model.Translation;
|
||||||
import org.joinmastodon.android.ui.BetterItemAnimator;
|
import org.joinmastodon.android.ui.BetterItemAnimator;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
|
import org.joinmastodon.android.ui.NonMutualPreReplySheet;
|
||||||
|
import org.joinmastodon.android.ui.OldPostPreReplySheet;
|
||||||
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
||||||
@@ -43,6 +47,8 @@ import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
|
|||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.joinmastodon.android.utils.TypedObjectPool;
|
import org.joinmastodon.android.utils.TypedObjectPool;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -106,6 +112,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
for(T s:items){
|
for(T s:items){
|
||||||
displayItems.addAll(buildDisplayItems(s));
|
displayItems.addAll(buildDisplayItems(s));
|
||||||
}
|
}
|
||||||
|
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,6 +134,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
}
|
}
|
||||||
if(notify)
|
if(notify)
|
||||||
adapter.notifyItemRangeInserted(0, offset);
|
adapter.notifyItemRangeInserted(0, offset);
|
||||||
|
loadRelationships(items.stream().map(DisplayItemsParent::getAccountID).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getMaxID(){
|
protected String getMaxID(){
|
||||||
@@ -240,6 +248,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
@Override
|
@Override
|
||||||
public void photoViewerDismissed(){
|
public void photoViewerDismissed(){
|
||||||
currentPhotoViewer=null;
|
currentPhotoViewer=null;
|
||||||
|
gridHolder.itemView.setHasTransientState(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -251,6 +260,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
return gridHolder.getViewController(index);
|
return gridHolder.getViewController(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
gridHolder.itemView.setHasTransientState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -357,7 +367,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
|
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
|
||||||
int prevSize=pollItems.size();
|
int prevSize=pollItems.size();
|
||||||
pollItems.clear();
|
pollItems.clear();
|
||||||
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems);
|
StatusDisplayItem.buildPollItems(itemID, this, poll, status, pollItems);
|
||||||
if(prevSize!=pollItems.size()){
|
if(prevSize!=pollItems.size()){
|
||||||
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
|
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
|
||||||
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
|
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
|
||||||
@@ -455,6 +465,9 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void loadRelationships(Set<String> ids){
|
protected void loadRelationships(Set<String> ids){
|
||||||
|
if(ids.isEmpty())
|
||||||
|
return;
|
||||||
|
ids=ids.stream().filter(id->!relationships.containsKey(id)).collect(Collectors.toSet());
|
||||||
if(ids.isEmpty())
|
if(ids.isEmpty())
|
||||||
return;
|
return;
|
||||||
// TODO somehow manage these and cancel outstanding requests on refresh
|
// TODO somehow manage these and cancel outstanding requests on refresh
|
||||||
@@ -586,11 +599,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
return;
|
return;
|
||||||
status.translation=result;
|
status.translation=result;
|
||||||
status.translationState=Status.TranslationState.SHOWN;
|
status.translationState=Status.TranslationState.SHOWN;
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
updateTranslation(itemID);
|
||||||
if(text!=null){
|
|
||||||
text.updateTranslation(true);
|
|
||||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -598,10 +607,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
if(getActivity()==null)
|
if(getActivity()==null)
|
||||||
return;
|
return;
|
||||||
status.translationState=Status.TranslationState.HIDDEN;
|
status.translationState=Status.TranslationState.HIDDEN;
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
updateTranslation(itemID);
|
||||||
if(text!=null){
|
|
||||||
text.updateTranslation(true);
|
|
||||||
}
|
|
||||||
new M3AlertDialogBuilder(getActivity())
|
new M3AlertDialogBuilder(getActivity())
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(R.string.translation_failed)
|
.setMessage(R.string.translation_failed)
|
||||||
@@ -613,11 +619,31 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateTranslation(itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTranslation(String itemID) {
|
||||||
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
|
||||||
if(text!=null){
|
if(text!=null){
|
||||||
text.updateTranslation(true);
|
text.updateTranslation(true);
|
||||||
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
|
||||||
|
if(spoiler!=null){
|
||||||
|
spoiler.rebind();
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaGridStatusDisplayItem.Holder media=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
|
||||||
|
if (media!=null) {
|
||||||
|
media.rebind();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<list.getChildCount();i++){
|
||||||
|
if(list.getChildViewHolder(list.getChildAt(i)) instanceof PollOptionStatusDisplayItem.Holder item){
|
||||||
|
item.rebind();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rebuildAllDisplayItems(){
|
public void rebuildAllDisplayItems(){
|
||||||
@@ -628,6 +654,26 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
adapter.notifyDataSetChanged();
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void maybeShowPreReplySheet(Status status, Runnable proceed){
|
||||||
|
Relationship rel=getRelationship(status.account.id);
|
||||||
|
if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, status.account, accountID) &&
|
||||||
|
!status.account.id.equals(AccountSessionManager.get(accountID).self.id) && rel!=null && !rel.followedBy && status.account.followingCount>=1){
|
||||||
|
new NonMutualPreReplySheet(getActivity(), notAgain->{
|
||||||
|
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.NON_MUTUAL, notAgain ? null : status.account, accountID);
|
||||||
|
proceed.run();
|
||||||
|
}, status.account, accountID).show();
|
||||||
|
}else if(!GlobalUserPreferences.isOptedOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null) &&
|
||||||
|
status.createdAt.isBefore(Instant.now().minus(90, ChronoUnit.DAYS))){
|
||||||
|
new OldPostPreReplySheet(getActivity(), notAgain->{
|
||||||
|
if(notAgain)
|
||||||
|
GlobalUserPreferences.optOutOfPreReplySheet(GlobalUserPreferences.PreReplySheetType.OLD_POST, null, null);
|
||||||
|
proceed.run();
|
||||||
|
}, status).show();
|
||||||
|
}else{
|
||||||
|
proceed.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void onModifyItemViewHolder(BindableViewHolder<StatusDisplayItem> holder){}
|
protected void onModifyItemViewHolder(BindableViewHolder<StatusDisplayItem> holder){}
|
||||||
|
|
||||||
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
|
||||||
@@ -700,7 +746,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||||||
// Do not draw dividers between hashtag and/or account rows
|
// Do not draw dividers between hashtag and/or account rows
|
||||||
if((ih instanceof HashtagStatusDisplayItem.Holder || ih instanceof AccountStatusDisplayItem.Holder) && (sh instanceof HashtagStatusDisplayItem.Holder || sh instanceof AccountStatusDisplayItem.Holder))
|
if((ih instanceof HashtagStatusDisplayItem.Holder || ih instanceof AccountStatusDisplayItem.Holder) && (sh instanceof HashtagStatusDisplayItem.Holder || sh instanceof AccountStatusDisplayItem.Holder))
|
||||||
return false;
|
return false;
|
||||||
return (!ih.getItemID().equals(sh.getItemID()) || sh instanceof ExtendedFooterStatusDisplayItem.Holder) && ih.getItem().getType()!=StatusDisplayItem.Type.GAP;
|
return !ih.getItemID().equals(sh.getItemID()) && ih.getItem().getType()!=StatusDisplayItem.Type.GAP;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package org.joinmastodon.android.fragments;
|
package org.joinmastodon.android.fragments;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
@@ -90,12 +93,14 @@ import java.util.stream.Collectors;
|
|||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
|
import me.grishka.appkit.fragments.CustomTransitionsFragment;
|
||||||
import me.grishka.appkit.fragments.OnBackPressedListener;
|
import me.grishka.appkit.fragments.OnBackPressedListener;
|
||||||
import me.grishka.appkit.imageloader.ViewImageLoader;
|
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener{
|
public class ComposeFragment extends MastodonToolbarFragment implements OnBackPressedListener, ComposeEditText.SelectionListener, CustomTransitionsFragment{
|
||||||
|
|
||||||
private static final int MEDIA_RESULT=717;
|
private static final int MEDIA_RESULT=717;
|
||||||
public static final int IMAGE_DESCRIPTION_RESULT=363;
|
public static final int IMAGE_DESCRIPTION_RESULT=363;
|
||||||
@@ -1012,8 +1017,26 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||||||
return new String[]{"image/jpeg", "image/gif", "image/png", "video/mp4"};
|
return new String[]{"image/jpeg", "image/gif", "image/png", "video/mp4"};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String sanitizeMediaDescription(String description){
|
||||||
|
if(description == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Gboard android keyboard attaches this text whenever the user
|
||||||
|
// pastes something from the keyboard's suggestion bar.
|
||||||
|
// Due to different end user locales, the exact text may vary, but at
|
||||||
|
// least in version 13.4.08, all of the translations contained the
|
||||||
|
// string "Gboard".
|
||||||
|
if (description.contains("Gboard")){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onAddMediaAttachmentFromEditText(Uri uri, String description){
|
public boolean onAddMediaAttachmentFromEditText(Uri uri, String description){
|
||||||
|
description = sanitizeMediaDescription(description);
|
||||||
return mediaViewController.addMediaAttachment(uri, description);
|
return mediaViewController.addMediaAttachment(uri, description);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1106,4 +1129,35 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||||||
private void setPostLanguage(ComposeLanguageAlertViewController.SelectedOption language){
|
private void setPostLanguage(ComposeLanguageAlertViewController.SelectedOption language){
|
||||||
postLang=language;
|
postLang=language;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Animator onCreateEnterTransition(View prev, View container){
|
||||||
|
AnimatorSet anim=new AnimatorSet();
|
||||||
|
if(getArguments().getBoolean("fromThreadFragment")){
|
||||||
|
anim.playTogether(
|
||||||
|
ObjectAnimator.ofFloat(container, View.ALPHA, 0f, 1f),
|
||||||
|
ObjectAnimator.ofFloat(container, View.TRANSLATION_Y, V.dp(200), 0)
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
anim.playTogether(
|
||||||
|
ObjectAnimator.ofFloat(container, View.ALPHA, 0f, 1f),
|
||||||
|
ObjectAnimator.ofFloat(container, View.TRANSLATION_X, V.dp(100), 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
anim.setDuration(300);
|
||||||
|
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
return anim;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Animator onCreateExitTransition(View prev, View container){
|
||||||
|
AnimatorSet anim=new AnimatorSet();
|
||||||
|
anim.playTogether(
|
||||||
|
ObjectAnimator.ofFloat(container, View.TRANSLATION_X, V.dp(100)),
|
||||||
|
ObjectAnimator.ofFloat(container, View.ALPHA, 0)
|
||||||
|
);
|
||||||
|
anim.setDuration(200);
|
||||||
|
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
return anim;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import org.joinmastodon.android.model.Status;
|
|||||||
import org.joinmastodon.android.model.TimelineMarkers;
|
import org.joinmastodon.android.model.TimelineMarkers;
|
||||||
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||||
|
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
|
||||||
import org.joinmastodon.android.ui.viewcontrollers.HomeTimelineMenuController;
|
import org.joinmastodon.android.ui.viewcontrollers.HomeTimelineMenuController;
|
||||||
import org.joinmastodon.android.ui.viewcontrollers.ToolbarDropdownMenuController;
|
import org.joinmastodon.android.ui.viewcontrollers.ToolbarDropdownMenuController;
|
||||||
import org.joinmastodon.android.ui.views.FixedAspectRatioImageView;
|
import org.joinmastodon.android.ui.views.FixedAspectRatioImageView;
|
||||||
@@ -61,6 +62,7 @@ import me.grishka.appkit.api.Callback;
|
|||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
import me.grishka.appkit.api.SimpleCallback;
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class HomeTimelineFragment extends StatusListFragment implements ToolbarDropdownMenuController.HostFragment{
|
public class HomeTimelineFragment extends StatusListFragment implements ToolbarDropdownMenuController.HostFragment{
|
||||||
@@ -77,6 +79,8 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD
|
|||||||
private List<FollowList> lists=List.of();
|
private List<FollowList> lists=List.of();
|
||||||
private ListMode listMode=ListMode.FOLLOWING;
|
private ListMode listMode=ListMode.FOLLOWING;
|
||||||
private FollowList currentList;
|
private FollowList currentList;
|
||||||
|
private MergeRecyclerAdapter mergeAdapter;
|
||||||
|
private DiscoverInfoBannerHelper localTimelineBannerHelper;
|
||||||
|
|
||||||
private String maxID;
|
private String maxID;
|
||||||
private String lastSavedMarkerID;
|
private String lastSavedMarkerID;
|
||||||
@@ -85,6 +89,12 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD
|
|||||||
setListLayoutId(R.layout.fragment_timeline);
|
setListLayoutId(R.layout.fragment_timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState){
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
localTimelineBannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.LOCAL_TIMELINE, accountID);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(Activity activity){
|
public void onAttach(Activity activity){
|
||||||
super.onAttach(activity);
|
super.onAttach(activity);
|
||||||
@@ -167,6 +177,7 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD
|
|||||||
public void onSuccess(List<Status> result){
|
public void onSuccess(List<Status> result){
|
||||||
if(refreshing)
|
if(refreshing)
|
||||||
list.scrollToPosition(0);
|
list.scrollToPosition(0);
|
||||||
|
maxID=result.isEmpty() ? null : result.get(result.size()-1).id;
|
||||||
onDataLoaded(result, !result.isEmpty());
|
onDataLoaded(result, !result.isEmpty());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -179,6 +190,7 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD
|
|||||||
public void onSuccess(List<Status> result){
|
public void onSuccess(List<Status> result){
|
||||||
if(refreshing)
|
if(refreshing)
|
||||||
list.scrollToPosition(0);
|
list.scrollToPosition(0);
|
||||||
|
maxID=result.isEmpty() ? null : result.get(result.size()-1).id;
|
||||||
onDataLoaded(result, !result.isEmpty());
|
onDataLoaded(result, !result.isEmpty());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -619,6 +631,26 @@ public class HomeTimelineFragment extends StatusListFragment implements ToolbarD
|
|||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RecyclerView.Adapter getAdapter(){
|
||||||
|
mergeAdapter=new MergeRecyclerAdapter();
|
||||||
|
mergeAdapter.addAdapter(super.getAdapter());
|
||||||
|
return mergeAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDataLoaded(List<Status> d, boolean more){
|
||||||
|
if(refreshing){
|
||||||
|
if(listMode==ListMode.LOCAL){
|
||||||
|
localTimelineBannerHelper.maybeAddBanner(list, mergeAdapter);
|
||||||
|
localTimelineBannerHelper.onBannerBecameVisible();
|
||||||
|
}else{
|
||||||
|
localTimelineBannerHelper.removeBanner(mergeAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onDataLoaded(d, more);
|
||||||
|
}
|
||||||
|
|
||||||
private String getCurrentListTitle(){
|
private String getCurrentListTitle(){
|
||||||
return switch(listMode){
|
return switch(listMode){
|
||||||
case FOLLOWING -> getString(R.string.timeline_following);
|
case FOLLOWING -> getString(R.string.timeline_following);
|
||||||
|
|||||||
@@ -314,6 +314,8 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void markAsRead(){
|
private void markAsRead(){
|
||||||
|
if(data.isEmpty())
|
||||||
|
return;
|
||||||
String id=data.get(0).id;
|
String id=data.get(0).id;
|
||||||
if(ObjectIdComparator.INSTANCE.compare(id, realUnreadMarker)>0){
|
if(ObjectIdComparator.INSTANCE.compare(id, realUnreadMarker)>0){
|
||||||
new SaveMarkers(null, id).exec(accountID);
|
new SaveMarkers(null, id).exec(accountID);
|
||||||
|
|||||||
@@ -516,7 +516,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||||||
// noinspection SetTextI18n
|
// noinspection SetTextI18n
|
||||||
username.setText('@'+account.acct+(isSelf ? ('@'+AccountSessionManager.getInstance().getAccount(accountID).domain) : ""));
|
username.setText('@'+account.acct+(isSelf ? ('@'+AccountSessionManager.getInstance().getAccount(accountID).domain) : ""));
|
||||||
}
|
}
|
||||||
CharSequence parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
CharSequence parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
|
||||||
if(TextUtils.isEmpty(parsedBio)){
|
if(TextUtils.isEmpty(parsedBio)){
|
||||||
bio.setVisibility(View.GONE);
|
bio.setVisibility(View.GONE);
|
||||||
}else{
|
}else{
|
||||||
@@ -551,7 +551,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||||||
fields.add(joined);
|
fields.add(joined);
|
||||||
|
|
||||||
for(AccountField field:account.fields){
|
for(AccountField field:account.fields){
|
||||||
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
|
||||||
field.valueEmojis=ssb.getSpans(0, ssb.length(), CustomEmojiSpan.class);
|
field.valueEmojis=ssb.getSpans(0, ssb.length(), CustomEmojiSpan.class);
|
||||||
ssb=new SpannableStringBuilder(field.name);
|
ssb=new SpannableStringBuilder(field.name);
|
||||||
HtmlParser.parseCustomEmoji(ssb, account.emojis);
|
HtmlParser.parseCustomEmoji(ssb, account.emojis);
|
||||||
|
|||||||
@@ -2,19 +2,24 @@ package org.joinmastodon.android.fragments;
|
|||||||
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowInsets;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.statuses.GetStatusContext;
|
import org.joinmastodon.android.api.requests.statuses.GetStatusContext;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.events.StatusCreatedEvent;
|
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.FilterContext;
|
import org.joinmastodon.android.model.FilterContext;
|
||||||
import org.joinmastodon.android.model.LegacyFilter;
|
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.model.StatusContext;
|
import org.joinmastodon.android.model.StatusContext;
|
||||||
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
||||||
import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem;
|
import org.joinmastodon.android.ui.displayitems.SpoilerStatusDisplayItem;
|
||||||
@@ -26,10 +31,12 @@ import org.parceler.Parcels;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.api.SimpleCallback;
|
import me.grishka.appkit.api.SimpleCallback;
|
||||||
|
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||||
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
@@ -37,10 +44,16 @@ import me.grishka.appkit.utils.V;
|
|||||||
public class ThreadFragment extends StatusListFragment{
|
public class ThreadFragment extends StatusListFragment{
|
||||||
private Status mainStatus;
|
private Status mainStatus;
|
||||||
private ImageView endMark;
|
private ImageView endMark;
|
||||||
|
private FrameLayout replyContainer;
|
||||||
|
private LinearLayout replyButton;
|
||||||
|
private ImageView replyButtonAva;
|
||||||
|
private TextView replyButtonText;
|
||||||
|
private int lastBottomInset;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
setLayout(R.layout.fragment_thread);
|
||||||
mainStatus=Parcels.unwrap(getArguments().getParcelable("status"));
|
mainStatus=Parcels.unwrap(getArguments().getParcelable("status"));
|
||||||
Account inReplyToAccount=Parcels.unwrap(getArguments().getParcelable("inReplyToAccount"));
|
Account inReplyToAccount=Parcels.unwrap(getArguments().getParcelable("inReplyToAccount"));
|
||||||
if(inReplyToAccount!=null)
|
if(inReplyToAccount!=null)
|
||||||
@@ -69,7 +82,7 @@ public class ThreadFragment extends StatusListFragment{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
items.add(new ExtendedFooterStatusDisplayItem(s.id, this, s.getContentStatus()));
|
items.add(items.size()-1, new ExtendedFooterStatusDisplayItem(s.id, this, s.getContentStatus()));
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
@@ -126,6 +139,20 @@ public class ThreadFragment extends StatusListFragment{
|
|||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState){
|
public void onViewCreated(View view, Bundle savedInstanceState){
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
replyContainer=view.findViewById(R.id.reply_button_wrapper);
|
||||||
|
replyButton=replyContainer.findViewById(R.id.reply_button);
|
||||||
|
replyButtonText=replyButton.findViewById(R.id.reply_btn_text);
|
||||||
|
replyButtonAva=replyButton.findViewById(R.id.avatar);
|
||||||
|
replyButton.setOutlineProvider(OutlineProviders.roundedRect(20));
|
||||||
|
replyButton.setClipToOutline(true);
|
||||||
|
replyButtonText.setText(getString(R.string.reply_to_user, mainStatus.account.displayName));
|
||||||
|
replyButtonAva.setOutlineProvider(OutlineProviders.OVAL);
|
||||||
|
replyButtonAva.setClipToOutline(true);
|
||||||
|
replyButton.setOnClickListener(v->openReply());
|
||||||
|
Account self=AccountSessionManager.get(accountID).self;
|
||||||
|
if(!TextUtils.isEmpty(self.avatar)){
|
||||||
|
ViewImageLoader.loadWithoutAnimation(replyButtonAva, getResources().getDrawable(R.drawable.image_placeholder), new UrlImageLoaderRequest(self.avatar, V.dp(24), V.dp(24)));
|
||||||
|
}
|
||||||
UiUtils.loadCustomEmojiInTextView(toolbarTitleView);
|
UiUtils.loadCustomEmojiInTextView(toolbarTitleView);
|
||||||
showContent();
|
showContent();
|
||||||
if(!loaded)
|
if(!loaded)
|
||||||
@@ -175,4 +202,24 @@ public class ThreadFragment extends StatusListFragment{
|
|||||||
}
|
}
|
||||||
super.onErrorRetryClick();
|
super.onErrorRetryClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplyWindowInsets(WindowInsets insets){
|
||||||
|
lastBottomInset=insets.getSystemWindowInsetBottom();
|
||||||
|
super.onApplyWindowInsets(UiUtils.applyBottomInsetToFixedView(replyContainer, insets));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openReply(){
|
||||||
|
maybeShowPreReplySheet(mainStatus, ()->{
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
args.putParcelable("replyTo", Parcels.wrap(mainStatus));
|
||||||
|
args.putBoolean("fromThreadFragment", true);
|
||||||
|
Nav.go(getActivity(), ComposeFragment.class, args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSnackbarOffset(){
|
||||||
|
return replyContainer.getHeight()-lastBottomInset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||||||
private DiscoverNewsFragment newsFragment;
|
private DiscoverNewsFragment newsFragment;
|
||||||
private DiscoverAccountsFragment accountsFragment;
|
private DiscoverAccountsFragment accountsFragment;
|
||||||
private SearchFragment searchFragment;
|
private SearchFragment searchFragment;
|
||||||
private LocalTimelineFragment localTimelineFragment;
|
|
||||||
|
|
||||||
private String accountID;
|
private String accountID;
|
||||||
private String currentQuery;
|
private String currentQuery;
|
||||||
@@ -71,15 +70,14 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||||||
tabLayout=view.findViewById(R.id.tabbar);
|
tabLayout=view.findViewById(R.id.tabbar);
|
||||||
pager=view.findViewById(R.id.pager);
|
pager=view.findViewById(R.id.pager);
|
||||||
|
|
||||||
tabViews=new FrameLayout[5];
|
tabViews=new FrameLayout[4];
|
||||||
for(int i=0;i<tabViews.length;i++){
|
for(int i=0;i<tabViews.length;i++){
|
||||||
FrameLayout tabView=new FrameLayout(getActivity());
|
FrameLayout tabView=new FrameLayout(getActivity());
|
||||||
tabView.setId(switch(i){
|
tabView.setId(switch(i){
|
||||||
case 0 -> R.id.discover_posts;
|
case 0 -> R.id.discover_posts;
|
||||||
case 1 -> R.id.discover_hashtags;
|
case 1 -> R.id.discover_hashtags;
|
||||||
case 2 -> R.id.discover_news;
|
case 2 -> R.id.discover_news;
|
||||||
case 3 -> R.id.discover_local_timeline;
|
case 3 -> R.id.discover_users;
|
||||||
case 4 -> R.id.discover_users;
|
|
||||||
default -> throw new IllegalStateException("Unexpected value: "+i);
|
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||||
});
|
});
|
||||||
tabView.setVisibility(View.GONE);
|
tabView.setVisibility(View.GONE);
|
||||||
@@ -122,12 +120,8 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||||||
accountsFragment=new DiscoverAccountsFragment();
|
accountsFragment=new DiscoverAccountsFragment();
|
||||||
accountsFragment.setArguments(args);
|
accountsFragment.setArguments(args);
|
||||||
|
|
||||||
localTimelineFragment=new LocalTimelineFragment();
|
|
||||||
localTimelineFragment.setArguments(args);
|
|
||||||
|
|
||||||
getChildFragmentManager().beginTransaction()
|
getChildFragmentManager().beginTransaction()
|
||||||
.add(R.id.discover_posts, postsFragment)
|
.add(R.id.discover_posts, postsFragment)
|
||||||
.add(R.id.discover_local_timeline, localTimelineFragment)
|
|
||||||
.add(R.id.discover_hashtags, hashtagsFragment)
|
.add(R.id.discover_hashtags, hashtagsFragment)
|
||||||
.add(R.id.discover_news, newsFragment)
|
.add(R.id.discover_news, newsFragment)
|
||||||
.add(R.id.discover_users, accountsFragment)
|
.add(R.id.discover_users, accountsFragment)
|
||||||
@@ -141,8 +135,7 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||||||
case 0 -> R.string.posts;
|
case 0 -> R.string.posts;
|
||||||
case 1 -> R.string.hashtags;
|
case 1 -> R.string.hashtags;
|
||||||
case 2 -> R.string.news;
|
case 2 -> R.string.news;
|
||||||
case 3 -> R.string.local_timeline;
|
case 3 -> R.string.for_you;
|
||||||
case 4 -> R.string.for_you;
|
|
||||||
default -> throw new IllegalStateException("Unexpected value: "+position);
|
default -> throw new IllegalStateException("Unexpected value: "+position);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -245,8 +238,7 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
|||||||
case 0 -> postsFragment;
|
case 0 -> postsFragment;
|
||||||
case 1 -> hashtagsFragment;
|
case 1 -> hashtagsFragment;
|
||||||
case 2 -> newsFragment;
|
case 2 -> newsFragment;
|
||||||
case 3 -> localTimelineFragment;
|
case 3 -> accountsFragment;
|
||||||
case 4 -> accountsFragment;
|
|
||||||
default -> throw new IllegalStateException("Unexpected value: "+page);
|
default -> throw new IllegalStateException("Unexpected value: "+page);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package org.joinmastodon.android.fragments.discover;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import org.joinmastodon.android.api.requests.timelines.GetPublicTimeline;
|
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
|
||||||
import org.joinmastodon.android.fragments.StatusListFragment;
|
|
||||||
import org.joinmastodon.android.model.FilterContext;
|
|
||||||
import org.joinmastodon.android.model.Status;
|
|
||||||
import org.joinmastodon.android.ui.utils.DiscoverInfoBannerHelper;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import me.grishka.appkit.api.SimpleCallback;
|
|
||||||
import me.grishka.appkit.utils.MergeRecyclerAdapter;
|
|
||||||
|
|
||||||
public class LocalTimelineFragment extends StatusListFragment{
|
|
||||||
private DiscoverInfoBannerHelper bannerHelper;
|
|
||||||
|
|
||||||
private String maxID;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState){
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
bannerHelper=new DiscoverInfoBannerHelper(DiscoverInfoBannerHelper.BannerType.LOCAL_TIMELINE, accountID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doLoadData(int offset, int count){
|
|
||||||
currentRequest=new GetPublicTimeline(true, false, refreshing ? null : maxID, null, count, null)
|
|
||||||
.setCallback(new SimpleCallback<>(this){
|
|
||||||
@Override
|
|
||||||
public void onSuccess(List<Status> result){
|
|
||||||
if(!result.isEmpty())
|
|
||||||
maxID=result.get(result.size()-1).id;
|
|
||||||
boolean empty=result.isEmpty();
|
|
||||||
AccountSessionManager.get(accountID).filterStatuses(result, FilterContext.PUBLIC);
|
|
||||||
onDataLoaded(result, !empty);
|
|
||||||
bannerHelper.onBannerBecameVisible();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.exec(accountID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RecyclerView.Adapter getAdapter(){
|
|
||||||
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
|
|
||||||
bannerHelper.maybeAddBanner(list, adapter);
|
|
||||||
adapter.addAdapter(super.getAdapter());
|
|
||||||
return adapter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -381,63 +381,6 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
|
|||||||
onNextClick(v);
|
onNextClick(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
@Override
|
||||||
protected void updateFilteredList(){
|
protected void updateFilteredList(){
|
||||||
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
ArrayList<CatalogInstance> prevData=new ArrayList<>(filteredData);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.view.WindowInsets;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
|
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
@@ -20,12 +21,17 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
|||||||
import org.joinmastodon.android.fragments.HomeFragment;
|
import org.joinmastodon.android.fragments.HomeFragment;
|
||||||
import org.joinmastodon.android.model.Account;
|
import org.joinmastodon.android.model.Account;
|
||||||
import org.joinmastodon.android.model.AccountField;
|
import org.joinmastodon.android.model.AccountField;
|
||||||
|
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
||||||
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.OutlineProviders;
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
|
import org.joinmastodon.android.ui.adapters.GenericListItemsAdapter;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
import org.joinmastodon.android.ui.viewholders.ListItemViewHolder;
|
||||||
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
|
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
|
||||||
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
import org.joinmastodon.android.utils.ElevationOnScrollListener;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
@@ -36,7 +42,7 @@ import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
|||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
|
|
||||||
public class OnboardingProfileSetupFragment extends ToolbarFragment implements ReorderableLinearLayout.OnDragListener{
|
public class OnboardingProfileSetupFragment extends ToolbarFragment{
|
||||||
private Button btn;
|
private Button btn;
|
||||||
private View buttonBar;
|
private View buttonBar;
|
||||||
private String accountID;
|
private String accountID;
|
||||||
@@ -44,9 +50,9 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
private ScrollView scroller;
|
private ScrollView scroller;
|
||||||
private EditText nameEdit, bioEdit;
|
private EditText nameEdit, bioEdit;
|
||||||
private ImageView avaImage, coverImage;
|
private ImageView avaImage, coverImage;
|
||||||
private Button addRow;
|
|
||||||
private ReorderableLinearLayout profileFieldsLayout;
|
|
||||||
private Uri avatarUri, coverUri;
|
private Uri avatarUri, coverUri;
|
||||||
|
private LinearLayout scrollContent;
|
||||||
|
private CheckableListItem<Void> discoverableItem;
|
||||||
|
|
||||||
private static final int AVATAR_RESULT=348;
|
private static final int AVATAR_RESULT=348;
|
||||||
private static final int COVER_RESULT=183;
|
private static final int COVER_RESULT=183;
|
||||||
@@ -74,8 +80,6 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
bioEdit=view.findViewById(R.id.bio);
|
bioEdit=view.findViewById(R.id.bio);
|
||||||
avaImage=view.findViewById(R.id.avatar);
|
avaImage=view.findViewById(R.id.avatar);
|
||||||
coverImage=view.findViewById(R.id.header);
|
coverImage=view.findViewById(R.id.header);
|
||||||
addRow=view.findViewById(R.id.add_row);
|
|
||||||
profileFieldsLayout=view.findViewById(R.id.profile_fields);
|
|
||||||
|
|
||||||
btn=view.findViewById(R.id.btn_next);
|
btn=view.findViewById(R.id.btn_next);
|
||||||
btn.setOnClickListener(v->onButtonClick());
|
btn.setOnClickListener(v->onButtonClick());
|
||||||
@@ -87,31 +91,20 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
Account account=AccountSessionManager.getInstance().getAccount(accountID).self;
|
Account account=AccountSessionManager.getInstance().getAccount(accountID).self;
|
||||||
if(savedInstanceState==null){
|
if(savedInstanceState==null){
|
||||||
nameEdit.setText(account.displayName);
|
nameEdit.setText(account.displayName);
|
||||||
makeFieldsRow();
|
|
||||||
}else{
|
|
||||||
ArrayList<String> fieldTitles=savedInstanceState.getStringArrayList("fieldTitles");
|
|
||||||
ArrayList<String> fieldValues=savedInstanceState.getStringArrayList("fieldValues");
|
|
||||||
for(int i=0;i<fieldTitles.size();i++){
|
|
||||||
View row=makeFieldsRow();
|
|
||||||
EditText title=row.findViewById(R.id.title);
|
|
||||||
EditText content=row.findViewById(R.id.content);
|
|
||||||
title.setText(fieldTitles.get(i));
|
|
||||||
content.setText(fieldValues.get(i));
|
|
||||||
}
|
|
||||||
if(fieldTitles.size()==4)
|
|
||||||
addRow.setVisibility(View.GONE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addRow.setOnClickListener(v->{
|
|
||||||
makeFieldsRow();
|
|
||||||
if(profileFieldsLayout.getChildCount()==4){
|
|
||||||
addRow.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
profileFieldsLayout.setDragListener(this);
|
|
||||||
avaImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), AVATAR_RESULT));
|
avaImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), AVATAR_RESULT));
|
||||||
coverImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), COVER_RESULT));
|
coverImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), COVER_RESULT));
|
||||||
|
|
||||||
|
scrollContent=view.findViewById(R.id.scrollable_content);
|
||||||
|
discoverableItem=new CheckableListItem<>(R.string.make_profile_discoverable, 0, CheckableListItem.Style.SWITCH_SEPARATED, true, R.drawable.ic_campaign_24px, item->showDiscoverabilityAlert());
|
||||||
|
GenericListItemsAdapter<Void> fakeAdapter=new GenericListItemsAdapter<>(List.of(discoverableItem));
|
||||||
|
ListItemViewHolder<?> holder=fakeAdapter.onCreateViewHolder(scrollContent, fakeAdapter.getItemViewType(0));
|
||||||
|
fakeAdapter.bindViewHolder(holder, 0);
|
||||||
|
holder.itemView.setBackground(UiUtils.getThemeDrawable(getActivity(), android.R.attr.selectableItemBackground));
|
||||||
|
holder.itemView.setOnClickListener(v->holder.onClick());
|
||||||
|
scrollContent.addView(holder.itemView);
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,17 +123,8 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void onButtonClick(){
|
protected void onButtonClick(){
|
||||||
ArrayList<AccountField> fields=new ArrayList<>();
|
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, null)
|
||||||
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
|
.setDiscoverableIndexable(discoverableItem.checked, discoverableItem.checked)
|
||||||
View row=profileFieldsLayout.getChildAt(i);
|
|
||||||
EditText title=row.findViewById(R.id.title);
|
|
||||||
EditText content=row.findViewById(R.id.content);
|
|
||||||
AccountField fld=new AccountField();
|
|
||||||
fld.name=title.getText().toString();
|
|
||||||
fld.value=content.getText().toString();
|
|
||||||
fields.add(fld);
|
|
||||||
}
|
|
||||||
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, fields)
|
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Account result){
|
public void onSuccess(Account result){
|
||||||
@@ -164,39 +148,6 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
super.onApplyWindowInsets(UiUtils.applyBottomInsetToFixedView(buttonBar, insets));
|
super.onApplyWindowInsets(UiUtils.applyBottomInsetToFixedView(buttonBar, insets));
|
||||||
}
|
}
|
||||||
|
|
||||||
private View makeFieldsRow(){
|
|
||||||
View view=LayoutInflater.from(getActivity()).inflate(R.layout.onboarding_profile_field, profileFieldsLayout, false);
|
|
||||||
profileFieldsLayout.addView(view);
|
|
||||||
view.findViewById(R.id.dragger_thingy).setOnLongClickListener(v->{
|
|
||||||
profileFieldsLayout.startDragging(view);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
view.findViewById(R.id.delete).setOnClickListener(v->{
|
|
||||||
profileFieldsLayout.removeView(view);
|
|
||||||
if(addRow.getVisibility()==View.GONE)
|
|
||||||
addRow.setVisibility(View.VISIBLE);
|
|
||||||
});
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSwapItems(int oldIndex, int newIndex){}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(Bundle outState){
|
|
||||||
super.onSaveInstanceState(outState);
|
|
||||||
ArrayList<String> fieldTitles=new ArrayList<>(), fieldValues=new ArrayList<>();
|
|
||||||
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
|
|
||||||
View row=profileFieldsLayout.getChildAt(i);
|
|
||||||
EditText title=row.findViewById(R.id.title);
|
|
||||||
EditText content=row.findViewById(R.id.content);
|
|
||||||
fieldTitles.add(title.getText().toString());
|
|
||||||
fieldValues.add(content.getText().toString());
|
|
||||||
}
|
|
||||||
outState.putStringArrayList("fieldTitles", fieldTitles);
|
|
||||||
outState.putStringArrayList("fieldValues", fieldValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data){
|
public void onActivityResult(int requestCode, int resultCode, Intent data){
|
||||||
if(resultCode!=Activity.RESULT_OK)
|
if(resultCode!=Activity.RESULT_OK)
|
||||||
@@ -216,4 +167,12 @@ public class OnboardingProfileSetupFragment extends ToolbarFragment implements R
|
|||||||
img.setForeground(null);
|
img.setForeground(null);
|
||||||
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
|
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showDiscoverabilityAlert(){
|
||||||
|
new M3AlertDialogBuilder(getActivity())
|
||||||
|
.setTitle(R.string.discoverability)
|
||||||
|
.setMessage(R.string.discoverability_help)
|
||||||
|
.setPositiveButton(R.string.ok, null)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
package org.joinmastodon.android.fragments.onboarding;
|
package org.joinmastodon.android.fragments.onboarding;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.graphics.Typeface;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.LocaleList;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.Html;
|
|
||||||
import android.text.SpannableString;
|
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.text.style.TypefaceSpan;
|
import android.text.style.TypefaceSpan;
|
||||||
import android.text.style.URLSpan;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -46,10 +43,13 @@ import org.jsoup.select.NodeVisitor;
|
|||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -58,7 +58,6 @@ import me.grishka.appkit.api.APIRequest;
|
|||||||
import me.grishka.appkit.api.Callback;
|
import me.grishka.appkit.api.Callback;
|
||||||
import me.grishka.appkit.api.ErrorResponse;
|
import me.grishka.appkit.api.ErrorResponse;
|
||||||
import me.grishka.appkit.fragments.ToolbarFragment;
|
import me.grishka.appkit.fragments.ToolbarFragment;
|
||||||
import me.grishka.appkit.utils.V;
|
|
||||||
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
import me.grishka.appkit.views.FragmentRootLinearLayout;
|
||||||
|
|
||||||
public class SignupFragment extends ToolbarFragment{
|
public class SignupFragment extends ToolbarFragment{
|
||||||
@@ -79,6 +78,7 @@ public class SignupFragment extends ToolbarFragment{
|
|||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private HashSet<EditText> errorFields=new HashSet<>();
|
private HashSet<EditText> errorFields=new HashSet<>();
|
||||||
private ElevationOnScrollListener onScrollListener;
|
private ElevationOnScrollListener onScrollListener;
|
||||||
|
private Set<String> serverSupportedTimezones, serverSupportedLocales;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
@@ -87,6 +87,8 @@ public class SignupFragment extends ToolbarFragment{
|
|||||||
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
|
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
|
||||||
createAppAndGetToken();
|
createAppAndGetToken();
|
||||||
setTitle(R.string.signup_title);
|
setTitle(R.string.signup_title);
|
||||||
|
serverSupportedTimezones=Arrays.stream(getResources().getStringArray(R.array.server_supported_timezones)).collect(Collectors.toSet());
|
||||||
|
serverSupportedLocales=Arrays.stream(getResources().getStringArray(R.array.server_supported_locales)).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -190,7 +192,34 @@ public class SignupFragment extends ToolbarFragment{
|
|||||||
edit.setError(null);
|
edit.setError(null);
|
||||||
}
|
}
|
||||||
errorFields.clear();
|
errorFields.clear();
|
||||||
new RegisterAccount(username, email, password.getText().toString(), getResources().getConfiguration().locale.getLanguage(), reason.getText().toString(), ZoneId.systemDefault().getId())
|
String locale=null;
|
||||||
|
String timezone=ZoneId.systemDefault().getId();
|
||||||
|
|
||||||
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
|
||||||
|
LocaleList localeList=getResources().getConfiguration().getLocales();
|
||||||
|
for(int i=0;i<localeList.size();i++){
|
||||||
|
Locale l=localeList.get(i);
|
||||||
|
if(serverSupportedLocales.contains(l.toLanguageTag())){
|
||||||
|
locale=l.toLanguageTag();
|
||||||
|
break;
|
||||||
|
}else if(serverSupportedLocales.contains(l.getLanguage())){
|
||||||
|
locale=l.getLanguage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Locale l=getResources().getConfiguration().locale;
|
||||||
|
if(serverSupportedLocales.contains(l.toLanguageTag())){
|
||||||
|
locale=l.toLanguageTag();
|
||||||
|
}else if(serverSupportedLocales.contains(l.getLanguage())){
|
||||||
|
locale=l.getLanguage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!serverSupportedTimezones.contains(timezone))
|
||||||
|
timezone=null;
|
||||||
|
|
||||||
|
new RegisterAccount(username, email, password.getText().toString(), locale, reason.getText().toString(), timezone)
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Token result){
|
public void onSuccess(Token result){
|
||||||
@@ -271,7 +300,7 @@ public class SignupFragment extends ToolbarFragment{
|
|||||||
@Override
|
@Override
|
||||||
public void tail(Node node, int depth){
|
public void tail(Node node, int depth){
|
||||||
if(node instanceof Element){
|
if(node instanceof Element){
|
||||||
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null, null, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package org.joinmastodon.android.fragments.settings;
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.ClipData;
|
||||||
|
import android.content.ClipboardManager;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -13,6 +16,7 @@ import org.joinmastodon.android.api.MastodonAPIController;
|
|||||||
import org.joinmastodon.android.api.session.AccountSession;
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
import org.joinmastodon.android.model.viewmodel.ListItem;
|
import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||||
|
import org.joinmastodon.android.ui.Snackbar;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -57,6 +61,14 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
|
|||||||
versionInfo.setTextColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Outline));
|
versionInfo.setTextColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Outline));
|
||||||
versionInfo.setGravity(Gravity.CENTER);
|
versionInfo.setGravity(Gravity.CENTER);
|
||||||
versionInfo.setText(getString(R.string.settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
|
versionInfo.setText(getString(R.string.settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE));
|
||||||
|
versionInfo.setOnClickListener(v->{
|
||||||
|
getActivity().getSystemService(ClipboardManager.class).setPrimaryClip(ClipData.newPlainText("", BuildConfig.VERSION_NAME+" ("+BuildConfig.VERSION_CODE+")"));
|
||||||
|
if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.S_V2){
|
||||||
|
new Snackbar.Builder(getActivity())
|
||||||
|
.setText(R.string.app_version_copied)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
adapter.addAdapter(new SingleViewRecyclerAdapter(versionInfo));
|
adapter.addAdapter(new SingleViewRecyclerAdapter(versionInfo));
|
||||||
|
|
||||||
return adapter;
|
return adapter;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package org.joinmastodon.android.fragments.settings;
|
package org.joinmastodon.android.fragments.settings;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.joinmastodon.android.MastodonApp;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
import org.joinmastodon.android.api.session.AccountActivationInfo;
|
||||||
import org.joinmastodon.android.api.session.AccountSession;
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
@@ -28,7 +27,8 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
|||||||
new ListItem<>("Test email confirmation flow", null, this::onTestEmailConfirmClick),
|
new ListItem<>("Test email confirmation flow", null, this::onTestEmailConfirmClick),
|
||||||
selfUpdateItem=new ListItem<>("Force self-update", null, this::onForceSelfUpdateClick),
|
selfUpdateItem=new ListItem<>("Force self-update", null, this::onForceSelfUpdateClick),
|
||||||
resetUpdateItem=new ListItem<>("Reset self-updater", null, this::onResetUpdaterClick),
|
resetUpdateItem=new ListItem<>("Reset self-updater", null, this::onResetUpdaterClick),
|
||||||
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick)
|
new ListItem<>("Reset search info banners", null, this::onResetDiscoverBannersClick),
|
||||||
|
new ListItem<>("Reset pre-reply sheets", null, this::onResetPreReplySheetsClick)
|
||||||
));
|
));
|
||||||
if(!GithubSelfUpdater.needSelfUpdating()){
|
if(!GithubSelfUpdater.needSelfUpdating()){
|
||||||
resetUpdateItem.isEnabled=selfUpdateItem.isEnabled=false;
|
resetUpdateItem.isEnabled=selfUpdateItem.isEnabled=false;
|
||||||
@@ -65,6 +65,11 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
|||||||
restartUI();
|
restartUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onResetPreReplySheetsClick(ListItem<?> item){
|
||||||
|
GlobalUserPreferences.resetPreReplySheets();
|
||||||
|
Toast.makeText(getActivity(), "Pre-reply sheets were reset", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
private void restartUI(){
|
private void restartUI(){
|
||||||
Bundle args=new Bundle();
|
Bundle args=new Bundle();
|
||||||
args.putString("account", accountID);
|
args.putString("account", accountID);
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onManageAccountsClick(ListItem<?> item){
|
private void onManageAccountsClick(ListItem<?> item){
|
||||||
new AccountSwitcherSheet(getActivity(), null).show();
|
new AccountSwitcherSheet(getActivity(), null).setOnLoggedOutCallback(()->loggedOut=true).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLogOutClick(ListItem<?> item_){
|
private void onLogOutClick(ListItem<?> item_){
|
||||||
|
|||||||
@@ -5,4 +5,8 @@ package org.joinmastodon.android.model;
|
|||||||
*/
|
*/
|
||||||
public interface DisplayItemsParent{
|
public interface DisplayItemsParent{
|
||||||
String getID();
|
String getID();
|
||||||
|
|
||||||
|
default String getAccountID(){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ public class Notification extends BaseModel implements DisplayItemsParent{
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccountID(){
|
||||||
|
return status!=null ? account.id : null;
|
||||||
|
}
|
||||||
|
|
||||||
public enum Type{
|
public enum Type{
|
||||||
@SerializedName("follow")
|
@SerializedName("follow")
|
||||||
FOLLOW,
|
FOLLOW,
|
||||||
|
|||||||
@@ -34,10 +34,18 @@ public class SearchResult extends BaseModel implements DisplayItemsParent{
|
|||||||
generateID();
|
generateID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getID(){
|
public String getID(){
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccountID(){
|
||||||
|
if(type==Type.STATUS)
|
||||||
|
return status.getAccountID();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postprocess() throws ObjectValidationException{
|
public void postprocess() throws ObjectValidationException{
|
||||||
super.postprocess();
|
super.postprocess();
|
||||||
|
|||||||
@@ -143,6 +143,11 @@ public class Status extends BaseModel implements DisplayItemsParent{
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAccountID(){
|
||||||
|
return getContentStatus().account.id;
|
||||||
|
}
|
||||||
|
|
||||||
public void update(StatusCountersUpdatedEvent ev){
|
public void update(StatusCountersUpdatedEvent ev){
|
||||||
favouritesCount=ev.favorites;
|
favouritesCount=ev.favorites;
|
||||||
reblogsCount=ev.reblogs;
|
reblogsCount=ev.reblogs;
|
||||||
|
|||||||
@@ -1,10 +1,30 @@
|
|||||||
package org.joinmastodon.android.model;
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
import org.joinmastodon.android.api.AllFieldsAreRequired;
|
|
||||||
|
|
||||||
@AllFieldsAreRequired
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
|
|
||||||
public class Translation extends BaseModel{
|
public class Translation extends BaseModel{
|
||||||
|
@RequiredField
|
||||||
public String content;
|
public String content;
|
||||||
|
@RequiredField
|
||||||
public String detectedSourceLanguage;
|
public String detectedSourceLanguage;
|
||||||
|
@RequiredField
|
||||||
public String provider;
|
public String provider;
|
||||||
|
public String spoilerText;
|
||||||
|
public MediaAttachment[] mediaAttachments;
|
||||||
|
public PollTranslation poll;
|
||||||
|
|
||||||
|
public static class MediaAttachment {
|
||||||
|
public String id;
|
||||||
|
public String description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PollTranslation {
|
||||||
|
public String id;
|
||||||
|
public PollOption[] options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PollOption {
|
||||||
|
public String title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class AccountViewModel{
|
|||||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||||
else
|
else
|
||||||
parsedName=account.displayName;
|
parsedName=account.displayName;
|
||||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID, account);
|
||||||
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
|
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
|
||||||
ssb.append(parsedBio);
|
ssb.append(parsedBio);
|
||||||
emojiHelper.setText(ssb);
|
emojiHelper.setText(ssb);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class CheckableListItem<T> extends ListItem<T>{
|
|||||||
case CHECKBOX -> R.id.list_item_checkbox;
|
case CHECKBOX -> R.id.list_item_checkbox;
|
||||||
case RADIO -> R.id.list_item_radio;
|
case RADIO -> R.id.list_item_radio;
|
||||||
case SWITCH -> R.id.list_item_switch;
|
case SWITCH -> R.id.list_item_switch;
|
||||||
|
case SWITCH_SEPARATED -> R.id.list_item_switch_separated;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ public class CheckableListItem<T> extends ListItem<T>{
|
|||||||
public enum Style{
|
public enum Style{
|
||||||
CHECKBOX,
|
CHECKBOX,
|
||||||
RADIO,
|
RADIO,
|
||||||
SWITCH
|
SWITCH,
|
||||||
|
SWITCH_SEPARATED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|||||||
private UsableRecyclerView list;
|
private UsableRecyclerView list;
|
||||||
private List<WrappedAccount> accounts;
|
private List<WrappedAccount> accounts;
|
||||||
private ListImageLoaderWrapper imgLoader;
|
private ListImageLoaderWrapper imgLoader;
|
||||||
|
private Runnable onLoggedOutCallback;
|
||||||
|
|
||||||
public AccountSwitcherSheet(@NonNull Activity activity, @Nullable HomeFragment fragment){
|
public AccountSwitcherSheet(@NonNull Activity activity, @Nullable HomeFragment fragment){
|
||||||
super(activity);
|
super(activity);
|
||||||
@@ -95,6 +96,11 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|||||||
UiUtils.getThemeColor(activity, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
|
UiUtils.getThemeColor(activity, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AccountSwitcherSheet setOnLoggedOutCallback(Runnable onLoggedOutCallback){
|
||||||
|
this.onLoggedOutCallback=onLoggedOutCallback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private void confirmLogOut(String accountID){
|
private void confirmLogOut(String accountID){
|
||||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||||
new M3AlertDialogBuilder(activity)
|
new M3AlertDialogBuilder(activity)
|
||||||
@@ -113,7 +119,10 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void logOut(String accountID){
|
private void logOut(String accountID){
|
||||||
|
String activeAccount=AccountSessionManager.getInstance().getLastActiveAccountID();
|
||||||
AccountSessionManager.get(accountID).logOut(activity, ()->{
|
AccountSessionManager.get(accountID).logOut(activity, ()->{
|
||||||
|
if(accountID.equals(activeAccount) && onLoggedOutCallback!=null)
|
||||||
|
onLoggedOutCallback.run();
|
||||||
dismiss();
|
dismiss();
|
||||||
((MainActivity)activity).restartHomeFragment();
|
((MainActivity)activity).restartHomeFragment();
|
||||||
});
|
});
|
||||||
@@ -133,6 +142,8 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|||||||
AccountSessionManager.getInstance().removeAccount(session.getID());
|
AccountSessionManager.getInstance().removeAccount(session.getID());
|
||||||
sessions.remove(session);
|
sessions.remove(session);
|
||||||
if(sessions.isEmpty()){
|
if(sessions.isEmpty()){
|
||||||
|
if(onLoggedOutCallback!=null)
|
||||||
|
onLoggedOutCallback.run();
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
Nav.goClearingStack(activity, SplashFragment.class, null);
|
Nav.goClearingStack(activity, SplashFragment.class, null);
|
||||||
dismiss();
|
dismiss();
|
||||||
@@ -144,6 +155,8 @@ public class AccountSwitcherSheet extends BottomSheet{
|
|||||||
AccountSessionManager.getInstance().removeAccount(session.getID());
|
AccountSessionManager.getInstance().removeAccount(session.getID());
|
||||||
sessions.remove(session);
|
sessions.remove(session);
|
||||||
if(sessions.isEmpty()){
|
if(sessions.isEmpty()){
|
||||||
|
if(onLoggedOutCallback!=null)
|
||||||
|
onLoggedOutCallback.run();
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
Nav.goClearingStack(activity, SplashFragment.class, null);
|
Nav.goClearingStack(activity, SplashFragment.class, null);
|
||||||
dismiss();
|
dismiss();
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
|
import org.joinmastodon.android.model.Account;
|
||||||
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||||
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
|
public class NonMutualPreReplySheet extends PreReplySheet{
|
||||||
|
private boolean fullBioShown=false;
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
public NonMutualPreReplySheet(@NonNull Context context, ResultListener resultListener, Account account, String accountID){
|
||||||
|
super(context, resultListener);
|
||||||
|
icon.setImageResource(R.drawable.ic_waving_hand_24px);
|
||||||
|
title.setText(R.string.non_mutual_sheet_title);
|
||||||
|
text.setText(R.string.non_mutual_sheet_text);
|
||||||
|
|
||||||
|
LinearLayout userInfo=new LinearLayout(context);
|
||||||
|
userInfo.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
userInfo.setBackgroundResource(R.drawable.bg_user_info);
|
||||||
|
UiUtils.setAllPaddings(userInfo, 12);
|
||||||
|
|
||||||
|
ImageView ava=new ImageView(context);
|
||||||
|
ava.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||||
|
ava.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||||
|
ava.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||||
|
ava.setClipToOutline(true);
|
||||||
|
ava.setForeground(context.getResources().getDrawable(R.drawable.fg_user_info_ava, context.getTheme()));
|
||||||
|
userInfo.addView(ava, UiUtils.makeLayoutParams(56, 56, 0, 0, 12, 0));
|
||||||
|
ViewImageLoader.loadWithoutAnimation(ava, context.getResources().getDrawable(R.drawable.image_placeholder), new UrlImageLoaderRequest(account.avatarStatic, V.dp(56), V.dp(56)));
|
||||||
|
|
||||||
|
LinearLayout nameAndFields=new LinearLayout(context);
|
||||||
|
nameAndFields.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
nameAndFields.setMinimumHeight(V.dp(56));
|
||||||
|
nameAndFields.setGravity(Gravity.CENTER_VERTICAL);
|
||||||
|
userInfo.addView(nameAndFields, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
TextView name=new TextView(context);
|
||||||
|
name.setSingleLine();
|
||||||
|
name.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
|
name.setTextAppearance(R.style.m3_title_medium);
|
||||||
|
name.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3OnSurface));
|
||||||
|
if(AccountSessionManager.get(accountID).getLocalPreferences().customEmojiInNames){
|
||||||
|
name.setText(HtmlParser.parseCustomEmoji(account.displayName, account.emojis));
|
||||||
|
UiUtils.loadCustomEmojiInTextView(name);
|
||||||
|
}else{
|
||||||
|
name.setText(account.displayName);
|
||||||
|
}
|
||||||
|
name.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||||
|
nameAndFields.addView(name, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(24)));
|
||||||
|
if(!TextUtils.isEmpty(account.note)){
|
||||||
|
CharSequence strippedBio=HtmlParser.parseCustomEmoji(HtmlParser.stripAndRemoveInvisibleSpans(account.note), account.emojis);
|
||||||
|
TextView bioShort=new TextView(context);
|
||||||
|
bioShort.setTextAppearance(R.style.m3_body_medium);
|
||||||
|
bioShort.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||||
|
bioShort.setMaxLines(2);
|
||||||
|
bioShort.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
|
bioShort.setText(strippedBio);
|
||||||
|
nameAndFields.addView(bioShort, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
|
||||||
|
TextView bioFull=new TextView(context);
|
||||||
|
bioFull.setTextAppearance(R.style.m3_body_medium);
|
||||||
|
bioFull.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||||
|
bioFull.setText(strippedBio);
|
||||||
|
bioFull.setVisibility(View.GONE);
|
||||||
|
nameAndFields.addView(bioFull, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
nameAndFields.setOnClickListener(v->{
|
||||||
|
UiUtils.beginLayoutTransition((ViewGroup) getWindow().getDecorView());
|
||||||
|
fullBioShown=!fullBioShown;
|
||||||
|
if(fullBioShown){
|
||||||
|
bioFull.setVisibility(View.VISIBLE);
|
||||||
|
bioShort.setVisibility(View.GONE);
|
||||||
|
}else{
|
||||||
|
bioFull.setVisibility(View.GONE);
|
||||||
|
bioShort.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
UiUtils.loadCustomEmojiInTextView(bioShort);
|
||||||
|
UiUtils.loadCustomEmojiInTextView(bioFull);
|
||||||
|
}else{
|
||||||
|
TextView username=new TextView(context);
|
||||||
|
username.setTextAppearance(R.style.m3_body_medium);
|
||||||
|
username.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3Secondary));
|
||||||
|
username.setSingleLine();
|
||||||
|
username.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
|
username.setText(account.getDisplayUsername());
|
||||||
|
username.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||||
|
nameAndFields.addView(username, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(20)));
|
||||||
|
}
|
||||||
|
|
||||||
|
contentWrap.addView(userInfo, UiUtils.makeLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0, 0, 8));
|
||||||
|
|
||||||
|
for(int i=0;i<3;i++){
|
||||||
|
View item=context.getSystemService(LayoutInflater.class).inflate(R.layout.item_other_numbered_rule, contentWrap, false);
|
||||||
|
TextView number=item.findViewById(R.id.number);
|
||||||
|
number.setText(String.format("%d", i+1));
|
||||||
|
TextView title=item.findViewById(R.id.title);
|
||||||
|
TextView text=item.findViewById(R.id.text);
|
||||||
|
title.setText(switch(i){
|
||||||
|
case 0 -> R.string.non_mutual_title1;
|
||||||
|
case 1 -> R.string.non_mutual_title2;
|
||||||
|
case 2 -> R.string.non_mutual_title3;
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||||
|
});
|
||||||
|
text.setText(switch(i){
|
||||||
|
case 0 -> R.string.non_mutual_text1;
|
||||||
|
case 1 -> R.string.non_mutual_text2;
|
||||||
|
case 2 -> R.string.non_mutual_text3;
|
||||||
|
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||||
|
});
|
||||||
|
contentWrap.addView(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.model.Status;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class OldPostPreReplySheet extends PreReplySheet{
|
||||||
|
public OldPostPreReplySheet(@NonNull Context context, ResultListener resultListener, Status status){
|
||||||
|
super(context, resultListener);
|
||||||
|
int months=(int)status.createdAt.atZone(ZoneId.systemDefault()).until(ZonedDateTime.now(), ChronoUnit.MONTHS);
|
||||||
|
String monthsStr=months>24 ? context.getString(R.string.more_than_two_years) : context.getResources().getQuantityString(R.plurals.x_months, months, months);
|
||||||
|
title.setText(context.getString(R.string.old_post_sheet_title, monthsStr));
|
||||||
|
text.setText(R.string.old_post_sheet_text);
|
||||||
|
icon.setImageResource(R.drawable.ic_history_24px);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
import me.grishka.appkit.views.BottomSheet;
|
||||||
|
|
||||||
|
public abstract class PreReplySheet extends BottomSheet{
|
||||||
|
protected ImageView icon;
|
||||||
|
protected TextView title, text;
|
||||||
|
protected Button gotItButton, dontRemindButton;
|
||||||
|
protected LinearLayout contentWrap;
|
||||||
|
|
||||||
|
public PreReplySheet(@NonNull Context context, ResultListener resultListener){
|
||||||
|
super(context);
|
||||||
|
|
||||||
|
View content=context.getSystemService(LayoutInflater.class).inflate(R.layout.sheet_pre_reply, null);
|
||||||
|
setContentView(content);
|
||||||
|
FrameLayout.LayoutParams lp=(FrameLayout.LayoutParams) content.getLayoutParams();
|
||||||
|
lp.topMargin=V.dp(72);
|
||||||
|
|
||||||
|
setNavigationBarBackground(new ColorDrawable(UiUtils.alphaBlendColors(UiUtils.getThemeColor(context, R.attr.colorM3Surface),
|
||||||
|
UiUtils.getThemeColor(context, R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
|
||||||
|
|
||||||
|
icon=findViewById(R.id.icon);
|
||||||
|
title=findViewById(R.id.title);
|
||||||
|
text=findViewById(R.id.text);
|
||||||
|
gotItButton=findViewById(R.id.btn_got_it);
|
||||||
|
dontRemindButton=findViewById(R.id.btn_dont_remind_again);
|
||||||
|
contentWrap=findViewById(R.id.content_wrap);
|
||||||
|
|
||||||
|
gotItButton.setOnClickListener(v->{
|
||||||
|
dismiss();
|
||||||
|
resultListener.onButtonClicked(false);
|
||||||
|
});
|
||||||
|
dontRemindButton.setOnClickListener(v->{
|
||||||
|
dismiss();
|
||||||
|
resultListener.onButtonClicked(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ResultListener{
|
||||||
|
void onButtonClicked(boolean notAgain);
|
||||||
|
}
|
||||||
|
}
|
||||||
217
mastodon/src/main/java/org/joinmastodon/android/ui/Snackbar.java
Normal file
217
mastodon/src/main/java/org/joinmastodon/android/ui/Snackbar.java
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
package org.joinmastodon.android.ui;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.graphics.Outline;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewOutlineProvider;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
|
|
||||||
|
import androidx.annotation.Keep;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
|
public class Snackbar{
|
||||||
|
private static Snackbar current;
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private int bottomOffset;
|
||||||
|
private FrameLayout windowView;
|
||||||
|
private LinearLayout contentView;
|
||||||
|
private boolean hasAction;
|
||||||
|
private AnimatableOutlineProvider outlineProvider;
|
||||||
|
private Animator currentAnim;
|
||||||
|
private Runnable dismissRunnable=this::dismiss;
|
||||||
|
|
||||||
|
private Snackbar(Context context, String text, String action, Runnable onActionClick, int bottomOffset){
|
||||||
|
this.context=context;
|
||||||
|
this.bottomOffset=bottomOffset;
|
||||||
|
hasAction=onActionClick!=null;
|
||||||
|
|
||||||
|
windowView=new FrameLayout(context);
|
||||||
|
windowView.setClipToPadding(false);
|
||||||
|
contentView=new LinearLayout(context);
|
||||||
|
contentView.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
contentView.setBaselineAligned(false);
|
||||||
|
contentView.setBackgroundColor(UiUtils.getThemeColor(context, R.attr.colorM3SurfaceInverse));
|
||||||
|
contentView.setOutlineProvider(outlineProvider=new AnimatableOutlineProvider(contentView));
|
||||||
|
contentView.setClipToOutline(true);
|
||||||
|
contentView.setElevation(V.dp(6));
|
||||||
|
contentView.setPaddingRelative(V.dp(16), 0, V.dp(8), 0);
|
||||||
|
FrameLayout.LayoutParams lp=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||||
|
lp.leftMargin=lp.topMargin=lp.rightMargin=lp.bottomMargin=V.dp(16);
|
||||||
|
windowView.addView(contentView, lp);
|
||||||
|
|
||||||
|
TextView textView=new TextView(context);
|
||||||
|
textView.setTextAppearance(R.style.m3_body_medium);
|
||||||
|
textView.setTextColor(UiUtils.getThemeColor(context, R.attr.colorM3OnSurfaceInverse));
|
||||||
|
textView.setMaxLines(2);
|
||||||
|
textView.setEllipsize(TextUtils.TruncateAt.END);
|
||||||
|
textView.setText(text);
|
||||||
|
textView.setMinHeight(V.dp(48));
|
||||||
|
textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
|
||||||
|
textView.setPadding(0, V.dp(14), 0, V.dp(14));
|
||||||
|
contentView.addView(textView, new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
|
||||||
|
|
||||||
|
if(action!=null){
|
||||||
|
Button button=new Button(context);
|
||||||
|
int primaryInverse=UiUtils.getThemeColor(context, R.attr.colorM3PrimaryInverse);
|
||||||
|
button.setTextColor(primaryInverse);
|
||||||
|
button.setBackgroundResource(R.drawable.bg_rect_4dp_ripple);
|
||||||
|
button.setBackgroundTintList(ColorStateList.valueOf(primaryInverse));
|
||||||
|
button.setText(action);
|
||||||
|
button.setPadding(V.dp(8), 0, V.dp(8), 0);
|
||||||
|
button.setOnClickListener(v->onActionClick.run());
|
||||||
|
LinearLayout.LayoutParams blp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, V.dp(40));
|
||||||
|
blp.leftMargin=blp.topMargin=blp.rightMargin=blp.bottomMargin=V.dp(4);
|
||||||
|
contentView.addView(button, blp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(){
|
||||||
|
if(current!=null)
|
||||||
|
current.dismiss();
|
||||||
|
current=this;
|
||||||
|
WindowManager.LayoutParams lp=new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT);
|
||||||
|
lp.width=ViewGroup.LayoutParams.MATCH_PARENT;
|
||||||
|
lp.height=ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||||
|
lp.gravity=Gravity.BOTTOM;
|
||||||
|
lp.y=bottomOffset;
|
||||||
|
WindowManager wm=context.getSystemService(WindowManager.class);
|
||||||
|
wm.addView(windowView, lp);
|
||||||
|
windowView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||||
|
@Override
|
||||||
|
public boolean onPreDraw(){
|
||||||
|
windowView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
|
|
||||||
|
AnimatorSet set=new AnimatorSet();
|
||||||
|
set.playTogether(
|
||||||
|
ObjectAnimator.ofFloat(outlineProvider, "fraction", 0, 1),
|
||||||
|
ObjectAnimator.ofFloat(contentView, View.ALPHA, 0, 1)
|
||||||
|
);
|
||||||
|
set.setInterpolator(AnimationUtils.loadInterpolator(context, R.interpolator.m3_sys_motion_easing_standard_decelerate));
|
||||||
|
set.setDuration(350);
|
||||||
|
set.addListener(new AnimatorListenerAdapter(){
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation){
|
||||||
|
currentAnim=null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
currentAnim=set;
|
||||||
|
set.start();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
windowView.postDelayed(dismissRunnable, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dismiss(){
|
||||||
|
current=null;
|
||||||
|
if(currentAnim!=null){
|
||||||
|
currentAnim.cancel();
|
||||||
|
}
|
||||||
|
windowView.removeCallbacks(dismissRunnable);
|
||||||
|
ObjectAnimator anim=ObjectAnimator.ofFloat(contentView, View.ALPHA, 0);
|
||||||
|
anim.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
anim.setDuration(200);
|
||||||
|
anim.addListener(new AnimatorListenerAdapter(){
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation){
|
||||||
|
WindowManager wm=context.getSystemService(WindowManager.class);
|
||||||
|
wm.removeView(windowView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
anim.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnimatableOutlineProvider extends ViewOutlineProvider{
|
||||||
|
private float fraction=1f;
|
||||||
|
private final View view;
|
||||||
|
|
||||||
|
private AnimatableOutlineProvider(View view){
|
||||||
|
this.view=view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getOutline(View view, Outline outline){
|
||||||
|
outline.setRoundRect(0, Math.round(view.getHeight()*(1f-fraction)), view.getWidth(), view.getHeight(), V.dp(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
public float getFraction(){
|
||||||
|
return fraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
public void setFraction(float fraction){
|
||||||
|
this.fraction=fraction;
|
||||||
|
view.invalidateOutline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder{
|
||||||
|
private final Context context;
|
||||||
|
private String text;
|
||||||
|
private String action;
|
||||||
|
private Runnable onActionClick;
|
||||||
|
private int bottomOffset;
|
||||||
|
|
||||||
|
public Builder(Context context){
|
||||||
|
this.context=context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setText(String text){
|
||||||
|
this.text=text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setText(@StringRes int res){
|
||||||
|
text=context.getString(res);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAction(String action, Runnable onActionClick){
|
||||||
|
this.action=action;
|
||||||
|
this.onActionClick=onActionClick;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setAction(@StringRes int action, Runnable onActionClick){
|
||||||
|
this.action=context.getString(action);
|
||||||
|
this.onActionClick=onActionClick;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setBottomOffset(int offset){
|
||||||
|
bottomOffset=offset;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Snackbar create(){
|
||||||
|
return new Snackbar(context, text, action, onActionClick, bottomOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show(){
|
||||||
|
create().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,8 +39,8 @@ public class GenericListItemsAdapter<T> extends UsableRecyclerView.Adapter<ListI
|
|||||||
public ListItemViewHolder<?> onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
public ListItemViewHolder<?> onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||||
if(viewType==R.id.list_item_simple || viewType==R.id.list_item_simple_tinted)
|
if(viewType==R.id.list_item_simple || viewType==R.id.list_item_simple_tinted)
|
||||||
return new SimpleListItemViewHolder(parent.getContext(), parent);
|
return new SimpleListItemViewHolder(parent.getContext(), parent);
|
||||||
if(viewType==R.id.list_item_switch)
|
if(viewType==R.id.list_item_switch || viewType==R.id.list_item_switch_separated)
|
||||||
return new SwitchListItemViewHolder(parent.getContext(), parent);
|
return new SwitchListItemViewHolder(parent.getContext(), parent, viewType==R.id.list_item_switch_separated);
|
||||||
if(viewType==R.id.list_item_checkbox)
|
if(viewType==R.id.list_item_checkbox)
|
||||||
return new CheckboxOrRadioListItemViewHolder(parent.getContext(), parent, false);
|
return new CheckboxOrRadioListItemViewHolder(parent.getContext(), parent, false);
|
||||||
if(viewType==R.id.list_item_radio)
|
if(viewType==R.id.list_item_radio)
|
||||||
|
|||||||
@@ -2,37 +2,49 @@ package org.joinmastodon.android.ui.displayitems;
|
|||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
import android.text.style.StyleSpan;
|
||||||
import android.text.style.TypefaceSpan;
|
import android.text.style.TypefaceSpan;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.fragments.StatusEditHistoryFragment;
|
import org.joinmastodon.android.fragments.StatusEditHistoryFragment;
|
||||||
|
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||||
import org.joinmastodon.android.fragments.account_list.StatusFavoritesListFragment;
|
import org.joinmastodon.android.fragments.account_list.StatusFavoritesListFragment;
|
||||||
import org.joinmastodon.android.fragments.account_list.StatusReblogsListFragment;
|
import org.joinmastodon.android.fragments.account_list.StatusReblogsListFragment;
|
||||||
import org.joinmastodon.android.fragments.account_list.StatusRelatedAccountListFragment;
|
import org.joinmastodon.android.fragments.account_list.StatusRelatedAccountListFragment;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
|
import org.joinmastodon.android.ui.Snackbar;
|
||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.FormatStyle;
|
import java.time.format.FormatStyle;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import androidx.annotation.PluralsRes;
|
import androidx.annotation.PluralsRes;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
public final Status status;
|
public final Status status;
|
||||||
|
|
||||||
private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
|
private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT);
|
||||||
|
private static final DateTimeFormatter TIME_FORMATTER_LONG=DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM);
|
||||||
|
private static final DateTimeFormatter DATE_FORMATTER=DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
|
||||||
|
|
||||||
public ExtendedFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){
|
public ExtendedFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){
|
||||||
super(parentID, parentFragment);
|
super(parentID, parentFragment);
|
||||||
@@ -45,7 +57,7 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends StatusDisplayItem.Holder<ExtendedFooterStatusDisplayItem>{
|
public static class Holder extends StatusDisplayItem.Holder<ExtendedFooterStatusDisplayItem>{
|
||||||
private final TextView time;
|
private final TextView time, date, app, dateAppSeparator;
|
||||||
private final TextView favorites, reblogs, editHistory;
|
private final TextView favorites, reblogs, editHistory;
|
||||||
|
|
||||||
public Holder(Context context, ViewGroup parent){
|
public Holder(Context context, ViewGroup parent){
|
||||||
@@ -53,30 +65,46 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
reblogs=findViewById(R.id.reblogs);
|
reblogs=findViewById(R.id.reblogs);
|
||||||
favorites=findViewById(R.id.favorites);
|
favorites=findViewById(R.id.favorites);
|
||||||
editHistory=findViewById(R.id.edit_history);
|
editHistory=findViewById(R.id.edit_history);
|
||||||
time=findViewById(R.id.timestamp);
|
time=findViewById(R.id.time);
|
||||||
|
date=findViewById(R.id.date);
|
||||||
|
app=findViewById(R.id.app_name);
|
||||||
|
dateAppSeparator=findViewById(R.id.date_app_separator);
|
||||||
|
|
||||||
reblogs.setOnClickListener(v->startAccountListFragment(StatusReblogsListFragment.class));
|
reblogs.setOnClickListener(v->startAccountListFragment(StatusReblogsListFragment.class));
|
||||||
favorites.setOnClickListener(v->startAccountListFragment(StatusFavoritesListFragment.class));
|
favorites.setOnClickListener(v->startAccountListFragment(StatusFavoritesListFragment.class));
|
||||||
editHistory.setOnClickListener(v->startEditHistoryFragment());
|
editHistory.setOnClickListener(v->startEditHistoryFragment());
|
||||||
|
time.setOnClickListener(v->showTimeSnackbar());
|
||||||
|
app.setOnClickListener(v->UiUtils.launchWebBrowser(context, item.status.application.website));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
@SuppressLint("DefaultLocale")
|
||||||
@Override
|
@Override
|
||||||
public void onBind(ExtendedFooterStatusDisplayItem item){
|
public void onBind(ExtendedFooterStatusDisplayItem item){
|
||||||
Status s=item.status;
|
Status s=item.status;
|
||||||
favorites.setText(itemView.getResources().getQuantityString(R.plurals.x_favorites, (int)item.status.favouritesCount, item.status.favouritesCount));
|
favorites.setText(getFormattedPlural(R.plurals.x_favorites, item.status.favouritesCount));
|
||||||
reblogs.setText(itemView.getResources().getQuantityString(R.plurals.x_reblogs, (int)item.status.reblogsCount, item.status.reblogsCount));
|
reblogs.setText(getFormattedPlural(R.plurals.x_reblogs, item.status.reblogsCount));
|
||||||
if(s.editedAt!=null){
|
if(s.editedAt!=null){
|
||||||
editHistory.setVisibility(View.VISIBLE);
|
editHistory.setVisibility(View.VISIBLE);
|
||||||
editHistory.setText(item.parentFragment.getString(R.string.last_edit_at_x, UiUtils.formatRelativeTimestampAsMinutesAgo(itemView.getContext(), s.editedAt, false)));
|
ZonedDateTime dt=s.editedAt.atZone(ZoneId.systemDefault());
|
||||||
|
String time=TIME_FORMATTER.format(dt);
|
||||||
|
if(!dt.toLocalDate().equals(LocalDate.now())){
|
||||||
|
time+=" · "+DATE_FORMATTER.format(dt);
|
||||||
|
}
|
||||||
|
editHistory.setText(getFormattedSubstitutedString(R.string.last_edit_at_x, time));
|
||||||
}else{
|
}else{
|
||||||
editHistory.setVisibility(View.GONE);
|
editHistory.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
String timeStr=TIME_FORMATTER.format(item.status.createdAt.atZone(ZoneId.systemDefault()));
|
ZonedDateTime dt=item.status.createdAt.atZone(ZoneId.systemDefault());
|
||||||
|
time.setText(TIME_FORMATTER.format(dt));
|
||||||
|
date.setText(DATE_FORMATTER.format(dt));
|
||||||
if(item.status.application!=null && !TextUtils.isEmpty(item.status.application.name)){
|
if(item.status.application!=null && !TextUtils.isEmpty(item.status.application.name)){
|
||||||
time.setText(item.parentFragment.getString(R.string.timestamp_via_app, timeStr, item.status.application.name));
|
app.setVisibility(View.VISIBLE);
|
||||||
|
dateAppSeparator.setVisibility(View.VISIBLE);
|
||||||
|
app.setText(item.status.application.name);
|
||||||
|
app.setEnabled(!TextUtils.isEmpty(item.status.application.website));
|
||||||
}else{
|
}else{
|
||||||
time.setText(timeStr);
|
app.setVisibility(View.GONE);
|
||||||
|
dateAppSeparator.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,14 +113,39 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SpannableStringBuilder getFormattedPlural(@PluralsRes int res, int quantity){
|
private SpannableStringBuilder getFormattedPlural(@PluralsRes int res, long quantity){
|
||||||
String str=item.parentFragment.getResources().getQuantityString(res, quantity, quantity);
|
String str=item.parentFragment.getResources().getQuantityString(res, (int)quantity, quantity);
|
||||||
String formattedNumber=String.format(Locale.getDefault(), "%,d", quantity);
|
String formattedNumber=String.format(Locale.getDefault(), "%,d", quantity);
|
||||||
int index=str.indexOf(formattedNumber);
|
int index=str.indexOf(formattedNumber);
|
||||||
SpannableStringBuilder ssb=new SpannableStringBuilder(str);
|
SpannableStringBuilder ssb=new SpannableStringBuilder(str);
|
||||||
if(index>=0){
|
if(index>=0){
|
||||||
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), index, index+formattedNumber.length(), 0);
|
ForegroundColorSpan colorSpan=new ForegroundColorSpan(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3OnSurfaceVariant));
|
||||||
ssb.setSpan(new ForegroundColorSpan(UiUtils.getThemeColor(item.parentFragment.getActivity(), android.R.attr.textColorPrimary)), index, index+formattedNumber.length(), 0);
|
ssb.setSpan(colorSpan, index, index+formattedNumber.length(), 0);
|
||||||
|
Object typefaceSpan;
|
||||||
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){
|
||||||
|
typefaceSpan=new TypefaceSpan(Typeface.create(Typeface.DEFAULT, 600, false));
|
||||||
|
}else{
|
||||||
|
typefaceSpan=new StyleSpan(Typeface.BOLD);
|
||||||
|
}
|
||||||
|
ssb.setSpan(typefaceSpan, index, index+formattedNumber.length(), 0);
|
||||||
|
}
|
||||||
|
return ssb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpannableStringBuilder getFormattedSubstitutedString(@StringRes int res, String substitution){
|
||||||
|
String str=item.parentFragment.getString(res, substitution);
|
||||||
|
int index=item.parentFragment.getString(res).indexOf("%s");
|
||||||
|
SpannableStringBuilder ssb=new SpannableStringBuilder(str);
|
||||||
|
if(index>=0){
|
||||||
|
ForegroundColorSpan colorSpan=new ForegroundColorSpan(UiUtils.getThemeColor(itemView.getContext(), R.attr.colorM3OnSurfaceVariant));
|
||||||
|
ssb.setSpan(colorSpan, index, index+substitution.length(), 0);
|
||||||
|
Object typefaceSpan;
|
||||||
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.S){
|
||||||
|
typefaceSpan=new TypefaceSpan(Typeface.create(Typeface.DEFAULT, 600, false));
|
||||||
|
}else{
|
||||||
|
typefaceSpan=new StyleSpan(Typeface.BOLD);
|
||||||
|
}
|
||||||
|
ssb.setSpan(typefaceSpan, index, index+substitution.length(), 0);
|
||||||
}
|
}
|
||||||
return ssb;
|
return ssb;
|
||||||
}
|
}
|
||||||
@@ -110,5 +163,16 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
args.putString("id", item.status.id);
|
args.putString("id", item.status.id);
|
||||||
Nav.go(item.parentFragment.getActivity(), StatusEditHistoryFragment.class, args);
|
Nav.go(item.parentFragment.getActivity(), StatusEditHistoryFragment.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showTimeSnackbar(){
|
||||||
|
int bottomOffset=0;
|
||||||
|
if(item.parentFragment instanceof ThreadFragment tf){
|
||||||
|
bottomOffset=tf.getSnackbarOffset();
|
||||||
|
}
|
||||||
|
new Snackbar.Builder(itemView.getContext())
|
||||||
|
.setText(itemView.getContext().getString(R.string.posted_at, TIME_FORMATTER_LONG.format(item.status.createdAt.atZone(ZoneId.systemDefault()))))
|
||||||
|
.setBottomOffset(bottomOffset)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package org.joinmastodon.android.ui.displayitems;
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
@@ -25,10 +24,7 @@ import org.joinmastodon.android.model.StatusPrivacy;
|
|||||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
|
|
||||||
import me.grishka.appkit.Nav;
|
import me.grishka.appkit.Nav;
|
||||||
import me.grishka.appkit.utils.BindableViewHolder;
|
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
|
|
||||||
public class FooterStatusDisplayItem extends StatusDisplayItem{
|
public class FooterStatusDisplayItem extends StatusDisplayItem{
|
||||||
@@ -51,6 +47,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private final TextView reply, boost, favorite;
|
private final TextView reply, boost, favorite;
|
||||||
private final ImageView share;
|
private final ImageView share;
|
||||||
private final ColorStateList buttonColors;
|
private final ColorStateList buttonColors;
|
||||||
|
private final View replyBtn, boostBtn, favoriteBtn, shareBtn;
|
||||||
|
|
||||||
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
private final View.AccessibilityDelegate buttonAccessibilityDelegate=new View.AccessibilityDelegate(){
|
||||||
@Override
|
@Override
|
||||||
@@ -93,18 +90,18 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
|
UiUtils.fixCompoundDrawableTintOnAndroid6(boost);
|
||||||
UiUtils.fixCompoundDrawableTintOnAndroid6(favorite);
|
UiUtils.fixCompoundDrawableTintOnAndroid6(favorite);
|
||||||
}
|
}
|
||||||
View reply=findViewById(R.id.reply_btn);
|
replyBtn=findViewById(R.id.reply_btn);
|
||||||
View boost=findViewById(R.id.boost_btn);
|
boostBtn=findViewById(R.id.boost_btn);
|
||||||
View favorite=findViewById(R.id.favorite_btn);
|
favoriteBtn=findViewById(R.id.favorite_btn);
|
||||||
View share=findViewById(R.id.share_btn);
|
shareBtn=findViewById(R.id.share_btn);
|
||||||
reply.setOnClickListener(this::onReplyClick);
|
replyBtn.setOnClickListener(this::onReplyClick);
|
||||||
reply.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
replyBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
boost.setOnClickListener(this::onBoostClick);
|
boostBtn.setOnClickListener(this::onBoostClick);
|
||||||
boost.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
boostBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
favorite.setOnClickListener(this::onFavoriteClick);
|
favoriteBtn.setOnClickListener(this::onFavoriteClick);
|
||||||
favorite.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
favoriteBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
share.setOnClickListener(this::onShareClick);
|
shareBtn.setOnClickListener(this::onShareClick);
|
||||||
share.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
shareBtn.setAccessibilityDelegate(buttonAccessibilityDelegate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -112,10 +109,18 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
bindButton(reply, item.status.repliesCount);
|
bindButton(reply, item.status.repliesCount);
|
||||||
bindButton(boost, item.status.reblogsCount);
|
bindButton(boost, item.status.reblogsCount);
|
||||||
bindButton(favorite, item.status.favouritesCount);
|
bindButton(favorite, item.status.favouritesCount);
|
||||||
boost.setSelected(item.status.reblogged);
|
boostBtn.setSelected(item.status.reblogged);
|
||||||
favorite.setSelected(item.status.favourited);
|
favoriteBtn.setSelected(item.status.favourited);
|
||||||
boost.setEnabled(item.status.visibility==StatusPrivacy.PUBLIC || item.status.visibility==StatusPrivacy.UNLISTED
|
boolean isOwn=item.status.account.id.equals(AccountSessionManager.getInstance().getAccount(item.accountID).self.id);
|
||||||
|| (item.status.visibility==StatusPrivacy.PRIVATE && item.status.account.id.equals(AccountSessionManager.getInstance().getAccount(item.accountID).self.id)));
|
boostBtn.setEnabled(item.status.visibility==StatusPrivacy.PUBLIC || item.status.visibility==StatusPrivacy.UNLISTED
|
||||||
|
|| (item.status.visibility==StatusPrivacy.PRIVATE && isOwn));
|
||||||
|
Drawable d=itemView.getResources().getDrawable(switch(item.status.visibility){
|
||||||
|
case PUBLIC, UNLISTED -> R.drawable.ic_boost;
|
||||||
|
case PRIVATE -> isOwn ? R.drawable.ic_boost_private : R.drawable.ic_boost_disabled_24px;
|
||||||
|
case DIRECT -> R.drawable.ic_boost_disabled_24px;
|
||||||
|
}, itemView.getContext().getTheme());
|
||||||
|
d.setBounds(0, 0, V.dp(20), V.dp(20));
|
||||||
|
boost.setCompoundDrawablesRelative(d, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindButton(TextView btn, long count){
|
private void bindButton(TextView btn, long count){
|
||||||
@@ -129,10 +134,12 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onReplyClick(View v){
|
private void onReplyClick(View v){
|
||||||
Bundle args=new Bundle();
|
item.parentFragment.maybeShowPreReplySheet(item.status, ()->{
|
||||||
args.putString("account", item.accountID);
|
Bundle args=new Bundle();
|
||||||
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
args.putString("account", item.accountID);
|
||||||
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
args.putParcelable("replyTo", Parcels.wrap(item.status));
|
||||||
|
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onBoostClick(View v){
|
private void onBoostClick(View v){
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private final TextView name, timeAndUsername, extraText;
|
private final TextView name, timeAndUsername, extraText;
|
||||||
private final ImageView avatar, more;
|
private final ImageView avatar, more;
|
||||||
private final PopupMenu optionsMenu;
|
private final PopupMenu optionsMenu;
|
||||||
private Relationship relationship;
|
|
||||||
private APIRequest<?> currentRelationshipRequest;
|
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
this(activity, R.layout.display_item_header, parent);
|
this(activity, R.layout.display_item_header, parent);
|
||||||
@@ -136,10 +134,11 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
optionsMenu=new PopupMenu(activity, more);
|
optionsMenu=new PopupMenu(activity, more);
|
||||||
optionsMenu.inflate(R.menu.post);
|
optionsMenu.inflate(R.menu.post);
|
||||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P)
|
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.P && !UiUtils.isEMUI())
|
||||||
optionsMenu.getMenu().setGroupDividerEnabled(true);
|
optionsMenu.getMenu().setGroupDividerEnabled(true);
|
||||||
optionsMenu.setOnMenuItemClickListener(menuItem->{
|
optionsMenu.setOnMenuItemClickListener(menuItem->{
|
||||||
Account account=item.user;
|
Account account=item.user;
|
||||||
|
Relationship relationship=item.parentFragment.getRelationship(account.id);
|
||||||
int id=menuItem.getItemId();
|
int id=menuItem.getItemId();
|
||||||
if(id==R.id.edit){
|
if(id==R.id.edit){
|
||||||
final Bundle args=new Bundle();
|
final Bundle args=new Bundle();
|
||||||
@@ -192,7 +191,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
else
|
else
|
||||||
progress.dismiss();
|
progress.dismiss();
|
||||||
}, rel->{
|
}, rel->{
|
||||||
relationship=rel;
|
item.parentFragment.putRelationship(account.id, rel);
|
||||||
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : rel.requested ? R.string.following_user_requested : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
|
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : rel.requested ? R.string.following_user_requested : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
|
||||||
});
|
});
|
||||||
}else if(id==R.id.bookmark){
|
}else if(id==R.id.bookmark){
|
||||||
@@ -235,10 +234,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
more.setVisibility(item.inset ? View.GONE : View.VISIBLE);
|
more.setVisibility(item.inset ? View.GONE : View.VISIBLE);
|
||||||
avatar.setClickable(!item.inset);
|
avatar.setClickable(!item.inset);
|
||||||
avatar.setContentDescription(item.parentFragment.getString(R.string.avatar_description, item.user.acct));
|
avatar.setContentDescription(item.parentFragment.getString(R.string.avatar_description, item.user.acct));
|
||||||
if(currentRelationshipRequest!=null){
|
|
||||||
currentRelationshipRequest.cancel();
|
|
||||||
}
|
|
||||||
relationship=null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -272,31 +267,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private void onMoreClick(View v){
|
private void onMoreClick(View v){
|
||||||
updateOptionsMenu();
|
updateOptionsMenu();
|
||||||
optionsMenu.show();
|
optionsMenu.show();
|
||||||
if(relationship==null && currentRelationshipRequest==null){
|
|
||||||
currentRelationshipRequest=new GetAccountRelationships(Collections.singletonList(item.user.id))
|
|
||||||
.setCallback(new Callback<>(){
|
|
||||||
@Override
|
|
||||||
public void onSuccess(List<Relationship> result){
|
|
||||||
if(!result.isEmpty()){
|
|
||||||
relationship=result.get(0);
|
|
||||||
updateOptionsMenu();
|
|
||||||
}
|
|
||||||
currentRelationshipRequest=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(ErrorResponse error){
|
|
||||||
currentRelationshipRequest=null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.exec(item.parentFragment.getAccountID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateOptionsMenu(){
|
private void updateOptionsMenu(){
|
||||||
if(item.parentFragment.getActivity()==null)
|
if(item.parentFragment.getActivity()==null)
|
||||||
return;
|
return;
|
||||||
Account account=item.user;
|
Account account=item.user;
|
||||||
|
Relationship relationship=item.parentFragment.getRelationship(account.id);
|
||||||
Menu menu=optionsMenu.getMenu();
|
Menu menu=optionsMenu.getMenu();
|
||||||
boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account);
|
boolean isOwnPost=AccountSessionManager.getInstance().isSelf(item.parentFragment.getAccountID(), account);
|
||||||
boolean canTranslate=item.status!=null && item.status.getContentStatus().isEligibleForTranslation();
|
boolean canTranslate=item.status!=null && item.status.getContentStatus().isEligibleForTranslation();
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
|
|||||||
if(item.imgRequest!=null){
|
if(item.imgRequest!=null){
|
||||||
crossfadeDrawable.setSize(card.width, card.height);
|
crossfadeDrawable.setSize(card.width, card.height);
|
||||||
crossfadeDrawable.setBlurhashDrawable(card.blurhashPlaceholder);
|
crossfadeDrawable.setBlurhashDrawable(card.blurhashPlaceholder);
|
||||||
crossfadeDrawable.setCrossfadeAlpha(item.status.spoilerRevealed ? 0f : 1f);
|
crossfadeDrawable.setCrossfadeAlpha(0f);
|
||||||
|
photo.setImageDrawable(null);
|
||||||
photo.setImageDrawable(crossfadeDrawable);
|
photo.setImageDrawable(crossfadeDrawable);
|
||||||
didClear=false;
|
didClear=false;
|
||||||
}
|
}
|
||||||
@@ -84,8 +85,14 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
|
|||||||
@Override
|
@Override
|
||||||
public void setImage(int index, Drawable drawable){
|
public void setImage(int index, Drawable drawable){
|
||||||
crossfadeDrawable.setImageDrawable(drawable);
|
crossfadeDrawable.setImageDrawable(drawable);
|
||||||
if(didClear && item.status.spoilerRevealed)
|
if(didClear)
|
||||||
crossfadeDrawable.animateAlpha(0f);
|
crossfadeDrawable.animateAlpha(0f);
|
||||||
|
Card card=item.status.card;
|
||||||
|
// Make sure the image is not stretched if the server returned wrong dimensions
|
||||||
|
if(drawable!=null && (drawable.getIntrinsicWidth()!=card.width || drawable.getIntrinsicHeight()!=card.height)){
|
||||||
|
photo.setImageDrawable(null);
|
||||||
|
photo.setImageDrawable(crossfadeDrawable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -95,7 +102,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onClick(View v){
|
private void onClick(View v){
|
||||||
UiUtils.launchWebBrowser(itemView.getContext(), item.status.card.url);
|
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), item.status.card.url, item.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import android.graphics.drawable.ColorDrawable;
|
|||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Pair;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -21,6 +22,8 @@ import org.joinmastodon.android.R;
|
|||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Attachment;
|
import org.joinmastodon.android.model.Attachment;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
|
import org.joinmastodon.android.model.Translation;
|
||||||
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||||
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
|
||||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||||
@@ -31,7 +34,12 @@ import org.joinmastodon.android.ui.views.MediaGridLayout;
|
|||||||
import org.joinmastodon.android.utils.TypedObjectPool;
|
import org.joinmastodon.android.utils.TypedObjectPool;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||||
@@ -45,6 +53,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
|
private final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
|
||||||
private final TypedObjectPool<GridItemType, MediaAttachmentViewController> viewPool;
|
private final TypedObjectPool<GridItemType, MediaAttachmentViewController> viewPool;
|
||||||
private final List<Attachment> attachments;
|
private final List<Attachment> attachments;
|
||||||
|
private final Map<String, Pair<String, String>> translatedAttachments = new HashMap<>();
|
||||||
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
|
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
|
||||||
public final Status status;
|
public final Status status;
|
||||||
public boolean sensitiveRevealed;
|
public boolean sensitiveRevealed;
|
||||||
@@ -181,6 +190,25 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
|
|||||||
c.altButton.setAlpha(1f);
|
c.altButton.setAlpha(1f);
|
||||||
}
|
}
|
||||||
controllers.add(c);
|
controllers.add(c);
|
||||||
|
|
||||||
|
if (item.status.translation != null){
|
||||||
|
if(item.status.translationState==Status.TranslationState.SHOWN){
|
||||||
|
if(!item.translatedAttachments.containsKey(att.id)){
|
||||||
|
Optional<Translation.MediaAttachment> translatedAttachment=Arrays.stream(item.status.translation.mediaAttachments).filter(mediaAttachment->mediaAttachment.id.equals(att.id)).findFirst();
|
||||||
|
translatedAttachment.ifPresent(mediaAttachment->{
|
||||||
|
item.translatedAttachments.put(mediaAttachment.id, new Pair<>(att.description, mediaAttachment.description));
|
||||||
|
att.description=mediaAttachment.description;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
//SAFETY: must be non-null, as we check if the map contains the attachment before
|
||||||
|
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).second;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (item.translatedAttachments.containsKey(att.id)) {
|
||||||
|
att.description=Objects.requireNonNull(item.translatedAttachments.get(att.id)).first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
c.bind(att, item.status);
|
c.bind(att, item.status);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.widget.TextView;
|
|||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
import org.joinmastodon.android.model.Poll;
|
import org.joinmastodon.android.model.Poll;
|
||||||
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.OutlineProviders;
|
import org.joinmastodon.android.ui.OutlineProviders;
|
||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||||
@@ -22,6 +23,7 @@ import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
|||||||
|
|
||||||
public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
||||||
private CharSequence text;
|
private CharSequence text;
|
||||||
|
private CharSequence translatedText;
|
||||||
public final Poll.Option option;
|
public final Poll.Option option;
|
||||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||||
private boolean showResults;
|
private boolean showResults;
|
||||||
@@ -29,12 +31,15 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||||||
private boolean isMostVoted;
|
private boolean isMostVoted;
|
||||||
private final int optionIndex;
|
private final int optionIndex;
|
||||||
public final Poll poll;
|
public final Poll poll;
|
||||||
|
public final Status status;
|
||||||
|
|
||||||
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){
|
|
||||||
|
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment, Status status){
|
||||||
super(parentID, parentFragment);
|
super(parentID, parentFragment);
|
||||||
this.optionIndex=optionIndex;
|
this.optionIndex=optionIndex;
|
||||||
option=poll.options.get(optionIndex);
|
option=poll.options.get(optionIndex);
|
||||||
this.poll=poll;
|
this.poll=poll;
|
||||||
|
this.status=status;
|
||||||
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
text=HtmlParser.parseCustomEmoji(option.title, poll.emojis);
|
||||||
emojiHelper.setText(text);
|
emojiHelper.setText(text);
|
||||||
showResults=poll.isExpired() || poll.voted;
|
showResults=poll.isExpired() || poll.voted;
|
||||||
@@ -83,7 +88,14 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(PollOptionStatusDisplayItem item){
|
public void onBind(PollOptionStatusDisplayItem item){
|
||||||
text.setText(item.text);
|
if (item.status.translation != null && item.status.translationState == Status.TranslationState.SHOWN) {
|
||||||
|
if(item.translatedText==null){
|
||||||
|
item.translatedText=item.status.translation.poll.options[item.optionIndex].title;
|
||||||
|
}
|
||||||
|
text.setText(item.translatedText);
|
||||||
|
} else {
|
||||||
|
text.setText(item.text);
|
||||||
|
}
|
||||||
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
percent.setVisibility(item.showResults ? View.VISIBLE : View.GONE);
|
||||||
itemView.setClickable(!item.showResults);
|
itemView.setClickable(!item.showResults);
|
||||||
if(item.showResults){
|
if(item.showResults){
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
|
|||||||
public final Status status;
|
public final Status status;
|
||||||
public final ArrayList<StatusDisplayItem> contentItems=new ArrayList<>();
|
public final ArrayList<StatusDisplayItem> contentItems=new ArrayList<>();
|
||||||
private final CharSequence parsedTitle;
|
private final CharSequence parsedTitle;
|
||||||
|
private CharSequence translatedTitle;
|
||||||
private final CustomEmojiHelper emojiHelper;
|
private final CustomEmojiHelper emojiHelper;
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
|
||||||
@@ -85,7 +86,14 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(SpoilerStatusDisplayItem item){
|
public void onBind(SpoilerStatusDisplayItem item){
|
||||||
title.setText(item.parsedTitle);
|
if(item.status.translationState==Status.TranslationState.SHOWN){
|
||||||
|
if(item.translatedTitle==null){
|
||||||
|
item.translatedTitle=item.status.translation.spoilerText;
|
||||||
|
}
|
||||||
|
title.setText(item.translatedTitle);
|
||||||
|
}else{
|
||||||
|
title.setText(item.parsedTitle);
|
||||||
|
}
|
||||||
action.setText(item.status.spoilerRevealed ? R.string.spoiler_hide : R.string.spoiler_show);
|
action.setText(item.status.spoilerRevealed ? R.string.spoiler_hide : R.string.spoiler_show);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public abstract class StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!TextUtils.isEmpty(statusForContent.content)){
|
if(!TextUtils.isEmpty(statusForContent.content)){
|
||||||
SpannableStringBuilder parsedText=HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID);
|
SpannableStringBuilder parsedText=HtmlParser.parse(statusForContent.content, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, accountID, statusForContent);
|
||||||
if(filtered){
|
if(filtered){
|
||||||
HtmlParser.applyFilterHighlights(fragment.getActivity(), parsedText, status.filtered);
|
HtmlParser.applyFilterHighlights(fragment.getActivity(), parsedText, status.filtered);
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ public abstract class StatusDisplayItem{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(statusForContent.poll!=null){
|
if(statusForContent.poll!=null){
|
||||||
buildPollItems(parentID, fragment, statusForContent.poll, contentItems);
|
buildPollItems(parentID, fragment, statusForContent.poll, status, contentItems);
|
||||||
}
|
}
|
||||||
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty() && TextUtils.isEmpty(statusForContent.spoilerText)){
|
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty() && TextUtils.isEmpty(statusForContent.spoilerText)){
|
||||||
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
|
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
|
||||||
@@ -192,10 +192,10 @@ public abstract class StatusDisplayItem{
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
|
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, Status status, List<StatusDisplayItem> items){
|
||||||
int i=0;
|
int i=0;
|
||||||
for(Poll.Option opt:poll.options){
|
for(Poll.Option opt:poll.options){
|
||||||
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment));
|
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment, status));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));
|
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll));
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
|||||||
|
|
||||||
public void setTranslatedText(String text){
|
public void setTranslatedText(String text){
|
||||||
Status statusForContent=status.getContentStatus();
|
Status statusForContent=status.getContentStatus();
|
||||||
translatedText=HtmlParser.parse(text, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, parentFragment.getAccountID());
|
translatedText=HtmlParser.parse(text, statusForContent.emojis, statusForContent.mentions, statusForContent.tags, parentFragment.getAccountID(), statusForContent);
|
||||||
translationEmojiHelper.setText(translatedText);
|
translationEmojiHelper.setText(translatedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import android.graphics.Insets;
|
|||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
@@ -533,23 +534,31 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MediaPlayer findCurrentVideoPlayer(){
|
private GifVViewHolder findCurrentVideoPlayerHolder(){
|
||||||
RecyclerView rv=(RecyclerView) pager.getChildAt(0);
|
RecyclerView rv=(RecyclerView) pager.getChildAt(0);
|
||||||
if(rv.findViewHolderForAdapterPosition(pager.getCurrentItem()) instanceof GifVViewHolder vvh && vvh.playerReady){
|
if(rv.findViewHolderForAdapterPosition(pager.getCurrentItem()) instanceof GifVViewHolder vvh && vvh.playerReady){
|
||||||
return vvh.player;
|
return vvh;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MediaPlayer findCurrentVideoPlayer(){
|
||||||
|
GifVViewHolder holder=findCurrentVideoPlayerHolder();
|
||||||
|
return holder!=null ? holder.player : null;
|
||||||
|
}
|
||||||
|
|
||||||
private void pauseVideo(){
|
private void pauseVideo(){
|
||||||
MediaPlayer player=findCurrentVideoPlayer();
|
GifVViewHolder holder=findCurrentVideoPlayerHolder();
|
||||||
if(player==null || !player.isPlaying())
|
if(holder==null || !holder.player.isPlaying())
|
||||||
return;
|
return;
|
||||||
player.pause();
|
holder.player.pause();
|
||||||
videoPlayPauseButton.setImageResource(R.drawable.ic_play_24);
|
videoPlayPauseButton.setImageResource(R.drawable.ic_play_24);
|
||||||
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
|
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
|
||||||
stopUpdatingVideoPosition();
|
stopUpdatingVideoPosition();
|
||||||
windowView.removeCallbacks(uiAutoHider);
|
windowView.removeCallbacks(uiAutoHider);
|
||||||
|
// Some MediaPlayer implementations clear the texture when the app goes into background.
|
||||||
|
// This makes sure the frame on which the video was paused is retained on the screen.
|
||||||
|
holder.wrap.setBackground(new BitmapDrawable(holder.textureView.getBitmap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resumeVideo(){
|
private void resumeVideo(){
|
||||||
@@ -817,7 +826,10 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface){
|
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface){
|
||||||
|
// A new frame of video was rendered. Clear the thumbnail or paused frame, if any, to avoid overdraw and free up some memory.
|
||||||
|
if(player.isPlaying() && wrap.getBackground()!=null){
|
||||||
|
wrap.setBackground(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startPlayer(){
|
private void startPlayer(){
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class HtmlParser{
|
|||||||
* @param emojis Custom emojis that are present in source as <code>:code:</code>
|
* @param emojis Custom emojis that are present in source as <code>:code:</code>
|
||||||
* @return a spanned string
|
* @return a spanned string
|
||||||
*/
|
*/
|
||||||
public static SpannableStringBuilder parse(String source, List<Emoji> emojis, List<Mention> mentions, List<Hashtag> tags, String accountID){
|
public static SpannableStringBuilder parse(String source, List<Emoji> emojis, List<Mention> mentions, List<Hashtag> tags, String accountID, Object parentObject){
|
||||||
class SpanInfo{
|
class SpanInfo{
|
||||||
public Object span;
|
public Object span;
|
||||||
public int start;
|
public int start;
|
||||||
@@ -120,7 +120,7 @@ public class HtmlParser{
|
|||||||
}else{
|
}else{
|
||||||
linkType=LinkSpan.Type.URL;
|
linkType=LinkSpan.Type.URL;
|
||||||
}
|
}
|
||||||
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, linkObject), ssb.length(), el));
|
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, linkObject, parentObject), ssb.length(), el));
|
||||||
}
|
}
|
||||||
case "br" -> ssb.append('\n');
|
case "br" -> ssb.append('\n');
|
||||||
case "span" -> {
|
case "span" -> {
|
||||||
@@ -203,8 +203,28 @@ public class HtmlParser{
|
|||||||
public static String stripAndRemoveInvisibleSpans(String html){
|
public static String stripAndRemoveInvisibleSpans(String html){
|
||||||
Document doc=Jsoup.parseBodyFragment(html);
|
Document doc=Jsoup.parseBodyFragment(html);
|
||||||
doc.body().select("span.invisible").remove();
|
doc.body().select("span.invisible").remove();
|
||||||
Cleaner cleaner=new Cleaner(Safelist.none());
|
Cleaner cleaner=new Cleaner(Safelist.none().addTags("br", "p"));
|
||||||
return cleaner.clean(doc).body().html();
|
StringBuilder sb=new StringBuilder();
|
||||||
|
cleaner.clean(doc).body().traverse(new NodeVisitor(){
|
||||||
|
@Override
|
||||||
|
public void head(Node node, int depth){
|
||||||
|
if(node instanceof TextNode tn){
|
||||||
|
sb.append(tn.text());
|
||||||
|
}else if(node instanceof Element el){
|
||||||
|
if("br".equals(el.tagName())){
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tail(Node node, int depth){
|
||||||
|
if(node instanceof Element el && "p".equals(el.tagName()) && el.nextSibling()!=null){
|
||||||
|
sb.append("\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharSequence parseLinks(String text){
|
public static CharSequence parseLinks(String text){
|
||||||
@@ -216,7 +236,7 @@ public class HtmlParser{
|
|||||||
String url=matcher.group(3);
|
String url=matcher.group(3);
|
||||||
if(TextUtils.isEmpty(matcher.group(4)))
|
if(TextUtils.isEmpty(matcher.group(4)))
|
||||||
url="http://"+url;
|
url="http://"+url;
|
||||||
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, null), matcher.start(3), matcher.end(3), 0);
|
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, null, null), matcher.start(3), matcher.end(3), 0);
|
||||||
}while(matcher.find()); // Find more URLs
|
}while(matcher.find()); // Find more URLs
|
||||||
return ssb;
|
return ssb;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,15 @@ public class LinkSpan extends CharacterStyle {
|
|||||||
private Type type;
|
private Type type;
|
||||||
private String accountID;
|
private String accountID;
|
||||||
private Object linkObject;
|
private Object linkObject;
|
||||||
|
private Object parentObject;
|
||||||
|
|
||||||
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, Object linkObject){
|
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, Object linkObject, Object parentObject){
|
||||||
this.listener=listener;
|
this.listener=listener;
|
||||||
this.link=link;
|
this.link=link;
|
||||||
this.type=type;
|
this.type=type;
|
||||||
this.accountID=accountID;
|
this.accountID=accountID;
|
||||||
this.linkObject=linkObject;
|
this.linkObject=linkObject;
|
||||||
|
this.parentObject=parentObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getColor(){
|
public int getColor(){
|
||||||
@@ -36,7 +38,7 @@ public class LinkSpan extends CharacterStyle {
|
|||||||
|
|
||||||
public void onClick(Context context){
|
public void onClick(Context context){
|
||||||
switch(getType()){
|
switch(getType()){
|
||||||
case URL -> UiUtils.openURL(context, accountID, link);
|
case URL -> UiUtils.openURL(context, accountID, link, parentObject);
|
||||||
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
|
case MENTION -> UiUtils.openProfileByID(context, accountID, link);
|
||||||
case HASHTAG -> {
|
case HASHTAG -> {
|
||||||
if(linkObject instanceof Hashtag ht)
|
if(linkObject instanceof Hashtag ht)
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public class DiscoverInfoBannerHelper{
|
|||||||
private final BannerType type;
|
private final BannerType type;
|
||||||
private final String accountID;
|
private final String accountID;
|
||||||
private static EnumSet<BannerType> bannerTypesToShow=EnumSet.noneOf(BannerType.class);
|
private static EnumSet<BannerType> bannerTypesToShow=EnumSet.noneOf(BannerType.class);
|
||||||
|
private SingleViewRecyclerAdapter bannerAdapter;
|
||||||
|
private boolean added;
|
||||||
|
|
||||||
static{
|
static{
|
||||||
for(BannerType t:BannerType.values()){
|
for(BannerType t:BannerType.values()){
|
||||||
@@ -40,6 +42,8 @@ public class DiscoverInfoBannerHelper{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void maybeAddBanner(RecyclerView list, MergeRecyclerAdapter adapter){
|
public void maybeAddBanner(RecyclerView list, MergeRecyclerAdapter adapter){
|
||||||
|
if(added)
|
||||||
|
return;
|
||||||
if(bannerTypesToShow.contains(type)){
|
if(bannerTypesToShow.contains(type)){
|
||||||
banner=((Activity)list.getContext()).getLayoutInflater().inflate(R.layout.discover_info_banner, list, false);
|
banner=((Activity)list.getContext()).getLayoutInflater().inflate(R.layout.discover_info_banner, list, false);
|
||||||
TextView text=banner.findViewById(R.id.banner_text);
|
TextView text=banner.findViewById(R.id.banner_text);
|
||||||
@@ -56,7 +60,8 @@ public class DiscoverInfoBannerHelper{
|
|||||||
case LOCAL_TIMELINE -> R.drawable.ic_stream_24px;
|
case LOCAL_TIMELINE -> R.drawable.ic_stream_24px;
|
||||||
case ACCOUNTS -> R.drawable.ic_group_add_24px;
|
case ACCOUNTS -> R.drawable.ic_group_add_24px;
|
||||||
});
|
});
|
||||||
adapter.addAdapter(new SingleViewRecyclerAdapter(banner));
|
adapter.addAdapter(0, bannerAdapter=new SingleViewRecyclerAdapter(banner));
|
||||||
|
added=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +70,13 @@ public class DiscoverInfoBannerHelper{
|
|||||||
// bannerTypesToShow is not updated here on purpose so the banner keeps showing until the app is relaunched
|
// bannerTypesToShow is not updated here on purpose so the banner keeps showing until the app is relaunched
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void removeBanner(MergeRecyclerAdapter adapter){
|
||||||
|
if(bannerAdapter!=null){
|
||||||
|
adapter.removeAdapter(bannerAdapter);
|
||||||
|
added=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void reset(){
|
public static void reset(){
|
||||||
SharedPreferences prefs=getPrefs();
|
SharedPreferences prefs=getPrefs();
|
||||||
SharedPreferences.Editor e=prefs.edit();
|
SharedPreferences.Editor e=prefs.edit();
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class InsetStatusItemDecoration extends RecyclerView.ItemDecoration{
|
|||||||
outRect.left=outRect.right=V.dp(8);
|
outRect.left=outRect.right=V.dp(8);
|
||||||
if(!bottomSiblingInset)
|
if(!bottomSiblingInset)
|
||||||
outRect.bottom=V.dp(16);
|
outRect.bottom=V.dp(16);
|
||||||
if(!topSiblingInset && displayItems.get(pos-1) instanceof NotificationHeaderStatusDisplayItem)
|
if(!topSiblingInset && pos > 1 && displayItems.get(pos-1) instanceof NotificationHeaderStatusDisplayItem)
|
||||||
outRect.top=V.dp(-8);
|
outRect.top=V.dp(-8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,14 @@ import android.widget.Toolbar;
|
|||||||
|
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
|
import org.joinmastodon.android.MainActivity;
|
||||||
import org.joinmastodon.android.MastodonApp;
|
import org.joinmastodon.android.MastodonApp;
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.api.requests.accounts.SetAccountBlocked;
|
import org.joinmastodon.android.api.requests.accounts.SetAccountBlocked;
|
||||||
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
|
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
|
||||||
import org.joinmastodon.android.api.requests.accounts.SetAccountMuted;
|
import org.joinmastodon.android.api.requests.accounts.SetAccountMuted;
|
||||||
import org.joinmastodon.android.api.requests.accounts.SetDomainBlocked;
|
import org.joinmastodon.android.api.requests.accounts.SetDomainBlocked;
|
||||||
|
import org.joinmastodon.android.api.requests.search.GetSearchResults;
|
||||||
import org.joinmastodon.android.api.requests.statuses.DeleteStatus;
|
import org.joinmastodon.android.api.requests.statuses.DeleteStatus;
|
||||||
import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
|
import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
|
||||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||||
@@ -63,6 +65,7 @@ import org.joinmastodon.android.model.Account;
|
|||||||
import org.joinmastodon.android.model.Emoji;
|
import org.joinmastodon.android.model.Emoji;
|
||||||
import org.joinmastodon.android.model.Hashtag;
|
import org.joinmastodon.android.model.Hashtag;
|
||||||
import org.joinmastodon.android.model.Relationship;
|
import org.joinmastodon.android.model.Relationship;
|
||||||
|
import org.joinmastodon.android.model.SearchResults;
|
||||||
import org.joinmastodon.android.model.Status;
|
import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||||
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
||||||
@@ -80,6 +83,7 @@ import java.time.format.FormatStyle;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.BiPredicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -613,12 +617,18 @@ public class UiUtils{
|
|||||||
return GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK;
|
return GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void openURL(Context context, String accountID, String url){
|
public static void openURL(Context context, String accountID, String url, Object parentObject){
|
||||||
|
String objectURL=null;
|
||||||
|
if(parentObject instanceof Status s){
|
||||||
|
objectURL=s.url;
|
||||||
|
}else if(parentObject instanceof Account a){
|
||||||
|
objectURL=a.url;
|
||||||
|
}
|
||||||
Uri uri=Uri.parse(url);
|
Uri uri=Uri.parse(url);
|
||||||
if(accountID!=null && "https".equals(uri.getScheme()) && AccountSessionManager.getInstance().getAccount(accountID).domain.equalsIgnoreCase(uri.getAuthority())){
|
if(accountID!=null && "https".equals(uri.getScheme()) && !Objects.equals(url, objectURL)){
|
||||||
List<String> path=uri.getPathSegments();
|
List<String> path=uri.getPathSegments();
|
||||||
// Match URLs like https://mastodon.social/@Gargron/108132679274083591
|
if(AccountSessionManager.getInstance().getAccount(accountID).domain.equalsIgnoreCase(uri.getAuthority()) && path.size()==2 && path.get(0).matches("^@[a-zA-Z0-9_]+$") && path.get(1).matches("^[0-9]+$")){
|
||||||
if(path.size()==2 && path.get(0).matches("^@[a-zA-Z0-9_]+$") && path.get(1).matches("^[0-9]+$")){
|
// Match URLs like https://mastodon.social/@Gargron/108132679274083591
|
||||||
new GetStatusByID(path.get(1))
|
new GetStatusByID(path.get(1))
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
@@ -638,6 +648,42 @@ public class UiUtils{
|
|||||||
.wrapProgress((Activity)context, R.string.loading, true)
|
.wrapProgress((Activity)context, R.string.loading, true)
|
||||||
.exec(accountID);
|
.exec(accountID);
|
||||||
return;
|
return;
|
||||||
|
}else{
|
||||||
|
new GetSearchResults(url, null, true, null, 0, 0)
|
||||||
|
.setCallback(new Callback<>(){
|
||||||
|
@Override
|
||||||
|
public void onSuccess(SearchResults result){
|
||||||
|
Bundle args=new Bundle();
|
||||||
|
args.putString("account", accountID);
|
||||||
|
if(result.statuses!=null && !result.statuses.isEmpty()){
|
||||||
|
Status s=result.statuses.get(0);
|
||||||
|
if(parentObject instanceof Status status && s.id.equals(status.id)){
|
||||||
|
launchWebBrowser(context, url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
args.putParcelable("status", Parcels.wrap(s));
|
||||||
|
Nav.go((Activity)context, ThreadFragment.class, args);
|
||||||
|
}else if(result.accounts!=null && !result.accounts.isEmpty()){
|
||||||
|
Account a=result.accounts.get(0);
|
||||||
|
if(parentObject instanceof Account account && a.id.equals(account.id)){
|
||||||
|
launchWebBrowser(context, url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
args.putParcelable("profileAccount", Parcels.wrap(a));
|
||||||
|
Nav.go((Activity)context, ProfileFragment.class, args);
|
||||||
|
}else{
|
||||||
|
launchWebBrowser(context, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(ErrorResponse error){
|
||||||
|
launchWebBrowser(context, url);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.wrapProgress((Activity)context, R.string.loading, true)
|
||||||
|
.exec(accountID);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
launchWebBrowser(context, url);
|
launchWebBrowser(context, url);
|
||||||
@@ -656,6 +702,10 @@ public class UiUtils{
|
|||||||
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.code"));
|
return !TextUtils.isEmpty(getSystemProperty("ro.miui.ui.version.code"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isEMUI() {
|
||||||
|
return !TextUtils.isEmpty(getSystemProperty("ro.build.version.emui"));
|
||||||
|
}
|
||||||
|
|
||||||
public static int alphaBlendColors(int color1, int color2, float alpha){
|
public static int alphaBlendColors(int color1, int color2, float alpha){
|
||||||
float alpha0=1f-alpha;
|
float alpha0=1f-alpha;
|
||||||
int r=Math.round(((color1 >> 16) & 0xFF)*alpha0+((color2 >> 16) & 0xFF)*alpha);
|
int r=Math.round(((color1 >> 16) & 0xFF)*alpha0+((color2 >> 16) & 0xFF)*alpha);
|
||||||
@@ -802,4 +852,18 @@ public class UiUtils{
|
|||||||
Toast.makeText(context, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
Toast.makeText(context, R.string.text_copied, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setAllPaddings(View view, int paddingDp){
|
||||||
|
int pad=V.dp(paddingDp);
|
||||||
|
view.setPadding(pad, pad, pad, pad);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ViewGroup.MarginLayoutParams makeLayoutParams(int width, int height, int marginStart, int marginTop, int marginEnd, int marginBottom){
|
||||||
|
ViewGroup.MarginLayoutParams lp=new ViewGroup.MarginLayoutParams(width>0 ? V.dp(width) : width, height>0 ? V.dp(height) : height);
|
||||||
|
lp.topMargin=V.dp(marginTop);
|
||||||
|
lp.bottomMargin=V.dp(marginBottom);
|
||||||
|
lp.setMarginStart(V.dp(marginStart));
|
||||||
|
lp.setMarginEnd(V.dp(marginEnd));
|
||||||
|
return lp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class ComposeMediaViewController{
|
|||||||
updateMediaAttachmentsLayout();
|
updateMediaAttachmentsLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean addMediaAttachment(Uri uri, String description){
|
public boolean addMediaAttachment(Uri uri, String description){
|
||||||
if(getMediaAttachmentsCount()==MAX_ATTACHMENTS){
|
if(getMediaAttachmentsCount()==MAX_ATTACHMENTS){
|
||||||
showMediaAttachmentError(fragment.getResources().getQuantityString(R.plurals.cant_add_more_than_x_attachments, MAX_ATTACHMENTS, MAX_ATTACHMENTS));
|
showMediaAttachmentError(fragment.getResources().getQuantityString(R.plurals.cant_add_more_than_x_attachments, MAX_ATTACHMENTS, MAX_ATTACHMENTS));
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ public class ToolbarDropdownMenuController{
|
|||||||
public void resizeOnNextFrame(){
|
public void resizeOnNextFrame(){
|
||||||
if(currentTransition!=null)
|
if(currentTransition!=null)
|
||||||
currentTransition.cancel();
|
currentTransition.cancel();
|
||||||
|
if(windowView==null)
|
||||||
|
return;
|
||||||
int origBottom=menuContainer.getBottom();
|
int origBottom=menuContainer.getBottom();
|
||||||
menuContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
menuContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ package org.joinmastodon.android.ui.viewholders;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
||||||
|
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.joinmastodon.android.ui.views.M3Switch;
|
import org.joinmastodon.android.ui.views.M3Switch;
|
||||||
|
|
||||||
import me.grishka.appkit.utils.V;
|
import me.grishka.appkit.utils.V;
|
||||||
@@ -14,8 +17,17 @@ public class SwitchListItemViewHolder extends CheckableListItemViewHolder{
|
|||||||
private final M3Switch sw;
|
private final M3Switch sw;
|
||||||
private boolean ignoreListener;
|
private boolean ignoreListener;
|
||||||
|
|
||||||
public SwitchListItemViewHolder(Context context, ViewGroup parent){
|
public SwitchListItemViewHolder(Context context, ViewGroup parent, boolean separated){
|
||||||
super(context, parent);
|
super(context, parent);
|
||||||
|
if(separated){
|
||||||
|
View separator=new View(context);
|
||||||
|
separator.setBackgroundColor(UiUtils.getThemeColor(context, R.attr.colorM3OutlineVariant));
|
||||||
|
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(V.dp(1), V.dp(32));
|
||||||
|
lp.gravity=Gravity.TOP;
|
||||||
|
lp.setMarginStart(V.dp(16));
|
||||||
|
lp.setMarginEnd(V.dp(-1));
|
||||||
|
checkableLayout.addView(separator, lp);
|
||||||
|
}
|
||||||
sw=new M3Switch(context);
|
sw=new M3Switch(context);
|
||||||
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(V.dp(52), V.dp(32));
|
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(V.dp(52), V.dp(32));
|
||||||
lp.gravity=Gravity.TOP;
|
lp.gravity=Gravity.TOP;
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ public class ReorderableLinearLayout extends LinearLayout implements CustomViewH
|
|||||||
else
|
else
|
||||||
bottomSibling=null;
|
bottomSibling=null;
|
||||||
dragListener.onSwapItems(prevIndex, index);
|
dragListener.onSwapItems(prevIndex, index);
|
||||||
|
final View draggedView=this.draggedView;
|
||||||
draggedView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
draggedView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreDraw(){
|
public boolean onPreDraw(){
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package org.joinmastodon.android.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Something like a horizontal LinearLayout, but wraps child views onto a new line if they don't fit
|
||||||
|
*/
|
||||||
|
public class WrappingLinearLayout extends ViewGroup{
|
||||||
|
private int verticalGap, horizontalGap;
|
||||||
|
private ArrayList<Integer> rowHeights=new ArrayList<>();
|
||||||
|
|
||||||
|
public WrappingLinearLayout(Context context){
|
||||||
|
this(context, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappingLinearLayout(Context context, AttributeSet attrs){
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappingLinearLayout(Context context, AttributeSet attrs, int defStyle){
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.WrappingLinearLayout);
|
||||||
|
verticalGap=ta.getDimensionPixelOffset(R.styleable.WrappingLinearLayout_android_verticalGap, 0);
|
||||||
|
horizontalGap=ta.getDimensionPixelOffset(R.styleable.WrappingLinearLayout_android_horizontalGap, 0);
|
||||||
|
ta.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
|
||||||
|
int w=MeasureSpec.getSize(widthMeasureSpec)-getPaddingLeft()-getPaddingRight();
|
||||||
|
int heightUsed=0, widthRemain=w, currentRowHeight=0;
|
||||||
|
rowHeights.clear();
|
||||||
|
for(int i=0;i<getChildCount();i++){
|
||||||
|
View child=getChildAt(i);
|
||||||
|
if(child.getVisibility()==GONE)
|
||||||
|
continue;
|
||||||
|
LayoutParams lp=child.getLayoutParams();
|
||||||
|
int horizontalPadding=getPaddingLeft()+getPaddingRight();
|
||||||
|
int verticalPadding=getPaddingTop()+getPaddingBottom();
|
||||||
|
int horizontalMargins=0, verticalMargins=0;
|
||||||
|
if(lp instanceof MarginLayoutParams mlp){
|
||||||
|
horizontalPadding+=mlp.leftMargin+mlp.rightMargin;
|
||||||
|
verticalPadding+=mlp.topMargin+mlp.bottomMargin;
|
||||||
|
horizontalMargins=mlp.leftMargin+mlp.rightMargin;
|
||||||
|
verticalMargins=mlp.topMargin+mlp.bottomMargin;
|
||||||
|
}
|
||||||
|
child.measure(getChildMeasureSpec(widthMeasureSpec, horizontalPadding, lp.width), getChildMeasureSpec(heightMeasureSpec, verticalPadding, lp.height));
|
||||||
|
currentRowHeight=Math.max(child.getMeasuredHeight()+verticalMargins, currentRowHeight);
|
||||||
|
if(child.getMeasuredWidth()+(widthRemain<w ? horizontalGap : 0)+horizontalMargins>widthRemain){
|
||||||
|
// Doesn't fit into the current row. Start a new one.
|
||||||
|
heightUsed+=currentRowHeight+verticalGap;
|
||||||
|
rowHeights.add(currentRowHeight);
|
||||||
|
currentRowHeight=child.getMeasuredHeight()+verticalMargins;
|
||||||
|
widthRemain=w;
|
||||||
|
}else{
|
||||||
|
// Does fit. Advance horizontally.
|
||||||
|
if(widthRemain<w)
|
||||||
|
widthRemain-=horizontalGap;
|
||||||
|
widthRemain-=child.getMeasuredWidth()+horizontalMargins;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Take last row into account
|
||||||
|
heightUsed+=currentRowHeight;
|
||||||
|
rowHeights.add(currentRowHeight);
|
||||||
|
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), heightUsed+getPaddingTop()+getPaddingBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int l, int t, int r, int b){
|
||||||
|
if(rowHeights.isEmpty())
|
||||||
|
return;
|
||||||
|
boolean rtl=getLayoutDirection()==LAYOUT_DIRECTION_RTL;
|
||||||
|
int xOffset=rtl ? getPaddingRight() : getPaddingLeft();
|
||||||
|
int endPadding=rtl ? getPaddingLeft() : getPaddingRight();
|
||||||
|
int yOffset=getPaddingTop();
|
||||||
|
int w=getWidth()-getPaddingLeft()-getPaddingRight();
|
||||||
|
int currentRowIndex=0;
|
||||||
|
boolean firstInRow=true;
|
||||||
|
for(int i=0;i<getChildCount();i++){
|
||||||
|
View child=getChildAt(i);
|
||||||
|
if(child.getVisibility()==GONE)
|
||||||
|
continue;
|
||||||
|
int childW=child.getMeasuredWidth();
|
||||||
|
int childH=child.getMeasuredHeight();
|
||||||
|
int rowHeight=rowHeights.get(currentRowIndex);
|
||||||
|
int childY, childX=xOffset;
|
||||||
|
if(getWidth()-(xOffset+childW+(firstInRow ? 0 : horizontalGap))>=endPadding){
|
||||||
|
xOffset+=childW+horizontalGap;
|
||||||
|
if(child.getLayoutParams() instanceof MarginLayoutParams mlp){
|
||||||
|
xOffset+=mlp.leftMargin+mlp.rightMargin;
|
||||||
|
}
|
||||||
|
firstInRow=false;
|
||||||
|
}else if(currentRowIndex<rowHeights.size()-1){
|
||||||
|
xOffset=rtl ? getPaddingRight() : getPaddingLeft();
|
||||||
|
yOffset+=rowHeight+verticalGap;
|
||||||
|
currentRowIndex++;
|
||||||
|
childX=xOffset;
|
||||||
|
rowHeight=rowHeights.get(currentRowIndex);
|
||||||
|
}
|
||||||
|
if(childH<rowHeight){
|
||||||
|
childY=yOffset+rowHeight/2-childH/2;
|
||||||
|
}else{
|
||||||
|
childY=yOffset;
|
||||||
|
}
|
||||||
|
if(rtl){
|
||||||
|
childX=getWidth()-childX-childW;
|
||||||
|
}
|
||||||
|
if(child.getLayoutParams() instanceof MarginLayoutParams mlp){
|
||||||
|
childX+=rtl ? mlp.rightMargin : mlp.leftMargin;
|
||||||
|
childY+=mlp.topMargin;
|
||||||
|
}
|
||||||
|
child.layout(childX, childY, childX+childW, childY+childH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayoutParams generateLayoutParams(AttributeSet attrs){
|
||||||
|
return new MarginLayoutParams(getContext(), attrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
8
mastodon/src/main/res/drawable/bg_rect_ripple.xml
Normal file
8
mastodon/src/main/res/drawable/bg_rect_ripple.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/m3_on_surface_overlay">
|
||||||
|
<item android:id="@android:id/mask">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="#000"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
||||||
6
mastodon/src/main/res/drawable/bg_user_info.xml
Normal file
6
mastodon/src/main/res/drawable/bg_user_info.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<corners android:radius="12dp"/>
|
||||||
|
<solid android:color="?colorM3SurfaceVariant"/>
|
||||||
|
<stroke android:color="?colorM3OutlineVariant" android:width="1dp"/>
|
||||||
|
</shape>
|
||||||
9
mastodon/src/main/res/drawable/divider_inset_16dp.xml
Normal file
9
mastodon/src/main/res/drawable/divider_inset_16dp.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:left="16dp" android:right="16dp">
|
||||||
|
<shape>
|
||||||
|
<solid android:color="?colorM3OutlineVariant"/>
|
||||||
|
<size android:height="0.5dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</layer-list>
|
||||||
5
mastodon/src/main/res/drawable/fg_user_info_ava.xml
Normal file
5
mastodon/src/main/res/drawable/fg_user_info_ava.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<stroke android:width="1dp" android:color="?colorM3OutlineVariant"/>
|
||||||
|
<corners android:radius="11dp"/>
|
||||||
|
</shape>
|
||||||
5
mastodon/src/main/res/drawable/ic_boost.xml
Normal file
5
mastodon/src/main/res/drawable/ic_boost.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:state_selected="true" android:drawable="@drawable/ic_boost_fill_alt_24px"/>
|
||||||
|
<item android:drawable="@drawable/ic_boost_24px"/>
|
||||||
|
</selector>
|
||||||
9
mastodon/src/main/res/drawable/ic_boost_24px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_boost_24px.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="M7,22L3,18L7,14L8.4,15.45L6.85,17H17V13H19V19H6.85L8.4,20.55L7,22ZM5,11V5H17.15L15.6,3.45L17,2L21,6L17,10L15.6,8.55L17.15,7H7V11H5Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
15
mastodon/src/main/res/drawable/ic_boost_disabled_24px.xml
Normal file
15
mastodon/src/main/res/drawable/ic_boost_disabled_24px.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<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="M19,13V17.879L17,15.879V13H19Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M2.414,2.707L1,4.121L5,8.121V11H7V10.121L13.879,17H6.85L8.4,15.45L7,14L3,18L7,22L8.4,20.55L6.85,19H15.879L19.385,22.506L20.799,21.092L2.414,2.707Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M17.15,7H8.121L6.121,5H17.15L15.6,3.45L17,2L21,6L17,10L15.6,8.55L17.15,7Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
@@ -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="M6.775,22.875L2.15,18.25L6.775,13.625L8.8,15.7L7.675,16.8H16.95V12.8H19.85V19.7H7.675L8.8,20.8L6.775,22.875ZM4.15,11.45V4.55H16.35L15.225,3.45L17.25,1.375L21.875,6L17.25,10.625L15.225,8.55L16.35,7.45H7.05V11.45H4.15Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
5
mastodon/src/main/res/drawable/ic_boost_private.xml
Normal file
5
mastodon/src/main/res/drawable/ic_boost_private.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:state_selected="true" android:drawable="@drawable/ic_private_boost_fill_alt_24px"/>
|
||||||
|
<item android:drawable="@drawable/ic_private_boost_24px"/>
|
||||||
|
</selector>
|
||||||
9
mastodon/src/main/res/drawable/ic_campaign_24px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_campaign_24px.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:fillColor="@android:color/white"
|
||||||
|
android:pathData="M18,13V11H22V13ZM19.2,20 L16,17.6 17.2,16 20.4,18.4ZM17.2,8 L16,6.4 19.2,4 20.4,5.6ZM5,19V15H4Q3.175,15 2.588,14.412Q2,13.825 2,13V11Q2,10.175 2.588,9.587Q3.175,9 4,9H8L13,6V18L8,15H7V19ZM14,15.35V8.65Q14.675,9.25 15.088,10.113Q15.5,10.975 15.5,12Q15.5,13.025 15.088,13.887Q14.675,14.75 14,15.35ZM4,11Q4,11 4,11Q4,11 4,11V13Q4,13 4,13Q4,13 4,13H8.55L11,14.45V9.55L8.55,11ZM7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Q7.5,12 7.5,12Z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M15,31c0,2.209 -0.791,4 -3,4H5c-4,0 -4,-14 0,-14h7c2.209,0 3,1.791 3,4v6z"
|
|
||||||
android:fillColor="#553788"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M34,33h-1V23h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H10c-4,0 -4,14 0,14h24c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
|
|
||||||
android:fillColor="#9266CC"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M34.172,33H11c-2,0 -2,-10 0,-10h23.172c1.104,0 1.104,10 0,10z"
|
|
||||||
android:fillColor="#CCD6DD"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M11.5,25h23.35c-0.135,-1.175 -0.36,-2 -0.678,-2H11c-1.651,0 -1.938,6.808 -0.863,9.188C9.745,29.229 10.199,25 11.5,25z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M12,8c0,2.209 -1.791,4 -4,4H4C0,12 0,1 4,1h4c2.209,0 4,1.791 4,4v3z"
|
|
||||||
android:fillColor="#269"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M31,10h-1V3h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H7C3,1 3,12 7,12h24c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
|
|
||||||
android:fillColor="#55ACEE"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M31.172,10H8c-2,0 -2,-7 0,-7h23.172c1.104,0 1.104,7 0,7z"
|
|
||||||
android:fillColor="#CCD6DD"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M8,5h23.925c-0.114,-1.125 -0.364,-2 -0.753,-2H8C6.807,3 6.331,5.489 6.562,7.5 6.718,6.142 7.193,5 8,5z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M20,17c0,2.209 -1.791,4 -4,4H6c-4,0 -4,-9 0,-9h10c2.209,0 4,1.791 4,4v1z"
|
|
||||||
android:fillColor="#F4900C"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M35,19h-1v-5h1c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1H15c-4,0 -4,9 0,9h20c0.553,0 1,-0.447 1,-1s-0.447,-1 -1,-1z"
|
|
||||||
android:fillColor="#FFAC33"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M35.172,19H16c-2,0 -2,-5 0,-5h19.172c1.104,0 1.104,5 0,5z"
|
|
||||||
android:fillColor="#CCD6DD"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M16,16h19.984c-0.065,-1.062 -0.334,-2 -0.812,-2H16c-1.274,0 -1.733,2.027 -1.383,3.5 0.198,-0.839 0.657,-1.5 1.383,-1.5z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M32.218,10.913c-0.81,-1.187 -2.172,-1.967 -3.718,-1.967H28s-5.353,-5.672 -5.15,-6.091C21.754,3.446 21,4.591 21,5.924c0,0 -5.509,-3.431 -5.247,-3.947C14.71,2.669 14,3.946 14,5.424v0.522S8.553,4.321 8.857,3.851C7.757,4.441 7,5.588 7,6.924V8.81l-6,6.272v2.645l17.16,14.439c0,0.001 13.128,-22.164 14.058,-21.253z"
|
|
||||||
android:fillColor="#EF9645"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M4.124,18.946c1.474,0 2.738,-0.831 3.392,-2.043 0.678,1.212 1.958,2.043 3.446,2.043h0.076c1.153,0 2.169,-0.51 2.889,-1.298 0.023,-0.024 0.073,-0.082 0.073,-0.082 0.185,-0.212 0.343,-0.448 0.481,-0.695 0.04,-0.072 0.281,-0.621 0.342,-0.833 0.052,-0.173 0.106,-0.344 0.134,-0.526 0.141,0.167 0.296,0.319 0.46,0.46 0.069,0.059 0.45,0.339 0.576,0.413 0.589,0.351 1.271,0.56 2.008,0.56h3.166c-0.535,0.27 -0.999,0.614 -1.424,1 -1.729,1.568 -2.579,4.085 -2.579,7.663 0,0.276 0.224,0.5 0.5,0.5s0.5,-0.224 0.5,-0.5c0,-3.962 1.01,-6.427 3.24,-7.663 1.175,-0.651 2.682,-0.967 4.571,-0.967 0.059,0 0.526,-0.033 0.526,-0.033 0.276,0 0.5,-0.224 0.5,-0.5s-0.224,-0.5 -0.5,-0.5H18c-1.657,0 -3,-1.343 -3,-3s1.343,-3 3,-3h11c0.973,0 2.288,0.056 3.218,0.967 0.325,0.318 0.604,0.736 0.803,1.297l1.659,5.472c0.156,0.512 0.73,2.857 0.626,3.346 0,7.34 -8.7,14.972 -19.004,14.972C6.326,36 1,27.883 1,17.957v-0.229c0.01,0.01 0.021,0.016 0.031,0.026 0.881,0.882 1.799,1.192 2.845,1.192h0.248z"
|
|
||||||
android:fillColor="#FFDC5D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M3.864,5.946h0.271C5.718,5.946 7,7.229 7,8.81v6.272c0,1.582 -1.282,2.864 -2.864,2.864h-0.272C2.282,17.946 1,16.664 1,15.082L1,8.81c0,-1.581 1.282,-2.864 2.864,-2.864zM14,14.946c0,0.891 -0.396,1.683 -1.014,2.233 -0.53,0.472 -1.221,0.767 -1.986,0.767 -1.657,0 -3,-1.343 -3,-3v-9c0,-0.816 0.328,-1.554 0.857,-2.095 0.544,-0.557 1.302,-0.905 2.143,-0.905 1.657,0 3,1.343 3,3v9zM18,8.946c-1.201,0 -2.267,0.541 -3,1.38v-6.38c0,-0.758 0.29,-1.442 0.753,-1.97 0.55,-0.627 1.347,-1.03 2.247,-1.03 1.657,0 3,1.343 3,3v5h-3zM22,4.939c0,-0.812 0.326,-1.545 0.85,-2.085 0.544,-0.559 1.301,-0.909 2.143,-0.909h0.014C26.66,1.946 28,3.286 28,4.939v4.007h-6L22,4.939z"
|
|
||||||
android:fillColor="#FFDC5D"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M18,1C8.059,1 0,7.268 0,15c0,4.368 2.574,8.268 6.604,10.835C6.08,28.144 4.859,31.569 2,35c5.758,-0.96 9.439,-3.761 11.716,-6.416 1.376,0.262 2.805,0.416 4.284,0.416 9.941,0 18,-6.268 18,-14S27.941,1 18,1z"
|
|
||||||
android:fillColor="#BDDDF4"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
|
||||||
android:fillColor="#2A6797"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M26,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
|
||||||
android:fillColor="#2A6797"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M10,15m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"
|
|
||||||
android:fillColor="#2A6797"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M18,3.143c-9.941,0 -18,6.908 -18,15.428 0,1.066 0.126,2.107 0.367,3.112C2.146,24.744 3.377,22.812 9,20c5.727,-2.864 0,4 -2,8 -0.615,1.23 -0.282,2.271 0.56,3.124C10.506,32.928 14.104,34 18,34c9.941,0 18,-6.907 18,-15.429 0,-8.52 -8.059,-15.428 -18,-15.428zM20.849,27.59c-0.395,1.346 -2.46,1.924 -4.613,1.291 -2.153,-0.632 -3.578,-2.234 -3.183,-3.581 0.395,-1.346 2.46,-1.924 4.613,-1.29 2.153,0.631 3.578,2.233 3.183,3.58z"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M10,11m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
|
|
||||||
android:fillColor="#5C913B"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M20,9m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
|
|
||||||
android:fillColor="#269"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M29,15m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
|
|
||||||
android:fillColor="#DD2E44"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M28,24m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
|
|
||||||
android:fillColor="#FFCC4D"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M18,4c7.257,0 13,4 14.699,2 0.197,-0.323 0.301,-0.657 0.301,-1 0,-2 -6.716,-5 -15,-5C9.716,0 3,3 3,5c0,0.343 0.104,0.677 0.301,1C5,8 10.743,4 18,4z"
|
|
||||||
android:fillColor="#F4900C"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,3C11.787,3 7.384,4.81 5.727,5.618c-0.477,0.233 -0.539,0.84 -0.415,1.278S16,34 16,34s0.896,2 2,2 2,-2 2,-2L30.704,6.779s0.213,-0.842 -0.569,-1.229C28.392,4.689 24.047,3 18,3z"
|
|
||||||
android:fillColor="#FFCC4D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,31c0,-2.208 -1.791,-4 -4,-4 -0.254,0 -0.5,0.029 -0.741,0.075L16,34s0.071,0.14 0.19,0.342C17.279,33.627 18,32.399 18,31zM17,20c0,-2.209 -1.792,-4 -4,-4 -1.426,0 -2.67,0.752 -3.378,1.876l2.362,5.978c0.327,0.086 0.663,0.146 1.016,0.146 2.208,0 4,-1.792 4,-4z"
|
|
||||||
android:fillColor="#BE1931"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M16,8m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
|
||||||
android:fillColor="#BE1931"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M25,9c-2.208,0 -4,1.791 -4,4s1.792,4 4,4c0.682,0 1.315,-0.187 1.877,-0.488l1.89,-4.806C28.227,10.135 26.752,9 25,9zM19,25c0,1.868 1.288,3.425 3.019,3.864l2.893,-7.357C24.342,21.194 23.697,21 23,21c-2.208,0 -4,1.792 -4,4zM10,12c0,-2.209 -1.791,-4 -4,-4 -0.087,0 -0.169,0.02 -0.255,0.026 0.55,1.412 1.575,4.016 2.775,7.057C9.416,14.349 10,13.248 10,12z"
|
|
||||||
android:fillColor="#BE1931"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M32.325,10.958s2.315,0.024 3.511,1.177c-0.336,-4.971 -2.104,-8.249 -5.944,-10.13 -3.141,-1.119 -6.066,1.453 -6.066,1.453s0.862,-1.99 2.19,-2.746C23.789,0.236 21.146,0 18,0c-3.136,0 -5.785,0.227 -8.006,0.701 1.341,0.745 2.215,2.758 2.215,2.758S9.194,0.803 6,2.053C2.221,3.949 0.481,7.223 0.158,12.174c1.183,-1.19 3.55,-1.215 3.55,-1.215S-0.105,13.267 0.282,16.614c0.387,2.947 1.394,5.967 2.879,8.722C3.039,22.15 5.917,20 5.917,20s-2.492,5.96 -0.581,8.738c1.935,2.542 4.313,4.641 6.976,5.916 -0.955,-1.645 -0.136,-3.044 -0.103,-2.945 0.042,0.125 0.459,3.112 2.137,3.743 1.178,0.356 2.4,0.548 3.654,0.548 1.292,0 2.55,-0.207 3.761,-0.583 1.614,-0.691 2.024,-3.585 2.064,-3.708 0.032,-0.098 0.843,1.287 -0.09,2.921 2.706,-1.309 5.118,-3.463 7.064,-6.073 1.699,-2.846 -0.683,-8.557 -0.683,-8.557s2.85,2.13 2.757,5.288c1.556,-2.906 2.585,-6.104 2.911,-9.2 -0.035,-3.061 -3.459,-5.13 -3.459,-5.13z"
|
|
||||||
android:fillColor="#662113"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M13.859,9.495c0.596,2.392 0.16,4.422 -2.231,5.017 -2.392,0.596 -6.363,0.087 -6.958,-2.304 -0.596,-2.392 0.469,-5.39 1.81,-5.724 1.341,-0.334 6.784,0.62 7.379,3.011zM22.963,27.927c0,2.74 -2.222,4.963 -4.963,4.963s-4.963,-2.223 -4.963,-4.963c0,-2.741 2.223,-4.964 4.963,-4.964 2.741,0 4.963,2.222 4.963,4.964z"
|
|
||||||
android:fillColor="#FFCC4D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M21.309,27.927c0,1.827 -1.481,3.309 -3.309,3.309s-3.309,-1.481 -3.309,-3.309c0,-1.827 1.481,-3.31 3.309,-3.31s3.309,1.483 3.309,3.31z"
|
|
||||||
android:fillColor="#DD2E44"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M11.052,8.997c0.871,1.393 0.447,3.229 -0.946,4.1 -1.394,0.871 -2.608,0.797 -3.479,-0.596 -0.871,-1.394 -0.186,-4.131 0.324,-4.45 0.51,-0.319 3.23,-0.448 4.101,0.946z"
|
|
||||||
android:fillColor="#E6AAAA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M22.141,9.495c-0.596,2.392 -0.159,4.422 2.232,5.017 2.392,0.596 6.363,0.087 6.959,-2.304 0.596,-2.392 -0.47,-5.39 -1.811,-5.724 -1.342,-0.334 -6.786,0.62 -7.38,3.011z"
|
|
||||||
android:fillColor="#FFCC4D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M24.948,8.997c-0.871,1.393 -0.447,3.229 0.945,4.1 1.394,0.871 2.608,0.797 3.479,-0.596 0.871,-1.394 0.185,-4.131 -0.324,-4.45 -0.51,-0.319 -3.229,-0.448 -4.1,0.946z"
|
|
||||||
android:fillColor="#E6AAAA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,7.125h-0.002C5.167,7.126 7.125,12.083 8.5,18.667 9.875,25.25 10.384,27 10.384,27h15.228s0.51,-1.75 1.885,-8.333C28.872,12.083 30.829,7.126 18,7.125z"
|
|
||||||
android:fillColor="#FFCC4D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M12,16s0,-1.5 1.5,-1.5S15,16 15,16v1.5s0,1.5 -1.5,1.5 -1.5,-1.5 -1.5,-1.5L12,16zM21,16s0,-1.5 1.5,-1.5S24,16 24,16v1.5s0,1.5 -1.5,1.5 -1.5,-1.5 -1.5,-1.5L21,16z"
|
|
||||||
android:fillColor="#272B2B"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M20.168,21.521c-1.598,0 -1.385,0.848 -2.168,2.113 -0.783,-1.266 -0.571,-2.113 -2.168,-2.113 -6.865,0 -6.837,0.375 -6.865,2.828 -0.058,4.986 2.802,6.132 5.257,6.06 1.597,-0.048 2.994,-0.88 3.777,-2.131 0.783,1.251 2.179,2.083 3.776,2.131 2.455,0.072 5.315,-1.073 5.257,-6.06 -0.029,-2.453 -0.001,-2.828 -6.866,-2.828z"
|
|
||||||
android:fillColor="#FFE8B6"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M14.582,21.411c-1.14,0.233 2.279,4.431 3.418,4.431s4.559,-4.198 3.419,-4.431c-1.14,-0.232 -5.698,-0.232 -6.837,0z"
|
|
||||||
android:fillColor="#272B2B"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M11.5,24.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M10.5,26.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M12.5,27.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M24.5,24.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M25.5,26.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M23.5,27.5m-0.5,0a0.5,0.5 0,1 1,1 0a0.5,0.5 0,1 1,-1 0"
|
|
||||||
android:fillColor="#D99E82"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M16,9h4v17h-4z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M10,24.5c0,0.828 -0.672,1.5 -1.5,1.5h-3c-0.828,0 -1.5,-0.672 -1.5,-1.5S4.672,23 5.5,23h3c0.828,0 1.5,0.672 1.5,1.5z"
|
|
||||||
android:fillColor="#DA2F47"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M34,33c0,1.104 -0.896,2 -2,2H4c-1.104,0 -2,-0.896 -2,-2v-6c0,-1.104 0.896,-2 2,-2h28c1.104,0 2,0.896 2,2v6z"
|
|
||||||
android:fillColor="#31373D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M10,34.5c0,0.828 -0.671,1.5 -1.5,1.5h-3c-0.829,0 -1.5,-0.672 -1.5,-1.5S4.671,33 5.5,33h3c0.829,0 1.5,0.672 1.5,1.5zM32,34.5c0,0.828 -0.672,1.5 -1.5,1.5h-3c-0.828,0 -1.5,-0.672 -1.5,-1.5s0.672,-1.5 1.5,-1.5h3c0.828,0 1.5,0.672 1.5,1.5z"
|
|
||||||
android:fillColor="#31373D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,7m-5,0a5,5 0,1 1,10 0a5,5 0,1 1,-10 0"
|
|
||||||
android:fillColor="#DA2F47"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M25,26c0,1.104 -0.896,2 -2,2H13c-1.104,0 -2,-0.896 -2,-2v-1c0,-1.104 3.896,-6 5,-6h4c1.104,0 5,4.896 5,6v1z"
|
|
||||||
android:fillColor="#31373D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M33,28c0,0.553 -0.447,1 -1,1H4c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h28c0.553,0 1,0.447 1,1z"
|
|
||||||
android:fillColor="#66757F"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M34.453,15.573c-0.864,-7.3 -5.729,-10.447 -13.93,-10.447 -0.391,0 -0.763,0.017 -1.139,0.031 -0.013,-0.01 -0.022,-0.021 -0.035,-0.031C14.655,1.605 4.091,2.779 1.745,6.3c-3.255,4.883 -1.174,22.3 0,24.646 1.173,2.35 4.694,3.521 5.868,2.35 1.174,-1.176 0,-1.176 -1.173,-3.521 -0.85,-1.701 -0.466,-5.859 0.255,-8.471 0.028,0.168 0.068,0.322 0.1,0.486 0.39,2.871 1.993,7.412 1.993,9.744 0,3.564 2.102,4.107 4.694,4.107 2.593,0 4.695,-0.543 4.695,-4.107 0,-0.24 -0.008,-0.463 -0.012,-0.695 0.757,0.064 1.535,0.107 2.359,0.107 0.497,0 0.977,-0.016 1.448,-0.039 -0.004,0.209 -0.013,0.41 -0.013,0.627 0,3.564 2.103,4.107 4.694,4.107 2.593,0 4.695,-0.543 4.695,-4.107 0,-1.801 1.192,-4.625 2.039,-6.982 0.159,-0.354 0.291,-0.732 0.42,-1.117 0.118,1.307 0.193,2.706 0.193,4.206 0,0.553 0.447,1 1,1s1,-0.447 1,-1c0,-5.153 -0.771,-9.248 -1.547,-12.068z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M19.35,5.126S23,10.641 20,15.641c-3,5 -7.838,5 -11,5 -2,0 -1,2 0,2 1.414,0 8.395,1.211 12,-6 3,-6 -1.65,-11.515 -1.65,-11.515z"
|
|
||||||
android:fillColor="#66757F"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M6.5,14.141m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"
|
|
||||||
android:fillColor="#292F33"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M33,36H4c4,0 3,-9 3,-9 0,-2.209 1.791,-15 4,-15h21s4,0 4,4v17s0,3 -3,3z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M30,33c0,3 3,3 3,3H3s-3,0 -3,-4V4c0,-2.209 1.791,-4 4,-4h22c2.209,0 4,1.791 4,4v29z"
|
|
||||||
android:fillColor="#CCD6DD"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M27,20c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,16c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,12c0,0.553 -0.447,1 -1,1h-8c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h8c0.553,0 1,0.447 1,1zM27,24c0,0.553 -0.447,1 -1,1L4,25c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM27,28c0,0.553 -0.447,1 -1,1L4,29c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM27,32c0,0.553 -0.447,1 -1,1L4,33c-0.552,0 -1,-0.447 -1,-1 0,-0.553 0.448,-1 1,-1h22c0.553,0 1,0.447 1,1zM25,9s2,0 2,-2L27,5s0,-2 -2,-2L5,3S3,3 3,5v2s0,2 2,2h20z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M13,21s2,0 2,-2v-6s0,-2 -2,-2H5s-2,0 -2,2v6s0,2 2,2h8z"
|
|
||||||
android:fillColor="#55ACEE"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M0,27c0,2.209 1.791,4 4,4h28c2.209,0 4,-1.791 4,-4v-0.5H0v0.5z"
|
|
||||||
android:fillColor="#880082"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M0,22.07h36v4.6H0z"
|
|
||||||
android:fillColor="#3558A0"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M0,17.83h36v4.5H0z"
|
|
||||||
android:fillColor="#138F3E"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M0,13.5h36V18H0z"
|
|
||||||
android:fillColor="#FAD220"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M0,9.17h36v4.5H0z"
|
|
||||||
android:fillColor="#FF5000"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M32,5H4C1.791,5 0,6.791 0,9v0.33h36V9c0,-2.209 -1.791,-4 -4,-4z"
|
|
||||||
android:fillColor="#FF000E"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M36,5V3H0v30h36v-2H6v-5h30v-2H6v-5h30v-2H6v-5h30v-2H6V5z"
|
|
||||||
android:fillColor="#8899A6"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M27.827,20.562c-0.223,-0.646 -0.543,-1.227 -0.947,-1.723 -0.411,-0.513 -0.926,-0.928 -1.529,-1.232 -0.61,-0.31 -1.259,-0.46 -1.981,-0.46 -0.086,0 -0.208,0.009 -0.366,0.026l-0.533,-2.593c0.613,-0.603 1.156,-1.299 1.616,-2.077 0.499,-0.847 0.885,-1.77 1.145,-2.741 0.269,-0.978 0.399,-1.942 0.399,-2.945 0,-2.106 -0.542,-3.94 -1.627,-5.475 -0.158,-0.196 -0.288,-0.343 -0.387,-0.431 -0.394,-0.355 -0.788,-0.412 -1.704,0.266 -0.47,0.352 -0.883,0.86 -1.224,1.506 -0.352,0.644 -0.608,1.366 -0.786,2.2 -0.185,0.826 -0.283,1.723 -0.292,2.684 0.041,1.352 0.234,2.701 0.576,4.013 -0.77,0.779 -1.392,1.43 -1.881,1.951 -0.521,0.569 -1.038,1.222 -1.539,1.943 -0.495,0.711 -0.91,1.493 -1.233,2.324 -0.317,0.807 -0.497,1.693 -0.533,2.655 0.008,0.982 0.195,1.944 0.561,2.864 0.365,0.902 0.884,1.726 1.546,2.45 0.665,0.718 1.448,1.287 2.325,1.694 1.23,0.569 2.644,0.749 4.02,0.51 0.063,0.288 0.146,0.629 0.244,1.022 0.157,0.647 0.274,1.172 0.35,1.56 0.073,0.391 0.109,0.766 0.109,1.122 0,0.541 -0.059,0.955 -0.197,1.301 -0.05,0.202 -0.185,0.412 -0.401,0.62 -0.233,0.227 -0.508,0.401 -0.839,0.533 -0.468,0.184 -0.922,0.231 -1.289,0.181 0.195,-0.105 0.375,-0.241 0.537,-0.405 0.433,-0.443 0.652,-0.988 0.652,-1.622 0,-0.447 -0.109,-0.875 -0.328,-1.282 -0.215,-0.375 -0.508,-0.684 -0.886,-0.929 -0.378,-0.225 -0.778,-0.341 -1.226,-0.341h-0.006c-0.512,0.034 -0.954,0.195 -1.301,0.471 -0.36,0.266 -0.646,0.619 -0.852,1.051 -0.193,0.406 -0.307,0.847 -0.338,1.362 0.04,1.04 0.477,1.885 1.306,2.508 0.784,0.581 1.707,0.877 2.739,0.877 0.743,0 1.434,-0.164 2.053,-0.487 0.634,-0.326 1.148,-0.796 1.529,-1.402 0.37,-0.602 0.559,-1.291 0.559,-2.046 0,-0.495 -0.043,-0.96 -0.129,-1.419 -0.085,-0.458 -0.211,-1.08 -0.384,-1.869 -0.124,-0.535 -0.219,-0.987 -0.288,-1.35 0.965,-0.428 1.712,-1.049 2.226,-1.85 0.576,-0.898 0.867,-1.908 0.867,-3 -0.001,-0.665 -0.112,-1.342 -0.333,-2.015zM24.705,25.74l-1.047,-5.149c0.261,0.056 0.502,0.147 0.727,0.276 0.396,0.224 0.703,0.529 0.945,0.938 0.241,0.39 0.392,0.838 0.456,1.303 0,1.246 -0.354,2.115 -1.081,2.632zM23.547,7.101c-0.181,0.526 -0.43,1.057 -0.743,1.577 -0.307,0.517 -0.629,0.973 -0.959,1.359 -0.105,0.125 -0.202,0.231 -0.288,0.322 -0.078,-0.354 -0.128,-0.746 -0.149,-1.165 0.016,-0.685 0.116,-1.364 0.305,-2.081 0.17,-0.661 0.408,-1.259 0.695,-1.756 0.305,-0.468 0.621,-0.705 0.944,-0.705 0.115,0 0.196,0.028 0.259,0.087 0.07,0.071 0.119,0.208 0.15,0.454 0.03,0.133 0.047,0.303 0.047,0.494 0,0.443 -0.088,0.918 -0.261,1.414zM18.602,18.58c0.653,-0.943 1.452,-1.837 2.431,-2.718l0.339,1.739c-0.717,0.362 -1.321,0.9 -1.801,1.61 -0.552,0.82 -0.846,1.727 -0.872,2.717 0.017,0.913 0.309,1.736 0.871,2.451 0.566,0.708 1.294,1.181 2.169,1.4l0.12,0.03 0.122,-0.029c0.537,-0.127 0.594,-0.471 0.594,-0.613 0,-0.345 -0.224,-0.621 -0.579,-0.72 -0.367,-0.17 -0.637,-0.417 -0.82,-0.758 -0.202,-0.368 -0.309,-0.713 -0.309,-0.994 0,-0.476 0.17,-0.903 0.516,-1.303 0.214,-0.242 0.432,-0.432 0.654,-0.572l1.093,5.508c-0.382,0.081 -0.733,0.132 -1.046,0.152 -1.384,-0.045 -2.518,-0.5 -3.369,-1.35 -0.434,-0.442 -0.747,-0.907 -0.958,-1.423 -0.213,-0.516 -0.327,-1.059 -0.342,-1.584 0.029,-1.27 0.429,-2.463 1.187,-3.543z"
|
|
||||||
android:fillColor="#31373D"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M14,34.5a4,1.5 0,1 0,8 0a4,1.5 0,1 0,-8 0z"
|
|
||||||
android:fillColor="#292F33"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M14.339,10.725S16.894,34.998 18.001,35c1.106,0.001 3.66,-24.275 3.66,-24.275h-7.322z"
|
|
||||||
android:fillColor="#99AAB5"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M18,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
|
|
||||||
android:fillColor="#DD2E44"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M11,36s-4,0 -4,-4V4s0,-4 4,-4h14s4,0 4,4v28s0,4 -4,4H11z"
|
|
||||||
android:fillColor="#31373D"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M9,5h18v26H9z"
|
|
||||||
android:fillColor="#55ACEE"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="36dp"
|
|
||||||
android:height="36dp"
|
|
||||||
android:viewportWidth="36"
|
|
||||||
android:viewportHeight="36">
|
|
||||||
<path
|
|
||||||
android:pathData="M17,27c-1.657,0 -3,-1.343 -3,-3v-4c0,-1.657 1.343,-3 3,-3 0.603,-0.006 6,-1 6,-5 0,-2 -2,-4 -5,-4 -2.441,0 -4,2 -4,3 0,1.657 -1.343,3 -3,3s-3,-1.343 -3,-3c0,-4.878 4.58,-9 10,-9 8,0 11,5.982 11,11 0,4.145 -2.277,7.313 -6.413,8.92 -0.9,0.351 -1.79,0.587 -2.587,0.747V24c0,1.657 -1.343,3 -3,3z"
|
|
||||||
android:fillColor="#BE1931"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M17,32m-3,0a3,3 0,1 1,6 0a3,3 0,1 1,-6 0"
|
|
||||||
android:fillColor="#BE1931"/>
|
|
||||||
</vector>
|
|
||||||
15
mastodon/src/main/res/drawable/ic_private_boost_24px.xml
Normal file
15
mastodon/src/main/res/drawable/ic_private_boost_24px.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<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="M8.4,15.45L7,14L3,18L7,22L8.4,20.55L6.85,19H13.5V18C13.5,17.657 13.564,17.317 13.699,17H6.85L8.4,15.45Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M5,5V11H7V7H17.15L15.6,8.55L17,10L21,6L17,2L15.6,3.45L17.15,5H5Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M16,22C15.717,22 15.475,21.908 15.275,21.725C15.092,21.525 15,21.283 15,21V18C15,17.717 15.092,17.483 15.275,17.3C15.475,17.1 15.717,17 16,17V16C16,15.45 16.192,14.983 16.575,14.6C16.975,14.2 17.45,14 18,14C18.55,14 19.017,14.2 19.4,14.6C19.8,14.983 20,15.45 20,16V17C20.283,17 20.517,17.1 20.7,17.3C20.9,17.483 21,17.717 21,18V21C21,21.283 20.9,21.525 20.7,21.725C20.517,21.908 20.283,22 20,22H16ZM17,17H19V16C19,15.717 18.9,15.483 18.7,15.3C18.517,15.1 18.283,15 18,15C17.717,15 17.475,15.1 17.275,15.3C17.092,15.483 17,15.717 17,16V17Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<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="M2.15,18.25L6.775,22.875L8.8,20.8L7.675,19.7H13.5V18C13.5,17.583 13.594,17.172 13.795,16.8H7.675L8.8,15.7L6.775,13.625L2.15,18.25Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M4.15,4.55V11.45H7.05V7.45H16.35L15.225,8.55L17.25,10.625L21.875,6L17.25,1.375L15.225,3.45L16.35,4.55H4.15Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M16,22C15.717,22 15.475,21.908 15.275,21.725C15.092,21.525 15,21.283 15,21V18C15,17.717 15.092,17.483 15.275,17.3C15.475,17.1 15.717,17 16,17V16C16,15.45 16.192,14.983 16.575,14.6C16.975,14.2 17.45,14 18,14C18.55,14 19.017,14.2 19.4,14.6C19.8,14.983 20,15.45 20,16V17C20.283,17 20.517,17.1 20.7,17.3C20.9,17.483 21,17.717 21,18V21C21,21.283 20.9,21.525 20.7,21.725C20.517,21.908 20.283,22 20,22H16ZM17,17H19V16C19,15.717 18.9,15.483 18.7,15.3C18.517,15.1 18.283,15 18,15C17.717,15 17.475,15.1 17.275,15.3C17.092,15.483 17,15.717 17,16V17Z"
|
||||||
|
android:fillColor="#000000"/>
|
||||||
|
</vector>
|
||||||
9
mastodon/src/main/res/drawable/ic_waving_hand_24px.xml
Normal file
9
mastodon/src/main/res/drawable/ic_waving_hand_24px.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:fillColor="@android:color/white"
|
||||||
|
android:pathData="M17,23Q19.5,23 21.25,21.25Q23,19.5 23,17H21.5Q21.5,18.875 20.188,20.188Q18.875,21.5 17,21.5ZM1,7H2.5Q2.5,5.125 3.812,3.812Q5.125,2.5 7,2.5V1Q4.5,1 2.75,2.75Q1,4.5 1,7ZM3.525,20.475Q1.025,17.975 1.025,14.475Q1.025,10.975 3.525,8.475L7.05,4.925Q7.775,4.2 8.812,4.2Q9.85,4.2 10.575,4.925Q10.675,5.025 10.763,5.125Q10.85,5.225 10.9,5.325L13.425,2.8Q14.15,2.075 15.188,2.075Q16.225,2.075 16.95,2.8Q17.075,2.925 17.15,3.025Q17.225,3.125 17.3,3.225Q18.025,2.725 18.925,2.8Q19.825,2.875 20.475,3.525Q21.05,4.1 21.175,4.837Q21.3,5.575 21,6.3Q21.15,6.375 21.288,6.475Q21.425,6.575 21.55,6.7Q22.275,7.425 22.275,8.463Q22.275,9.5 21.55,10.225L21.15,10.625Q21.25,10.675 21.35,10.762Q21.45,10.85 21.55,10.95Q22.275,11.675 22.275,12.712Q22.275,13.75 21.55,14.475L15.525,20.475Q13.025,22.975 9.525,22.975Q6.025,22.975 3.525,20.475ZM4.925,19.075Q5.875,20.025 7.075,20.5Q8.275,20.975 9.525,20.975Q10.775,20.975 11.975,20.5Q13.175,20.025 14.125,19.075L20.125,13.05Q20.275,12.9 20.275,12.7Q20.275,12.5 20.125,12.35Q19.975,12.2 19.775,12.2Q19.575,12.2 19.425,12.35L15.9,15.9L14.475,14.475L20.125,8.825Q20.275,8.675 20.275,8.462Q20.275,8.25 20.125,8.1Q19.975,7.975 19.775,7.962Q19.575,7.95 19.425,8.1L14.475,13.05L13.05,11.65L19.075,5.625Q19.225,5.475 19.225,5.275Q19.225,5.075 19.075,4.925Q18.925,4.775 18.725,4.775Q18.525,4.775 18.375,4.925L12.35,10.95L10.95,9.525L15.525,4.925Q15.675,4.775 15.675,4.575Q15.675,4.375 15.525,4.225Q15.4,4.075 15.188,4.075Q14.975,4.075 14.825,4.225L8.525,10.525Q9.05,11.875 8.775,13.337Q8.5,14.8 7.4,15.9L6,14.475Q6.875,13.6 6.875,12.35Q6.875,11.1 6,10.225L9.175,7.05Q9.325,6.9 9.325,6.7Q9.325,6.5 9.175,6.35Q9.025,6.2 8.825,6.212Q8.625,6.225 8.475,6.35L4.925,9.875Q3.975,10.825 3.5,12.025Q3.025,13.225 3.025,14.475Q3.025,15.725 3.5,16.925Q3.975,18.125 4.925,19.075Z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="110dp"
|
|
||||||
android:height="18dp"
|
|
||||||
android:viewportWidth="110"
|
|
||||||
android:viewportHeight="18">
|
|
||||||
<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"/>
|
|
||||||
</vector>
|
|
||||||
@@ -4,73 +4,133 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:divider="@drawable/divider_inset_16dp_start"
|
android:paddingBottom="8dp"
|
||||||
|
android:divider="@drawable/divider_inset_16dp"
|
||||||
android:showDividers="middle">
|
android:showDividers="middle">
|
||||||
|
|
||||||
<TextView
|
<org.joinmastodon.android.ui.views.WrappingLinearLayout
|
||||||
android:id="@+id/timestamp"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:paddingVertical="8dp"
|
||||||
android:layout_marginTop="12dp"
|
android:horizontalGap="8dp"
|
||||||
android:layout_marginBottom="12dp"
|
android:verticalGap="8dp"
|
||||||
android:minHeight="20dp"
|
android:clipToPadding="false">
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:textAppearance="@style/m3_body_large"
|
<TextView
|
||||||
android:textSize="16sp"
|
android:id="@+id/time"
|
||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:layout_width="wrap_content"
|
||||||
tools:text="Dec 12, 2021, 12:42 PM via Mastodon for Android"/>
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:background="@drawable/bg_button_borderless_rounded"
|
||||||
|
android:backgroundTint="?colorM3Secondary"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:paddingVertical="4dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:layout_marginVertical="-4dp"
|
||||||
|
android:layout_marginHorizontal="-8dp"
|
||||||
|
tools:text="8:24 AM"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:text="·"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
tools:text="2023-11-08"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/date_app_separator"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:text="·"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:paddingVertical="4dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:layout_marginVertical="-4dp"
|
||||||
|
android:layout_marginHorizontal="-8dp"
|
||||||
|
android:background="@drawable/bg_button_borderless_rounded"
|
||||||
|
android:backgroundTint="?colorM3Secondary"
|
||||||
|
tools:text="Mastodon for Android dfjklafjdsalkfjdslakfjdsaklfjdslak"/>
|
||||||
|
|
||||||
|
</org.joinmastodon.android.ui.views.WrappingLinearLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/edit_history"
|
android:id="@+id/edit_history"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="36dp"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="24dp"
|
android:paddingEnd="24dp"
|
||||||
android:background="?android:selectableItemBackground"
|
android:background="?android:selectableItemBackground"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:textAppearance="@style/m3_label_large"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3Secondary"
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:drawableStart="@drawable/ic_edit_24px"
|
|
||||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
tools:text="Last edit bla bla"/>
|
tools:text="Last edit bla bla"/>
|
||||||
|
|
||||||
<TextView
|
<org.joinmastodon.android.ui.views.WrappingLinearLayout
|
||||||
android:id="@+id/reblogs"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
android:paddingEnd="24dp"
|
android:paddingVertical="8dp"
|
||||||
android:background="?android:selectableItemBackground"
|
android:horizontalGap="8dp"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:verticalGap="8dp"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:clipToPadding="false">
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:drawableStart="@drawable/ic_repeat_24px"
|
|
||||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
tools:text="123 boosts"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/favorites"
|
android:id="@+id/reblogs"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="48dp"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="16dp"
|
android:textAppearance="@style/m3_label_large"
|
||||||
android:paddingEnd="24dp"
|
android:textColor="?colorM3Secondary"
|
||||||
android:background="?android:selectableItemBackground"
|
android:background="@drawable/bg_button_borderless_rounded"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:backgroundTint="?colorM3Secondary"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:singleLine="true"
|
||||||
android:singleLine="true"
|
android:ellipsize="end"
|
||||||
android:ellipsize="end"
|
android:paddingVertical="4dp"
|
||||||
android:gravity="center_vertical"
|
android:paddingHorizontal="8dp"
|
||||||
android:drawableStart="@drawable/ic_star_24px"
|
android:layout_marginVertical="-4dp"
|
||||||
android:drawableTint="?colorM3OnSurfaceVariant"
|
android:layout_marginHorizontal="-8dp"
|
||||||
android:drawablePadding="16dp"
|
tools:text="123 boosts"/>
|
||||||
tools:text="123 favorites"/>
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/favorites"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="?colorM3Secondary"
|
||||||
|
android:background="@drawable/bg_button_borderless_rounded"
|
||||||
|
android:backgroundTint="?colorM3Secondary"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:paddingVertical="4dp"
|
||||||
|
android:paddingHorizontal="8dp"
|
||||||
|
android:layout_marginVertical="-4dp"
|
||||||
|
android:layout_marginHorizontal="-8dp"
|
||||||
|
tools:text="123 favorites"/>
|
||||||
|
|
||||||
|
</org.joinmastodon.android.ui.views.WrappingLinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_medium"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
|
android:duplicateParentState="true"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_medium"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
|
android:duplicateParentState="true"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -81,6 +83,7 @@
|
|||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:textAppearance="@style/m3_label_medium"
|
android:textAppearance="@style/m3_label_medium"
|
||||||
|
android:duplicateParentState="true"
|
||||||
tools:text="123"/>
|
tools:text="123"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1">
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/scrollable_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
android:foregroundGravity="center"
|
android:foregroundGravity="center"
|
||||||
android:foregroundTint="?colorM3OnSecondaryContainer"
|
android:foregroundTint="?colorM3OnSecondaryContainer"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
android:contentDescription="@string/profile_header"
|
||||||
android:background="?colorM3SecondaryContainer"/>
|
android:background="?colorM3SecondaryContainer"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
@@ -51,6 +53,7 @@
|
|||||||
android:foregroundGravity="center"
|
android:foregroundGravity="center"
|
||||||
android:foregroundTint="?colorM3OnSecondaryContainer"
|
android:foregroundTint="?colorM3OnSecondaryContainer"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
android:contentDescription="@string/profile_picture"
|
||||||
android:background="?colorM3SecondaryContainer"/>
|
android:background="?colorM3SecondaryContainer"/>
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
@@ -104,39 +107,6 @@
|
|||||||
android:hint="@string/profile_bio"/>
|
android:hint="@string/profile_bio"/>
|
||||||
|
|
||||||
</org.joinmastodon.android.ui.views.FloatingHintEditTextLayout>
|
</org.joinmastodon.android.ui.views.FloatingHintEditTextLayout>
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.ReorderableLinearLayout
|
|
||||||
android:id="@+id/profile_fields"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/add_row"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="56dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingEnd="24dp"
|
|
||||||
android:textAppearance="@style/m3_body_large"
|
|
||||||
android:textColor="?colorM3OnSurface"
|
|
||||||
android:drawableEnd="@drawable/ic_add_24px"
|
|
||||||
android:drawableTint="?colorM3OnSurface"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:stateListAnimator="@null"
|
|
||||||
android:text="@string/profile_add_row"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:textAppearance="@style/m3_body_small"
|
|
||||||
android:textColor="?colorM3OnSurfaceVariant"
|
|
||||||
android:text="@string/profile_setup_explanation"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
81
mastodon/src/main/res/layout/fragment_thread.xml
Normal file
81
mastodon/src/main/res/layout/fragment_thread.xml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?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"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:id="@+id/appkit_loader_root"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:background="?colorM3Surface">
|
||||||
|
|
||||||
|
<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="?colorM3OutlineVariant"/>
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/reply_button_wrapper"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/bg_m3_surface2">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/reply_button"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_marginHorizontal="16dp"
|
||||||
|
android:layout_marginVertical="8dp"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="?colorM3SurfaceVariant"
|
||||||
|
android:foreground="@drawable/bg_rect_4dp_ripple"
|
||||||
|
android:foregroundTint="?colorM3OnSurfaceVariant"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/reply_btn_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:ellipsize="end"
|
||||||
|
tools:text="Reply to ..."/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<org.joinmastodon.android.ui.views.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<org.joinmastodon.android.ui.views.CheckableRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center_vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_margin="16dp"
|
android:layout_margin="16dp"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
android:importantForAccessibility="no"/>
|
android:importantForAccessibility="no"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
@@ -26,11 +27,13 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="24dp"
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="24dp"
|
||||||
android:layout_marginTop="14dp"
|
android:layout_marginTop="14dp"
|
||||||
android:layout_toEndOf="@id/avatar"
|
android:layout_toEndOf="@id/avatar"
|
||||||
android:layout_toStartOf="@id/radiobtn"
|
android:layout_toStartOf="@id/radiobtn"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3OnSurface"
|
||||||
android:gravity="center_vertical|start"
|
android:gravity="center_vertical|start"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
@@ -40,12 +43,15 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/username"
|
android:id="@+id/username"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="20dp"
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="20dp"
|
||||||
|
android:layout_marginBottom="14dp"
|
||||||
android:layout_below="@id/name"
|
android:layout_below="@id/name"
|
||||||
android:layout_toEndOf="@id/avatar"
|
android:layout_toEndOf="@id/avatar"
|
||||||
android:layout_toStartOf="@id/radiobtn"
|
android:layout_toStartOf="@id/radiobtn"
|
||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:textAppearance="@style/m3_body_medium"
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textSize="14sp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:gravity="center_vertical|start"
|
android:gravity="center_vertical|start"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
android:minHeight="24dp"
|
android:minHeight="24dp"
|
||||||
android:gravity="center_vertical|start"
|
android:gravity="center_vertical|start"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3OnSurface"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
tools:text="Title"/>
|
tools:text="Title"/>
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
android:minHeight="20dp"
|
android:minHeight="20dp"
|
||||||
android:gravity="center_vertical|start"
|
android:gravity="center_vertical|start"
|
||||||
android:textAppearance="@style/m3_body_medium"
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textSize="14sp"
|
||||||
android:textColor="?colorM3OnSurfaceVariant"
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
tools:text="Subtitle"/>
|
tools:text="Subtitle"/>
|
||||||
|
|||||||
50
mastodon/src/main/res/layout/item_other_numbered_rule.xml
Normal file
50
mastodon/src/main/res/layout/item_other_numbered_rule.xml
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?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:paddingVertical="8dp"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/number"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:textColor="?colorM3Primary"
|
||||||
|
android:fontFamily="sans-serif-condensed"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="22dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
tools:text="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/number"
|
||||||
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
|
android:minHeight="20sp"
|
||||||
|
android:gravity="center_vertical|start"
|
||||||
|
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/number"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
|
android:paddingVertical="2sp"
|
||||||
|
android:lineSpacingExtra="4sp"
|
||||||
|
android:gravity="start"
|
||||||
|
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top"
|
android:layout_gravity="top"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3OnSurface"
|
||||||
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
tools:text="No discrimination, including (but not limited to) racism, sexism, homophobia or transphobia."/>
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="56dp"
|
||||||
android:gravity="center_vertical|start"
|
android:gravity="center_vertical|start"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textColor="?colorM3OnSurface"
|
android:textColor="?colorM3OnSurface"
|
||||||
android:textAppearance="@style/m3_body_large"
|
android:textAppearance="@style/m3_body_large"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:paddingVertical="14dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:paddingLeft="24dp"
|
android:paddingLeft="24dp"
|
||||||
|
|||||||
83
mastodon/src/main/res/layout/sheet_pre_reply.xml
Normal file
83
mastodon/src/main/res/layout/sheet_pre_reply.xml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<org.joinmastodon.android.ui.views.CustomScrollView 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:background="@drawable/bg_bottom_sheet">
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingHorizontal="16dp">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/handle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="36dp"
|
||||||
|
android:background="@drawable/bg_bottom_sheet_handle"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_below="@id/handle"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:background="@drawable/white_circle"
|
||||||
|
android:backgroundTint="?colorM3PrimaryContainer"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:tint="?colorM3OnPrimaryContainer"
|
||||||
|
tools:src="@drawable/ic_waving_hand_24px"
|
||||||
|
android:importantForAccessibility="no"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:layout_below="@id/handle"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:textAppearance="@style/m3_title_large"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textColor="?colorM3OnSurface"
|
||||||
|
tools:text="@string/non_mutual_sheet_title"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/title"
|
||||||
|
android:layout_toEndOf="@id/icon"
|
||||||
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textColor="?colorM3OnSurfaceVariant"
|
||||||
|
tools:text="@string/non_mutual_sheet_text"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/content_wrap"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/text"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:minHeight="8dp"
|
||||||
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_got_it"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_below="@id/content_wrap"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
style="@style/Widget.Mastodon.M3.Button.Tonal"
|
||||||
|
android:text="@string/got_it"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_dont_remind_again"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_below="@id/btn_got_it"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
style="@style/Widget.Mastodon.M3.Button.Text"
|
||||||
|
android:text="@string/dont_remind_again"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</org.joinmastodon.android.ui.views.CustomScrollView>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@+id/delete" android:showAsAction="always" android:icon="@drawable/ic_delete_24px" android:title="@string/delete"/>
|
|
||||||
</menu>
|
|
||||||
@@ -18,9 +18,9 @@
|
|||||||
<string name="poll_ended">الاطلاع على نتائج استطلاع الرأي الذي صوّت فيه</string>
|
<string name="poll_ended">الاطلاع على نتائج استطلاع الرأي الذي صوّت فيه</string>
|
||||||
<string name="share_toot_title">شارك</string>
|
<string name="share_toot_title">شارك</string>
|
||||||
<string name="settings">الإعدادات</string>
|
<string name="settings">الإعدادات</string>
|
||||||
<string name="publish">انشر</string>
|
<string name="publish">نَشر</string>
|
||||||
<string name="discard_draft">أتريد التخلص من المسودة؟</string>
|
<string name="discard_draft">أتريد إلغاء المسودة؟</string>
|
||||||
<string name="discard">تخلص</string>
|
<string name="discard">إلغاء</string>
|
||||||
<string name="cancel">إلغاء</string>
|
<string name="cancel">إلغاء</string>
|
||||||
<plurals name="followers">
|
<plurals name="followers">
|
||||||
<item quantity="zero">لا متابِعين</item>
|
<item quantity="zero">لا متابِعين</item>
|
||||||
@@ -211,19 +211,7 @@
|
|||||||
<string name="password">كلمة المرور</string>
|
<string name="password">كلمة المرور</string>
|
||||||
<string name="confirm_password">تأكيد كلمة المرور</string>
|
<string name="confirm_password">تأكيد كلمة المرور</string>
|
||||||
<string name="password_note">ضمّن الأحرف الكبيرة والأحرف الخاصة والأرقام لزيادة قوة كلمة المرور.</string>
|
<string name="password_note">ضمّن الأحرف الكبيرة والأحرف الخاصة والأرقام لزيادة قوة كلمة المرور.</string>
|
||||||
<string name="category_academia">أكاديمي</string>
|
|
||||||
<string name="category_activism">النشطاء</string>
|
|
||||||
<string name="category_all">الكل</string>
|
|
||||||
<string name="category_art">فنون</string>
|
|
||||||
<string name="category_food">طعام</string>
|
|
||||||
<string name="category_furry">حيوان ذو فرو</string>
|
|
||||||
<string name="category_games">ألعاب</string>
|
|
||||||
<string name="category_general">عام</string>
|
<string name="category_general">عام</string>
|
||||||
<string name="category_journalism">صحافة</string>
|
|
||||||
<string name="category_lgbt">مجتمع الميم</string>
|
|
||||||
<string name="category_music">موسيقى</string>
|
|
||||||
<string name="category_regional">إقليمي</string>
|
|
||||||
<string name="category_tech">تقني</string>
|
|
||||||
<string name="confirm_email_title">تحقق من صندوق الوارد الخاص بك</string>
|
<string name="confirm_email_title">تحقق من صندوق الوارد الخاص بك</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="confirm_email_subtitle">اضغط على الرابط الذي أرسلناه إليك للتحقق من %s. سننتظر هنا.</string>
|
<string name="confirm_email_subtitle">اضغط على الرابط الذي أرسلناه إليك للتحقق من %s. سننتظر هنا.</string>
|
||||||
@@ -314,6 +302,7 @@
|
|||||||
<!-- %s is the server domain -->
|
<!-- %s is the server domain -->
|
||||||
<string name="local_timeline_info_banner">هذه هي جميع المشاركات من جميع المستخدمين في الخادم الخاص بك (%s).</string>
|
<string name="local_timeline_info_banner">هذه هي جميع المشاركات من جميع المستخدمين في الخادم الخاص بك (%s).</string>
|
||||||
<string name="recommended_accounts_info_banner">قد تعجبك هذه الحسابات استنادا إلى حسابات أخرى تتابعها.</string>
|
<string name="recommended_accounts_info_banner">قد تعجبك هذه الحسابات استنادا إلى حسابات أخرى تتابعها.</string>
|
||||||
|
<string name="see_new_posts">المنشورات الجديدة</string>
|
||||||
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
|
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
|
||||||
<string name="follow_back">رُدّ المتابعة</string>
|
<string name="follow_back">رُدّ المتابعة</string>
|
||||||
<string name="button_follow_pending">معلق</string>
|
<string name="button_follow_pending">معلق</string>
|
||||||
@@ -352,7 +341,6 @@
|
|||||||
<item quantity="many">أعيد نشره %,d مرات</item>
|
<item quantity="many">أعيد نشره %,d مرات</item>
|
||||||
<item quantity="other">أعيد نشره %,d مرات</item>
|
<item quantity="other">أعيد نشره %,d مرات</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="timestamp_via_app">%1$s عبر %2$s</string>
|
|
||||||
<string name="time_now">الآن</string>
|
<string name="time_now">الآن</string>
|
||||||
<string name="edit_history">تاريخ التعديل</string>
|
<string name="edit_history">تاريخ التعديل</string>
|
||||||
<string name="last_edit_at_x">آخر تعديل %s</string>
|
<string name="last_edit_at_x">آخر تعديل %s</string>
|
||||||
@@ -432,7 +420,6 @@
|
|||||||
<string name="profile_add_row">إضافة صف</string>
|
<string name="profile_add_row">إضافة صف</string>
|
||||||
<string name="profile_setup">إعداد الملف الشخصي</string>
|
<string name="profile_setup">إعداد الملف الشخصي</string>
|
||||||
<string name="profile_setup_subtitle">يمكنك دائماً إكمال هذا في وقت لاحق في علامة التبويب الملف الشخصي.</string>
|
<string name="profile_setup_subtitle">يمكنك دائماً إكمال هذا في وقت لاحق في علامة التبويب الملف الشخصي.</string>
|
||||||
<string name="profile_setup_explanation">يمكنك إضافة ما يصل إلى أربعة حقول شخصية لأي شيء تريده. الموقع، الروابط، الضمائر - السماء هي الحد الأقصى.</string>
|
|
||||||
<string name="popular_on_mastodon">مشهور على ماستدون</string>
|
<string name="popular_on_mastodon">مشهور على ماستدون</string>
|
||||||
<string name="follow_all">اتبع الكل</string>
|
<string name="follow_all">اتبع الكل</string>
|
||||||
<string name="server_rules_disagree">لا أوافق</string>
|
<string name="server_rules_disagree">لا أوافق</string>
|
||||||
@@ -703,6 +690,9 @@
|
|||||||
<string name="post_translated">مُترجَم مِن %1$s باستخدام %2$s</string>
|
<string name="post_translated">مُترجَم مِن %1$s باستخدام %2$s</string>
|
||||||
<string name="translation_show_original">إظهار الأصل</string>
|
<string name="translation_show_original">إظهار الأصل</string>
|
||||||
<string name="translation_failed">فشِلَت الترجَمة. قد لم يتمكّن مدير الخادم من تفعيل الترجمات على هذا الخادم أو أنّ هذا الخادم يُشغِّل نسخة قديمة من ماستدون حيث الترجمات غير مدعومة بعد.</string>
|
<string name="translation_failed">فشِلَت الترجَمة. قد لم يتمكّن مدير الخادم من تفعيل الترجمات على هذا الخادم أو أنّ هذا الخادم يُشغِّل نسخة قديمة من ماستدون حيث الترجمات غير مدعومة بعد.</string>
|
||||||
|
<string name="settings_privacy">الخصوصية و الوصول</string>
|
||||||
|
<string name="settings_discoverable">ميزة الملف الشخصي والمشاركات في خوارزميات الاكتشاف</string>
|
||||||
|
<string name="settings_indexable">تضمين المشاركات العامة في نتائج البحث</string>
|
||||||
<plurals name="x_participants">
|
<plurals name="x_participants">
|
||||||
<item quantity="zero">لا مُشارِك</item>
|
<item quantity="zero">لا مُشارِك</item>
|
||||||
<item quantity="one">مشارِك واحد</item>
|
<item quantity="one">مشارِك واحد</item>
|
||||||
@@ -711,7 +701,44 @@
|
|||||||
<item quantity="many">مُشارِكًا</item>
|
<item quantity="many">مُشارِكًا</item>
|
||||||
<item quantity="other">مُشارك</item>
|
<item quantity="other">مُشارك</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="error_playing_video">خطأ في تشغيل الفيديو</string>
|
||||||
|
<string name="timeline_following">الصفحة الرئيسية</string>
|
||||||
|
<string name="lists">القوائم</string>
|
||||||
|
<string name="followed_hashtags">الوسوم المتابَعة</string>
|
||||||
|
<string name="manage_lists">إدارة القوائم</string>
|
||||||
|
<string name="manage_hashtags">إدارة الوسوم</string>
|
||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
|
<string name="dropdown_menu">القائمة المنسدلة</string>
|
||||||
|
<string name="edit_list">تعديل القائمة</string>
|
||||||
|
<string name="list_members">قائمة الاعضاء</string>
|
||||||
|
<string name="delete_list">حذف القائمة</string>
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
|
<string name="delete_list_confirm">حذف \"%s\"؟</string>
|
||||||
|
<string name="list_exclusive">إخفاء الأعضاء في المتابعة</string>
|
||||||
|
<string name="list_exclusive_subtitle">إذا كان هناك شخص ما في هذه القائمة، فقم بإخفائه في مخططك الزمني لتجنب رؤية مشاركاته مرتين.</string>
|
||||||
|
<string name="list_name">اسم القائمة</string>
|
||||||
|
<string name="list_show_replies_to">إظهار الردود على</string>
|
||||||
|
<string name="list_replies_no_one">لا أحد</string>
|
||||||
|
<string name="list_replies_members">أعضاء القائمة</string>
|
||||||
|
<string name="list_replies_anyone">أي شخص أتابعه</string>
|
||||||
|
<string name="confirm_remove_list_members">إزالة أعضاء؟</string>
|
||||||
|
<string name="remove">إزالة</string>
|
||||||
|
<string name="add_list_member">إضافة عضو</string>
|
||||||
|
<string name="search_among_people_you_follow">البحث بين الأشخاص الذين تتابعهم</string>
|
||||||
|
<string name="add_user_to_list">إضافة القائمة…</string>
|
||||||
|
<string name="add_user_to_list_title">إضافة إلى القائمة</string>
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<string name="remove_from_list">إزالة من القائمة</string>
|
||||||
|
<string name="confirm_remove_list_member">إزالة عضو؟</string>
|
||||||
|
<string name="no_followed_hashtags_title">مواكبة الاهتمامات من خلال متابعة الوسوم</string>
|
||||||
|
<string name="no_followed_hashtags_subtitle">سوف تظهر المتابعات هنا</string>
|
||||||
|
<string name="no_lists_title">تنظيم موجزك باستخدام القوائم</string>
|
||||||
|
<string name="manage_accounts">إضافة أو تبديل الحسابات</string>
|
||||||
|
<string name="create_list">إنشاء قائمة</string>
|
||||||
|
<string name="step_x_of_y">الخطوة %1$d من %2$d</string>
|
||||||
|
<string name="create">إنشاء</string>
|
||||||
|
<string name="manage_list_members">إدارة قائمة الأعضاء</string>
|
||||||
|
<string name="list_no_members">لا أعضاء حتى الآن</string>
|
||||||
|
<string name="list_find_users">البحث عن مستخدمين للإضافة</string>
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="user_sent_follow_request">%s адправіў вам запыт на падпіску</string>
|
<string name="user_sent_follow_request">%s адправіў вам запыт на падпіску</string>
|
||||||
<string name="user_favorited">%s упадабаў ваш допіс</string>
|
<string name="user_favorited">%s упадабаў ваш допіс</string>
|
||||||
<string name="notification_boosted">%s пашырыў ваш допіс</string>
|
<string name="notification_boosted">%s пашырыў ваш допіс</string>
|
||||||
|
<string name="poll_ended">Прагляд вынікаў апытання, у якім вы прынялі ўдзел</string>
|
||||||
<string name="share_toot_title">Абагуліць</string>
|
<string name="share_toot_title">Абагуліць</string>
|
||||||
<string name="settings">Налады</string>
|
<string name="settings">Налады</string>
|
||||||
<string name="publish">Апублікаваць</string>
|
<string name="publish">Апублікаваць</string>
|
||||||
@@ -186,19 +187,7 @@
|
|||||||
<string name="password">Пароль</string>
|
<string name="password">Пароль</string>
|
||||||
<string name="confirm_password">Пацвердзіць пароль</string>
|
<string name="confirm_password">Пацвердзіць пароль</string>
|
||||||
<string name="password_note">Выкарыстоўвайце вялікія літары, спецыяльныя сімвалы і лічбы, каб павялічыць надзейнасць пароля.</string>
|
<string name="password_note">Выкарыстоўвайце вялікія літары, спецыяльныя сімвалы і лічбы, каб павялічыць надзейнасць пароля.</string>
|
||||||
<string name="category_academia">Акадэмія</string>
|
|
||||||
<string name="category_activism">Актывізм</string>
|
|
||||||
<string name="category_all">Усе</string>
|
|
||||||
<string name="category_art">Мастацтва</string>
|
|
||||||
<string name="category_food">Ежа</string>
|
|
||||||
<string name="category_furry">Furry</string>
|
|
||||||
<string name="category_games">Гульні</string>
|
|
||||||
<string name="category_general">Асноўныя</string>
|
<string name="category_general">Асноўныя</string>
|
||||||
<string name="category_journalism">Журналістыка</string>
|
|
||||||
<string name="category_lgbt">ЛГБТ</string>
|
|
||||||
<string name="category_music">Музыка</string>
|
|
||||||
<string name="category_regional">Рэгіянальныя</string>
|
|
||||||
<string name="category_tech">Тэхналогіі</string>
|
|
||||||
<string name="confirm_email_title">Праверце паштовую скрыню</string>
|
<string name="confirm_email_title">Праверце паштовую скрыню</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="confirm_email_subtitle">Націсніце на спасылку, якую мы адправілі, каб спраўдзіць %s. Мы вас пачакаем тут.</string>
|
<string name="confirm_email_subtitle">Націсніце на спасылку, якую мы адправілі, каб спраўдзіць %s. Мы вас пачакаем тут.</string>
|
||||||
@@ -222,9 +211,16 @@
|
|||||||
<string name="notification_type_poll">Апытанні</string>
|
<string name="notification_type_poll">Апытанні</string>
|
||||||
<string name="choose_account">Выберыце ўліковы запіс</string>
|
<string name="choose_account">Выберыце ўліковы запіс</string>
|
||||||
<string name="err_not_logged_in">Спачатку ўвайдзіце ў Mastodon</string>
|
<string name="err_not_logged_in">Спачатку ўвайдзіце ў Mastodon</string>
|
||||||
|
<plurals name="cant_add_more_than_x_attachments">
|
||||||
|
<item quantity="one">Вы не можаце дадаць больш за %d далучэнне</item>
|
||||||
|
<item quantity="few">Вы не можаце дадаць больш за %d далучэнняў</item>
|
||||||
|
<item quantity="many">Вы не можаце дадаць больш за %d далучэнняў</item>
|
||||||
|
<item quantity="other">Вы не можаце дадаць больш за %d далучэнняў</item>
|
||||||
|
</plurals>
|
||||||
<string name="media_attachment_unsupported_type">Тып файла %s не падтрымліваецца</string>
|
<string name="media_attachment_unsupported_type">Тып файла %s не падтрымліваецца</string>
|
||||||
<string name="media_attachment_too_big">Памер файла %1$s перавышае абмежаванне ў %2$s МБ</string>
|
<string name="media_attachment_too_big">Памер файла %1$s перавышае абмежаванне ў %2$s МБ</string>
|
||||||
<string name="settings_theme">Знешні выгляд</string>
|
<string name="settings_theme">Знешні выгляд</string>
|
||||||
|
<string name="theme_auto">Выкарыстоўваць сістэмную тэму</string>
|
||||||
<string name="theme_light">Светлая</string>
|
<string name="theme_light">Светлая</string>
|
||||||
<string name="theme_dark">Цёмная</string>
|
<string name="theme_dark">Цёмная</string>
|
||||||
<string name="settings_behavior">Паводзіны</string>
|
<string name="settings_behavior">Паводзіны</string>
|
||||||
@@ -237,6 +233,8 @@
|
|||||||
<string name="settings_clear_cache">Ачысціць кэш медыя</string>
|
<string name="settings_clear_cache">Ачысціць кэш медыя</string>
|
||||||
<string name="settings_app_version">Mastodon для Android v%1$s (%2$d)</string>
|
<string name="settings_app_version">Mastodon для Android v%1$s (%2$d)</string>
|
||||||
<string name="media_cache_cleared">Кэш медыя ачышчаны</string>
|
<string name="media_cache_cleared">Кэш медыя ачышчаны</string>
|
||||||
|
<string name="confirm_log_out">Выйсці з %s?</string>
|
||||||
|
<string name="sensitive_content_explain">Аўтар пазначыў гэтае медыя як адчувальнае.</string>
|
||||||
<string name="avatar_description">Перайсці да профілю %s</string>
|
<string name="avatar_description">Перайсці да профілю %s</string>
|
||||||
<string name="more_options">Больш опцый</string>
|
<string name="more_options">Больш опцый</string>
|
||||||
<string name="new_post">Новы допіс</string>
|
<string name="new_post">Новы допіс</string>
|
||||||
@@ -271,8 +269,14 @@
|
|||||||
<string name="error_saving_file">Памылка пры захаванні файла</string>
|
<string name="error_saving_file">Памылка пры захаванні файла</string>
|
||||||
<string name="file_saved">Файл захаваны</string>
|
<string name="file_saved">Файл захаваны</string>
|
||||||
<string name="downloading">Спампоўванне…</string>
|
<string name="downloading">Спампоўванне…</string>
|
||||||
|
<string name="no_app_to_handle_action">Няма патрэбнай праграмы для гэтага дзеяння</string>
|
||||||
<string name="local_timeline">Лакальнае</string>
|
<string name="local_timeline">Лакальнае</string>
|
||||||
|
<string name="trending_posts_info_banner">Гэтыя допісы набіраюць папулярнасць у Mastodon.</string>
|
||||||
|
<string name="trending_links_info_banner">Гэта навіны, аб якіх кажуць на Mastodon.</string>
|
||||||
<!-- %s is the server domain -->
|
<!-- %s is the server domain -->
|
||||||
|
<string name="local_timeline_info_banner">Гэта ўсе допісы ад усіх карыстальнікаў на вашым серверы (%s).</string>
|
||||||
|
<string name="recommended_accounts_info_banner">Вам могуць спадабацца гэтыя ўліковыя запісы на аснове вашых падпісак.</string>
|
||||||
|
<string name="see_new_posts">Новыя допісы</string>
|
||||||
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
|
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
|
||||||
<string name="follow_back">Падпісацца ў адказ</string>
|
<string name="follow_back">Падпісацца ў адказ</string>
|
||||||
<string name="button_follow_pending">Чакаюць</string>
|
<string name="button_follow_pending">Чакаюць</string>
|
||||||
@@ -303,7 +307,6 @@
|
|||||||
<item quantity="many">%,d пашырэнняў</item>
|
<item quantity="many">%,d пашырэнняў</item>
|
||||||
<item quantity="other">%,d пашырэння</item>
|
<item quantity="other">%,d пашырэння</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="timestamp_via_app">%1$s праз %2$s</string>
|
|
||||||
<string name="time_now">толькі што</string>
|
<string name="time_now">толькі што</string>
|
||||||
<string name="edit_history">Гісторыя рэдагавання</string>
|
<string name="edit_history">Гісторыя рэдагавання</string>
|
||||||
<string name="last_edit_at_x">Апошняе рэдагаванне %s</string>
|
<string name="last_edit_at_x">Апошняе рэдагаванне %s</string>
|
||||||
@@ -361,6 +364,7 @@
|
|||||||
<string name="login_title">З вяртаннем</string>
|
<string name="login_title">З вяртаннем</string>
|
||||||
<string name="login_subtitle">Увайдзіце з дапамогай сервера, на якім вы стварылі свой уліковы запіс.</string>
|
<string name="login_subtitle">Увайдзіце з дапамогай сервера, на якім вы стварылі свой уліковы запіс.</string>
|
||||||
<string name="server_url">URL-адрас сервера</string>
|
<string name="server_url">URL-адрас сервера</string>
|
||||||
|
<string name="signup_random_server_explain">Мы абярэм сервер на аснове вашай мовы, калі вы працягнеце без выбару.</string>
|
||||||
<string name="server_filter_any_language">Любая мова</string>
|
<string name="server_filter_any_language">Любая мова</string>
|
||||||
<string name="server_filter_instant_signup">Імгненная рэгістрацыя</string>
|
<string name="server_filter_instant_signup">Імгненная рэгістрацыя</string>
|
||||||
<string name="server_filter_manual_review">Ручная праверка</string>
|
<string name="server_filter_manual_review">Ручная праверка</string>
|
||||||
@@ -378,7 +382,6 @@
|
|||||||
<string name="profile_add_row">Дадаць радок</string>
|
<string name="profile_add_row">Дадаць радок</string>
|
||||||
<string name="profile_setup">Налады профілю</string>
|
<string name="profile_setup">Налады профілю</string>
|
||||||
<string name="profile_setup_subtitle">Вы можаце завяршыць гэта пазней на ўкладцы Профіль.</string>
|
<string name="profile_setup_subtitle">Вы можаце завяршыць гэта пазней на ўкладцы Профіль.</string>
|
||||||
<string name="profile_setup_explanation">Вы можаце дадаць да чатырох палёў профіля для ўсяго, што хочаце. Месцазнаходжанне, спасылкі, займеннікі - няма мяжы магчымасцям.</string>
|
|
||||||
<string name="popular_on_mastodon">Папулярна на Mastodon</string>
|
<string name="popular_on_mastodon">Папулярна на Mastodon</string>
|
||||||
<string name="follow_all">Падпісацца на ўсіх</string>
|
<string name="follow_all">Падпісацца на ўсіх</string>
|
||||||
<string name="server_rules_disagree">Не згодны</string>
|
<string name="server_rules_disagree">Не згодны</string>
|
||||||
@@ -389,11 +392,16 @@
|
|||||||
<!-- Shown in a progress dialog when you tap "follow all" -->
|
<!-- Shown in a progress dialog when you tap "follow all" -->
|
||||||
<string name="sending_follows">Падпісваемся…</string>
|
<string name="sending_follows">Падпісваемся…</string>
|
||||||
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
|
<!-- %1$s is server domain, %2$s is email domain. You can reorder these placeholders to fit your language better. -->
|
||||||
|
<string name="signup_email_domain_blocked">%1$s не дазваляе зарэгістравацца ад %2$s. Паспрабуйце іншы ці <a>выберыце іншы сервер</a>.</string>
|
||||||
<string name="spoiler_show">Усё адно паказаць</string>
|
<string name="spoiler_show">Усё адно паказаць</string>
|
||||||
|
<string name="spoiler_hide">Схаваць зноў</string>
|
||||||
|
<string name="poll_multiple_choice">Абярыце адзін або некалькі</string>
|
||||||
<string name="save_changes">Захаваць змены</string>
|
<string name="save_changes">Захаваць змены</string>
|
||||||
<string name="profile_featured">Рэкамендаванае</string>
|
<string name="profile_featured">Рэкамендаванае</string>
|
||||||
|
<string name="profile_timeline">Стужка</string>
|
||||||
<string name="view_all">Праглядзець усё</string>
|
<string name="view_all">Праглядзець усё</string>
|
||||||
<string name="profile_endorsed_accounts">Уліковыя запісы</string>
|
<string name="profile_endorsed_accounts">Уліковыя запісы</string>
|
||||||
|
<string name="verified_link">Правераная спасылка</string>
|
||||||
<string name="show">Паказаць</string>
|
<string name="show">Паказаць</string>
|
||||||
<string name="hide">Схаваць</string>
|
<string name="hide">Схаваць</string>
|
||||||
<string name="join_default_server">Далучыцца да %s</string>
|
<string name="join_default_server">Далучыцца да %s</string>
|
||||||
@@ -403,30 +411,75 @@
|
|||||||
<string name="welcome_to_mastodon">Вітаем у Mastodon</string>
|
<string name="welcome_to_mastodon">Вітаем у Mastodon</string>
|
||||||
<string name="welcome_paragraph1">Mastodon - гэта дэцэнтралізаваная сацыяльная сетка, што азначае, што ні адна кампанія не кантралюе яе. Яна складаецца з мноства незалежна працуючых сервераў, злучаных разам.</string>
|
<string name="welcome_paragraph1">Mastodon - гэта дэцэнтралізаваная сацыяльная сетка, што азначае, што ні адна кампанія не кантралюе яе. Яна складаецца з мноства незалежна працуючых сервераў, злучаных разам.</string>
|
||||||
<string name="what_are_servers">Што такое серверы?</string>
|
<string name="what_are_servers">Што такое серверы?</string>
|
||||||
|
<string name="welcome_paragraph2">Кожны ўліковы запіс Mastodon размяшчаецца на серверы - кожны са сваімі каштоўнасцямі, правіламі, & адміністратарамі. Незалежна ад таго, які сервер вы вылучыце, вы можаце сачыць і ўзаемадзейнічаць з людзьмі на любым серверы.</string>
|
||||||
|
<string name="opening_link">Адкрыццё спасылкі…</string>
|
||||||
|
<string name="link_not_supported">Гэтая спасылка не падтрымліваецца ў праграме</string>
|
||||||
|
<string name="log_out_all_accounts">Выйсці з усіх уліковых запісаў</string>
|
||||||
|
<string name="confirm_log_out_all_accounts">Выйсці з усіх уліковых запісаў?</string>
|
||||||
<string name="retry">Паўтарыць</string>
|
<string name="retry">Паўтарыць</string>
|
||||||
|
<string name="post_failed">Не ўдалося адправіць допіс</string>
|
||||||
<!-- %s is formatted file size ("467 KB image") -->
|
<!-- %s is formatted file size ("467 KB image") -->
|
||||||
|
<string name="attachment_description_image">%s выява</string>
|
||||||
|
<string name="attachment_description_video">%s відэа</string>
|
||||||
|
<string name="attachment_description_audio">%s аўдыё</string>
|
||||||
|
<string name="attachment_description_unknown">%s файл</string>
|
||||||
|
<string name="attachment_type_image">Выява</string>
|
||||||
<string name="attachment_type_video">Відэа</string>
|
<string name="attachment_type_video">Відэа</string>
|
||||||
|
<string name="attachment_type_audio">Аўдыё</string>
|
||||||
<string name="attachment_type_gif">GIF</string>
|
<string name="attachment_type_gif">GIF</string>
|
||||||
<string name="attachment_type_unknown">Файл</string>
|
<string name="attachment_type_unknown">Файл</string>
|
||||||
|
<string name="attachment_x_percent_uploaded">%d%% загружана</string>
|
||||||
|
<string name="add_poll_option">Дадаць варыянт адказу</string>
|
||||||
|
<string name="poll_length">Тэрмін апытання</string>
|
||||||
<string name="poll_style">Стыль</string>
|
<string name="poll_style">Стыль</string>
|
||||||
|
<string name="compose_poll_single_choice">Адзін варыянт</string>
|
||||||
|
<string name="compose_poll_multiple_choice">Некалькі варыянтаў</string>
|
||||||
|
<string name="delete_poll_option">Выдаліць варыянт адказу</string>
|
||||||
|
<string name="poll_style_title">Стыль апытання</string>
|
||||||
|
<string name="alt_text">Альтэрнатыўны тэкст</string>
|
||||||
<string name="help">Даведка</string>
|
<string name="help">Даведка</string>
|
||||||
|
<string name="what_is_alt_text">Што такое альтэрнатыўны тэкст?</string>
|
||||||
|
<string name="alt_text_help">Альтэрнатыўны тэкст змяшчае апісанні выяў для людзей з парушэннямі зроку, нізкахуткаснымі злучэннямі або тых, хто шукае дадатковы кантэкст.\n\nВы можаце палепшыць даступнасць і разуменне для ўсіх, напісаўшы ясны і кароткі альтэрнатыўны тэкст.\n\n<ul><li>Адзначце важныя элементы</li>\n<li>Ахоплівайце тэкст выявам</li>\n<li>Выкарыстоўвайце звычайную структуру прапаноў</li>\n<li>Пазбягайце лішняй інфармацыі</li>\n<li>Засяродзьцеся на тэндэнцыях і ключавых высновах у складаных візуальных формах (напрыклад, дыяграмах або картах)</li></ul></string>
|
||||||
<string name="edit_post">Рэдагаваць допіс</string>
|
<string name="edit_post">Рэдагаваць допіс</string>
|
||||||
<string name="no_verified_link">Няма спраўджанай спасылкі</string>
|
<string name="no_verified_link">Няма спраўджанай спасылкі</string>
|
||||||
|
<string name="compose_autocomplete_emoji_empty">Агляд emoji</string>
|
||||||
|
<string name="compose_autocomplete_users_empty">Знайдзіце тых, каго шукаеце</string>
|
||||||
|
<string name="no_search_results">Нічога не знойдзена па гэтым запыце</string>
|
||||||
<string name="language">Мова</string>
|
<string name="language">Мова</string>
|
||||||
<string name="language_default">Перадвызначана</string>
|
<string name="language_default">Перадвызначана</string>
|
||||||
<string name="language_system">Сістэма</string>
|
<string name="language_system">Сістэма</string>
|
||||||
|
<string name="language_detecting">Вызначэнне мовы</string>
|
||||||
|
<string name="language_cant_detect">Не ўдалося вызначыць мову</string>
|
||||||
|
<string name="language_detected">Выяўлена</string>
|
||||||
<string name="media_hidden">Медыя схавана</string>
|
<string name="media_hidden">Медыя схавана</string>
|
||||||
<string name="post_hidden">Допіс схаваны</string>
|
<string name="post_hidden">Допіс схаваны</string>
|
||||||
<string name="report_title_post">Паскардзіцца на допіс</string>
|
<string name="report_title_post">Паскардзіцца на допіс</string>
|
||||||
|
<string name="forward_report_explanation">Уліковы запіс належыць іншаму серверу. Адправіць туды ананімную копію гэтай справаздачы?</string>
|
||||||
<!-- %s is the server domain -->
|
<!-- %s is the server domain -->
|
||||||
|
<string name="forward_report_to_server">Пераслаць на %s</string>
|
||||||
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
|
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
|
||||||
|
<string name="reported">Паведамлена</string>
|
||||||
|
<string name="report_unfollow_explanation">Каб больш не бачыць іх допісы ў вашай стужцы, адмяніце падпіску на іх.</string>
|
||||||
|
<string name="muted_user">Ігнараваць %s</string>
|
||||||
|
<string name="report_sent_already_blocked">Вы ўжо заблакіравалі гэтага карыстальніка, таму вам больш нічога не трэба рабіць, пакуль мы разглядаем ваша данясенне.</string>
|
||||||
|
<string name="report_personal_already_blocked">Вы ўжо заблакіравалі гэтага карыстальніка, таму больш нічога рабіць не трэба.\n\nДзякуй, што дапамагаеце захаваць Mastodon бяспечным месцам для ўсіх!</string>
|
||||||
|
<string name="blocked_user">Заблакіраваць %s</string>
|
||||||
|
<string name="mark_all_notifications_read">Адзначыць усё як прачытанае</string>
|
||||||
<string name="settings_display">Адлюстраванне</string>
|
<string name="settings_display">Адлюстраванне</string>
|
||||||
<string name="settings_filters">Фільтры</string>
|
<string name="settings_filters">Фільтры</string>
|
||||||
|
<string name="settings_server_explanation">Агульныя звесткі, правілы, мадэратары</string>
|
||||||
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
|
<!-- %s is the app name (Mastodon, key app_name). I made it a placeholder so everything Just Works™ with forks -->
|
||||||
<string name="about_app">Аб %s</string>
|
<string name="about_app">Аб %s</string>
|
||||||
|
<string name="default_post_language">Мова допісаў па змаўчанні</string>
|
||||||
|
<string name="settings_alt_text_reminders">Даданне напамінаў пра тэкст alt</string>
|
||||||
|
<string name="settings_confirm_unfollow">Спытайце, перш чым адпісацца ад каго-небудзь</string>
|
||||||
<string name="settings_confirm_boost">Пытаць перад пашырэннем</string>
|
<string name="settings_confirm_boost">Пытаць перад пашырэннем</string>
|
||||||
|
<string name="settings_confirm_delete_post">Спытаць перад выдаленнем допісаў</string>
|
||||||
<string name="pause_all_notifications">Прыпыніць усе</string>
|
<string name="pause_all_notifications">Прыпыніць усе</string>
|
||||||
|
<string name="pause_notifications_off">Выкл.</string>
|
||||||
<string name="notifications_policy_anyone">Кожны</string>
|
<string name="notifications_policy_anyone">Кожны</string>
|
||||||
|
<string name="notifications_policy_followed">Людзі, якія падпісаны на вас</string>
|
||||||
|
<string name="notifications_policy_follower">Людзі, на якіх вы падпісаны</string>
|
||||||
<string name="notifications_policy_no_one">Ніхто</string>
|
<string name="notifications_policy_no_one">Ніхто</string>
|
||||||
<string name="settings_notifications_policy">Атрымліваць апавяшчэнні ад</string>
|
<string name="settings_notifications_policy">Атрымліваць апавяшчэнні ад</string>
|
||||||
<string name="notification_type_mentions_and_replies">Згадванні і адказы</string>
|
<string name="notification_type_mentions_and_replies">Згадванні і адказы</string>
|
||||||
@@ -445,9 +498,19 @@
|
|||||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||||
<string name="pause_notifications_ends">Скончыцца %s</string>
|
<string name="pause_notifications_ends">Скончыцца %s</string>
|
||||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||||
|
<string name="pause_notifications_banner">Апавяшчэнні адновяцца %s.</string>
|
||||||
|
<string name="resume_notifications_now">Аднавіць зараз</string>
|
||||||
|
<string name="open_system_notification_settings">Перайсці ў налады апавяшчэнняў</string>
|
||||||
<string name="about_server">Пра сервер</string>
|
<string name="about_server">Пра сервер</string>
|
||||||
<string name="server_rules">Правілы</string>
|
<string name="server_rules">Правілы</string>
|
||||||
<string name="server_administrator">Адміністратар</string>
|
<string name="server_administrator">Адміністратар</string>
|
||||||
|
<string name="send_email_to_server_admin">Напісаць адміністратару</string>
|
||||||
|
<string name="notifications_disabled_in_system">Уключыце апавяшчэння ў наладах прылады, каб бачыць абнаўлення адкуль згодна.</string>
|
||||||
|
<string name="settings_even_more">Яшчэ больш налад</string>
|
||||||
|
<string name="settings_show_cws">Паказваць папярэджанні аб змесце</string>
|
||||||
|
<string name="settings_hide_sensitive_media">Хаваць медыя пазначаныя як далікатныя</string>
|
||||||
|
<string name="settings_show_interaction_counts">Паказваць колькасць узаемадзеянняў пад допісамі</string>
|
||||||
|
<string name="settings_show_emoji_in_names">Карыстальніцкія emoji у імёнах</string>
|
||||||
<plurals name="in_x_seconds">
|
<plurals name="in_x_seconds">
|
||||||
<item quantity="one">праз %d секунду</item>
|
<item quantity="one">праз %d секунду</item>
|
||||||
<item quantity="few">праз %d секунды</item>
|
<item quantity="few">праз %d секунды</item>
|
||||||
@@ -472,41 +535,78 @@
|
|||||||
<item quantity="many">%d гадзін таму</item>
|
<item quantity="many">%d гадзін таму</item>
|
||||||
<item quantity="other">%d гадзіны таму</item>
|
<item quantity="other">%d гадзіны таму</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="alt_text_reminder_title">У медыя адсутнічае альтэрнатыўны тэкст</string>
|
||||||
|
<plurals name="alt_text_reminder_x_images">
|
||||||
|
<item quantity="one">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="few">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="many">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="other">%s выявы не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="alt_text_reminder_x_attachments">
|
||||||
|
<item quantity="one">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="few">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="many">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
<item quantity="other">%s медыя далучэнні не маюць альтэрнатыўны тэкст. Усё роўна апублікаваць?</item>
|
||||||
|
</plurals>
|
||||||
<string name="count_one">Адзін</string>
|
<string name="count_one">Адзін</string>
|
||||||
<string name="count_two">Два</string>
|
<string name="count_two">Два</string>
|
||||||
<string name="count_three">Тры</string>
|
<string name="count_three">Тры</string>
|
||||||
<string name="count_four">Чатыры</string>
|
<string name="count_four">Чатыры</string>
|
||||||
<string name="alt_text_reminder_post_anyway">Допіс</string>
|
<string name="alt_text_reminder_post_anyway">Допіс</string>
|
||||||
<!-- %s is the username -->
|
<!-- %s is the username -->
|
||||||
|
<string name="unfollow_confirmation">Адпісацца ад %s?</string>
|
||||||
<string name="filter_active">Актыўны</string>
|
<string name="filter_active">Актыўны</string>
|
||||||
<string name="filter_inactive">Неактыўны</string>
|
<string name="filter_inactive">Неактыўны</string>
|
||||||
<string name="settings_add_filter">Дадаць фільтр</string>
|
<string name="settings_add_filter">Дадаць фільтр</string>
|
||||||
<string name="settings_edit_filter">Рэдагаваць фільтр</string>
|
<string name="settings_edit_filter">Рэдагаваць фільтр</string>
|
||||||
<string name="settings_filter_duration">Працягласць</string>
|
<string name="settings_filter_duration">Працягласць</string>
|
||||||
<string name="settings_filter_muted_words">Ігнараваныя словы</string>
|
<string name="settings_filter_muted_words">Ігнараваныя словы</string>
|
||||||
|
<string name="settings_filter_context">Ігнараваць</string>
|
||||||
|
<string name="settings_filter_show_cw">Паказаць з папярэджаннем аб змесце</string>
|
||||||
|
<string name="settings_filter_show_cw_explanation">Па-ранейшаму паказваць допісы, якія адпавядаюць гэтаму фільтру, але з папярэджаннем аб змесце</string>
|
||||||
<string name="settings_delete_filter">Выдаліць фільтр</string>
|
<string name="settings_delete_filter">Выдаліць фільтр</string>
|
||||||
<string name="filter_duration_forever">Назаўсёды</string>
|
<string name="filter_duration_forever">Назаўсёды</string>
|
||||||
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
<!-- %s is the timestamp ("tomorrow at 12:34") -->
|
||||||
<string name="settings_filter_ends">Скончыцца %s</string>
|
<string name="settings_filter_ends">Скончыцца %s</string>
|
||||||
|
<plurals name="settings_x_muted_words">
|
||||||
|
<item quantity="one">%d заглушанае слова ці фраза</item>
|
||||||
|
<item quantity="few">%d заглушаных слоў ці фраз</item>
|
||||||
|
<item quantity="many">%d заглушаных слоў ці фраз</item>
|
||||||
|
<item quantity="other">%d заглушаных слоў ці фраз</item>
|
||||||
|
</plurals>
|
||||||
<string name="selection_2_options">%1$s і %2$s</string>
|
<string name="selection_2_options">%1$s і %2$s</string>
|
||||||
<string name="selection_3_options">%1$s, %2$s і %3$s</string>
|
<string name="selection_3_options">%1$s, %2$s і %3$s</string>
|
||||||
|
<string name="selection_4_or_more">%1$s, %2$s і %3$d больш</string>
|
||||||
|
<string name="filter_context_home_lists">Галоўная & спісы</string>
|
||||||
<string name="filter_context_notifications">Апавяшчэнні</string>
|
<string name="filter_context_notifications">Апавяшчэнні</string>
|
||||||
<string name="filter_context_public_timelines">Публічныя стужкі</string>
|
<string name="filter_context_public_timelines">Публічныя стужкі</string>
|
||||||
|
<string name="filter_context_threads_replies">Ланцугі & адказы</string>
|
||||||
<string name="filter_context_profiles">Профілі</string>
|
<string name="filter_context_profiles">Профілі</string>
|
||||||
<string name="settings_filter_title">Загаловак</string>
|
<string name="settings_filter_title">Загаловак</string>
|
||||||
<string name="settings_delete_filter_title">Выдаліць фільтр \"%s\"?</string>
|
<string name="settings_delete_filter_title">Выдаліць фільтр \"%s\"?</string>
|
||||||
|
<string name="settings_delete_filter_confirmation">Гэты фільтр будзе выдалены з уліковага запісу на ўсіх вашых прыладах.</string>
|
||||||
|
<string name="add_muted_word">Дадаць слова да ігнаруемых</string>
|
||||||
|
<string name="edit_muted_word">Рэдагаваць ігнараванае слова</string>
|
||||||
<string name="add">Дадаць</string>
|
<string name="add">Дадаць</string>
|
||||||
<string name="filter_word_or_phrase">Слова або фраза</string>
|
<string name="filter_word_or_phrase">Слова або фраза</string>
|
||||||
|
<string name="filter_add_word_help">Словы адчувальныя да рэгістра і павінны супадаць з поўным словам.\n\nКалі адфільтраваць слова «яблык», будуць схаваны паведамленні са словам «яблык» або «ЯбЛыК», але не, напрыклад, «яблычны».</string>
|
||||||
<string name="settings_delete_filter_word">Выдаліць слова \"%s\"?</string>
|
<string name="settings_delete_filter_word">Выдаліць слова \"%s\"?</string>
|
||||||
<string name="enter_selection_mode">Выбраць</string>
|
<string name="enter_selection_mode">Выбраць</string>
|
||||||
<string name="select_all">Выбраць усё</string>
|
<string name="select_all">Выбраць усё</string>
|
||||||
<string name="settings_filter_duration_title">Працягласць фільтра</string>
|
<string name="settings_filter_duration_title">Працягласць фільтра</string>
|
||||||
|
<string name="filter_duration_custom">Уласнае</string>
|
||||||
<plurals name="settings_delete_x_filter_words">
|
<plurals name="settings_delete_x_filter_words">
|
||||||
<item quantity="one">Выдаліць %d слова?</item>
|
<item quantity="one">Выдаліць %d слова?</item>
|
||||||
<item quantity="few">Выдаліць %d словы?</item>
|
<item quantity="few">Выдаліць %d словы?</item>
|
||||||
<item quantity="many">Выдаліць %d словаў?</item>
|
<item quantity="many">Выдаліць %d словаў?</item>
|
||||||
<item quantity="other">Выдаліць %d слова?</item>
|
<item quantity="other">Выдаліць %d слова?</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<plurals name="x_items_selected">
|
||||||
|
<item quantity="one">%d выбрана</item>
|
||||||
|
<item quantity="few">%d выбрана</item>
|
||||||
|
<item quantity="many">%d выбрана</item>
|
||||||
|
<item quantity="other">%d выбрана</item>
|
||||||
|
</plurals>
|
||||||
<string name="required_form_field_blank">Не можа быць пустым</string>
|
<string name="required_form_field_blank">Не можа быць пустым</string>
|
||||||
<string name="filter_word_already_in_list">Ужо ў спісе</string>
|
<string name="filter_word_already_in_list">Ужо ў спісе</string>
|
||||||
<string name="app_update_ready">Абнаўленне праграмы гатова</string>
|
<string name="app_update_ready">Абнаўленне праграмы гатова</string>
|
||||||
@@ -527,8 +627,73 @@
|
|||||||
<string name="time_hours_ago_short">%d г таму</string>
|
<string name="time_hours_ago_short">%d г таму</string>
|
||||||
<string name="time_days_ago_short">%d дз таму</string>
|
<string name="time_days_ago_short">%d дз таму</string>
|
||||||
<!-- %s is the name of the post language -->
|
<!-- %s is the name of the post language -->
|
||||||
|
<string name="translate_post">Перакласці з %s</string>
|
||||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||||
|
<string name="post_translated">Перакладзена з %1$s з дапамогай %2$s</string>
|
||||||
|
<string name="translation_show_original">Паказаць арыгінал</string>
|
||||||
|
<string name="translation_failed">Збой перакладу. Магчыма, адміністратар не ўключыў пераклады на гэтым серверы або гэты сервер працуе са старой версіяй Mastodon, дзе пераклады яшчэ не падтрымліваюцца.</string>
|
||||||
|
<string name="settings_privacy">Прыватнасць і дасяжнасць</string>
|
||||||
|
<string name="settings_discoverable">Уключыць профіль і допісы ў алгарытмы рэкамендацый</string>
|
||||||
|
<string name="settings_indexable">Індэксаваць публічныя допісы ў пошукавых сістэмах</string>
|
||||||
|
<plurals name="x_participants">
|
||||||
|
<item quantity="one">%,d удзельнік</item>
|
||||||
|
<item quantity="few">%,d удзельнікаў</item>
|
||||||
|
<item quantity="many">%,d удзельнікаў</item>
|
||||||
|
<item quantity="other">%,d удзельнікі</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="x_posts_today">
|
||||||
|
<item quantity="one">%,d допіс сёння</item>
|
||||||
|
<item quantity="few">%,d допісаў сёння</item>
|
||||||
|
<item quantity="many">%,d допісаў сёння</item>
|
||||||
|
<item quantity="other">%,d допісы сёння</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="error_playing_video">Памылка прайгравання відэа</string>
|
||||||
|
<string name="timeline_following">Галоўная</string>
|
||||||
|
<string name="lists">Спісы</string>
|
||||||
|
<string name="followed_hashtags">Адсочваныя хэштэгі</string>
|
||||||
|
<string name="manage_lists">Кіраванне спісамі</string>
|
||||||
|
<string name="manage_hashtags">Кіраванне хэштэгамі</string>
|
||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
|
<string name="dropdown_menu">Раскрываючаеся меню</string>
|
||||||
|
<string name="edit_list">Рэдагаваць спіс</string>
|
||||||
|
<string name="list_members">Спіс удзельнікаў</string>
|
||||||
|
<string name="delete_list">Выдаліць спіс</string>
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
|
<string name="delete_list_confirm">Выдаліць “%s”?</string>
|
||||||
|
<string name="list_exclusive">Схаваць удзельнікаў у падпісках</string>
|
||||||
|
<string name="list_exclusive_subtitle">Калі нехта ёсць у гэтым спісе, схавайце яго ў стужцы падпісак, каб яго допісы не з\'яўляліся двойчы.</string>
|
||||||
|
<string name="list_name">Назва спіса</string>
|
||||||
|
<string name="list_show_replies_to">Паказаць адказы да</string>
|
||||||
|
<string name="list_replies_no_one">Ніводны</string>
|
||||||
|
<string name="list_replies_members">Удзельнікі гэтага спісу</string>
|
||||||
|
<string name="list_replies_anyone">Нехта, на каго я падпісаны</string>
|
||||||
|
<string name="confirm_remove_list_members">Выдаліць удзельнікаў?</string>
|
||||||
|
<string name="remove">Выдаліць</string>
|
||||||
|
<string name="add_list_member">Дадаць удзельніка</string>
|
||||||
|
<string name="search_among_people_you_follow">Шукайце сярод людзей, на якіх Вы падпісаны</string>
|
||||||
|
<string name="add_user_to_list">Дадаць да спісу…</string>
|
||||||
|
<string name="add_user_to_list_title">Дадаць да спісу</string>
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<string name="manage_user_lists">Кіраваць спісамі з %s</string>
|
||||||
|
<string name="remove_from_list">Выдаліць са спісу</string>
|
||||||
|
<string name="confirm_remove_list_member">Выдаліць удзельніка?</string>
|
||||||
|
<string name="no_followed_hashtags_title">Сачыце за інтарэсамі па хэштэгах</string>
|
||||||
|
<string name="no_followed_hashtags_subtitle">Тут з\'явяцца хэштэгі</string>
|
||||||
|
<string name="no_lists_title">Арганізуйце сваю стужку з дапамогай спісаў</string>
|
||||||
|
<string name="no_lists_subtitle">Ваш з\'явіцца тут</string>
|
||||||
|
<string name="manage_accounts">Дадаць або пераключыць уліковыя запісы</string>
|
||||||
|
<plurals name="x_posts_recently">
|
||||||
|
<item quantity="one">%,d нядаўні допіс</item>
|
||||||
|
<item quantity="few">%,d нядаўніх допісаў</item>
|
||||||
|
<item quantity="many">%,d нядаўніх допісаў</item>
|
||||||
|
<item quantity="other">%,d нядаўнія допісы</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="create_list">Ствараць спiс</string>
|
||||||
|
<string name="step_x_of_y">Крок %1$d з %2$d</string>
|
||||||
|
<string name="create">Стварыць</string>
|
||||||
|
<string name="manage_list_members">Кіраванне ўдзельнікамі спісу</string>
|
||||||
|
<string name="list_no_members">Пакуль няма ўдзельнікаў</string>
|
||||||
|
<string name="list_find_users">Знайдзіце карыстальнікаў для дадання</string>
|
||||||
|
<string name="reply_to_user">Адказаць %s</string>
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -122,10 +122,6 @@
|
|||||||
<string name="email">ই-মেইল</string>
|
<string name="email">ই-মেইল</string>
|
||||||
<string name="password">পাসওয়ার্ড</string>
|
<string name="password">পাসওয়ার্ড</string>
|
||||||
<string name="confirm_password">পাসওয়ার্ড নিশ্চিত করুন</string>
|
<string name="confirm_password">পাসওয়ার্ড নিশ্চিত করুন</string>
|
||||||
<string name="category_lgbt">LGBT</string>
|
|
||||||
<string name="category_music">সঙ্গীত</string>
|
|
||||||
<string name="category_regional">আঞ্চলিক</string>
|
|
||||||
<string name="category_tech">তথ্য-প্রযুক্তি</string>
|
|
||||||
<string name="confirm_email_title">আপনার ইনবক্স দেখুন</string>
|
<string name="confirm_email_title">আপনার ইনবক্স দেখুন</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="open_email_app">ই-মেইল অ্যাপ খুলুন</string>
|
<string name="open_email_app">ই-মেইল অ্যাপ খুলুন</string>
|
||||||
@@ -204,4 +200,5 @@
|
|||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -93,19 +93,7 @@
|
|||||||
<string name="unfollow">Prestani pratiti</string>
|
<string name="unfollow">Prestani pratiti</string>
|
||||||
<string name="back">Nazad</string>
|
<string name="back">Nazad</string>
|
||||||
<string name="password_note">Koristite velika slova, brojeve i oznake da bi osigurali lozinku.</string>
|
<string name="password_note">Koristite velika slova, brojeve i oznake da bi osigurali lozinku.</string>
|
||||||
<string name="category_academia">Akademija</string>
|
|
||||||
<string name="category_activism">Aktivizam</string>
|
|
||||||
<string name="category_all">Sve</string>
|
|
||||||
<string name="category_art">Umjetnost</string>
|
|
||||||
<string name="category_food">Hrana</string>
|
|
||||||
<string name="category_furry">Ljubimci</string>
|
|
||||||
<string name="category_games">Igre</string>
|
|
||||||
<string name="category_general">Generalno</string>
|
<string name="category_general">Generalno</string>
|
||||||
<string name="category_journalism">Novinarstvo</string>
|
|
||||||
<string name="category_lgbt">LGBT</string>
|
|
||||||
<string name="category_music">Muzika</string>
|
|
||||||
<string name="category_regional">Regionalno</string>
|
|
||||||
<string name="category_tech">Tehnika</string>
|
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="resend">Ponovo poslato</string>
|
<string name="resend">Ponovo poslato</string>
|
||||||
<string name="open_email_app">Otvori email</string>
|
<string name="open_email_app">Otvori email</string>
|
||||||
@@ -187,4 +175,5 @@
|
|||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -136,19 +136,7 @@
|
|||||||
<string name="password">Contrasenya</string>
|
<string name="password">Contrasenya</string>
|
||||||
<string name="confirm_password">Confirmar contrasenya</string>
|
<string name="confirm_password">Confirmar contrasenya</string>
|
||||||
<string name="password_note">Inclou lletres majúscules, caràcters especials i números per augmentar la seguretat de la teva contrasenya.</string>
|
<string name="password_note">Inclou lletres majúscules, caràcters especials i números per augmentar la seguretat de la teva contrasenya.</string>
|
||||||
<string name="category_academia">Acadèmic</string>
|
|
||||||
<string name="category_activism">Activisme</string>
|
|
||||||
<string name="category_all">Totes</string>
|
|
||||||
<string name="category_art">Art</string>
|
|
||||||
<string name="category_food">Menjar</string>
|
|
||||||
<string name="category_furry">Furry</string>
|
|
||||||
<string name="category_games">Jocs</string>
|
|
||||||
<string name="category_general">General</string>
|
<string name="category_general">General</string>
|
||||||
<string name="category_journalism">Periodisme</string>
|
|
||||||
<string name="category_lgbt">LGBT</string>
|
|
||||||
<string name="category_music">Música</string>
|
|
||||||
<string name="category_regional">Regional</string>
|
|
||||||
<string name="category_tech">Tecnologia</string>
|
|
||||||
<string name="confirm_email_title">Comprova la teva safata d\'entrada</string>
|
<string name="confirm_email_title">Comprova la teva safata d\'entrada</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="resend">Reenvia</string>
|
<string name="resend">Reenvia</string>
|
||||||
@@ -226,7 +214,6 @@
|
|||||||
<item quantity="one">%,d favorit</item>
|
<item quantity="one">%,d favorit</item>
|
||||||
<item quantity="other">%,d favorits</item>
|
<item quantity="other">%,d favorits</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="timestamp_via_app">%1$s través de %2$s</string>
|
|
||||||
<string name="time_now">ara</string>
|
<string name="time_now">ara</string>
|
||||||
<string name="edit_history">Editar l’historial</string>
|
<string name="edit_history">Editar l’historial</string>
|
||||||
<string name="last_edit_at_x">Darrera edició: %s</string>
|
<string name="last_edit_at_x">Darrera edició: %s</string>
|
||||||
@@ -297,4 +284,5 @@
|
|||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -187,19 +187,7 @@
|
|||||||
<string name="password">Heslo</string>
|
<string name="password">Heslo</string>
|
||||||
<string name="confirm_password">Potvrdit heslo</string>
|
<string name="confirm_password">Potvrdit heslo</string>
|
||||||
<string name="password_note">Použijte velká písmena, speciální znaky a čísla, abyste zvýšili sílu hesla.</string>
|
<string name="password_note">Použijte velká písmena, speciální znaky a čísla, abyste zvýšili sílu hesla.</string>
|
||||||
<string name="category_academia">Akademická sféra</string>
|
|
||||||
<string name="category_activism">Aktivismus</string>
|
|
||||||
<string name="category_all">Vše</string>
|
|
||||||
<string name="category_art">Umění</string>
|
|
||||||
<string name="category_food">Jídlo</string>
|
|
||||||
<string name="category_furry">Furry</string>
|
|
||||||
<string name="category_games">Hry</string>
|
|
||||||
<string name="category_general">Obecné</string>
|
<string name="category_general">Obecné</string>
|
||||||
<string name="category_journalism">Žurnalistika</string>
|
|
||||||
<string name="category_lgbt">LGBT</string>
|
|
||||||
<string name="category_music">Hudba</string>
|
|
||||||
<string name="category_regional">Regionální</string>
|
|
||||||
<string name="category_tech">Technologie</string>
|
|
||||||
<string name="confirm_email_title">Zkontrolujte si příchozí poštu</string>
|
<string name="confirm_email_title">Zkontrolujte si příchozí poštu</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="confirm_email_subtitle">Klepněte na odkaz, který jsme vám poslali, abyste ověřili %s. Budeme tu na vás čekat.</string>
|
<string name="confirm_email_subtitle">Klepněte na odkaz, který jsme vám poslali, abyste ověřili %s. Budeme tu na vás čekat.</string>
|
||||||
@@ -318,7 +306,6 @@
|
|||||||
<item quantity="many">%,d boostů</item>
|
<item quantity="many">%,d boostů</item>
|
||||||
<item quantity="other">%,d boostů</item>
|
<item quantity="other">%,d boostů</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="timestamp_via_app">%1$s přes %2$s</string>
|
|
||||||
<string name="time_now">teď</string>
|
<string name="time_now">teď</string>
|
||||||
<string name="edit_history">Historie úprav</string>
|
<string name="edit_history">Historie úprav</string>
|
||||||
<string name="last_edit_at_x">Poslední úprava %s</string>
|
<string name="last_edit_at_x">Poslední úprava %s</string>
|
||||||
@@ -394,7 +381,6 @@
|
|||||||
<string name="profile_add_row">Přidat řádek</string>
|
<string name="profile_add_row">Přidat řádek</string>
|
||||||
<string name="profile_setup">Nastavení profilu</string>
|
<string name="profile_setup">Nastavení profilu</string>
|
||||||
<string name="profile_setup_subtitle">Toto můžete vždy dokončit později v záložce Profil.</string>
|
<string name="profile_setup_subtitle">Toto můžete vždy dokončit později v záložce Profil.</string>
|
||||||
<string name="profile_setup_explanation">Můžete přidat až čtyři pole profilu pro cokoliv, co chcete. Umístění, odkazy, oslovení — limitem je obloha.</string>
|
|
||||||
<string name="popular_on_mastodon">Populární na Mastodonu</string>
|
<string name="popular_on_mastodon">Populární na Mastodonu</string>
|
||||||
<string name="follow_all">Sledovat všechny</string>
|
<string name="follow_all">Sledovat všechny</string>
|
||||||
<string name="server_rules_disagree">Nesouhlasit</string>
|
<string name="server_rules_disagree">Nesouhlasit</string>
|
||||||
@@ -643,4 +629,5 @@
|
|||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -163,19 +163,7 @@
|
|||||||
<string name="password">Adgangskode</string>
|
<string name="password">Adgangskode</string>
|
||||||
<string name="confirm_password">Bekræft adgangskode</string>
|
<string name="confirm_password">Bekræft adgangskode</string>
|
||||||
<string name="password_note">Benyt majuskler, specialtegn og tal for at øge adgangskodens styrke.</string>
|
<string name="password_note">Benyt majuskler, specialtegn og tal for at øge adgangskodens styrke.</string>
|
||||||
<string name="category_academia">Forskning og højere uddannelser</string>
|
|
||||||
<string name="category_activism">Aktivisme</string>
|
|
||||||
<string name="category_all">Alt</string>
|
|
||||||
<string name="category_art">Kunst</string>
|
|
||||||
<string name="category_food">Mad</string>
|
|
||||||
<string name="category_furry">Pelsdyr</string>
|
|
||||||
<string name="category_games">Spil</string>
|
|
||||||
<string name="category_general">Generelt</string>
|
<string name="category_general">Generelt</string>
|
||||||
<string name="category_journalism">Journalistik</string>
|
|
||||||
<string name="category_lgbt">LGBT</string>
|
|
||||||
<string name="category_music">Musik</string>
|
|
||||||
<string name="category_regional">Regionalt</string>
|
|
||||||
<string name="category_tech">Teknologi</string>
|
|
||||||
<string name="confirm_email_title">Tjek din indbakke</string>
|
<string name="confirm_email_title">Tjek din indbakke</string>
|
||||||
<!-- %s is the email address -->
|
<!-- %s is the email address -->
|
||||||
<string name="confirm_email_subtitle">Tryk på det modtage link for at bekræfte %s. Vi venter her så længe.</string>
|
<string name="confirm_email_subtitle">Tryk på det modtage link for at bekræfte %s. Vi venter her så længe.</string>
|
||||||
@@ -284,7 +272,6 @@
|
|||||||
<item quantity="one">%,d fremhævning</item>
|
<item quantity="one">%,d fremhævning</item>
|
||||||
<item quantity="other">%,d fremhævninger</item>
|
<item quantity="other">%,d fremhævninger</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="timestamp_via_app">%1$s via %2$s</string>
|
|
||||||
<string name="time_now">nu</string>
|
<string name="time_now">nu</string>
|
||||||
<string name="edit_history">Rediger historik</string>
|
<string name="edit_history">Rediger historik</string>
|
||||||
<string name="last_edit_at_x">Senest ændret: %s</string>
|
<string name="last_edit_at_x">Senest ændret: %s</string>
|
||||||
@@ -356,7 +343,6 @@
|
|||||||
<string name="profile_add_row">Tilføj række</string>
|
<string name="profile_add_row">Tilføj række</string>
|
||||||
<string name="profile_setup">Profilopsætning</string>
|
<string name="profile_setup">Profilopsætning</string>
|
||||||
<string name="profile_setup_subtitle">Du kan altid afslutte dette senere i fanen Profil.</string>
|
<string name="profile_setup_subtitle">Du kan altid afslutte dette senere i fanen Profil.</string>
|
||||||
<string name="profile_setup_explanation">Du kan tilføje op til fire profilfelter til lige, hvad du ønsker. Placering, links, pronomener — du bestemmer.</string>
|
|
||||||
<string name="popular_on_mastodon">Populært på Mastodon</string>
|
<string name="popular_on_mastodon">Populært på Mastodon</string>
|
||||||
<string name="follow_all">Følg alle</string>
|
<string name="follow_all">Følg alle</string>
|
||||||
<string name="server_rules_disagree">Ikke enig</string>
|
<string name="server_rules_disagree">Ikke enig</string>
|
||||||
@@ -507,4 +493,5 @@
|
|||||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||||
<!-- %s is the name of the list -->
|
<!-- %s is the name of the list -->
|
||||||
<!-- %s is a username -->
|
<!-- %s is a username -->
|
||||||
|
<!-- %s is a time interval ("5 months") -->
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user