Fixed crash on pre-Lollipop devices (API levels 20 and prior) due to trying to load attributes in drawables.
This commit is contained in:
parent
8964c61397
commit
af4af94775
19 changed files with 130 additions and 46 deletions
|
@ -107,7 +107,7 @@ public class AccountActivity extends BaseActivity {
|
|||
int pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8,
|
||||
getResources().getDisplayMetrics());
|
||||
viewPager.setPageMargin(pageMargin);
|
||||
viewPager.setPageMarginDrawable(R.drawable.tab_page_margin);
|
||||
viewPager.setPageMarginDrawable(R.drawable.tab_page_margin_dark);
|
||||
viewPager.setAdapter(adapter);
|
||||
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
|
|
|
@ -99,7 +99,7 @@ public class AccountFragment extends Fragment implements AccountActionListener,
|
|||
recyclerView.setLayoutManager(layoutManager);
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
context, layoutManager.getOrientation());
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider);
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider_dark);
|
||||
divider.setDrawable(drawable);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
scrollListener = new EndlessOnScrollListener(layoutManager) {
|
||||
|
|
|
@ -242,15 +242,6 @@ public class ComposeActivity extends BaseActivity {
|
|||
}
|
||||
}
|
||||
|
||||
private static int getThemeColor(Context context, int attribute) {
|
||||
TypedValue value = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
return value.data;
|
||||
} else {
|
||||
return android.R.color.black;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -270,7 +261,7 @@ public class ComposeActivity extends BaseActivity {
|
|||
|
||||
textEditor = (EditText) findViewById(R.id.field_status);
|
||||
final TextView charactersLeft = (TextView) findViewById(R.id.characters_left);
|
||||
final int mentionColour = getThemeColor(this, R.attr.compose_mention_color);
|
||||
final int mentionColour = ThemeUtils.getColor(this, R.attr.compose_mention_color);
|
||||
TextWatcher textEditorWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
|
|
@ -205,10 +205,12 @@ public class LoginActivity extends BaseActivity {
|
|||
editor.putString("domain", domain);
|
||||
editor.putString("clientId", clientId);
|
||||
editor.putString("clientSecret", clientSecret);
|
||||
editor.commit();
|
||||
editor.apply();
|
||||
}
|
||||
|
||||
private void onLoginSuccess(String accessToken) {
|
||||
preferences = getSharedPreferences(
|
||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putString("accessToken", accessToken);
|
||||
editor.apply();
|
||||
|
@ -233,6 +235,8 @@ public class LoginActivity extends BaseActivity {
|
|||
/* During the redirect roundtrip this Activity usually dies, which wipes out the
|
||||
* instance variables, so they have to be recovered from where they were saved in
|
||||
* SharedPreferences. */
|
||||
preferences = getSharedPreferences(
|
||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
domain = preferences.getString("domain", null);
|
||||
clientId = preferences.getString("clientId", null);
|
||||
clientSecret = preferences.getString("clientSecret", null);
|
||||
|
@ -247,6 +251,7 @@ public class LoginActivity extends BaseActivity {
|
|||
parameters.put("grant_type", "authorization_code");
|
||||
} catch (JSONException e) {
|
||||
errorText.setText("Heck.");
|
||||
return;
|
||||
//TODO: I don't even know how to handle this error state.
|
||||
}
|
||||
String endpoint = getString(R.string.endpoint_token);
|
||||
|
@ -256,11 +261,12 @@ public class LoginActivity extends BaseActivity {
|
|||
new Response.Listener<JSONObject>() {
|
||||
@Override
|
||||
public void onResponse(JSONObject response) {
|
||||
String accessToken = "";
|
||||
String accessToken;
|
||||
try {
|
||||
accessToken = response.getString("access_token");
|
||||
} catch(JSONException e) {
|
||||
errorText.setText("Heck.");
|
||||
return;
|
||||
//TODO: I don't even know how to handle this error state.
|
||||
}
|
||||
onLoginSuccess(accessToken);
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.app.PendingIntent;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.SystemClock;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.design.widget.TabLayout;
|
||||
|
@ -72,7 +73,9 @@ public class MainActivity extends BaseActivity {
|
|||
ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
|
||||
int pageMargin = getResources().getDimensionPixelSize(R.dimen.tab_page_margin);
|
||||
viewPager.setPageMargin(pageMargin);
|
||||
viewPager.setPageMarginDrawable(R.drawable.tab_page_margin);
|
||||
Drawable pageMarginDrawable = ThemeUtils.getDrawable(this, R.attr.tab_page_margin_drawable,
|
||||
R.drawable.tab_page_margin_dark);
|
||||
viewPager.setPageMarginDrawable(pageMarginDrawable);
|
||||
viewPager.setAdapter(adapter);
|
||||
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
|
|
|
@ -77,7 +77,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
recyclerView.setLayoutManager(layoutManager);
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
context, layoutManager.getOrientation());
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider);
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider_dark);
|
||||
divider.setDrawable(drawable);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
scrollListener = new EndlessOnScrollListener(layoutManager) {
|
||||
|
|
|
@ -154,18 +154,22 @@ public class PullNotificationService extends IntentService {
|
|||
}
|
||||
|
||||
private void loadAvatar(final List<MentionResult> mentions, String url) {
|
||||
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
|
||||
@Override
|
||||
public void onResponse(Bitmap response) {
|
||||
updateNotification(mentions, response);
|
||||
}
|
||||
}, 0, 0, null, null, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
updateNotification(mentions, null);
|
||||
}
|
||||
});
|
||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
||||
if (url != null) {
|
||||
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
|
||||
@Override
|
||||
public void onResponse(Bitmap response) {
|
||||
updateNotification(mentions, response);
|
||||
}
|
||||
}, 0, 0, null, null, new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
updateNotification(mentions, null);
|
||||
}
|
||||
});
|
||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
||||
} else {
|
||||
updateNotification(mentions, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNotification(List<MentionResult> mentions, @Nullable Bitmap icon) {
|
||||
|
|
|
@ -80,10 +80,12 @@ public class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
mediaPreview1 = (NetworkImageView) itemView.findViewById(R.id.status_media_preview_1);
|
||||
mediaPreview2 = (NetworkImageView) itemView.findViewById(R.id.status_media_preview_2);
|
||||
mediaPreview3 = (NetworkImageView) itemView.findViewById(R.id.status_media_preview_3);
|
||||
mediaPreview0.setDefaultImageResId(R.drawable.media_preview_unloaded);
|
||||
mediaPreview1.setDefaultImageResId(R.drawable.media_preview_unloaded);
|
||||
mediaPreview2.setDefaultImageResId(R.drawable.media_preview_unloaded);
|
||||
mediaPreview3.setDefaultImageResId(R.drawable.media_preview_unloaded);
|
||||
int mediaPreviewUnloadedId = ThemeUtils.getDrawableId(itemView.getContext(),
|
||||
R.attr.media_preview_unloaded_drawable, android.R.color.black);
|
||||
mediaPreview0.setDefaultImageResId(mediaPreviewUnloadedId);
|
||||
mediaPreview1.setDefaultImageResId(mediaPreviewUnloadedId);
|
||||
mediaPreview2.setDefaultImageResId(mediaPreviewUnloadedId);
|
||||
mediaPreview3.setDefaultImageResId(mediaPreviewUnloadedId);
|
||||
sensitiveMediaWarning = itemView.findViewById(R.id.status_sensitive_media_warning);
|
||||
contentWarningBar = itemView.findViewById(R.id.status_content_warning_bar);
|
||||
contentWarningDescription =
|
||||
|
|
52
app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java
Normal file
52
app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is part of Tusky.
|
||||
*
|
||||
* Tusky 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
|
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.util.TypedValue;
|
||||
|
||||
public class ThemeUtils {
|
||||
public static Drawable getDrawable(Context context, int attribute, int fallbackDrawable) {
|
||||
TypedValue value = new TypedValue();
|
||||
int resourceId;
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
resourceId = value.resourceId;
|
||||
} else {
|
||||
resourceId = fallbackDrawable;
|
||||
}
|
||||
return ContextCompat.getDrawable(context, resourceId);
|
||||
}
|
||||
|
||||
public static int getDrawableId(Context context, int attribute, int fallbackDrawableId) {
|
||||
TypedValue value = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
return value.resourceId;
|
||||
} else {
|
||||
return fallbackDrawableId;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getColor(Context context, int attribute) {
|
||||
TypedValue value = new TypedValue();
|
||||
if (context.getTheme().resolveAttribute(attribute, value, true)) {
|
||||
return value.data;
|
||||
} else {
|
||||
return android.R.color.black;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -102,7 +102,8 @@ public class TimelineFragment extends SFragment implements
|
|||
recyclerView.setLayoutManager(layoutManager);
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
context, layoutManager.getOrientation());
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider);
|
||||
Drawable drawable = ThemeUtils.getDrawable(context, R.attr.status_divider_drawable,
|
||||
R.drawable.status_divider_dark);
|
||||
divider.setDrawable(drawable);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
scrollListener = new EndlessOnScrollListener(layoutManager) {
|
||||
|
|
|
@ -60,7 +60,7 @@ public class ViewThreadFragment extends SFragment implements StatusActionListene
|
|||
recyclerView.setLayoutManager(layoutManager);
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
context, layoutManager.getOrientation());
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider);
|
||||
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.status_divider_dark);
|
||||
divider.setDrawable(drawable);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
adapter = new ThreadAdapter(this);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="?attr/media_preview_unloaded_background_color" />
|
||||
<solid android:color="@color/media_preview_unloaded_background_dark" />
|
||||
|
||||
<stroke
|
||||
android:dashWidth="4dp"
|
14
app/src/main/res/drawable/media_preview_unloaded_light.xml
Normal file
14
app/src/main/res/drawable/media_preview_unloaded_light.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@color/media_preview_unloaded_background_light" />
|
||||
|
||||
<stroke
|
||||
android:dashWidth="4dp"
|
||||
android:dashGap="4dp"
|
||||
android:width="2dp"
|
||||
android:color="#AFAFAF" />
|
||||
|
||||
</shape>
|
|
@ -2,5 +2,5 @@
|
|||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="?attr/status_divider_color" />
|
||||
<solid android:color="@color/status_divider_dark" />
|
||||
</shape>
|
6
app/src/main/res/drawable/status_divider_light.xml
Normal file
6
app/src/main/res/drawable/status_divider_light.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="@color/status_divider_light" />
|
||||
</shape>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?attr/tab_page_margin_color" />
|
||||
<solid android:color="@color/tab_page_margin_dark" />
|
||||
</shape>
|
5
app/src/main/res/drawable/tab_page_margin_light.xml
Normal file
5
app/src/main/res/drawable/tab_page_margin_light.xml
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="@color/tab_page_margin_light" />
|
||||
</shape>
|
|
@ -18,10 +18,10 @@
|
|||
<attr name="status_reblog_button_style" format="reference" />
|
||||
<attr name="content_warning_button" format="reference" />
|
||||
<attr name="sensitive_media_warning_background_color" format="reference|color" />
|
||||
<attr name="media_preview_unloaded_background_color" format="reference|color" />
|
||||
<attr name="status_text_color_secondary" format="reference|color" />
|
||||
<attr name="status_divider_color" format="reference|color" />
|
||||
<attr name="tab_page_margin_color" format="reference|color" />
|
||||
<attr name="media_preview_unloaded_drawable" format="reference" />
|
||||
<attr name="status_divider_drawable" format="reference" />
|
||||
<attr name="tab_page_margin_drawable" format="reference" />
|
||||
<attr name="notification_content" format="reference" />
|
||||
<attr name="notification_icon_tint" format="reference|color" />
|
||||
<attr name="account_header_background_color" format="reference|color" />
|
||||
|
|
|
@ -31,10 +31,10 @@
|
|||
<item name="status_favourite_button_style">@style/AppTheme.FavouriteButton.Dark</item>
|
||||
<item name="content_warning_button">@drawable/toggle_small</item>
|
||||
<item name="sensitive_media_warning_background_color">@color/sensitive_media_warning_background_dark</item>
|
||||
<item name="media_preview_unloaded_background_color">@color/media_preview_unloaded_background_dark</item>
|
||||
<item name="status_text_color_secondary">@color/status_text_secondary_dark</item>
|
||||
<item name="status_divider_color">@color/status_divider_dark</item>
|
||||
<item name="tab_page_margin_color">@color/tab_page_margin_dark</item>
|
||||
<item name="media_preview_unloaded_drawable">@drawable/media_preview_unloaded_dark</item>
|
||||
<item name="status_divider_drawable">@drawable/status_divider_dark</item>
|
||||
<item name="tab_page_margin_drawable">@drawable/tab_page_margin_dark</item>
|
||||
<item name="account_header_background_color">@color/account_header_background_dark</item>
|
||||
<item name="compose_media_button_tint">@color/media_button_dark</item>
|
||||
<item name="compose_mention_color">@color/compose_mention_dark</item>
|
||||
|
@ -86,10 +86,10 @@
|
|||
<item name="status_favourite_button_style">@style/AppTheme.FavouriteButton.Light</item>
|
||||
<item name="content_warning_button">@drawable/toggle_small_light</item>
|
||||
<item name="sensitive_media_warning_background_color">@color/sensitive_media_warning_background_light</item>
|
||||
<item name="media_preview_unloaded_background_color">@color/media_preview_unloaded_background_light</item>
|
||||
<item name="status_text_color_secondary">@color/status_text_secondary_light</item>
|
||||
<item name="status_divider_color">@color/status_divider_light</item>
|
||||
<item name="tab_page_margin_color">@color/tab_page_margin_light</item>
|
||||
<item name="media_preview_unloaded_drawable">@drawable/media_preview_unloaded_light</item>
|
||||
<item name="status_divider_drawable">@drawable/status_divider_light</item>
|
||||
<item name="tab_page_margin_drawable">@drawable/tab_page_margin_light</item>
|
||||
<item name="account_header_background_color">@color/account_header_background_light</item>
|
||||
<item name="compose_media_button_tint">@color/media_button_light</item>
|
||||
<item name="compose_mention_color">@color/compose_mention_light</item>
|
||||
|
|
Loading…
Reference in a new issue