Compare commits
85 Commits
v1.1.4+for
...
v1.1.4+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e840c2584 | ||
|
|
adf628de44 | ||
|
|
7e4169644d | ||
|
|
e42988b51e | ||
|
|
7c2fd2b734 | ||
|
|
569e4e13ea | ||
|
|
b7b5785a97 | ||
|
|
95d6e51ae0 | ||
|
|
fc43d919e5 | ||
|
|
a8d19529cd | ||
|
|
c2c44ab25e | ||
|
|
96a56873c3 | ||
|
|
0100967597 | ||
|
|
5769b378e2 | ||
|
|
2c61551e5c | ||
|
|
c9b11a23a1 | ||
|
|
456d05a489 | ||
|
|
8ca7d9d7b4 | ||
|
|
2321549dca | ||
|
|
5ae96328d5 | ||
|
|
dbf3da3629 | ||
|
|
9a351de9b4 | ||
|
|
f871fa6743 | ||
|
|
85f6441a56 | ||
|
|
dd8354f91b | ||
|
|
21d78de3cc | ||
|
|
158af27309 | ||
|
|
b0446af54a | ||
|
|
064f0155f6 | ||
|
|
fbf4522260 | ||
|
|
8918bd5ce2 | ||
|
|
187693883c | ||
|
|
40868f90f9 | ||
|
|
1f89acec34 | ||
|
|
d75ce99a68 | ||
|
|
0a8846fa2a | ||
|
|
5253e2e24a | ||
|
|
3565223611 | ||
|
|
2343d7a046 | ||
|
|
8256fbadb6 | ||
|
|
b898dc010e | ||
|
|
de369633ec | ||
|
|
3f075eab13 | ||
|
|
96e5f854a5 | ||
|
|
0f5211f718 | ||
|
|
480915f377 | ||
|
|
15d559ad6a | ||
|
|
3b7a6e9385 | ||
|
|
314a15973c | ||
|
|
e99917945a | ||
|
|
d3ba8a4d0f | ||
|
|
9162b31ac1 | ||
|
|
51a80f3e03 | ||
|
|
a8c49b59f6 | ||
|
|
c79942c13f | ||
|
|
da121495c0 | ||
|
|
2d710cb558 | ||
|
|
f0a51a15a9 | ||
|
|
ae68b1e646 | ||
|
|
5da58d7834 | ||
|
|
24023e9843 | ||
|
|
29d9871e77 | ||
|
|
32d182f03a | ||
|
|
da4f54751e | ||
|
|
393c538464 | ||
|
|
ddcf61dc95 | ||
|
|
5b70c035d2 | ||
|
|
289564381d | ||
|
|
3fbcce8570 | ||
|
|
505b755df6 | ||
|
|
4b9618cad5 | ||
|
|
e7b0e022d6 | ||
|
|
7ffc58d52c | ||
|
|
30151cafc2 | ||
|
|
d0ce157069 | ||
|
|
be7d65989d | ||
|
|
08656a2678 | ||
|
|
b0f76739ba | ||
|
|
a09efd084e | ||
|
|
0bb85d71e4 | ||
|
|
7248ab9801 | ||
|
|
cd4d83e139 | ||
|
|
f1f7c1341c | ||
|
|
a7ab6945f9 | ||
|
|
896583aeec |
43
README.md
43
README.md
@@ -6,8 +6,11 @@
|
||||
|
||||
[](https://github.com/sk22/mastodos/releases/latest/download/mastodos.apk)
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
|
||||
## Key features
|
||||
|
||||
### **Unlisted posting**
|
||||
@@ -52,6 +55,28 @@ To install this app on your Android device, download the [latest release from Gi
|
||||
|
||||
Mastodos makes use of [Mastodon for Android](https://github.com/mastodon/mastodon-android)’s automatic update checker. Mastodos will check for new updates available on GitHub and offer to download and install them. You can also manually press “Check for updates” at the bottom of the settings page!
|
||||
|
||||
### Other sources
|
||||
|
||||
* **[Izzy's F-Droid repository](https://apt.izzysoft.de/fdroid/repo)**: https://apt.izzysoft.de/fdroid/index/apk/org.joinmastodon.android.sk
|
||||
|
||||
---
|
||||
|
||||
## Release variants
|
||||
|
||||
All downloads can be found on the [Releases](https://github.com/sk22/mastodos/releases) page.
|
||||
|
||||
**`mastodos.apk`**
|
||||
|
||||
Variant with an integrated updater. If you download Mastodos from here (and not from an app store), just download the regular `mastodos.apk`.
|
||||
|
||||
**`mastodon-1234abc.apk`**
|
||||
|
||||
This is an **unmodified version** of the official [Mastodon for Android](https://github.com/mastodon/mastodon-android) app the respective Mastodos release is based on. Should you find any bugs in Mastodos (which you will), try to see if it occurs with this variant, too. The last 7 digits of the file name are important to know which version of the official app you're using.
|
||||
|
||||
<!-- **`mastodon-fdroid.apk`**
|
||||
|
||||
Variant without the integrated updater. This is the variant to be published to F-Droid.org where an integrated updater is not necessary. -->
|
||||
|
||||
---
|
||||
|
||||
## Detailed changes
|
||||
@@ -74,6 +99,10 @@ Mastodos makes use of [Mastodon for Android](https://github.com/mastodon/mastodo
|
||||
* [List favorited posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/favs-list)
|
||||
* [Accept/reject follow requests](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/follow-requests)
|
||||
* [Display content warning title above text](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/cw-above-text)
|
||||
* [Add notifications tab for posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/posts-notifications-tab)
|
||||
* [Show visibility of original post when replying](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/display-reply-visibility)
|
||||
* [Clickable reply/boost line above posts](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:clickable-boost-reply-line)
|
||||
* [Long-click to copy username from profile](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/copy-username)
|
||||
|
||||
### Behavior
|
||||
|
||||
@@ -81,9 +110,15 @@ Mastodos makes use of [Mastodon for Android](https://github.com/mastodon/mastodo
|
||||
* [Always preserve content warnings when replying](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/always-preserve-cw) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/113))
|
||||
* [Display full image when adding image description](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/compose-image-description-full-image) ([Pull request](https://github.com/mastodon/mastodon-android/pull/182))
|
||||
* [Set spoiler height independently to content height](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:spoiler-height-independent) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/166))
|
||||
* [Custom extended footer redesign](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:compact-extended-footer)
|
||||
* [Option to hide interaction numbers](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:settings/hide-interaction-numbers)
|
||||
* [Option to always reveal content warnings](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:feature/cw-above-text)
|
||||
* [Option to disable scrolling title bars](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:settings/disable-marquee)
|
||||
|
||||
### Visual
|
||||
|
||||
* [Custom extended footer redesign](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:compact-extended-footer)
|
||||
* [Improvements to the true black mode](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:true-black-improvements)
|
||||
* [Profile header tweaks](https://github.com/mastodon/mastodon-android/compare/master...sk22:mastodos:ui/profile-header-tweaks)
|
||||
|
||||
### Branding
|
||||
|
||||
@@ -91,7 +126,7 @@ Mastodos makes use of [Mastodon for Android](https://github.com/mastodon/mastodo
|
||||
* Pink primary color
|
||||
* Custom icon: Modulate upstream icon using ImageMagick
|
||||
```bash
|
||||
mogrify -modulate 90,100,140 mastodon/src/main/res/mipmap-*/ic_launcher*.png
|
||||
mogrify -modulate 90,100,140 mastodon/src/main/res/mipmap-*/ic_launcher*.png mastodon/src/main/ic_launcher-playstore.png
|
||||
```
|
||||
|
||||
## Building
|
||||
@@ -105,3 +140,7 @@ As this app is using Java 17 features, you need JDK 17 or newer to build it. Oth
|
||||
## License
|
||||
|
||||
This project is released under the [GPL-3 License](./LICENSE).
|
||||
|
||||
## Links
|
||||
|
||||
<a rel="me" href="https://floss.social/@mastodos">@mastodos@floss.social</a>
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
title: Mastodos
|
||||
theme: minima
|
||||
layout: default
|
||||
|
||||
17
_layouts/default.html
Normal file
17
_layouts/default.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mastodos</title>
|
||||
<link rel="icon" href="mastodon/src/main/res/mipmap-mdpi/ic_launcher_round.png">
|
||||
<link rel="me" href="https://floss.social/@mastodon">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css">
|
||||
</head>
|
||||
<body class="markdown-body">
|
||||
<div style="margin: 0 auto; max-width: 45rem; padding: 2rem 1rem">
|
||||
{{ content }}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
3
get-upstream-commit.sh
Executable file
3
get-upstream-commit.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
git rev-parse --short --verify upstream/master
|
||||
BIN
img/banner.png
Normal file
BIN
img/banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 501 KiB |
@@ -9,8 +9,8 @@ android {
|
||||
applicationId "org.joinmastodon.android.sk"
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
versionCode 41
|
||||
versionName "1.1.4+fork.41"
|
||||
versionCode 47
|
||||
versionName "1.1.4+fork.47"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
resConfigs "en", "ar-rSA", "bs-rBA", "ca-rES", "cs-rCZ", "de-rDE", "el-rGR", "es-rES",
|
||||
"eu-rES", "fi-rFI", "fr-rFR", "gl-rES", "hr-rHR", "hy-rAM", "it-rIT", "iw-rIL",
|
||||
@@ -20,12 +20,13 @@ android {
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
shrinkResources true
|
||||
// minifyEnabled true
|
||||
// shrinkResources true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug{
|
||||
debuggable true
|
||||
versionNameSuffix '-debug'
|
||||
}
|
||||
appcenterPrivateBeta{
|
||||
initWith release
|
||||
|
||||
@@ -139,12 +139,12 @@ public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
|
||||
curForkNumber=Integer.parseInt(matcher.group(4));
|
||||
long newVersion=((long)newMajor << 32) | ((long)newMinor << 16) | newRevision;
|
||||
long curVersion=((long)curMajor << 32) | ((long)curMinor << 16) | curRevision;
|
||||
if(newVersion>curVersion || newForkNumber>curForkNumber || BuildConfig.DEBUG){
|
||||
if(newVersion>curVersion || newForkNumber>curForkNumber){
|
||||
String version=newMajor+"."+newMinor+"."+newRevision+"+fork."+newForkNumber;
|
||||
Log.d(TAG, "actuallyCheckForUpdates: new version: "+version);
|
||||
for(JsonElement el:obj.getAsJsonArray("assets")){
|
||||
JsonObject asset=el.getAsJsonObject();
|
||||
if("application/vnd.android.package-archive".equals(asset.get("content_type").getAsString()) && "uploaded".equals(asset.get("state").getAsString())){
|
||||
if("mastodos.apk".equals(asset.get("name")) && "application/vnd.android.package-archive".equals(asset.get("content_type").getAsString()) && "uploaded".equals(asset.get("state").getAsString())){
|
||||
long size=asset.get("size").getAsLong();
|
||||
String url=asset.get("browser_download_url").getAsString();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE"/>
|
||||
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||
|
||||
<permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 48 KiB |
@@ -12,9 +12,10 @@ public class GlobalUserPreferences{
|
||||
public static boolean loadNewPosts;
|
||||
public static boolean showInteractionCounts;
|
||||
public static boolean alwaysExpandContentWarnings;
|
||||
public static boolean disableMarquee;
|
||||
public static ThemePreference theme;
|
||||
|
||||
private static SharedPreferences getPrefs(){
|
||||
private static SharedPreferences getPrefs(){
|
||||
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@@ -28,6 +29,7 @@ public class GlobalUserPreferences{
|
||||
loadNewPosts=prefs.getBoolean("loadNewPosts", true);
|
||||
showInteractionCounts=prefs.getBoolean("showInteractionCounts", false);
|
||||
alwaysExpandContentWarnings=prefs.getBoolean("alwaysExpandContentWarnings", false);
|
||||
disableMarquee=prefs.getBoolean("disableMarquee", false);
|
||||
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
|
||||
}
|
||||
|
||||
@@ -41,6 +43,7 @@ public class GlobalUserPreferences{
|
||||
.putBoolean("trueBlackTheme", trueBlackTheme)
|
||||
.putBoolean("showInteractionCounts", showInteractionCounts)
|
||||
.putBoolean("alwaysExpandContentWarnings", alwaysExpandContentWarnings)
|
||||
.putBoolean("disableMarquee", disableMarquee)
|
||||
.putInt("theme", theme.ordinal())
|
||||
.apply();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import me.grishka.appkit.utils.WorkerThread;
|
||||
|
||||
public class CacheController{
|
||||
private static final String TAG="CacheController";
|
||||
private static final int DB_VERSION=2;
|
||||
private static final int DB_VERSION=3;
|
||||
private static final WorkerThread databaseThread=new WorkerThread("databaseThread");
|
||||
private static final Handler uiHandler=new Handler(Looper.getMainLooper());
|
||||
|
||||
@@ -73,7 +73,7 @@ public class CacheController{
|
||||
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0);
|
||||
newMaxID=status.id;
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(status.getContentStatus().content))
|
||||
if(filter.matches(status))
|
||||
continue outer;
|
||||
}
|
||||
result.add(status);
|
||||
@@ -126,14 +126,15 @@ public class CacheController{
|
||||
});
|
||||
}
|
||||
|
||||
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean forceReload, Callback<PaginatedResponse<List<Notification>>> callback){
|
||||
public void getNotifications(String maxID, int count, boolean onlyMentions, boolean onlyPosts, boolean forceReload, Callback<PaginatedResponse<List<Notification>>> callback){
|
||||
cancelDelayedClose();
|
||||
databaseThread.postRunnable(()->{
|
||||
try{
|
||||
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.NOTIFICATIONS)).collect(Collectors.toList());
|
||||
if(!forceReload){
|
||||
SQLiteDatabase db=getOrOpenDatabase();
|
||||
try(Cursor cursor=db.query(onlyMentions ? "notifications_mentions" : "notifications_all", new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
||||
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
|
||||
try(Cursor cursor=db.query(table, new String[]{"json"}, maxID==null ? null : "`id`<?", maxID==null ? null : new String[]{maxID}, null, null, "`id` DESC", count+"")){
|
||||
if(cursor.getCount()==count){
|
||||
ArrayList<Notification> result=new ArrayList<>();
|
||||
cursor.moveToFirst();
|
||||
@@ -145,7 +146,7 @@ public class CacheController{
|
||||
newMaxID=ntf.id;
|
||||
if(ntf.status!=null){
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(ntf.status.getContentStatus().content))
|
||||
if(filter.matches(ntf.status))
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
@@ -159,21 +160,21 @@ public class CacheController{
|
||||
Log.w(TAG, "getNotifications: corrupted notification object in database", x);
|
||||
}
|
||||
}
|
||||
new GetNotifications(maxID, count, onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class))
|
||||
new GetNotifications(maxID, count, onlyPosts ? EnumSet.of(Notification.Type.STATUS) : onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class))
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<Notification> result){
|
||||
callback.onSuccess(new PaginatedResponse<>(result.stream().filter(ntf->{
|
||||
if(ntf.status!=null){
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(ntf.status.getContentStatus().content)){
|
||||
if(filter.matches(ntf.status)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}).collect(Collectors.toList()), result.isEmpty() ? null : result.get(result.size()-1).id));
|
||||
putNotifications(result, onlyMentions, maxID==null);
|
||||
putNotifications(result, onlyMentions, onlyPosts, maxID==null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -191,9 +192,9 @@ public class CacheController{
|
||||
}, 0);
|
||||
}
|
||||
|
||||
private void putNotifications(List<Notification> notifications, boolean onlyMentions, boolean clear){
|
||||
private void putNotifications(List<Notification> notifications, boolean onlyMentions, boolean onlyPosts, boolean clear){
|
||||
runOnDbThread((db)->{
|
||||
String table=onlyMentions ? "notifications_mentions" : "notifications_all";
|
||||
String table=onlyPosts ? "notifications_posts" : onlyMentions ? "notifications_mentions" : "notifications_all";
|
||||
if(clear)
|
||||
db.delete(table, null, null);
|
||||
ContentValues values=new ContentValues(3);
|
||||
@@ -317,6 +318,7 @@ public class CacheController{
|
||||
`type` INTEGER NOT NULL
|
||||
)""");
|
||||
createRecentSearchesTable(db);
|
||||
createPostsNotificationsTable(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -324,6 +326,9 @@ public class CacheController{
|
||||
if(oldVersion==1){
|
||||
createRecentSearchesTable(db);
|
||||
}
|
||||
if(oldVersion==2){
|
||||
createPostsNotificationsTable(db);
|
||||
}
|
||||
}
|
||||
|
||||
private void createRecentSearchesTable(SQLiteDatabase db){
|
||||
@@ -334,6 +339,16 @@ public class CacheController{
|
||||
`time` INTEGER NOT NULL
|
||||
)""");
|
||||
}
|
||||
|
||||
private void createPostsNotificationsTable(SQLiteDatabase db){
|
||||
db.execSQL("""
|
||||
CREATE TABLE `notifications_posts` (
|
||||
`id` VARCHAR(25) NOT NULL PRIMARY KEY,
|
||||
`json` TEXT NOT NULL,
|
||||
`flags` INTEGER NOT NULL DEFAULT 0,
|
||||
`type` INTEGER NOT NULL
|
||||
)""");
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
|
||||
@@ -19,6 +19,7 @@ import android.view.WindowInsets;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||
import org.joinmastodon.android.api.requests.polls.SubmitPollVote;
|
||||
@@ -81,6 +82,10 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
if(GlobalUserPreferences.disableMarquee){
|
||||
setTitleMarqueeEnabled(false);
|
||||
setSubtitleMarqueeEnabled(false);
|
||||
}
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||
setRetainInstance(true);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.graphics.Outline;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.RenderEffect;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.icu.text.BreakIterator;
|
||||
import android.media.MediaMetadataRetriever;
|
||||
@@ -502,6 +503,24 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
spoilerEdit.addTextChangedListener(new SimpleTextWatcher(e->updateCharCounter()));
|
||||
if(replyTo!=null){
|
||||
replyText.setText(getString(R.string.in_reply_to, replyTo.account.displayName));
|
||||
int visibilityNameRes = switch (statusVisibility) {
|
||||
case PUBLIC -> R.string.visibility_public;
|
||||
case UNLISTED -> R.string.visibility_unlisted;
|
||||
case PRIVATE -> R.string.visibility_followers_only;
|
||||
case DIRECT -> R.string.visibility_private;
|
||||
};
|
||||
replyText.setContentDescription(getString(R.string.in_reply_to, replyTo.account.displayName) + ". " + getString(R.string.post_visibility) + ": " + getString(visibilityNameRes));
|
||||
Drawable visibilityIcon = getActivity().getDrawable(switch(statusVisibility){
|
||||
case PUBLIC -> R.drawable.ic_fluent_earth_20_regular;
|
||||
case UNLISTED -> R.drawable.ic_fluent_people_community_20_regular;
|
||||
case PRIVATE -> R.drawable.ic_fluent_people_checkmark_20_regular;
|
||||
case DIRECT -> R.drawable.ic_at_symbol;
|
||||
});
|
||||
visibilityIcon.setBounds(0, 0, V.dp(20), V.dp(20));
|
||||
Drawable replyArrow = getActivity().getDrawable(R.drawable.ic_fluent_arrow_reply_20_filled);
|
||||
replyArrow.setBounds(0, 0, V.dp(20), V.dp(20));
|
||||
replyText.setCompoundDrawables(replyArrow, null, visibilityIcon, null);
|
||||
|
||||
ArrayList<String> mentions=new ArrayList<>();
|
||||
String ownID=AccountSessionManager.getInstance().getAccount(accountID).self.id;
|
||||
if(!replyTo.account.id.equals(ownID))
|
||||
|
||||
@@ -66,8 +66,8 @@ public class HashtagTimelineFragment extends StatusListFragment{
|
||||
new SetHashtagFollowed(hashtag, following).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Hashtag i) {
|
||||
if (i.following == following) Toast.makeText(getActivity(), getString(i.following ? R.string.followed_user : R.string.unfollowed_user, "#" + i.name), Toast.LENGTH_SHORT).show();
|
||||
updateFollowingState(i.following);
|
||||
Toast.makeText(getActivity(), getString(i.following ? R.string.followed_user : R.string.unfollowed_user, "#" + i.name), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -268,7 +268,7 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||
if(idsBelowGap.contains(s.id))
|
||||
break;
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(s.getContentStatus().content)){
|
||||
if(filter.matches(s)){
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class ListTimelineFragment extends StatusListFragment {
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
// TODO: implement edit, delete
|
||||
// inflater.inflate(R.menu.list, menu);
|
||||
}
|
||||
|
||||
@@ -73,7 +74,6 @@ public class ListTimelineFragment extends StatusListFragment {
|
||||
private void onFabClick(View v){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putString("prefilledText", listID+' ');
|
||||
Nav.go(getActivity(), ComposeFragment.class, args);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
private FrameLayout[] tabViews;
|
||||
private TabLayoutMediator tabLayoutMediator;
|
||||
|
||||
private NotificationsListFragment allNotificationsFragment, mentionsFragment;
|
||||
private NotificationsListFragment allNotificationsFragment, mentionsFragment, postsFragment;
|
||||
|
||||
private String accountID;
|
||||
|
||||
@@ -92,12 +92,13 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
tabLayout=view.findViewById(R.id.tabbar);
|
||||
pager=view.findViewById(R.id.pager);
|
||||
|
||||
tabViews=new FrameLayout[2];
|
||||
tabViews=new FrameLayout[3];
|
||||
for(int i=0;i<tabViews.length;i++){
|
||||
FrameLayout tabView=new FrameLayout(getActivity());
|
||||
tabView.setId(switch(i){
|
||||
case 0 -> R.id.notifications_all;
|
||||
case 1 -> R.id.notifications_mentions;
|
||||
case 2 -> R.id.notifications_posts;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+i);
|
||||
});
|
||||
tabView.setVisibility(View.GONE);
|
||||
@@ -136,9 +137,15 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
mentionsFragment=new NotificationsListFragment();
|
||||
mentionsFragment.setArguments(args);
|
||||
|
||||
args=new Bundle(args);
|
||||
args.putBoolean("onlyPosts", true);
|
||||
postsFragment=new NotificationsListFragment();
|
||||
postsFragment.setArguments(args);
|
||||
|
||||
getChildFragmentManager().beginTransaction()
|
||||
.add(R.id.notifications_all, allNotificationsFragment)
|
||||
.add(R.id.notifications_mentions, mentionsFragment)
|
||||
.add(R.id.notifications_posts, postsFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@@ -148,6 +155,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
tab.setText(switch(position){
|
||||
case 0 -> R.string.all_notifications;
|
||||
case 1 -> R.string.mentions;
|
||||
case 2 -> R.string.posts;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+position);
|
||||
});
|
||||
tab.view.textView.setAllCaps(true);
|
||||
@@ -196,6 +204,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
return switch(page){
|
||||
case 0 -> allNotificationsFragment;
|
||||
case 1 -> mentionsFragment;
|
||||
case 2 -> postsFragment;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+page);
|
||||
};
|
||||
}
|
||||
@@ -216,7 +225,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
|
||||
|
||||
@Override
|
||||
public int getItemCount(){
|
||||
return 2;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ import me.grishka.appkit.utils.V;
|
||||
|
||||
public class NotificationsListFragment extends BaseStatusListFragment<Notification>{
|
||||
private boolean onlyMentions;
|
||||
private boolean onlyPosts;
|
||||
private String maxID;
|
||||
|
||||
@Override
|
||||
@@ -53,6 +54,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
|
||||
public void onAttach(Activity activity){
|
||||
super.onAttach(activity);
|
||||
onlyMentions=getArguments().getBoolean("onlyMentions", false);
|
||||
onlyPosts=getArguments().getBoolean("onlyPosts", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,7 +108,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
|
||||
protected void doLoadData(int offset, int count){
|
||||
AccountSessionManager.getInstance()
|
||||
.getAccount(accountID).getCacheController()
|
||||
.getNotifications(offset>0 ? maxID : null, count, onlyMentions, refreshing, new SimpleCallback<>(this){
|
||||
.getNotifications(offset>0 ? maxID : null, count, onlyMentions, onlyPosts, refreshing, new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(PaginatedResponse<List<Notification>> result){
|
||||
if(getActivity()==null)
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Outline;
|
||||
@@ -14,6 +19,8 @@ import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.ImageSpan;
|
||||
@@ -31,9 +38,11 @@ import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.widget.Toolbar;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
@@ -435,15 +444,25 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
ssb.append(AccountSessionManager.getInstance().getAccount(accountID).domain);
|
||||
}
|
||||
ssb.append(" ");
|
||||
Drawable lock=username.getResources().getDrawable(R.drawable.ic_fluent_lock_closed_20_filled, getActivity().getTheme()).mutate();
|
||||
Drawable lock=username.getResources().getDrawable(R.drawable.ic_lock, getActivity().getTheme()).mutate();
|
||||
lock.setBounds(0, 0, lock.getIntrinsicWidth(), lock.getIntrinsicHeight());
|
||||
lock.setTint(username.getCurrentTextColor());
|
||||
ssb.append(getString(R.string.manually_approves_followers), new ImageSpan(lock, ImageSpan.ALIGN_BOTTOM), 0);
|
||||
ssb.append(getString(R.string.manually_approves_followers), new ImageSpan(lock, ImageSpan.ALIGN_BASELINE), 0);
|
||||
username.setText(ssb);
|
||||
}else{
|
||||
// noinspection SetTextI18n
|
||||
username.setText('@'+account.acct+(isSelf ? ('@'+AccountSessionManager.getInstance().getAccount(accountID).domain) : ""));
|
||||
}
|
||||
username.setOnLongClickListener(l->{
|
||||
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE);
|
||||
Vibrator v = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText("Username", '@'+account.acct+'@'+AccountSessionManager.getInstance().getAccount(accountID).domain);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
Toast.makeText(getActivity(), R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) v.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
|
||||
else v.vibrate(50);
|
||||
return true;
|
||||
});
|
||||
CharSequence parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
if(TextUtils.isEmpty(parsedBio)){
|
||||
bio.setVisibility(View.GONE);
|
||||
@@ -648,7 +667,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
notifyProgress.setIndeterminateTintList(notifyButton.getTextColors());
|
||||
followsYouView.setVisibility(relationship.followedBy ? View.VISIBLE : View.GONE);
|
||||
notifyButton.setSelected(relationship.notifying);
|
||||
notifyButton.setContentDescription(getString(relationship.notifying ? R.string.user_post_notifications_on : R.string.user_post_notifications_off, '@'+account.username));
|
||||
if (getActivity() != null) notifyButton.setContentDescription(getString(relationship.notifying ? R.string.user_post_notifications_on : R.string.user_post_notifications_off, '@'+account.username));
|
||||
}
|
||||
|
||||
private void onScrollChanged(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
|
||||
|
||||
@@ -94,6 +94,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
|
||||
items.add(new HeaderItem(R.string.settings_theme));
|
||||
items.add(themeItem=new ThemeItem());
|
||||
items.add(new SwitchItem(R.string.theme_true_black, R.drawable.ic_fluent_dark_theme_24_regular, GlobalUserPreferences.trueBlackTheme, this::onTrueBlackThemeChanged));
|
||||
items.add(new SwitchItem(R.string.disable_marquee, R.drawable.ic_fluent_text_more_24_regular, GlobalUserPreferences.disableMarquee, i->{
|
||||
GlobalUserPreferences.disableMarquee=i.checked;
|
||||
GlobalUserPreferences.save();
|
||||
}));
|
||||
|
||||
items.add(new HeaderItem(R.string.settings_behavior));
|
||||
items.add(new SwitchItem(R.string.settings_gif, R.drawable.ic_fluent_gif_24_regular, GlobalUserPreferences.playGifs, i->{
|
||||
|
||||
@@ -139,7 +139,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
|
||||
action=getString(R.string.edit_multiple_changed);
|
||||
}
|
||||
}
|
||||
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" · "+date, Collections.emptyList(), 0));
|
||||
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" · "+date, Collections.emptyList(), 0, null));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class ThreadFragment extends StatusListFragment{
|
||||
return statuses;
|
||||
return statuses.stream().filter(status->{
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(status.getContentStatus().content))
|
||||
if(filter.matches(status))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
@@ -295,6 +296,14 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
private void proceedWithAuthOrSignup(Instance instance){
|
||||
getActivity().getSystemService(InputMethodManager.class).hideSoftInputFromWindow(contentView.getWindowToken(), 0);
|
||||
if(isSignup){
|
||||
if(!instance.registrations){
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.instance_signup_closed)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
Bundle args=new Bundle();
|
||||
args.putParcelable("instance", Parcels.wrap(instance));
|
||||
Nav.go(getActivity(), InstanceRulesFragment.class, args);
|
||||
@@ -478,7 +487,7 @@ public class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInstanc
|
||||
instanceProgressDialog=null;
|
||||
proceedWithAuthOrSignup(result);
|
||||
}
|
||||
if(domain.equals(currentSearchQuery) || currentSearchQuery.equals(redirects.get(domain)) || currentSearchQuery.equals(redirectsInverse.get(domain))){
|
||||
if(Objects.equals(domain, currentSearchQuery) || Objects.equals(currentSearchQuery, redirects.get(domain)) || Objects.equals(currentSearchQuery, redirectsInverse.get(domain))){
|
||||
boolean found=false;
|
||||
for(CatalogInstance ci:filteredData){
|
||||
if(ci.domain.equals(domain)){
|
||||
|
||||
@@ -102,7 +102,7 @@ public class ReportCommentFragment extends MastodonToolbarFragment{
|
||||
ReportReason reason=ReportReason.valueOf(getArguments().getString("reason"));
|
||||
ArrayList<String> statusIDs=getArguments().getStringArrayList("statusIDs");
|
||||
ArrayList<String> ruleIDs=getArguments().getStringArrayList("ruleIDs");
|
||||
new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, v.getId()==R.id.btn_back ? null : commentEdit.getText().toString(), false)
|
||||
new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, v.getId()==R.id.btn_back ? null : commentEdit.getText().toString(), true)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Object result){
|
||||
|
||||
@@ -50,6 +50,10 @@ public class Filter extends BaseModel{
|
||||
return pattern.matcher(text).find();
|
||||
}
|
||||
|
||||
public boolean matches(Status status){
|
||||
return matches(status.getContentStatus().getStrippedText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Filter{"+
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -57,6 +58,7 @@ public class Status extends BaseModel implements DisplayItemsParent{
|
||||
|
||||
public transient boolean spoilerRevealed;
|
||||
public transient boolean hasGapAfter;
|
||||
private transient String strippedText;
|
||||
|
||||
@Override
|
||||
public void postprocess() throws ObjectValidationException{
|
||||
@@ -134,4 +136,10 @@ public class Status extends BaseModel implements DisplayItemsParent{
|
||||
public Status getContentStatus(){
|
||||
return reblog!=null ? reblog : this;
|
||||
}
|
||||
|
||||
public String getStrippedText(){
|
||||
if(strippedText==null)
|
||||
strippedText=HtmlParser.strip(content);
|
||||
return strippedText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Activity;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -17,6 +18,8 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
|
||||
@@ -25,14 +28,16 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
@DrawableRes
|
||||
private int icon;
|
||||
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
|
||||
private View.OnClickListener handleClick;
|
||||
|
||||
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon){
|
||||
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, @Nullable View.OnClickListener handleClick){
|
||||
super(parentID, parentFragment);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(text);
|
||||
HtmlParser.parseCustomEmoji(ssb, emojis);
|
||||
this.text=ssb;
|
||||
emojiHelper.setText(ssb);
|
||||
this.icon=icon;
|
||||
this.handleClick=handleClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,6 +66,7 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
public void onBind(ReblogOrReplyLineStatusDisplayItem item){
|
||||
text.setText(item.text);
|
||||
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, 0, 0);
|
||||
if(item.handleClick!=null) text.setOnClickListener(item.handleClick);
|
||||
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N)
|
||||
UiUtils.fixCompoundDrawableTintOnAndroid6(text);
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
@@ -16,6 +18,7 @@ import org.joinmastodon.android.model.Poll;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -23,6 +26,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
@@ -73,11 +77,19 @@ public abstract class StatusDisplayItem{
|
||||
String parentID=parentObject.getID();
|
||||
ArrayList<StatusDisplayItem> items=new ArrayList<>();
|
||||
Status statusForContent=status.getContentStatus();
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
if(status.reblog!=null){
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled, i->{
|
||||
args.putParcelable("profileAccount", Parcels.wrap(status.account));
|
||||
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
|
||||
}));
|
||||
}else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)){
|
||||
Account account=Objects.requireNonNull(knownAccounts.get(status.inReplyToAccountId));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_fluent_arrow_reply_20_filled));
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_fluent_arrow_reply_20_filled, i->{
|
||||
args.putParcelable("profileAccount", Parcels.wrap(account));
|
||||
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
|
||||
}));
|
||||
}
|
||||
HeaderStatusDisplayItem header;
|
||||
items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null));
|
||||
|
||||
@@ -21,9 +21,8 @@ public class StatusFilterPredicate implements Predicate<Status>{
|
||||
|
||||
@Override
|
||||
public boolean test(Status status){
|
||||
CharSequence content=status.getContentStatus().content;
|
||||
for(Filter filter:filters){
|
||||
if(filter.matches(content))
|
||||
if(filter.matches(status))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="?colorBackgroundLightest"/>
|
||||
<solid android:color="?colorBackgroundPopup"/>
|
||||
<corners android:radius="10dp"/>
|
||||
<padding android:top="8dp" android:bottom="8dp"/>
|
||||
</shape>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?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_fluent_arrow_repeat_all_24_filled"/>
|
||||
<item android:state_enabled="true" android:drawable="@drawable/ic_fluent_arrow_repeat_all_24_regular"/>
|
||||
<item android:drawable="@drawable/ic_fluent_arrow_repeat_all_off_24_regular"/>
|
||||
</selector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M14.712 2.289L14.625 2.21c-0.392-0.31-0.964-0.285-1.327 0.078L13.22 2.376c-0.31 0.392-0.285 0.964 0.078 1.326l1.299 1.297H8.999L8.76 5.003C5.004 5.13 2 8.211 2 11.993c0 1.445 0.438 2.788 1.189 3.899C3.37 16.143 3.666 16.307 4 16.307c0.552 0 1-0.448 1-1 0-0.216-0.069-0.416-0.185-0.578L4.68 14.51C4.248 13.77 4 12.91 4 11.993c0-2.759 2.238-4.995 5-4.995h5.595l-1.297 1.297-0.078 0.087c-0.31 0.392-0.285 0.964 0.078 1.326 0.39 0.39 1.024 0.39 1.414 0l3.006-3.003 0.077-0.087c0.311-0.392 0.285-0.964-0.078-1.326l-3.005-3.003zm6.075 5.771C20.602 7.827 20.319 7.678 20 7.678c-0.552 0-1 0.448-1 1 0 0.208 0.064 0.4 0.172 0.56 0.523 0.79 0.828 1.737 0.828 2.755 0 2.76-2.238 4.996-5 4.996H9.416l1.294-1.292 0.083-0.095c0.281-0.361 0.28-0.871-0.006-1.23l-0.077-0.088-0.095-0.084c-0.362-0.28-0.873-0.278-1.232 0.006l-0.088 0.078-3.005 3.003-0.083 0.095c-0.281 0.361-0.28 0.872 0.006 1.231L6.289 18.7l3.005 3.003 0.095 0.084c0.392 0.304 0.96 0.277 1.32-0.084 0.362-0.362 0.388-0.933 0.077-1.326L10.71 20.29l-1.304-1.303h5.596l0.24-0.003C18.996 18.857 22 15.776 22 11.994c0-1.46-0.448-2.816-1.213-3.937V8.06z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
|
||||
<path android:pathData="M8.75 3.75C8.75 2.231 7.519 1 6 1S3.25 2.231 3.25 3.75 4.481 6.5 6 6.5s2.75-1.231 2.75-2.75zm-4.5 0C4.25 2.784 5.034 2 6 2s1.75 0.784 1.75 1.75S6.966 5.5 6 5.5 4.25 4.716 4.25 3.75zM2.5 7.5h4.183c-0.164 0.31-0.286 0.646-0.358 1H2.5C2.224 8.5 2 8.724 2 9v0.5c0 1.26 1.099 2.614 3.096 2.93-0.322 0.22-0.59 0.513-0.781 0.854C2.205 12.713 1 11.087 1 9.5V9c0-0.828 0.672-1.5 1.5-1.5zm5.379 0c0.504-0.61 1.267-1 2.121-1 0.854 0 1.617 0.39 2.121 1 0.24 0.29 0.42 0.629 0.525 1 0.068 0.238 0.104 0.49 0.104 0.75 0 1.07-0.611 1.997-1.503 2.452-0.355 0.18-0.754 0.287-1.177 0.297L10 12H9.93c-0.423-0.011-0.822-0.117-1.177-0.298C7.861 11.247 7.25 10.32 7.25 9.25c0-0.26 0.036-0.512 0.104-0.75 0.104-0.371 0.285-0.71 0.525-1zm0.54 1C8.31 8.727 8.25 8.982 8.25 9.25c0 0.714 0.428 1.328 1.04 1.6C9.509 10.947 9.749 11 10 11c0.252 0 0.492-0.053 0.71-0.15 0.612-0.272 1.04-0.886 1.04-1.6 0-0.268-0.06-0.523-0.168-0.75-0.246-0.516-0.737-0.894-1.322-0.98C10.175 7.506 10.088 7.5 10 7.5c-0.088 0-0.175 0.006-0.26 0.02C9.155 7.605 8.664 7.983 8.418 8.5zm7.266 4.784c-0.19-0.341-0.459-0.634-0.781-0.853C16.9 12.114 18 10.759 18 9.5V9c0-0.276-0.224-0.5-0.5-0.5h-3.825c-0.072-0.354-0.194-0.69-0.357-1H17.5C18.328 7.5 19 8.172 19 9v0.5c0 1.587-1.206 3.212-3.315 3.784zm-1.198 0.087C14.223 13.14 13.878 13 13.5 13h-7c-0.432 0-0.821 0.183-1.095 0.475C5.154 13.743 5 14.104 5 14.5V15c0 1.971 1.86 4 5 4 3.14 0 5-2.029 5-4v-0.5c0-0.45-0.198-0.854-0.513-1.13zM6 14.5C6 14.224 6.224 14 6.5 14h7c0.276 0 0.5 0.224 0.5 0.5V15c0 1.438-1.432 3-4 3s-4-1.562-4-3v-0.5zM14 1c1.519 0 2.75 1.231 2.75 2.75S15.519 6.5 14 6.5s-2.75-1.231-2.75-2.75S12.481 1 14 1zm0 1c-0.966 0-1.75 0.784-1.75 1.75S13.034 5.5 14 5.5s1.75-0.784 1.75-1.75S14.966 2 14 2z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M9.75 2c0.301 0 0.573 0.18 0.69 0.457l6.972 16.431C16.951 18.345 16.267 18 15.5 18c-0.031 0-0.063 0-0.094 0.002L13.92 14.5H5.58l-2.14 5.043c-0.161 0.381-0.601 0.56-0.983 0.397-0.381-0.161-0.559-0.602-0.397-0.983l7-16.5C9.177 2.18 9.45 2 9.75 2zm3.534 11L9.75 4.67 6.216 13h7.068zM12 20.5c0 0.828-0.672 1.5-1.5 1.5S9 21.328 9 20.5 9.672 19 10.5 19s1.5 0.672 1.5 1.5zm3.5 1.5c0.828 0 1.5-0.672 1.5-1.5S16.328 19 15.5 19 14 19.672 14 20.5s0.672 1.5 1.5 1.5zm5 0c0.828 0 1.5-0.672 1.5-1.5S21.328 19 20.5 19 19 19.672 19 20.5s0.672 1.5 1.5 1.5z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
6
mastodon/src/main/res/drawable/ic_lock.xml
Normal file
6
mastodon/src/main/res/drawable/ic_lock.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="16dp" android:height="16dp" android:viewportWidth="16" android:viewportHeight="16">
|
||||
<group android:translateX="-2" android:translateY="-1">
|
||||
<path android:pathData="M10 2c1.657 0 3 1.343 3 3v1h1c1.105 0 2 0.895 2 2v7c0 1.105-0.895 2-2 2H6c-1.105 0-2-0.895-2-2V8c0-1.105 0.895-2 2-2h1V5c0-1.657 1.343-3 3-3zm0 8.5c-0.552 0-1 0.448-1 1s0.448 1 1 1 1-0.448 1-1-0.448-1-1-1zM10 4C9.448 4 9 4.448 9 5v1h2V5c0-0.552-0.448-1-1-1z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</group>
|
||||
</vector>
|
||||
@@ -9,26 +9,29 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/more"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="-6dp"
|
||||
android:layout_marginRight="-8dp"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:contentDescription="@string/more_options"
|
||||
android:src="@drawable/ic_post_more" />
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_post_more"
|
||||
android:tint="?android:textColorSecondary" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/visibility"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_below="@id/more"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginTop="-6dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:layout_toLeftOf="@id/more"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:scaleType="center"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:src="@drawable/ic_visibility" />
|
||||
android:src="@drawable/ic_visibility"
|
||||
android:tint="?android:textColorSecondary" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
@@ -42,9 +45,9 @@
|
||||
android:id="@+id/name_wrap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:layout_toStartOf="@id/more"
|
||||
android:layout_marginEnd="8dp">
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:layout_toEndOf="@id/avatar">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
@@ -52,8 +55,8 @@
|
||||
android:layout_height="24dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
tools:text="Eugen" />
|
||||
|
||||
<TextView
|
||||
@@ -62,10 +65,10 @@
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:fontFamily="sans-serif"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
tools:text="boosted your cat picture" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
@@ -74,8 +77,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_below="@id/name_wrap"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:layoutDirection="locale"
|
||||
android:orientation="horizontal">
|
||||
|
||||
@@ -94,6 +98,7 @@
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="·"
|
||||
android:textAppearance="@style/m3_title_small" />
|
||||
|
||||
@@ -101,8 +106,8 @@
|
||||
android:id="@+id/timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
tools:text="3h" />
|
||||
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="-6dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="16dp">
|
||||
android:layout_marginBottom="-12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_20_filled"
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
android:layout_marginTop="16dp"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
android:drawableStart="@drawable/ic_fluent_arrow_reply_20_filled"
|
||||
tools:drawableEnd="@drawable/ic_fluent_earth_20_regular"
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
android:drawablePadding="6dp"
|
||||
android:singleLine="true"
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
<org.joinmastodon.android.ui.views.CoverImageView
|
||||
android:id="@+id/cover"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="229dp"
|
||||
android:background="#808080"
|
||||
android:layout_height="200dp"
|
||||
android:background="?profileHeaderBackground"
|
||||
android:contentDescription="@string/profile_header"
|
||||
android:scaleType="centerCrop"/>
|
||||
android:scaleType="centerCrop" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/follows_you"
|
||||
@@ -54,8 +54,8 @@
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/avatar_border"
|
||||
android:layout_width="102dp"
|
||||
android:layout_height="102dp"
|
||||
android:layout_width="112dp"
|
||||
android:layout_height="112dp"
|
||||
android:layout_below="@id/cover"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="-40dp"
|
||||
@@ -65,8 +65,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="98dp"
|
||||
android:layout_height="98dp"
|
||||
android:layout_width="108dp"
|
||||
android:layout_height="108dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/profile_picture"
|
||||
@@ -234,22 +234,27 @@
|
||||
android:layout_below="@id/avatar_border"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginTop="17dp"
|
||||
android:layout_marginBottom="0.4dp"
|
||||
android:layout_toStartOf="@id/profile_action_btn_wrap"
|
||||
android:textAppearance="@style/m3_headline_small"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAppearance="@style/m3_headline_small"
|
||||
tools:text="Eugen" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_below="@id/name"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_toStartOf="@id/profile_action_btn_wrap"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:background="?android:selectableItemBackground"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
tools:text="\@Gargron"/>
|
||||
tools:text="\@Gargron" />
|
||||
|
||||
<org.joinmastodon.android.ui.views.LinkedTextView
|
||||
android:id="@+id/bio"
|
||||
@@ -257,7 +262,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/username"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textSize="16sp"
|
||||
|
||||
@@ -367,5 +367,8 @@
|
||||
<string name="install_update">Instal·lar</string>
|
||||
<string name="privacy_policy_title">Mastodon i la teva privacitat</string>
|
||||
<string name="privacy_policy_subtitle">Tot i que l\'aplicació Mastodon no recull cap dada, el servidor mitjançant el qual et registres pot tenir una política diferent. Pren un minut per revisar i acceptar la política de privadesa de l\'aplicació Mastodon i la política de privadesa del teu servidor.</string>
|
||||
<string name="i_agree">Hi estic d\'acord</string>
|
||||
<string name="i_agree">D\'acord</string>
|
||||
<!-- Missing strings -->
|
||||
<string name="bookmarks">Marcadors</string>
|
||||
<string name="pinned_posts">Fixat</string>
|
||||
</resources>
|
||||
|
||||
@@ -414,4 +414,6 @@
|
||||
<string name="privacy_policy_subtitle">Obwohl die Mastodon-App keine Daten sammelt, kann der Server, über den Sie sich anmelden, eine andere Richtlinie haben. Nehmen Sie sich eine Minute Zeit, um die Mastodon-Datenschutzrichtlinien und die Datenschutzrichtlinien Ihres Servers zu lesen und zu akzeptieren.</string>
|
||||
<string name="i_agree">Ich stimme zu</string>
|
||||
<string name="settings_always_reveal_content_warnings">Inhaltswarnungen immer ausklappen</string>
|
||||
<string name="disable_marquee">Laufschrift in Titelleisten deaktivieren</string>
|
||||
<string name="copied_to_clipboard">In die Zwischenablage kopiert</string>
|
||||
</resources>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
</plurals>
|
||||
<string name="posts">게시물</string>
|
||||
<string name="posts_and_replies">게시물과 답장</string>
|
||||
<string name="pinned_posts">고정됨</string>
|
||||
<string name="media">미디어</string>
|
||||
<string name="profile_about">정보</string>
|
||||
<string name="button_follow">팔로우</string>
|
||||
@@ -108,9 +109,20 @@
|
||||
<string name="action_vote">투표</string>
|
||||
<string name="tap_to_reveal">눌러서 확인</string>
|
||||
<string name="delete">삭제</string>
|
||||
<string name="delete_and_redraft">삭제하고 다시 쓰기</string>
|
||||
<string name="confirm_delete_title">게시물 삭제</string>
|
||||
<string name="confirm_delete_and_redraft_title">게시물 삭제하고 다시 쓰기</string>
|
||||
<string name="confirm_delete">정말로 이 게시물을 삭제하시겠습니까?</string>
|
||||
<string name="confirm_delete_and_redraft">정말로 이 게시물을 삭제하고 다시 쓰시겠습니까?</string>
|
||||
<string name="deleting">삭제 중…</string>
|
||||
<string name="pin_post">고정</string>
|
||||
<string name="confirm_pin_post_title">게시물 고정</string>
|
||||
<string name="confirm_pin_post">정말로 이 게시물을 고정하시겠습니까?</string>
|
||||
<string name="pinning">고정 중…</string>
|
||||
<string name="unpin_post">고정 해제</string>
|
||||
<string name="confirm_unpin_post_title">게시물 고정 해제</string>
|
||||
<string name="confirm_unpin_post">정말로 이 게시물을 고정 해제하시겠습니까?</string>
|
||||
<string name="unpinning">고정 해제 중…</string>
|
||||
<string name="notification_channel_audio_player">오디오 재생</string>
|
||||
<string name="play">재생</string>
|
||||
<string name="pause">일시정지</string>
|
||||
@@ -189,6 +201,7 @@
|
||||
<string name="compose_hint">무슨 생각을 하고 있는지 입력하거나 붙여넣으세요</string>
|
||||
<string name="content_warning">열람 주의</string>
|
||||
<string name="add_image_description">이미지 설명 추가…</string>
|
||||
<string name="image_description">이미지 설명</string>
|
||||
<string name="retry_upload">업로드 재시도</string>
|
||||
<string name="edit_image">이미지 편집</string>
|
||||
<string name="save">저장</string>
|
||||
@@ -196,6 +209,7 @@
|
||||
<string name="alt_text_subtitle">대체 텍스트는 저시력자나 시각장애인들에게 당신의 사진을 설명합니다. 문맥을 파악할 수 있는 설명들만 넣도록 하세요.</string>
|
||||
<string name="alt_text_hint">예시: 강아지가 의심스러운 가는 눈초리로 카메라를 쳐다보고 있습니다.</string>
|
||||
<string name="visibility_public">공개</string>
|
||||
<string name="visibility_unlisted">타임라인에 비표시</string>
|
||||
<string name="visibility_followers_only">팔로워 전용</string>
|
||||
<string name="visibility_private">멘션한 사람만</string>
|
||||
<string name="search_all">모두</string>
|
||||
@@ -221,8 +235,12 @@
|
||||
<string name="theme_dark">어두움</string>
|
||||
<string name="theme_true_black">진정한 검정 모드</string>
|
||||
<string name="settings_behavior">동작</string>
|
||||
<string name="settings_show_replies">답장 표시</string>
|
||||
<string name="settings_show_boosts">리블로그 표시</string>
|
||||
<string name="settings_load_new_posts">자동으로 새 포스트 불러오기</string>
|
||||
<string name="settings_gif">아바타와 에모지의 애니메이션을 재생</string>
|
||||
<string name="settings_custom_tabs">앱내 브라우저 사용</string>
|
||||
<string name="settings_show_interaction_counts">상호 작용 수 표시</string>
|
||||
<string name="settings_notifications">알림</string>
|
||||
<string name="notify_me_when">알림을 보낼 조건</string>
|
||||
<string name="notify_anyone">누구든</string>
|
||||
@@ -255,8 +273,11 @@
|
||||
<string name="button_reblog">리블로그</string>
|
||||
<string name="button_favorite">좋아요</string>
|
||||
<string name="button_share">공유</string>
|
||||
<string name="button_bookmark">보관</string>
|
||||
<string name="bookmarks">보관함</string>
|
||||
<string name="media_no_description">설명이 없는 미디어</string>
|
||||
<string name="add_media">미디어 추가</string>
|
||||
<string name="mark_media_as_sensitive">미디어를 민감함으로 설정하기</string>
|
||||
<string name="add_poll">투표 추가</string>
|
||||
<string name="emoji">에모지</string>
|
||||
<string name="post_visibility">게시물 공개범위</string>
|
||||
@@ -269,6 +290,8 @@
|
||||
<string name="open_in_browser">브라우저에서 열기</string>
|
||||
<string name="hide_boosts_from_user">%s의 리블로그를 숨기기</string>
|
||||
<string name="show_boosts_from_user">%s의 리블로그를 보이기</string>
|
||||
<string name="user_post_notifications_on">%s의 게시물 알림 켜기</string>
|
||||
<string name="user_post_notifications_off">%s의 게시물 알림 끄기</string>
|
||||
<string name="signup_reason">가입하려는 이유가 무엇인가요?</string>
|
||||
<string name="signup_reason_note">이 정보는 우리가 심사를 하는 데에 참고할 수 있습니다.</string>
|
||||
<string name="clear">모두 지우기</string>
|
||||
@@ -283,11 +306,13 @@
|
||||
<string name="file_saved">파일 저장됨</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="federated_timeline">연합</string>
|
||||
<string name="trending_posts_info_banner">당신이 속한 마스토돈 서버에서 관심을 끌고 있는 게시물들입니다.</string>
|
||||
<string name="trending_hashtags_info_banner">당신이 속한 마스토돈 서버에서 관심을 끌고 있는 해시태그들입니다.</string>
|
||||
<string name="trending_links_info_banner">당신이 속한 마스토돈 서버에서 가장 많이 공유되고 있는 소식들입니다.</string>
|
||||
<string name="local_timeline_info_banner">당신과 같은 마스토돈 서버에 존재하는 사람들이 공유한 최신 게시물들입니다.</string>
|
||||
<string name="federated_timeline_info_banner">당신이 속한 연합에 존재하는 사람들이 공유한 최신 게시물들입니다.</string>
|
||||
<string name="dismiss">지우기</string>
|
||||
<string name="see_new_posts">새 게시물 보기</string>
|
||||
<string name="load_missing_posts">빈 게시물 불러오기</string>
|
||||
@@ -356,6 +381,18 @@
|
||||
<!-- %s is file size -->
|
||||
<string name="download_update">다운로드 (%s)</string>
|
||||
<string name="install_update">설치</string>
|
||||
<string name="check_for_update">업데이트 확인</string>
|
||||
<string name="no_update_available">사용 가능한 업데이트 없음</string>
|
||||
<string name="privacy_policy_title">마스토돈 및 개인정보</string>
|
||||
<string name="i_agree">동의합니다</string>
|
||||
<string name="list_timelines">리스트</string>
|
||||
<string name="favorited_posts">좋아요</string>
|
||||
<string name="follow_requests">팔로우 요청</string>
|
||||
<string name="accept_follow_request">팔로우 요청 허가</string>
|
||||
<string name="reject_follow_request">팔로우 요청 거부</string>
|
||||
<string name="lists_with_user">%s 님이 포함된 리스트</string>
|
||||
<string name="empty_list">리스트에 아무 것도 없습니다</string>
|
||||
<string name="instance_signup_closed">이 서버는 가입이 막혀 있는 상태입니다.</string>
|
||||
<string name="settings_always_reveal_content_warnings">열람주의 툿을 항상 펼치기</string>
|
||||
<string name="disable_marquee">제목 표시줄의 텍스트 스크롤 비활성화</string>
|
||||
</resources>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<attr name="colorSecondary" format="color"/>
|
||||
<attr name="colorBackgroundLight" format="color"/>
|
||||
<attr name="colorBackgroundLightest" format="color"/>
|
||||
<attr name="colorBackgroundPopup" format="color"/>
|
||||
<attr name="colorDarkIcon" format="color"/>
|
||||
<attr name="colorPollMostVoted" format="color"/>
|
||||
<attr name="colorPollVoted" format="color"/>
|
||||
@@ -15,6 +16,7 @@
|
||||
<attr name="colorSearchHint" format="color"/>
|
||||
<attr name="colorTabInactive" format="color"/>
|
||||
<attr name="colorAccentLightest" format="color"/>
|
||||
<attr name="profileHeaderBackground" format="color"/>
|
||||
|
||||
<attr name="primaryLargeButtonStyle" format="reference"/>
|
||||
<attr name="secondaryLargeButtonStyle" format="reference"/>
|
||||
|
||||
@@ -18,4 +18,5 @@
|
||||
|
||||
<item name="notifications_all" type="id"/>
|
||||
<item name="notifications_mentions" type="id"/>
|
||||
<item name="notifications_posts" type="id"/>
|
||||
</resources>
|
||||
@@ -421,5 +421,8 @@
|
||||
<string name="reject_follow_request">Reject follow request</string>
|
||||
<string name="lists_with_user">Lists with %s</string>
|
||||
<string name="empty_list">This list is empty</string>
|
||||
<string name="instance_signup_closed">This server does not accept new registrations.</string>
|
||||
<string name="settings_always_reveal_content_warnings">Always reveal content warnings</string>
|
||||
<string name="disable_marquee">Disable scrolling text in title bars</string>
|
||||
<string name="copied_to_clipboard">Copied to clipboard</string>
|
||||
</resources>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<item name="colorSecondary">#E9EDF2</item>
|
||||
<item name="colorBackgroundLight">@color/gray_50</item>
|
||||
<item name="colorBackgroundLightest">@color/gray_25</item>
|
||||
<item name="colorBackgroundPopup">?colorBackgroundLightest</item>
|
||||
<item name="colorDarkIcon">@color/gray_900</item>
|
||||
<item name="colorWindowBackground">@color/white</item>
|
||||
<item name="android:statusBarColor">@color/gray_50</item>
|
||||
@@ -35,6 +36,7 @@
|
||||
<item name="colorSearchHint">@color/gray_600</item>
|
||||
<item name="colorTabInactive">@color/gray_400</item>
|
||||
<item name="colorAccentLightest">@color/primary_100</item>
|
||||
<item name="profileHeaderBackground">@color/gray_500</item>
|
||||
|
||||
<item name="buttonBackground">@drawable/bg_button_primary_dark_on_light</item>
|
||||
<item name="android:editTextBackground">@drawable/bg_edittext_light</item>
|
||||
@@ -67,6 +69,7 @@
|
||||
<item name="colorSecondary">#E9EDF2</item>
|
||||
<item name="colorBackgroundLight">@color/gray_700</item>
|
||||
<item name="colorBackgroundLightest">@color/gray_900</item>
|
||||
<item name="colorBackgroundPopup">?colorBackgroundLightest</item>
|
||||
<item name="colorDarkIcon">@color/gray_25</item>
|
||||
<item name="colorWindowBackground">@color/gray_800</item>
|
||||
<item name="android:statusBarColor">@color/gray_800</item>
|
||||
@@ -78,6 +81,7 @@
|
||||
<item name="colorAccentLight">@color/primary_600</item>
|
||||
<item name="colorAccentLightest">@color/primary_800</item>
|
||||
<item name="colorTabInactive">@color/gray_400</item>
|
||||
<item name="profileHeaderBackground">?colorWindowBackground</item>
|
||||
|
||||
<!-- TODO dark colors -->
|
||||
<item name="colorSearchField">@color/gray_700</item>
|
||||
@@ -93,7 +97,17 @@
|
||||
</style>
|
||||
|
||||
<style name="Theme.Mastodon.Dark.TrueBlack">
|
||||
<item name="colorWindowBackground">#000</item>
|
||||
<item name="android:navigationBarColor">@color/black</item>
|
||||
<item name="android:colorBackground">@color/black</item>
|
||||
<item name="android:statusBarColor">@color/black</item>
|
||||
<item name="android:actionBarTheme">@style/Theme.Mastodon.Toolbar.Dark.TrueBlack</item>
|
||||
<item name="colorBackgroundLight">@color/black</item>
|
||||
<item name="colorWindowBackground">@color/black</item>
|
||||
<item name="colorButtonText">@color/black</item>
|
||||
<item name="colorPollVoted">@color/gray_800</item>
|
||||
<item name="colorSearchField">@color/gray_900</item>
|
||||
<item name="colorBackgroundLightest">@color/black</item>
|
||||
<item name="colorBackgroundPopup">@color/gray_900</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Mastodon.AutoLightDark" parent="Theme.Mastodon.Light"/>
|
||||
@@ -111,6 +125,10 @@
|
||||
<item name="android:textColorSecondary">@color/gray_50</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Mastodon.Toolbar.Dark.TrueBlack" parent="android:ThemeOverlay.Material.Dark.ActionBar">
|
||||
<item name="android:colorPrimary">@color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Mastodon.Toolbar.Profile">
|
||||
<item name="android:textColorPrimary">@color/gray_50</item>
|
||||
<item name="android:textColorSecondary">@color/gray_50</item>
|
||||
|
||||
@@ -1,43 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<locale android:name="en" />
|
||||
<locale android:name="ar" />
|
||||
<locale android:name="bn-BD"/>
|
||||
<locale android:name="bs" />
|
||||
<locale android:name="ca" />
|
||||
<locale android:name="cs" />
|
||||
<locale android:name="de" />
|
||||
<locale android:name="gd-GB"/>
|
||||
<locale android:name="el" />
|
||||
<locale android:name="es" />
|
||||
<locale android:name="eu" />
|
||||
<locale android:name="fi" />
|
||||
<locale android:name="fr" />
|
||||
<loacle android:name="sl"/>
|
||||
<locale android:name="gl" />
|
||||
<locale android:name="hi-IN"/>
|
||||
<locale android:name="hr" />
|
||||
<locale android:name="hy" />
|
||||
<locale android:name="id"/>
|
||||
<locale android:name="it" />
|
||||
<locale android:name="iw" />
|
||||
<locale android:name="ja" />
|
||||
<locale android:name="kab" />
|
||||
<locale android:name="ko" />
|
||||
<locale android:name="nl"/>
|
||||
<locale android:name="oc" />
|
||||
<locale android:name="pl" />
|
||||
<locale android:name="pt-BR" />
|
||||
<locale android:name="pt-PT" />
|
||||
<locale android:name="ro"/>
|
||||
<locale android:name="ru" />
|
||||
<locale android:name="si-LK"/>
|
||||
<locale android:name="sl"/>
|
||||
<locale android:name="sv" />
|
||||
<locale android:name="th" />
|
||||
<locale android:name="tr" />
|
||||
<locale android:name="uk" />
|
||||
<locale android:name="vi" />
|
||||
<locale android:name="zh-Hans" />
|
||||
<locale android:name="zh-Hant" />
|
||||
<locale android:name="ar-SA"/>
|
||||
<locale android:name="bn-BD"/>
|
||||
<locale android:name="bs-BA"/>
|
||||
<locale android:name="ca-ES"/>
|
||||
<locale android:name="cs-CZ"/>
|
||||
<locale android:name="de-DE"/>
|
||||
<locale android:name="el-GR"/>
|
||||
<locale android:name="en"/>
|
||||
<locale android:name="es-ES"/>
|
||||
<locale android:name="eu-ES"/>
|
||||
<locale android:name="fi-FI"/>
|
||||
<locale android:name="fr-FR"/>
|
||||
<locale android:name="gd-GB"/>
|
||||
<locale android:name="gl-ES"/>
|
||||
<locale android:name="hi-IN"/>
|
||||
<locale android:name="hr-HR"/>
|
||||
<locale android:name="hy-AM"/>
|
||||
<locale android:name="in-ID"/>
|
||||
<locale android:name="it-IT"/>
|
||||
<locale android:name="iw-IL"/>
|
||||
<locale android:name="ja-JP"/>
|
||||
<locale android:name="kab"/>
|
||||
<locale android:name="ko-KR"/>
|
||||
<locale android:name="nl-NL"/>
|
||||
<locale android:name="oc-FR"/>
|
||||
<locale android:name="pl-PL"/>
|
||||
<locale android:name="pt-BR"/>
|
||||
<locale android:name="pt-PT"/>
|
||||
<locale android:name="ru-RU"/>
|
||||
<locale android:name="si-LK"/>
|
||||
<locale android:name="sv-SE"/>
|
||||
<locale android:name="th-TH"/>
|
||||
<locale android:name="tr-TR"/>
|
||||
<locale android:name="uk-UA"/>
|
||||
<locale android:name="vi-VN"/>
|
||||
<locale android:name="zh-CN"/>
|
||||
<locale android:name="zh-TW"/>
|
||||
</locale-config>
|
||||
44
tools/GenerateLocaleConfig.java
Normal file
44
tools/GenerateLocaleConfig.java
Normal file
@@ -0,0 +1,44 @@
|
||||
// Run: java tools/GenerateLocaleConfig.java
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class GenerateLocaleConfig{
|
||||
public static void main(String[] args) throws IOException{
|
||||
File dir=new File("../mastodon/src/main/res/");
|
||||
if(!dir.exists())
|
||||
dir=new File("mastodon/src/main/res");
|
||||
if(!dir.exists())
|
||||
throw new RuntimeException("Please run from project directory (can't find mastodon/src/main/res)");
|
||||
|
||||
ArrayList<String> locales=new ArrayList<>();
|
||||
locales.add("en");
|
||||
|
||||
for(File file:dir.listFiles()){
|
||||
String name=file.getName();
|
||||
if(file.isDirectory() && name.startsWith("values-")){
|
||||
if(new File(file, "strings.xml").exists()){
|
||||
locales.add(name.substring(name.indexOf('-')+1).replace("-r", "-"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locales.sort(String::compareTo);
|
||||
try(OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream(new File(dir, "xml/locales_config.xml")), StandardCharsets.UTF_8)){
|
||||
writer.write("""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
""");
|
||||
for(String locale : locales){
|
||||
writer.write("\t<locale android:name=\"");
|
||||
writer.write(locale);
|
||||
writer.write("\"/>\n");
|
||||
}
|
||||
writer.write("</locale-config>");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user