Compare commits
20 Commits
v1.1.1-dev
...
v1.1.1+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f21b647ee0 | ||
|
|
2a628a3791 | ||
|
|
ecd568503d | ||
|
|
4d950e43ac | ||
|
|
99405f307d | ||
|
|
f1bfe05263 | ||
|
|
0f223159c0 | ||
|
|
ad9518e87c | ||
|
|
1c16cfb09e | ||
|
|
d4a4b10017 | ||
|
|
74ae5bd04e | ||
|
|
9638cf079f | ||
|
|
a6d161c1b4 | ||
|
|
1136e40eb4 | ||
|
|
98de3a2984 | ||
|
|
080a320e12 | ||
|
|
b08415ca8f | ||
|
|
3639c69d36 | ||
|
|
37cefcaf6d | ||
|
|
558adc6936 |
@@ -1,18 +1,19 @@
|
|||||||
# Forked Mastodon for Android
|
# Forked Mastodon for Android
|
||||||
[](https://crowdin.com/project/mastodon-for-android)
|
|
||||||
|
|
||||||
This is the repository for an officially forked Android app for Mastodon.
|
This is the repository for an officially forked Android app for Mastodon.
|
||||||
|
|
||||||
Learn more about this app in the [blog post](https://blog.joinmastodon.org/2022/02/official-mastodon-for-android-app-is-coming-soon/).
|
Learn more about the official app in the [blog post](https://blog.joinmastodon.org/2022/02/official-mastodon-for-android-app-is-coming-soon/).
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
* [Enable "Unlisted" as a visibility option](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted)
|
* [Enable "Unlisted" as a visibility option](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted)
|
||||||
([Pull request](https://github.com/mastodon/mastodon-android/pull/103)) and
|
([Pull request](https://github.com/mastodon/mastodon-android/pull/103)) and
|
||||||
[set as default](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted-as-default)
|
[set as default](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted-as-default)
|
||||||
* [Add "Federation" tab and change Discover tab order](https://github.com/sk22/mastodon-android-fork/tree/feature/add-federated-timeline)
|
* [Add "Federation" tab and change Discover tab order](https://github.com/sk22/mastodon-android-fork/tree/feature/add-federated-timeline) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/8))
|
||||||
* [Add image description button and viewer](https://github.com/sk22/mastodon-android-fork/tree/feature/display-alt-text) ([Pull request](https://github.com/mastodon/mastodon-android/pull/129))
|
* [Add image description button and viewer](https://github.com/sk22/mastodon-android-fork/tree/feature/display-alt-text) ([Pull request](https://github.com/mastodon/mastodon-android/pull/129))
|
||||||
* [Implement pinning posts and displaying pinned posts](https://github.com/sk22/mastodon-android-fork/tree/feature/pin-posts) ([Pull request](https://github.com/mastodon/mastodon-android/pull/140))
|
* [Implement pinning posts and displaying pinned posts](https://github.com/sk22/mastodon-android-fork/tree/feature/pin-posts) ([Pull request](https://github.com/mastodon/mastodon-android/pull/140))
|
||||||
|
* [Display full image when adding image description](https://github.com/sk22/mastodon-android-fork/tree/feature/compose-image-description-full-image) ([Pull request](https://github.com/mastodon/mastodon-android/pull/182))
|
||||||
|
* [Always preserve content warnings when replying](https://github.com/sk22/mastodon-android-fork/tree/feature/always-preserve-cw) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/113))
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "org.joinmastodon.android.sk"
|
applicationId "org.joinmastodon.android.sk"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 31
|
targetSdk 31
|
||||||
versionCode 9
|
versionCode 13
|
||||||
versionName '1.1.1-dev+fork.9'
|
versionName '1.1.1+fork.13'
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import android.util.Log;
|
|||||||
import org.joinmastodon.android.api.ObjectValidationException;
|
import org.joinmastodon.android.api.ObjectValidationException;
|
||||||
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.fragments.ComposeFragment;
|
||||||
import org.joinmastodon.android.fragments.HomeFragment;
|
import org.joinmastodon.android.fragments.HomeFragment;
|
||||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||||
import org.joinmastodon.android.fragments.SplashFragment;
|
import org.joinmastodon.android.fragments.SplashFragment;
|
||||||
@@ -56,6 +57,8 @@ public class MainActivity extends FragmentStackActivity{
|
|||||||
if(intent.getBooleanExtra("fromNotification", false) && intent.hasExtra("notification")){
|
if(intent.getBooleanExtra("fromNotification", false) && intent.hasExtra("notification")){
|
||||||
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
|
Notification notification=Parcels.unwrap(intent.getParcelableExtra("notification"));
|
||||||
showFragmentForNotification(notification, session.getID());
|
showFragmentForNotification(notification, session.getID());
|
||||||
|
}else if(intent.getBooleanExtra("compose", false)){
|
||||||
|
showCompose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +94,8 @@ public class MainActivity extends FragmentStackActivity{
|
|||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
showFragmentClearingBackStack(fragment);
|
showFragmentClearingBackStack(fragment);
|
||||||
}
|
}
|
||||||
|
}else if(intent.getBooleanExtra("compose", false)){
|
||||||
|
showCompose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,4 +120,15 @@ public class MainActivity extends FragmentStackActivity{
|
|||||||
fragment.setArguments(args);
|
fragment.setArguments(args);
|
||||||
showFragment(fragment);
|
showFragment(fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showCompose(){
|
||||||
|
AccountSession session=AccountSessionManager.getInstance().getLastActiveAccount();
|
||||||
|
if(session==null || !session.activated)
|
||||||
|
return;
|
||||||
|
ComposeFragment compose=new ComposeFragment();
|
||||||
|
Bundle composeArgs=new Bundle();
|
||||||
|
composeArgs.putString("account", session.getID());
|
||||||
|
compose.setArguments(composeArgs);
|
||||||
|
showFragment(compose);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,15 +2,22 @@ package org.joinmastodon.android.api.session;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ShortcutInfo;
|
||||||
|
import android.content.pm.ShortcutManager;
|
||||||
|
import android.graphics.drawable.Icon;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.gson.JsonParseException;
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.BuildConfig;
|
||||||
import org.joinmastodon.android.E;
|
import org.joinmastodon.android.E;
|
||||||
|
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.MastodonAPIController;
|
import org.joinmastodon.android.api.MastodonAPIController;
|
||||||
@@ -90,6 +97,7 @@ public class AccountSessionManager{
|
|||||||
}
|
}
|
||||||
lastActiveAccountID=prefs.getString("lastActiveAccount", null);
|
lastActiveAccountID=prefs.getString("lastActiveAccount", null);
|
||||||
MastodonAPIController.runInBackground(()->readInstanceInfo(domains));
|
MastodonAPIController.runInBackground(()->readInstanceInfo(domains));
|
||||||
|
maybeUpdateShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAccount(Instance instance, Token token, Account self, Application app, boolean active){
|
public void addAccount(Instance instance, Token token, Account self, Application app, boolean active){
|
||||||
@@ -102,6 +110,7 @@ public class AccountSessionManager{
|
|||||||
if(PushSubscriptionManager.arePushNotificationsAvailable()){
|
if(PushSubscriptionManager.arePushNotificationsAvailable()){
|
||||||
session.getPushSubscriptionManager().registerAccountForPush(null);
|
session.getPushSubscriptionManager().registerAccountForPush(null);
|
||||||
}
|
}
|
||||||
|
maybeUpdateShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void writeAccountsFile(){
|
public synchronized void writeAccountsFile(){
|
||||||
@@ -181,6 +190,7 @@ public class AccountSessionManager{
|
|||||||
NotificationManager nm=MastodonApp.context.getSystemService(NotificationManager.class);
|
NotificationManager nm=MastodonApp.context.getSystemService(NotificationManager.class);
|
||||||
nm.deleteNotificationChannelGroup(id);
|
nm.deleteNotificationChannelGroup(id);
|
||||||
}
|
}
|
||||||
|
maybeUpdateShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -395,6 +405,29 @@ public class AccountSessionManager{
|
|||||||
writeAccountsFile();
|
writeAccountsFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void maybeUpdateShortcuts(){
|
||||||
|
if(Build.VERSION.SDK_INT<26)
|
||||||
|
return;
|
||||||
|
ShortcutManager sm=MastodonApp.context.getSystemService(ShortcutManager.class);
|
||||||
|
if((sm.getDynamicShortcuts().isEmpty() || BuildConfig.DEBUG) && !sessions.isEmpty()){
|
||||||
|
// There are no shortcuts, but there are accounts. Add a compose shortcut.
|
||||||
|
ShortcutInfo info=new ShortcutInfo.Builder(MastodonApp.context, "compose")
|
||||||
|
.setActivity(ComponentName.createRelative(MastodonApp.context, MainActivity.class.getName()))
|
||||||
|
.setShortLabel(MastodonApp.context.getString(R.string.new_post))
|
||||||
|
.setIcon(Icon.createWithResource(MastodonApp.context, R.mipmap.ic_shortcut_compose))
|
||||||
|
.setIntent(new Intent(MastodonApp.context, MainActivity.class)
|
||||||
|
.setAction(Intent.ACTION_MAIN)
|
||||||
|
.putExtra("compose", true))
|
||||||
|
.build();
|
||||||
|
sm.setDynamicShortcuts(Collections.singletonList(info));
|
||||||
|
}else if(sessions.isEmpty()){
|
||||||
|
// There are shortcuts, but no accounts. Disable existing shortcuts.
|
||||||
|
sm.disableShortcuts(Collections.singletonList("compose"), MastodonApp.context.getString(R.string.err_not_logged_in));
|
||||||
|
}else{
|
||||||
|
sm.enableShortcuts(Collections.singletonList("compose"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class SessionsStorageWrapper{
|
private static class SessionsStorageWrapper{
|
||||||
public List<AccountSession> accounts;
|
public List<AccountSession> accounts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -453,7 +453,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||||||
if(savedInstanceState==null){
|
if(savedInstanceState==null){
|
||||||
mainEditText.setText(initialText);
|
mainEditText.setText(initialText);
|
||||||
mainEditText.setSelection(mainEditText.length());
|
mainEditText.setSelection(mainEditText.length());
|
||||||
if(!TextUtils.isEmpty(replyTo.spoilerText) && AccountSessionManager.getInstance().isSelf(accountID, replyTo.account)){
|
// TODO: setting for preserving cw always / only when replying to own posts
|
||||||
|
// && AccountSessionManager.getInstance().isSelf(accountID, replyTo.account)
|
||||||
|
if(!TextUtils.isEmpty(replyTo.spoilerText)){
|
||||||
hasSpoiler=true;
|
hasSpoiler=true;
|
||||||
spoilerEdit.setVisibility(View.VISIBLE);
|
spoilerEdit.setVisibility(View.VISIBLE);
|
||||||
spoilerEdit.setText(replyTo.spoilerText);
|
spoilerEdit.setText(replyTo.spoilerText);
|
||||||
|
|||||||
@@ -255,9 +255,14 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
|||||||
@Override
|
@Override
|
||||||
public boolean onBackPressed(){
|
public boolean onBackPressed(){
|
||||||
if(currentTab==R.id.tab_profile)
|
if(currentTab==R.id.tab_profile)
|
||||||
return profileFragment.onBackPressed();
|
if (profileFragment.onBackPressed()) return true;
|
||||||
if(currentTab==R.id.tab_search)
|
if(currentTab==R.id.tab_search)
|
||||||
return searchFragment.onBackPressed();
|
if (searchFragment.onBackPressed()) return true;
|
||||||
|
if (currentTab!=R.id.tab_home) {
|
||||||
|
tabBar.selectTab(R.id.tab_home);
|
||||||
|
onTabSelected(R.id.tab_home);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public class ImageAttachmentFrameLayout extends FrameLayout{
|
|||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int w=Math.min(((View)getParent()).getMeasuredWidth()-horizontalInset, V.dp(MAX_WIDTH));
|
int w=Math.min(((View)getParent()).getMeasuredWidth(), V.dp(MAX_WIDTH))-horizontalInset;
|
||||||
int actualHeight=Math.round(tile.height/1000f*w)+V.dp(1)*(tile.rowSpan-1);
|
int actualHeight=Math.round(tile.height/1000f*w)+V.dp(1)*(tile.rowSpan-1);
|
||||||
int actualWidth=Math.round(tile.width/1000f*w);
|
int actualWidth=Math.round(tile.width/1000f*w);
|
||||||
if(tile.startCol+tile.colSpan<tileLayout.columnSizes.length)
|
if(tile.startCol+tile.colSpan<tileLayout.columnSizes.length)
|
||||||
|
|||||||
7
mastodon/src/main/res/drawable/ic_compose_foreground.xml
Normal file
7
mastodon/src/main/res/drawable/ic_compose_foreground.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<vector android:height="108dp"
|
||||||
|
android:viewportHeight="48" android:viewportWidth="48"
|
||||||
|
android:width="108dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<group android:translateX="12" android:translateY="12">
|
||||||
|
<path android:fillColor="@color/shortcut_icon_foreground" android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
@@ -9,20 +9,21 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<org.joinmastodon.android.ui.views.ComposeMediaLayout
|
<org.joinmastodon.android.ui.views.MaxWidthFrameLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal">
|
android:layout_gravity="center"
|
||||||
|
android:maxWidth="400dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/photo"
|
android:id="@+id/photo"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="centerCrop"
|
android:adjustViewBounds="true"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
tools:src="#0f0"/>
|
tools:src="#0f0"/>
|
||||||
|
|
||||||
</org.joinmastodon.android.ui.views.ComposeMediaLayout>
|
</org.joinmastodon.android.ui.views.MaxWidthFrameLayout>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background>
|
||||||
|
<shape>
|
||||||
|
<solid android:color="@color/shortcut_icon_background"/>
|
||||||
|
<size android:width="108dp" android:height="108dp"/>
|
||||||
|
</shape>
|
||||||
|
</background>
|
||||||
|
<foreground android:drawable="@drawable/ic_compose_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
5
mastodon/src/main/res/values-night/colors.xml
Normal file
5
mastodon/src/main/res/values-night/colors.xml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="shortcut_icon_background">@color/gray_700</color>
|
||||||
|
<color name="shortcut_icon_foreground">@color/primary_600</color>
|
||||||
|
</resources>
|
||||||
@@ -93,4 +93,7 @@
|
|||||||
|
|
||||||
<color name="favorite_selected">@color/warning_500</color>
|
<color name="favorite_selected">@color/warning_500</color>
|
||||||
<color name="boost_selected">@color/primary_500</color>
|
<color name="boost_selected">@color/primary_500</color>
|
||||||
|
|
||||||
|
<color name="shortcut_icon_background">@color/gray_100</color>
|
||||||
|
<color name="shortcut_icon_foreground">@color/primary_700</color>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Mastođon</string>
|
<string name="app_name" translatable="false">Mastadon</string>
|
||||||
|
|
||||||
<string name="get_started">Get started</string>
|
<string name="get_started">Get started</string>
|
||||||
<string name="log_in">Log in</string>
|
<string name="log_in">Log in</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user