diff --git a/app/build.gradle b/app/build.gradle
index 45f98aad..a63d95dc 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -13,11 +13,11 @@ def getGitSha = { ->
}
android {
- compileSdkVersion 28
+ compileSdkVersion 29
defaultConfig {
applicationId "com.keylesspalace.tusky"
minSdkVersion 21
- targetSdkVersion 28
+ targetSdkVersion 29
versionCode 68
versionName "9.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -105,6 +105,7 @@ dependencies {
implementation 'androidx.exifinterface:exifinterface:1.0.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.preference:preference:1.1.0'
+ implementation 'androidx.sharetarget:sharetarget:1.0.0-beta01'
implementation "com.squareup.retrofit2:retrofit:$retrofitVersion"
implementation "com.squareup.retrofit2:converter-gson:$retrofitVersion"
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofitVersion"
@@ -136,7 +137,7 @@ dependencies {
implementation "com.google.dagger:dagger-android:$daggerVersion"
implementation "com.google.dagger:dagger-android-support:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
- testImplementation 'org.robolectric:robolectric:4.3'
+ testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'org.mockito:mockito-inline:3.1.0'
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0'
androidTestImplementation('androidx.test.espresso:espresso-core:3.1.1', {
diff --git a/app/src/blue/res/xml-v25/shortcuts.xml b/app/src/blue/res/xml-v25/shortcuts.xml
deleted file mode 100644
index d0aaa2e8..00000000
--- a/app/src/blue/res/xml-v25/shortcuts.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/green/res/xml-v25/shortcuts.xml b/app/src/green/res/xml-v25/shortcuts.xml
deleted file mode 100644
index 130274fa..00000000
--- a/app/src/green/res/xml-v25/shortcuts.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index edc4856e..ea510482 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -31,7 +31,8 @@
+ android:resource="@xml/share_shortcuts" />
+
+ android:configChanges="orientation|screenSize|keyboardHidden|screenLayout|smallestScreenSize">
@@ -91,7 +92,8 @@
+ android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
+
+ android:configChanges="orientation|screenSize|keyboardHidden|screenLayout|smallestScreenSize" />
@@ -153,16 +155,8 @@
+
-
-
-
-
-
(context, R.layout.item_autocomplete_account) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java
index 119669a9..edd93082 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/AccountViewHolder.java
@@ -1,13 +1,13 @@
package com.keylesspalace.tusky.adapter;
-import androidx.recyclerview.widget.RecyclerView;
-
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.AccountActionListener;
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java
index cc861df2..70a44ba8 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/BlocksAdapter.java
@@ -15,10 +15,6 @@
package com.keylesspalace.tusky.adapter;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -26,6 +22,10 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.AccountActionListener;
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java
index a82a10ea..37f09f01 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.java
@@ -15,10 +15,6 @@
package com.keylesspalace.tusky.adapter;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -26,6 +22,10 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.AccountActionListener;
diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java
index 5f494658..a7d14545 100644
--- a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java
+++ b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.java
@@ -1,9 +1,5 @@
package com.keylesspalace.tusky.adapter;
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -11,6 +7,10 @@ import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Account;
import com.keylesspalace.tusky.interfaces.AccountActionListener;
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
index db2dc2cc..268fd5b7 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
+++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationViewHolder.java
@@ -16,7 +16,6 @@
package com.keylesspalace.tusky.components.conversation;
import android.content.Context;
-import android.preference.PreferenceManager;
import android.text.InputFilter;
import android.text.TextUtils;
import android.view.View;
@@ -24,6 +23,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import android.widget.ToggleButton;
+import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.RecyclerView;
import com.keylesspalace.tusky.R;
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt
index 7799688e..b6eef435 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/conversation/ConversationsFragment.kt
@@ -17,13 +17,13 @@ package com.keylesspalace.tusky.components.conversation
import android.content.Intent
import android.os.Bundle
-import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.paging.PagedList
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt
index 2fc35d11..59d15517 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/report/fragments/ReportStatusesFragment.kt
@@ -16,7 +16,6 @@
package com.keylesspalace.tusky.components.report.fragments
import android.os.Bundle
-import android.preference.PreferenceManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -26,6 +25,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.paging.PagedList
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.SimpleItemAnimator
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
index 1362db88..2829e6b6 100644
--- a/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/components/search/fragments/SearchStatusesFragment.kt
@@ -24,7 +24,6 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Environment
-import android.preference.PreferenceManager
import android.util.Log
import android.view.View
import android.widget.Toast
@@ -36,6 +35,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LiveData
import androidx.paging.PagedList
import androidx.paging.PagedListAdapter
+import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.keylesspalace.tusky.*
@@ -277,8 +277,7 @@ class SearchStatusesFragment : SearchFragment {
val clipboard = activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- val clip = ClipData.newPlainText(null, statusUrl)
- clipboard.primaryClip = clip
+ clipboard.setPrimaryClip(ClipData.newPlainText(null, statusUrl))
return@setOnMenuItemClickListener true
}
R.id.status_open_as -> {
diff --git a/app/src/main/java/com/keylesspalace/tusky/di/AppModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/AppModule.kt
index 1cbe2190..bbc87061 100644
--- a/app/src/main/java/com/keylesspalace/tusky/di/AppModule.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/di/AppModule.kt
@@ -19,8 +19,8 @@ package com.keylesspalace.tusky.di
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
-import android.preference.PreferenceManager
import androidx.localbroadcastmanager.content.LocalBroadcastManager
+import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.TuskyApplication
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.EventHubImpl
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java
index b888d8cb..4150a6ee 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.preference.PreferenceManager;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.LayoutInflater;
@@ -39,6 +38,7 @@ import androidx.arch.core.util.Function;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.core.util.Pair;
import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.AsyncDifferConfig;
import androidx.recyclerview.widget.AsyncListDiffer;
import androidx.recyclerview.widget.DiffUtil;
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
index 44937d15..2431bc92 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java
@@ -19,13 +19,29 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.arch.core.util.Function;
+import androidx.core.util.Pair;
+import androidx.core.widget.ContentLoadingProgressBar;
+import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceManager;
+import androidx.recyclerview.widget.AsyncDifferConfig;
+import androidx.recyclerview.widget.AsyncListDiffer;
+import androidx.recyclerview.widget.DiffUtil;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.ListUpdateCallback;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.SimpleItemAnimator;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.keylesspalace.tusky.AccountListActivity;
import com.keylesspalace.tusky.BaseActivity;
@@ -77,22 +93,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.arch.core.util.Function;
-import androidx.core.util.Pair;
-import androidx.core.widget.ContentLoadingProgressBar;
-import androidx.lifecycle.Lifecycle;
-import androidx.recyclerview.widget.AsyncDifferConfig;
-import androidx.recyclerview.widget.AsyncListDiffer;
-import androidx.recyclerview.widget.DiffUtil;
-import androidx.recyclerview.widget.DividerItemDecoration;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.ListUpdateCallback;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.SimpleItemAnimator;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-
import at.connyduck.sparkbutton.helpers.Utils;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -307,7 +307,7 @@ public class TimelineFragment extends SFragment implements
Iterator> iterator = this.statuses.iterator();
while (iterator.hasNext()) {
Either item = iterator.next();
- if(item.isRight()) {
+ if (item.isRight()) {
Status status = item.asRight();
if (status.getId().length() < topId.length() || status.getId().compareTo(topId) < 0) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java
index 825cd23c..b047064c 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java
@@ -19,7 +19,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
-import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -31,6 +30,7 @@ import androidx.annotation.Nullable;
import androidx.arch.core.util.Function;
import androidx.core.util.Pair;
import androidx.lifecycle.Lifecycle;
+import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
diff --git a/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt b/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt
deleted file mode 100644
index b97ca3ee..00000000
--- a/app/src/main/java/com/keylesspalace/tusky/service/AccountChooserService.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/* Copyright 2019 Levi Bard
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky.service
-
-import android.annotation.TargetApi
-import android.content.ComponentName
-import android.content.IntentFilter
-import android.graphics.drawable.Icon
-import android.os.Bundle
-import android.service.chooser.ChooserTarget
-import android.service.chooser.ChooserTargetService
-import android.text.TextUtils
-import com.bumptech.glide.Glide
-import com.keylesspalace.tusky.R
-import com.keylesspalace.tusky.TuskyApplication
-import com.keylesspalace.tusky.db.AccountManager
-import com.keylesspalace.tusky.di.Injectable
-import com.keylesspalace.tusky.util.NotificationHelper
-
-
-@TargetApi(23)
-class AccountChooserService : ChooserTargetService(), Injectable {
-
- // cannot inject here, it crashes on APIs < 23
- lateinit var accountManager: AccountManager
-
- override fun onCreate() {
- super.onCreate()
- accountManager = (application as TuskyApplication).serviceLocator.get(AccountManager::class.java)
- }
-
- override fun onGetChooserTargets(targetActivityName: ComponentName?, intentFilter: IntentFilter?): MutableList {
- val targets = mutableListOf()
- for (account in accountManager.getAllAccountsOrderedByActive()) {
- val icon: Icon = if (TextUtils.isEmpty(account.profilePictureUrl)) {
- Icon.createWithResource(applicationContext, R.drawable.avatar_default)
- } else {
- val bmp = Glide.with(this)
- .asBitmap()
- .load(account.profilePictureUrl)
- .error(R.drawable.avatar_default)
- .placeholder(R.drawable.avatar_default)
- .submit()
- Icon.createWithBitmap(bmp.get())
- }
- val bundle = Bundle()
- bundle.putLong(NotificationHelper.ACCOUNT_ID, account.id)
- targets.add(ChooserTarget(account.displayName, icon, 1.0f, targetActivityName, bundle))
- }
- return targets
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.java b/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
similarity index 50%
rename from app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.java
rename to app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
index 6aad5d22..f064089d 100644
--- a/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.java
+++ b/app/src/main/java/com/keylesspalace/tusky/service/TuskyTileService.kt
@@ -1,4 +1,4 @@
-/* Copyright 2017 Andrew Dawson
+/* Copyright 2019 Tusky Contributors
*
* This file is a part of Tusky.
*
@@ -13,29 +13,28 @@
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see . */
-package com.keylesspalace.tusky.service;
+package com.keylesspalace.tusky.service
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.service.quicksettings.TileService;
+import android.annotation.TargetApi
+import android.content.Intent
+import android.service.quicksettings.TileService
-import com.keylesspalace.tusky.ComposeActivity;
+import com.keylesspalace.tusky.MainActivity
/**
- * Small Addition that adds in a QuickSettings tile that opens the Compose activity when clicked
- * Created by ztepps on 4/3/17.
+ * Small Addition that adds in a QuickSettings tile
+ * opens the Compose activity or shows an account selector when multiple accounts are present
*/
@TargetApi(24)
-public class TuskyTileService extends TileService {
- public TuskyTileService() {
- super();
- }
+class TuskyTileService : TileService() {
- @Override
- public void onClick() {
- Intent intent = new Intent(this, ComposeActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivityAndCollapse(intent);
+ override fun onClick() {
+ val intent = Intent(this, MainActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ action = Intent.ACTION_SEND
+ type = "text/plain"
+ }
+ startActivityAndCollapse(intent)
}
}
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.java b/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.java
index 2505649d..606a36a9 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.java
+++ b/app/src/main/java/com/keylesspalace/tusky/util/LinkHelper.java
@@ -19,11 +19,6 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.preference.PreferenceManager;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.browser.customtabs.CustomTabsIntent;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
@@ -33,11 +28,15 @@ import android.util.Log;
import android.view.View;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.preference.PreferenceManager;
+
import com.keylesspalace.tusky.R;
import com.keylesspalace.tusky.entity.Status;
import com.keylesspalace.tusky.interfaces.LinkListener;
-import java.lang.CharSequence;
import java.net.URI;
import java.net.URISyntaxException;
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/LocaleManager.kt b/app/src/main/java/com/keylesspalace/tusky/util/LocaleManager.kt
index 3cb34e85..4a80bca2 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/LocaleManager.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/LocaleManager.kt
@@ -18,9 +18,8 @@ package com.keylesspalace.tusky.util
import android.content.Context
import android.content.SharedPreferences
import android.content.res.Configuration
-import android.preference.PreferenceManager
-
-import java.util.Locale
+import androidx.preference.PreferenceManager
+import java.util.*
class LocaleManager(context: Context) {
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
index 39f19c30..4e0d298d 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
+++ b/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
@@ -295,6 +295,7 @@ public class NotificationHelper {
.setColor(BuildConfig.DEBUG ? Color.parseColor("#19A341") : ContextCompat.getColor(context, R.color.tusky_blue))
.setGroup(account.getAccountId())
.setAutoCancel(true)
+ .setShortcutId(Long.toString(account.getId()))
.setDefaults(0); // So it doesn't ring twice, notify only in Target callback
setupPreferences(account, builder);
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.java b/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.java
index 7647c2c8..22e13e5e 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.java
+++ b/app/src/main/java/com/keylesspalace/tusky/util/OkHttpUtils.java
@@ -18,7 +18,9 @@ package com.keylesspalace.tusky.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
-import android.preference.PreferenceManager;
+
+import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
import com.keylesspalace.tusky.BuildConfig;
@@ -26,7 +28,6 @@ import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;
-import androidx.annotation.NonNull;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt b/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt
new file mode 100644
index 00000000..9c0cd0c7
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt
@@ -0,0 +1,101 @@
+/* Copyright 2019 Tusky Contributors
+ *
+ * This file is a part of Tusky.
+ *
+ * This program is free software; you can redistribute it and/or modify it under the terms of the
+ * GNU General Public License as published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with Tusky; if not,
+ * see . */
+
+@file:JvmName("ShareShortcutHelper")
+
+package com.keylesspalace.tusky.util
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.text.TextUtils
+import androidx.core.app.Person
+import androidx.core.content.pm.ShortcutInfoCompat
+import androidx.core.content.pm.ShortcutManagerCompat
+import androidx.core.graphics.drawable.IconCompat
+import com.bumptech.glide.Glide
+import com.keylesspalace.tusky.MainActivity
+import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.db.AccountEntity
+import io.reactivex.Single
+import io.reactivex.schedulers.Schedulers
+
+fun updateShortcut(context: Context, account: AccountEntity) {
+
+ Single.fromCallable {
+
+ val innerSize = context.resources.getDimensionPixelSize(R.dimen.adaptive_bitmap_inner_size)
+ val outerSize = context.resources.getDimensionPixelSize(R.dimen.adaptive_bitmap_outer_size)
+
+ val bmp = if (TextUtils.isEmpty(account.profilePictureUrl)) {
+ Glide.with(context)
+ .asBitmap()
+ .load(R.drawable.avatar_default)
+ .submit(innerSize, innerSize)
+ .get()
+ } else {
+ Glide.with(context)
+ .asBitmap()
+ .load(account.profilePictureUrl)
+ .error(R.drawable.avatar_default)
+ .submit(innerSize, innerSize)
+ .get()
+ }
+
+ // inset the loaded bitmap inside a 108dp transparent canvas so it looks good as adaptive icon
+ val outBmp = Bitmap.createBitmap(outerSize, outerSize, Bitmap.Config.ARGB_8888)
+
+ val canvas = Canvas(outBmp)
+ canvas.drawBitmap(bmp, (outerSize - innerSize).toFloat() / 2f, (outerSize - innerSize).toFloat() / 2f, null)
+
+ val icon = IconCompat.createWithAdaptiveBitmap(outBmp)
+
+ val person = Person.Builder()
+ .setIcon(icon)
+ .setName(account.displayName)
+ .setKey(account.identifier)
+ .build()
+
+ // This intent will be sent when the user clicks on one of the launcher shortcuts. Intent from share sheet will be different
+ val intent = Intent(context, MainActivity::class.java).apply {
+ action = Intent.ACTION_SEND
+ type = "text/plain"
+ putExtra(NotificationHelper.ACCOUNT_ID, account.id)
+ }
+
+ val shortcutInfo = ShortcutInfoCompat.Builder(context, account.id.toString())
+ .setIntent(intent)
+ .setCategories(setOf("com.keylesspalace.tusky.Share"))
+ .setShortLabel(account.displayName)
+ .setPerson(person)
+ .setLongLived(true)
+ .setIcon(icon)
+ .build()
+
+ ShortcutManagerCompat.addDynamicShortcuts(context, listOf(shortcutInfo))
+
+ }
+ .subscribeOn(Schedulers.io())
+ .subscribe()
+
+
+}
+
+fun removeShortcut(context: Context, account: AccountEntity) {
+
+ ShortcutManagerCompat.removeDynamicShortcuts(context, listOf(account.id.toString()))
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_about.xml b/app/src/main/res/layout/activity_about.xml
index 4ebaf394..9bc43d64 100644
--- a/app/src/main/res/layout/activity_about.xml
+++ b/app/src/main/res/layout/activity_about.xml
@@ -16,8 +16,8 @@
+ android:layout_gravity="center"
+ android:textDirection="anyRtl">
diff --git a/app/src/main/res/layout/fragment_view_image.xml b/app/src/main/res/layout/fragment_view_image.xml
index 39bbd9fb..faf1f806 100644
--- a/app/src/main/res/layout/fragment_view_image.xml
+++ b/app/src/main/res/layout/fragment_view_image.xml
@@ -1,7 +1,7 @@
+ android:layout_gravity="center"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_view_video.xml b/app/src/main/res/layout/fragment_view_video.xml
index 0247a9cb..083bdb20 100644
--- a/app/src/main/res/layout/fragment_view_video.xml
+++ b/app/src/main/res/layout/fragment_view_video.xml
@@ -2,9 +2,9 @@
@@ -14,6 +14,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="?attr/actionBarSize"
android:background="#60000000"
+ android:hyphenationFrequency="full"
android:lineSpacingMultiplier="1.1"
android:padding="8dp"
android:textAlignment="center"
diff --git a/app/src/main/res/layout/item_status.xml b/app/src/main/res/layout/item_status.xml
index a0e2b851..167579df 100644
--- a/app/src/main/res/layout/item_status.xml
+++ b/app/src/main/res/layout/item_status.xml
@@ -105,6 +105,7 @@
android:id="@+id/status_content_warning_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
+ android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
@@ -145,6 +146,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:focusable="true"
+ android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
diff --git a/app/src/main/res/layout/item_status_detailed.xml b/app/src/main/res/layout/item_status_detailed.xml
index 8db4d0d9..6cdc1a40 100644
--- a/app/src/main/res/layout/item_status_detailed.xml
+++ b/app/src/main/res/layout/item_status_detailed.xml
@@ -84,6 +84,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
+ android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
@@ -120,6 +121,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:focusable="true"
+ android:hyphenationFrequency="full"
android:importantForAccessibility="no"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorPrimary"
diff --git a/app/src/main/res/layout/item_status_notification.xml b/app/src/main/res/layout/item_status_notification.xml
index f9f0a4b6..94f40c45 100644
--- a/app/src/main/res/layout/item_status_notification.xml
+++ b/app/src/main/res/layout/item_status_notification.xml
@@ -13,8 +13,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
- android:layout_marginBottom="6dp"
android:layout_marginTop="8dp"
+ android:layout_marginBottom="6dp"
android:drawablePadding="10dp"
android:ellipsize="end"
android:gravity="center_vertical"
@@ -39,8 +39,8 @@
android:layout_alignParentStart="true"
android:ellipsize="end"
android:maxLines="1"
- android:paddingEnd="@dimen/status_display_name_padding_end"
android:paddingStart="0dp"
+ android:paddingEnd="@dimen/status_display_name_padding_end"
android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
@@ -51,8 +51,8 @@
android:id="@+id/status_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_toEndOf="@id/status_display_name"
android:layout_toStartOf="@+id/status_timestamp_info"
+ android:layout_toEndOf="@id/status_display_name"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?android:textColorTertiary"
@@ -77,27 +77,27 @@
android:layout_height="wrap_content"
android:layout_below="@id/status_name_bar"
android:layout_toEndOf="@id/notification_status_avatar"
+ android:hyphenationFrequency="full"
android:lineSpacingMultiplier="1.1"
android:textColor="?android:textColorTertiary"
android:textSize="?attr/status_text_medium"
tools:text="Example CW text" />
-
+ android:id="@+id/button_toggle_notification_content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/notification_content"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:layout_toEndOf="@id/notification_status_avatar"
+ android:background="?attr/content_warning_button"
+ android:minWidth="150dp"
+ android:minHeight="0dp"
+ android:paddingLeft="16dp"
+ android:paddingTop="4dp"
+ android:paddingRight="16dp"
+ android:paddingBottom="4dp"
+ android:textAllCaps="true"
+ android:textOff="@string/status_content_show_less"
+ android:textOn="@string/status_content_show_more"
+ android:textSize="?attr/status_text_medium"
+ android:visibility="gone" />
@@ -157,7 +158,7 @@
android:id="@+id/notification_notification_avatar"
android:layout_width="24dp"
android:layout_height="24dp"
- android:layout_alignBottom="@+id/notification_status_avatar"
- android:layout_alignEnd="@id/notification_status_avatar" />
+ android:layout_alignEnd="@id/notification_status_avatar"
+ android:layout_alignBottom="@+id/notification_status_avatar" />
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index c2f1bdd9..f8bbe3d4 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -46,4 +46,7 @@
5dp
12dp
+
+ 72dp
+ 108dp
diff --git a/app/src/main/res/xml/share_shortcuts.xml b/app/src/main/res/xml/share_shortcuts.xml
new file mode 100644
index 00000000..54ecd5db
--- /dev/null
+++ b/app/src/main/res/xml/share_shortcuts.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
index bb924ee4..c8a06252 100644
--- a/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/ComposeActivityTest.kt
@@ -49,7 +49,7 @@ import retrofit2.Response
* Created by charlag on 3/7/18.
*/
-@Config(application = FakeTuskyApplication::class)
+@Config(application = FakeTuskyApplication::class, sdk = [28])
@RunWith(AndroidJUnit4::class)
class ComposeActivityTest {
diff --git a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
index 2e627d96..b7e95dc1 100644
--- a/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/FilterTest.kt
@@ -24,7 +24,7 @@ import retrofit2.Callback
import retrofit2.Response
import java.util.*
-@Config(application = FakeTuskyApplication::class)
+@Config(application = FakeTuskyApplication::class, sdk = [28])
@RunWith(AndroidJUnit4::class)
class FilterTest {
diff --git a/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt b/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
index f90a95e7..66bf73e8 100644
--- a/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/SpanUtilsTest.kt
@@ -100,15 +100,10 @@ class SpanUtilsTest {
spans.add(BoundedSpan(what, start, end))
}
- override fun getSpans(start: Int, end: Int, type: Class?): Array {
- val matching = if (type == null) {
- ArrayList()
- } else {
- spans.filter { it.start >= start && it.end <= end && type.isAssignableFrom(it.span?.javaClass) }
+ override fun getSpans(start: Int, end: Int, type: Class): Array {
+ return spans.filter { it.start >= start && it.end <= end && type.isInstance(it)}
.map { it.span }
- .let { ArrayList(it) }
- }
- return matching.toArray() as Array
+ .toTypedArray() as Array
}
override fun removeSpan(what: Any?) {
diff --git a/app/src/test/java/com/keylesspalace/tusky/util/RickRollTest.kt b/app/src/test/java/com/keylesspalace/tusky/util/RickRollTest.kt
index 6a6a5d53..c307e552 100644
--- a/app/src/test/java/com/keylesspalace/tusky/util/RickRollTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/util/RickRollTest.kt
@@ -11,7 +11,7 @@ import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.annotation.Config
-@Config(application = FakeTuskyApplication::class)
+@Config(application = FakeTuskyApplication::class, sdk = [28])
@RunWith(AndroidJUnit4::class)
class RickRollTest {
private lateinit var activity: Activity
diff --git a/app/src/test/java/com/keylesspalace/tusky/util/SmartLengthInputFilterTest.kt b/app/src/test/java/com/keylesspalace/tusky/util/SmartLengthInputFilterTest.kt
index f11658b0..acb6cf88 100644
--- a/app/src/test/java/com/keylesspalace/tusky/util/SmartLengthInputFilterTest.kt
+++ b/app/src/test/java/com/keylesspalace/tusky/util/SmartLengthInputFilterTest.kt
@@ -9,7 +9,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
-@Config(application = FakeTuskyApplication::class)
+@Config(application = FakeTuskyApplication::class, sdk = [28])
@RunWith(AndroidJUnit4::class)
class SmartLengthInputFilterTest {