diff --git a/Awful.apk/build.gradle b/Awful.apk/build.gradle index f19987ae4..057f95ab0 100644 --- a/Awful.apk/build.gradle +++ b/Awful.apk/build.gradle @@ -1,40 +1,31 @@ buildscript { - ext.kotlin_version = '1.7.20' + ext.kotlin_version = '1.9.21' - repositories { - google() - jcenter() - maven { url 'https://maven.fabric.io/public' } - } dependencies { - classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'com.android.tools.build:gradle:8.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath 'com.google.gms:google-services:4.3.14' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9' - } } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' -apply plugin: 'com.google.gms.google-services' -apply plugin: 'com.google.firebase.crashlytics' - - -repositories { - google() - jcenter() - maven { url 'https://jitpack.io' } +plugins { + id 'com.android.application' + id 'org.jetbrains.kotlin.android' + id 'com.google.devtools.ksp' } android { - compileSdkVersion 33 + namespace "com.ferg.awfulapp" + compileSdk 34 + + buildFeatures { + viewBinding = true + buildConfig = true + } defaultConfig { applicationId = "com.ferg.awfulapp" - minSdkVersion 21 - targetSdkVersion 33 + minSdkVersion 24 + targetSdkVersion 34 resConfigs 'en' // Stops the Gradle plugin’s automatic rasterization of vectors @@ -76,9 +67,8 @@ android { } } - compileOptions { - sourceCompatibility 1.8 - targetCompatibility 1.8 + kotlin { + jvmToolchain(17) } task copyThreadTags { @@ -116,9 +106,9 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.9.0' + implementation 'com.google.android.material:material:1.11.0' // these are all needed to override some old versions that are dependencies... somewhere - implementation 'androidx.media:media:1.6.0' + implementation 'androidx.media:media:1.7.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' // used to fix SSL issues on older devices @@ -126,7 +116,7 @@ dependencies { implementation 'com.android.volley:volley:1.2.1' - implementation 'com.google.code.gson:gson:2.8.9' + implementation 'com.google.code.gson:gson:2.10' implementation 'org.jsoup:jsoup:1.15.4' implementation 'com.jakewharton.threetenabp:threetenabp:1.2.4' @@ -142,16 +132,12 @@ dependencies { implementation 'com.ToxicBakery.viewpager.transforms:view-pager-transforms:2.0.24@aar' implementation 'com.github.orangegangsters:swipy:1.2.3@aar' implementation 'com.bignerdranch.android:expandablerecyclerview:2.1.1' - implementation 'com.jakewharton:butterknife:10.2.1' implementation 'com.jakewharton.timber:timber:4.7.1' - implementation 'com.github.bumptech.glide:glide:4.11.0' - kapt 'com.github.bumptech.glide:compiler:4.11.0' + implementation 'com.github.bumptech.glide:glide:4.16.0' + ksp 'com.github.bumptech.glide:ksp:4.16.0' implementation 'com.github.chrisbanes:PhotoView:2.3.0' - kapt 'com.jakewharton:butterknife-compiler:10.2.1' - - implementation 'com.google.firebase:firebase-crashlytics:18.4.3' implementation 'com.github.rubensousa:BottomSheetBuilder:1.5.1' diff --git a/Awful.apk/src/main/AndroidManifest.xml b/Awful.apk/src/main/AndroidManifest.xml index 21a04ccaf..5af3bda84 100644 --- a/Awful.apk/src/main/AndroidManifest.xml +++ b/Awful.apk/src/main/AndroidManifest.xml @@ -7,8 +7,8 @@ -->
+
+

3.9.2

+
    +
  • Made imgur upload work again. You can finally uninstall that awful app. No, I mean theirs. I should have written terrible app, that's clearer.
  • +
  • Removed crash report library because Google considers it collecting user data. Now collecting user data via the base functionality again like in 2012. Remember to include your username in the crash reports. Or don't, that's ok too.
  • +
  • Removed some older libraries that are no longer maintained. Something might have broken? If you see something, say something
  • +
+

3.9.1

    diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/Authentication.kt b/Awful.apk/src/main/java/com/ferg/awfulapp/Authentication.kt index 8befd7bba..572ab87dc 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/Authentication.kt +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/Authentication.kt @@ -23,7 +23,7 @@ import com.ferg.awfulapp.preferences.AwfulPreferences class LogOutDialog : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = - AlertDialog.Builder(activity!!) + AlertDialog.Builder(requireActivity()) .setTitle(R.string.logout) .setMessage(R.string.logout_message) .setPositiveButton(R.string.logout, { _, _ -> diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulApplication.java b/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulApplication.java index 7511a84f4..248e1ced1 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulApplication.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulApplication.java @@ -7,7 +7,6 @@ import android.os.StrictMode; import android.webkit.WebView; -import com.google.firebase.crashlytics.FirebaseCrashlytics; import com.ferg.awfulapp.announcements.AnnouncementsManager; import com.ferg.awfulapp.constants.Constants; import com.ferg.awfulapp.network.NetworkUtils; @@ -26,7 +25,6 @@ public class AwfulApplication extends Application { * Used for storing misc app data, separate from user preferences, so onPreferenceChange callbacks aren't triggered */ private static SharedPreferences appStatePrefs; - private static boolean crashlyticsEnabled = false; /** * Stores the user agent used by web views in this application, which is required to be @@ -71,21 +69,6 @@ public void onCreate() { long hoursSinceInstall = getHoursSinceInstall(); - // enable Crashlytics on non-debug builds, or debug builds that have been installed for a while - crashlyticsEnabled = !BuildConfig.DEBUG || hoursSinceInstall > 4; - - if (crashlyticsEnabled) { - FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true); - FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); - - if (mPref.sendUsernameInReport) - crashlytics.setUserId(mPref.username); - } else { - FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(false); - } - - Timber.plant(crashlyticsEnabled ? new CrashlyticsReportingTree() : new Timber.DebugTree()); - Timber.i("App installed %d hours ago", hoursSinceInstall); if (Constants.DEBUG) { @@ -120,13 +103,6 @@ private long getHoursSinceInstall() { return hoursSinceInstall; } - /** - * Returns true if the Crashlytics singleton has been initialised and can be used. - */ - public static boolean crashlyticsEnabled() { - return crashlyticsEnabled; - } - /** * Get the SharedPreferences used for storing basic app state. *

    diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulFragment.kt b/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulFragment.kt index c8c5d0530..23fe9703f 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulFragment.kt +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/AwfulFragment.kt @@ -57,7 +57,7 @@ abstract class AwfulFragment : Fragment(), AwfulPreferences.AwfulPreferenceUpdat AwfulRequest.ProgressListener, ForumsPagerPage, NavigationEventHandler { protected var TAG = "AwfulFragment" - protected val prefs: AwfulPreferences by lazy { AwfulPreferences.getInstance(context!!, this) } + protected val prefs: AwfulPreferences by lazy { AwfulPreferences.getInstance(requireContext(), this) } protected val handler: Handler by lazy { Handler() } protected val alertView: AlertView by lazy { AlertView(activity) } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/CrashlyticsReportingTree.kt b/Awful.apk/src/main/java/com/ferg/awfulapp/CrashlyticsReportingTree.kt deleted file mode 100644 index 8d88757d7..000000000 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/CrashlyticsReportingTree.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.ferg.awfulapp - -import com.google.firebase.crashlytics.FirebaseCrashlytics -import timber.log.Timber - - -class CrashlyticsReportingTree : Timber.Tree() { - override fun log(priority: Int, tag: String?, message: String, throwable: Throwable?) { - val crashlytics = FirebaseCrashlytics.getInstance() - - crashlytics.log("$priority/$tag:$message") - - if (throwable != null) { - crashlytics.log(throwable.localizedMessage) - } - } -} \ No newline at end of file diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/ForumsIndexFragment.java b/Awful.apk/src/main/java/com/ferg/awfulapp/ForumsIndexFragment.java index 309c731a0..4e1b5f9ca 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/ForumsIndexFragment.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/ForumsIndexFragment.java @@ -5,6 +5,8 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import com.ferg.awfulapp.databinding.ForumIndexFragmentBinding; import com.google.android.material.snackbar.Snackbar; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -27,9 +29,6 @@ import java.util.ArrayList; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; - import static com.ferg.awfulapp.forums.ForumStructure.FLAT; import static com.ferg.awfulapp.forums.ForumStructure.TWO_LEVEL; @@ -55,11 +54,8 @@ public class ForumsIndexFragment extends AwfulFragment private static final String KEY_SHOW_FAVOURITES = "show_favourites"; - @BindView(R.id.forum_index_list) RecyclerView forumRecyclerView; - @BindView(R.id.view_switcher) ViewSwitcher forumsListSwitcher; - @BindView(R.id.status_frog) StatusFrog statusFrog; private ForumListAdapter forumListAdapter; @@ -91,8 +87,11 @@ public void onCreate(Bundle savedInstanceState) { @Override public View onCreateView(@NonNull LayoutInflater aInflater, ViewGroup aContainer, Bundle aSavedState) { - View view = inflateView(R.layout.forum_index_fragment, aContainer, aInflater); - ButterKnife.bind(this, view); + ForumIndexFragmentBinding binding = ForumIndexFragmentBinding.inflate(getLayoutInflater()); + View view = binding.getRoot(); + forumRecyclerView = binding.forumIndexList; + forumsListSwitcher = binding.viewSwitcher; + statusFrog = binding.statusFrog; updateViewColours(); refreshProbationBar(); forumsListSwitcher.setInAnimation(AnimationUtils.makeInAnimation(getContext(), true)); diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyActivity.java b/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyActivity.java index d622f219c..e043bdcc6 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyActivity.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyActivity.java @@ -32,21 +32,21 @@ import androidx.appcompat.widget.Toolbar; import android.view.MenuItem; -import butterknife.BindView; -import butterknife.ButterKnife; +import com.ferg.awfulapp.databinding.PostReplyActivityBinding; public class PostReplyActivity extends AwfulActivity { - @BindView(R.id.toolbar) + Toolbar mToolbar; PostReplyFragment replyFragment; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.post_reply_activity); - ButterKnife.bind(this); + PostReplyActivityBinding binding = PostReplyActivityBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + mToolbar = binding.toolbar; setSupportActionBar(mToolbar); setUpActionBar(); diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyFragment.java b/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyFragment.java index a1f3328dc..aa8cb900b 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyFragment.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/PostReplyFragment.java @@ -48,6 +48,8 @@ import android.provider.MediaStore; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import com.ferg.awfulapp.databinding.PostReplyActivityBinding; import com.google.android.material.snackbar.Snackbar; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; @@ -92,11 +94,10 @@ import org.apache.commons.lang3.StringUtils; import org.threeten.bp.Duration; import org.threeten.bp.Instant; +import org.w3c.dom.Text; import java.io.File; -import butterknife.BindView; -import butterknife.ButterKnife; import timber.log.Timber; import static com.ferg.awfulapp.constants.Constants.ATTACHMENT_MAX_BYTES; @@ -118,8 +119,6 @@ public class PostReplyFragment extends AwfulFragment { private static final String TAG = "PostReplyFragment"; // UI components - @BindView(R.id.thread_title) - TextView threadTitleView = null; private MessageComposer messageComposer; @Nullable private ProgressDialog progressDialog; @@ -172,16 +171,15 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater aInflater, ViewGroup aContainer, Bundle aSavedState) { super.onCreateView(aInflater, aContainer, aSavedState); Timber.v("onCreateView"); - return inflateView(R.layout.post_reply, aContainer, aInflater); + View view = inflateView(R.layout.post_reply, aContainer, aInflater); + return view; } - @Override public void onActivityCreated(Bundle aSavedState) { super.onActivityCreated(aSavedState); Timber.v("onActivityCreated"); Activity activity = getActivity(); - ButterKnife.bind(this, activity); messageComposer = (MessageComposer) getChildFragmentManager().findFragmentById(R.id.message_composer_fragment); messageComposer.setBackgroundColor(ColorProvider.BACKGROUND.getColor()); @@ -1042,6 +1040,7 @@ private void dismissProgressDialog() { * Update the title view to show the current thread title, if we have it */ private void updateThreadTitle() { + TextView threadTitleView = getActivity().findViewById(R.id.thread_title); if (threadTitleView != null) { threadTitleView.setText(mThreadTitle == null ? "" : mThreadTitle); } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/announcements/AnnouncementsFragment.java b/Awful.apk/src/main/java/com/ferg/awfulapp/announcements/AnnouncementsFragment.java index 68cf49cce..f98505411 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/announcements/AnnouncementsFragment.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/announcements/AnnouncementsFragment.java @@ -16,6 +16,7 @@ import com.android.volley.VolleyError; import com.ferg.awfulapp.AwfulFragment; import com.ferg.awfulapp.R; +import com.ferg.awfulapp.databinding.AnnouncementsFragmentBinding; import com.ferg.awfulapp.preferences.AwfulPreferences; import com.ferg.awfulapp.provider.AwfulTheme; import com.ferg.awfulapp.task.AnnouncementsRequest; @@ -28,8 +29,6 @@ import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; import timber.log.Timber; /** @@ -47,23 +46,19 @@ public class AnnouncementsFragment extends AwfulFragment { - @BindView(R.id.announcements_webview) - AwfulWebView webView; - @BindView(R.id.status_frog) - StatusFrog statusFrog; + AnnouncementsFragmentBinding binding; @NonNull @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View view = inflateView(R.layout.announcements_fragment, container, inflater); - ButterKnife.bind(this, view); - + binding = AnnouncementsFragmentBinding.inflate(inflater, container, false); + View view = binding.getRoot(); initialiseWebView(); return view; } private void initialiseWebView() { - webView.setJavascriptHandler(new WebViewJsInterface() { + binding.announcementsWebview.setJavascriptHandler(new WebViewJsInterface() { @JavascriptInterface public String getCSS() { @@ -93,7 +88,7 @@ public void resumeSwipe() { } }); - webView.setWebViewClient(new WebViewClient() { + binding.announcementsWebview.setWebViewClient(new WebViewClient() { // this lets links open back in the main activity if we handle them (e.g. 'look at this thread'), // and opens them in a browser or whatever if we don't (e.g. 'click here to buy a thing on the site') @Override @@ -104,7 +99,7 @@ public boolean shouldOverrideUrlLoading(WebView aView, String url) { return true; } }); - webView.setContent(AwfulHtmlPage.getContainerHtml(getPrefs(), -1, false)); + binding.announcementsWebview.setContent(AwfulHtmlPage.getContainerHtml(getPrefs(), -1, false)); } @@ -120,7 +115,7 @@ public void onActivityCreated(Bundle aSavedState) { */ private void showAnnouncements() { Context context = getContext().getApplicationContext(); - statusFrog.setStatusText(R.string.announcements_status_fetching).showSpinner(true); + binding.statusFrog.setStatusText(R.string.announcements_status_fetching).showSpinner(true); queueRequest( new AnnouncementsRequest(context).build(this, new AwfulRequest.AwfulResultCallback>() { @Override @@ -128,22 +123,22 @@ public void success(List result) { AnnouncementsManager.getInstance().markAllRead(); // update the status frog if there are no announcements, otherwise hide it and display them if (result.size() < 1) { - statusFrog.setStatusText(R.string.announcements_status_none).showSpinner(false); + binding.statusFrog.setStatusText(R.string.announcements_status_none).showSpinner(false); } else { - webView.setVisibility(View.VISIBLE); + binding.announcementsWebview.setVisibility(View.VISIBLE); // these page params don't mean anything in the context of the announcement page // we just want it to a) display ok, and b) not let the user click anything bad String bodyHtml = AwfulHtmlPage.getThreadHtml(result, AwfulPreferences.getInstance(), 1, 1); - if (webView != null) { - webView.setBodyHtml(bodyHtml); + if (binding.announcementsWebview != null) { + binding.announcementsWebview.setBodyHtml(bodyHtml); } - statusFrog.setVisibility(View.INVISIBLE); + binding.statusFrog.setVisibility(View.INVISIBLE); } } @Override public void failure(VolleyError error) { - statusFrog.setStatusText(R.string.announcements_status_failed).showSpinner(false); + binding.statusFrog.setStatusText(R.string.announcements_status_failed).showSpinner(false); Timber.w("Announcement get failed!\n" + error.getMessage()); } }) @@ -159,28 +154,28 @@ public String getTitle() { @Override public void onPause() { - if (webView != null) { - webView.onPause(); + if (binding.announcementsWebview != null) { + binding.announcementsWebview.onPause(); } super.onPause(); } @Override public void onResume() { - if (webView != null) { - webView.onResume(); + if (binding.announcementsWebview != null) { + binding.announcementsWebview.onResume(); } super.onResume(); } @Override protected boolean doScroll(boolean down) { - if (webView == null) { + if (binding.announcementsWebview == null) { return false; } else if (down) { - webView.pageDown(false); + binding.announcementsWebview.pageDown(false); } else { - webView.pageUp(false); + binding.announcementsWebview.pageUp(false); } return true; } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/forums/ForumListAdapter.java b/Awful.apk/src/main/java/com/ferg/awfulapp/forums/ForumListAdapter.java index ff5bfebde..58bedfaf1 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/forums/ForumListAdapter.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/forums/ForumListAdapter.java @@ -17,16 +17,14 @@ import com.bignerdranch.expandablerecyclerview.ViewHolder.ChildViewHolder; import com.bignerdranch.expandablerecyclerview.ViewHolder.ParentViewHolder; import com.ferg.awfulapp.R; +import com.ferg.awfulapp.databinding.ForumIndexItemBinding; +import com.ferg.awfulapp.databinding.ForumIndexSubforumItemBinding; import com.ferg.awfulapp.preferences.AwfulPreferences; import com.ferg.awfulapp.provider.ColorProvider; import java.util.ArrayList; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; @@ -239,28 +237,8 @@ class TopLevelForumHolder extends ParentViewHolder { // list item sections - overall view, left column (tags etc), right column (details) private final View itemView; - @BindView(R.id.tag_and_dropdown_arrow) - View tagArea; - @BindView(R.id.forum_details) - View detailsArea; - // right column (used for forums) - @BindView(R.id.forum_title) - TextView title; - @BindView(R.id.forum_subtitle) - TextView subtitle; - @BindView(R.id.forum_favourite_marker) - ImageView favouriteMarker; - // left column (used for forums) - @BindView(R.id.subforums_expand_arrow) - ImageView dropdownButton; - @BindView(R.id.forum_tag) - SquareForumTag forumTag; - // section title (used for section headers) - @BindView(R.id.section_title) - TextView sectionTitle; - // the divider line - @BindView(R.id.list_divider) - View listDivider; + private ForumIndexItemBinding binding; + private Forum forum; private boolean hasSubforums; @@ -269,8 +247,9 @@ class TopLevelForumHolder extends ParentViewHolder { TopLevelForumHolder(View itemView) { super(itemView); this.itemView = itemView; - ButterKnife.bind(this, itemView); - detailsArea.setOnCreateContextMenuListener((contextMenu, view, contextMenuInfo) -> eventListener.onContextMenuCreated(forum, contextMenu)); + binding = ForumIndexItemBinding.bind(itemView); + + binding.forumDetails.setOnCreateContextMenuListener((contextMenu, view, contextMenuInfo) -> eventListener.onContextMenuCreated(forum, contextMenu)); } @@ -281,20 +260,20 @@ void bind(final TopLevelForum forumItem) { /* section items hide everything but the section title, other forum types hide the section title and show the other components. Think of of them as two alternative layouts in the same Layout file */ - tagArea.setVisibility(forum.isType(SECTION) ? GONE : VISIBLE); - detailsArea.setVisibility(forum.isType(SECTION) ? GONE : VISIBLE); - sectionTitle.setVisibility(forum.isType(SECTION) ? VISIBLE : GONE); + binding.tagAndDropdownArrow.setVisibility(forum.isType(SECTION) ? GONE : VISIBLE); + binding.forumDetails.setVisibility(forum.isType(SECTION) ? GONE : VISIBLE); + binding.sectionTitle.setVisibility(forum.isType(SECTION) ? VISIBLE : GONE); // hide the list divider for section titles and expanded parent forums boolean hideDivider = forum.isType(SECTION) || forumItem.isInitiallyExpanded(); - listDivider.setVisibility(hideDivider ? INVISIBLE : VISIBLE); + binding.listDivider.setVisibility(hideDivider ? INVISIBLE : VISIBLE); // sectionTitle is basically a differently formatted version of the title - setText(forum, title, subtitle, sectionTitle); - setThemeColours(itemView, title, subtitle); - handleSubtitles(forum, subtitle); + setText(forum, binding.forumTitle, binding.forumSubtitle, binding.sectionTitle); + setThemeColours(itemView, binding.forumTitle, binding.forumSubtitle); + handleSubtitles(forum, binding.forumSubtitle); - favouriteMarker.setVisibility(forum.isFavourite() ? VISIBLE : GONE); + binding.forumFavouriteMarker.setVisibility(forum.isFavourite() ? VISIBLE : GONE); /* the left section (potentially) has a tag and a dropdown button, anything missing is set to GONE so whatever's there gets vertically centred, and the space remains */ @@ -302,33 +281,38 @@ void bind(final TopLevelForum forumItem) { // if there's a forum tag then display it, otherwise remove it boolean hasForumTag = forum.getTagUrl() != null; if (hasForumTag) { - TagProvider.setSquareForumTag(forumTag, forum); - forumTag.setVisibility(View.VISIBLE); + TagProvider.setSquareForumTag(binding.forumTag, forum); + binding.forumTag.setVisibility(View.VISIBLE); } else { - forumTag.setVisibility(View.GONE); + binding.forumTag.setVisibility(View.GONE); } // if this item has subforums, show the dropdown and make it work, otherwise remove it if (hasSubforums) { - rotateDropdown(dropdownButton, !isExpanded(), true); - dropdownButton.setVisibility(VISIBLE); + rotateDropdown(binding.subforumsExpandArrow, !isExpanded(), true); + binding.subforumsExpandArrow.setVisibility(VISIBLE); } else { - dropdownButton.setVisibility(GONE); - } - } - - - @OnClick(R.id.tag_and_dropdown_arrow) - void toggleExpanded() { - if (hasSubforums) { - onClick(null); + binding.subforumsExpandArrow.setVisibility(GONE); } - } - - - @OnClick(R.id.forum_details) - void selectForum() { - eventListener.onForumClicked(forum); + binding.tagAndDropdownArrow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (hasSubforums) { + if (isExpanded()) { + collapseView(); + } else { + expandView(); + } + } + } + }); + + binding.forumDetails.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + eventListener.onForumClicked(forum); + } + }); } @@ -341,46 +325,37 @@ public boolean shouldItemViewClickToggleExpansion() { @Override public void onExpansionToggled(boolean closing) { super.onExpansionToggled(closing); - rotateDropdown(dropdownButton, closing, false); - listDivider.setVisibility(closing ? VISIBLE : INVISIBLE); + rotateDropdown(binding.subforumsExpandArrow, closing, false); + binding.listDivider.setVisibility(closing ? VISIBLE : INVISIBLE); } } class SubforumHolder extends ChildViewHolder { Forum forum; + ForumIndexSubforumItemBinding binding; - @BindView(R.id.forum_details) - View detailsArea; - @BindView(R.id.forum_title) - TextView title; - @BindView(R.id.forum_subtitle) - TextView subtitle; - @BindView(R.id.forum_favourite_marker) - ImageView favouriteMarker; - @BindView(R.id.item_container) - View itemLayout; SubforumHolder(View itemView) { super(itemView); - ButterKnife.bind(this, itemView); - detailsArea.setOnCreateContextMenuListener((contextMenu, view, contextMenuInfo) -> eventListener.onContextMenuCreated(forum, contextMenu)); + binding = ForumIndexSubforumItemBinding.bind(itemView); + binding.forumDetails.setOnCreateContextMenuListener((contextMenu, view, contextMenuInfo) -> eventListener.onContextMenuCreated(forum, contextMenu)); } void bind(final Forum forumItem) { forum = forumItem; - setText(forum, title, subtitle, null); - setThemeColours(itemLayout, title, subtitle); - handleSubtitles(forum, subtitle); - favouriteMarker.setVisibility(forum.isFavourite() ? VISIBLE : GONE); - } - - - @OnClick(R.id.forum_details) - void selectForum() { - eventListener.onForumClicked(forum); + setText(forum, binding.forumTitle, binding.forumSubtitle, null); + setThemeColours(binding.getRoot(), binding.forumTitle, binding.forumSubtitle); + handleSubtitles(forum, binding.forumSubtitle); + binding.forumFavouriteMarker.setVisibility(forum.isFavourite() ? VISIBLE : GONE); + binding.forumDetails.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + eventListener.onForumClicked(forum); + } + }); } } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/network/NetworkUtils.java b/Awful.apk/src/main/java/com/ferg/awfulapp/network/NetworkUtils.java index 3cabc4854..9c498f17c 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/network/NetworkUtils.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/network/NetworkUtils.java @@ -53,6 +53,7 @@ import timber.log.Timber; +@SuppressWarnings({"unchecked", "unsafe"}) public class NetworkUtils { private static final String CHARSET = "windows-1252"; diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/BasePopupMenu.java b/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/BasePopupMenu.java index 04531a2b0..ad8699aa0 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/BasePopupMenu.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/BasePopupMenu.java @@ -15,12 +15,11 @@ import android.widget.TextView; import com.ferg.awfulapp.R; +import com.ferg.awfulapp.databinding.ActionItemBinding; import com.ferg.awfulapp.provider.ColorProvider; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; /** * Created by baka kaba on 22/05/2017. @@ -72,7 +71,6 @@ public void onCreate(@Nullable Bundle savedInstanceState) { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { final View result = inflater.inflate(layoutResId, container, false); - ButterKnife.bind(this, result); TextView actionTitle = result.findViewById(R.id.actionTitle); actionTitle.setMovementMethod(new ScrollingMovementMethod()); @@ -135,14 +133,11 @@ String getMenuLabel(@NonNull T action) { class ActionHolder extends RecyclerView.ViewHolder { - @BindView(R.id.actionTag) - ImageView actionTag; - @BindView(R.id.actionTitle) - TextView actionText; + ActionItemBinding binding; ActionHolder(View view) { super(view); - ButterKnife.bind(this, view); + binding = ActionItemBinding.bind(view); } } @@ -158,9 +153,9 @@ public ActionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) @Override public void onBindViewHolder(@NonNull ActionHolder holder, final int position) { final T action = menuItems.get(position); - holder.actionText.setText(getMenuLabel(action)); - holder.actionText.setTextColor(ColorProvider.PRIMARY_TEXT.getColor()); - holder.actionTag.setImageResource(action.getIconId()); + holder.binding.actionTitle.setText(getMenuLabel(action)); + holder.binding.actionTitle.setTextColor(ColorProvider.PRIMARY_TEXT.getColor()); + holder.binding.actionTag.setImageResource(action.getIconId()); holder.itemView.setOnClickListener(v -> { onActionClicked(action); if (onActionClickedListener != null) { diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/UrlContextMenu.java b/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/UrlContextMenu.java index 3be33108d..07d486225 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/UrlContextMenu.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/popupmenu/UrlContextMenu.java @@ -18,7 +18,6 @@ import java.util.ArrayList; import java.util.List; -import butterknife.BindView; import static android.view.View.GONE; import static android.view.View.VISIBLE; @@ -52,9 +51,8 @@ public class UrlContextMenu extends BasePopupMenu private boolean isImage; private boolean isGif; - @BindView(R.id.actionTitle) TextView titleText; - @BindView(R.id.title_subheading) + TextView subheading = null; @Nullable private String subheadingText = null; @@ -93,8 +91,10 @@ void init(@NonNull Bundle args) { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); + titleText = view.findViewById(R.id.actionTitle); + subheading = view.findViewById(R.id.title_subheading); // tiny title text for long URLs - need to reapply the colour set in the xml - titleText.setTextAppearance(getContext(), R.style.TextAppearance_AppCompat_Small); + titleText.setTextAppearance(getContext(), androidx.appcompat.R.style.TextAppearance_AppCompat_Small); titleText.setTextColor(ColorProvider.ACTION_BAR_TEXT.getColor()); setSubheading(subheadingText); diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulProvider.java b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulProvider.java index c34f96ed4..2d9908a73 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulProvider.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulProvider.java @@ -50,7 +50,6 @@ import com.ferg.awfulapp.thread.AwfulMessage; import com.ferg.awfulapp.thread.AwfulPost; import com.ferg.awfulapp.thread.AwfulThread; -import com.google.firebase.crashlytics.FirebaseCrashlytics; import java.util.Arrays; import java.util.HashMap; @@ -454,13 +453,7 @@ public Cursor query(@NonNull Uri aUri, String[] aProjection, String aSelection, if (uriType == UriMatcher.NO_MATCH) { String msg = String.format("Unrecognised query Uri!\nUri: %s\nProjection: %s\nSelection: %s\nSelection args: %s\nSort order: %s", aUri, Arrays.toString(aProjection), aSelection, Arrays.toString(aSelectionArgs), aSortOrder); - if (AwfulApplication.crashlyticsEnabled()) { - FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); - - crashlytics.log("WARN/" + TAG+ ": "+msg); - } else { - Log.w(TAG, msg); - } + Log.w(TAG, msg); return null; } @@ -533,12 +526,7 @@ public Cursor query(@NonNull Uri aUri, String[] aProjection, String aSelection, return result; } catch (Exception e) { String msg = String.format("aUri:\n%s\nQuery tables string:\n%s", aUri, builder.getTables()); - if (AwfulApplication.crashlyticsEnabled()){ - FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); - crashlytics.log("WARN/" + TAG+ ": "+msg); - } else{ - Log.w(TAG, msg, e); - } + Log.w(TAG, msg, e); throw e; } } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulTheme.java b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulTheme.java index 18e0e17e1..bca8d1b9d 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulTheme.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/AwfulTheme.java @@ -214,7 +214,7 @@ public boolean isDark() { // initialise the dark theme flag - we're storing this per enum value, so we can avoid heavy processing TypedValue isLight = new TypedValue(); // this should pull the correct attribute from the thene - it's specified in the base platform themes - getTheme(AwfulPreferences.getInstance()).resolveAttribute(R.attr.isLightTheme, isLight, true); + getTheme(AwfulPreferences.getInstance()).resolveAttribute(androidx.appcompat.R.attr.isLightTheme, isLight, true); int FALSE = 0; isDark = (isLight.data == FALSE); } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/ColorProvider.java b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/ColorProvider.java index 421804df7..9c8f685c2 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/provider/ColorProvider.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/provider/ColorProvider.java @@ -29,7 +29,7 @@ public enum ColorProvider { PRIMARY_TEXT(R.attr.primaryPostFontColor), ALT_TEXT(R.attr.secondaryPostFontColor), - BACKGROUND(R.attr.background), + BACKGROUND(androidx.appcompat.R.attr.background), UNREAD_BACKGROUND(R.attr.unreadColor), UNREAD_BACKGROUND_DIM(R.attr.unreadColorDim), UNREAD_TEXT(R.attr.unreadFontColor), diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/reply/ImgurInserter.java b/Awful.apk/src/main/java/com/ferg/awfulapp/reply/ImgurInserter.java index b0af2a28d..8da0f779f 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/reply/ImgurInserter.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/reply/ImgurInserter.java @@ -16,11 +16,15 @@ import androidx.annotation.Nullable; import com.ferg.awfulapp.AwfulApplication; +import com.ferg.awfulapp.databinding.InsertImgurDialogBinding; import com.google.android.material.textfield.TextInputLayout; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.appcompat.app.AlertDialog; + +import android.text.Editable; +import android.text.TextWatcher; import android.text.format.DateFormat; import android.text.format.Formatter; import android.util.Log; @@ -28,6 +32,7 @@ import android.util.Patterns; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; @@ -50,14 +55,8 @@ import java.io.InputStream; import java.io.UnsupportedEncodingException; -import butterknife.BindView; -import butterknife.OnClick; -import butterknife.OnItemSelected; -import butterknife.OnTextChanged; - import static android.view.View.GONE; import static android.view.View.VISIBLE; -import static butterknife.ButterKnife.bind; /** * Created by baka kaba on 31/05/2017. @@ -78,37 +77,7 @@ public class ImgurInserter extends DialogFragment { private java.text.DateFormat dateFormat; private java.text.DateFormat timeFormat; - @BindView(R.id.upload_type) - Spinner uploadTypeSelector; - - @BindView(R.id.upload_image_section) - ViewGroup uploadImageSection; - @BindView(R.id.image_preview) - ImageView imagePreview; - @BindView(R.id.image_name) - TextView imageNameLabel; - @BindView(R.id.image_details) - TextView imageDetailsLabel; - - @BindView(R.id.upload_url_text_input_layout) - TextInputLayout uploadUrlTextWrapper; - @BindView(R.id.upload_url_edittext) - EditText uploadUrlEditText; - - @BindView(R.id.use_thumbnail) - CheckBox thumbnailCheckbox; - @BindView(R.id.add_gifs_as_video) - CheckBox gifsAsVideoCheckbox; - - @BindView(R.id.upload_status) - TextView uploadStatus; - @BindView(R.id.upload_progress_bar) - ProgressBar uploadProgressBar; - @BindView(R.id.remaining_uploads) - TextView remainingUploads; - @BindView(R.id.credits_reset_time) - TextView creditsResetTime; - + private InsertImgurDialogBinding binding; private Button uploadButton; Uri imageFile = null; @@ -126,7 +95,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { timeFormat = DateFormat.getTimeFormat(activity); View layout = activity.getLayoutInflater().inflate(R.layout.insert_imgur_dialog, null); - bind(this, layout); + binding = InsertImgurDialogBinding.bind(layout); AlertDialog dialog = new AlertDialog.Builder(activity) .setTitle(R.string.imgur_uploader_dialog_title) .setView(layout) @@ -138,9 +107,36 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { uploadButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); uploadButton.setOnClickListener(view -> startUpload()); // TODO: 05/06/2017 is that method guaranteed to be fired when the system creates the spinner and sets the first item? - uploadTypeSelector.setSelection(AwfulApplication.getAppStatePrefs().getInt(KEY_IMGUR_LAST_CHOSEN_UPLOAD_OPTION, 0)); + binding.uploadType.setSelection(AwfulApplication.getAppStatePrefs().getInt(KEY_IMGUR_LAST_CHOSEN_UPLOAD_OPTION, 0)); updateUploadType(); updateRemainingUploads(); + binding.uploadType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + updateUploadType(); + } + + @Override + public void onNothingSelected(AdapterView parent) {} + }); + binding.uploadImageSection.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + launchImagePicker(); + } + }); + binding.uploadUrlEdittext.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) {} + + @Override + public void afterTextChanged(Editable s) { + onUrlTextChanged(); + } + }); return dialog; } @@ -167,10 +163,9 @@ private void cancelUploadTask() { /** * Check the currently selected upload type, and update state as necessary. */ - @OnItemSelected(R.id.upload_type) void updateUploadType() { // this assumes the first entry in the spinner is URL, and the second is IMAGE - int position = uploadTypeSelector.getSelectedItemPosition(); + int position = binding.uploadType.getSelectedItemPosition(); uploadSourceIsUrl = (position == 0); setState(State.CHOOSING); } @@ -183,13 +178,13 @@ void updateRemainingUploads() { Pair uploadLimit = ImgurUploadRequest.getCurrentUploadLimit(); Integer remaining = uploadLimit.first; Long resetTime = uploadLimit.second; - creditsResetTime.setText(resetTime == null ? "" : getString(R.string.imgur_uploader_remaining_uploads_reset_time, timeFormat.format(resetTime), dateFormat.format(resetTime))); + binding.creditsResetTime.setText(resetTime == null ? "" : getString(R.string.imgur_uploader_remaining_uploads_reset_time, timeFormat.format(resetTime), dateFormat.format(resetTime))); if (remaining == null) { - remainingUploads.setText(R.string.imgur_uploader_remaining_uploads_unknown); - creditsResetTime.setText(""); + binding.remainingUploads.setText(R.string.imgur_uploader_remaining_uploads_unknown); + binding.creditsResetTime.setText(""); } else { - remainingUploads.setText(getResources().getQuantityString(R.plurals.imgur_uploader_remaining_uploads, remaining, remaining)); + binding.remainingUploads.setText(getResources().getQuantityString(R.plurals.imgur_uploader_remaining_uploads, remaining, remaining)); if (remaining < 1) { setState(State.NO_UPLOAD_CREDITS); } @@ -204,7 +199,7 @@ void updateRemainingUploads() { /** * Display an image chooser to pick a file to upload. */ - @OnClick(R.id.upload_image_section) + void launchImagePicker() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT) .addCategory(Intent.CATEGORY_OPENABLE) @@ -234,7 +229,7 @@ private void onImageSelected(@NonNull Uri imageUri) { // check if this image looks invalid - if so, complain instead of using it String invalidReason = reasonImageIsInvalid(imageUri); if (invalidReason != null) { - uploadStatus.setText(invalidReason); + binding.uploadStatus.setText(invalidReason); return; } @@ -304,13 +299,13 @@ private Pair getFileNameAndSize(@NonNull Uri fileUri) { private void displayImageDetails(@NonNull Uri imageUri) { Pair nameAndSize = getFileNameAndSize(imageUri); if (nameAndSize.first == null && nameAndSize.second == null) { - imageNameLabel.setText(""); - imageDetailsLabel.setText(R.string.imgur_uploader_no_file_details); + binding.imageName.setText(""); + binding.imageDetails.setText(R.string.imgur_uploader_no_file_details); } else { String name = (nameAndSize.first == null) ? getString(R.string.imgur_uploader_unknown_value) : nameAndSize.first; - imageNameLabel.setText(getString(R.string.imgur_uploader_file_name, name)); + binding.imageName.setText(getString(R.string.imgur_uploader_file_name, name)); String size = (nameAndSize.second == null) ? getString(R.string.imgur_uploader_unknown_value) : Formatter.formatShortFileSize(getContext(), nameAndSize.second); - imageDetailsLabel.setText(getString(R.string.imgur_uploader_file_size, size)); + binding.imageDetails.setText(getString(R.string.imgur_uploader_file_size, size)); } } @@ -329,7 +324,7 @@ private void displayImagePreview(@NonNull Uri imageUri) { options.inSampleSize = 4; inputStream = getActivity().getContentResolver().openInputStream(imageUri); previewBitmap = BitmapFactory.decodeStream(inputStream, null, options); - imagePreview.setImageDrawable(new BitmapDrawable(previewBitmap)); + binding.imagePreview.setImageDrawable(new BitmapDrawable(previewBitmap)); } catch (FileNotFoundException e) { e.printStackTrace(); // TODO: 05/06/2017 'no preview' or something? @@ -345,12 +340,12 @@ private void displayImagePreview(@NonNull Uri imageUri) { /** * Handle changes to the 'image source URL' field, updating state where necessary. */ - @OnTextChanged(R.id.upload_url_edittext) + void onUrlTextChanged() { // change state when (and only when) the url contents no longer match the current state // this also avoids a circular call when the url is reset in #setState (url becomes empty // but state is already set appropriately to CHOOSING) - boolean urlIsEmpty = uploadUrlEditText.length() == 0; + boolean urlIsEmpty = binding.uploadUrlEdittext.length() == 0; if (urlIsEmpty && state == State.READY_TO_UPLOAD) { setState(State.CHOOSING); } else if (!urlIsEmpty && state == State.CHOOSING) { @@ -362,7 +357,7 @@ void onUrlTextChanged() { return; } - String url = uploadUrlEditText.getText().toString().toLowerCase(); + String url = binding.uploadUrlEdittext.getText().toString().toLowerCase(); boolean looksLikeUrl = Patterns.WEB_URL.matcher(url).matches(); String warningMessage = null; if (!StringUtils.startsWithAny(url, "http://", "https://")) { @@ -371,7 +366,7 @@ void onUrlTextChanged() { } else if (!looksLikeUrl) { warningMessage = getString(R.string.imgur_uploader_url_validation_warning); } - uploadUrlTextWrapper.setError(warningMessage); + binding.uploadUrlTextInputLayout.setError(warningMessage); } @@ -387,13 +382,13 @@ void startUpload() { if (state != State.READY_TO_UPLOAD) { return; } - AwfulApplication.getAppStatePrefs().edit().putInt(KEY_IMGUR_LAST_CHOSEN_UPLOAD_OPTION, uploadTypeSelector.getSelectedItemPosition()).apply(); + AwfulApplication.getAppStatePrefs().edit().putInt(KEY_IMGUR_LAST_CHOSEN_UPLOAD_OPTION, binding.uploadType.getSelectedItemPosition()).apply(); setState(State.UPLOADING); cancelUploadTask(); // do a url if we have one if (uploadSourceIsUrl) { - uploadTask = new ImgurUploadRequest(uploadUrlEditText.getText().toString(), this::parseUploadResponse, this::handleUploadError); + uploadTask = new ImgurUploadRequest(binding.uploadUrlEdittext.getText().toString(), this::parseUploadResponse, this::handleUploadError); NetworkUtils.queueRequest(uploadTask); } else { ContentResolver contentResolver = getActivity().getContentResolver(); @@ -435,10 +430,10 @@ private void parseUploadResponse(JSONObject response) { JSONObject data = response.getJSONObject("data"); String videoUrl = StringUtils.defaultIfBlank(data.optString("gifv"), data.optString("mp4")); String imageUrl = data.getString("link"); - if (gifsAsVideoCheckbox.isChecked() && StringUtils.isNotBlank(videoUrl)) { + if (binding.addGifsAsVideo.isChecked() && StringUtils.isNotBlank(videoUrl)) { ((MessageComposer) getTargetFragment()).onHtml5VideoUploaded(videoUrl); } else { - ((MessageComposer) getTargetFragment()).onImageUploaded(imageUrl, thumbnailCheckbox.isChecked()); + ((MessageComposer) getTargetFragment()).onImageUploaded(imageUrl, binding.useThumbnail.isChecked()); } dismiss(); return; @@ -463,7 +458,7 @@ private void parseUploadResponse(JSONObject response) { private void onUploadError(@NonNull String errorMessage) { // revert back to pre-upload state setState(State.READY_TO_UPLOAD); - uploadStatus.setText(errorMessage); + binding.uploadStatus.setText(errorMessage); updateRemainingUploads(); } @@ -532,45 +527,45 @@ private void setState(State newState) { // this intentionally sets the appearing view to visible BEFORE removing the other // which avoids too much weirdness with the layout change animation if (uploadSourceIsUrl) { - uploadUrlTextWrapper.setVisibility(VISIBLE); - uploadImageSection.setVisibility(GONE); + binding.uploadUrlTextInputLayout.setVisibility(VISIBLE); + binding.uploadImageSection.setVisibility(GONE); } else { - uploadImageSection.setVisibility(VISIBLE); - uploadUrlTextWrapper.setVisibility(GONE); + binding.uploadImageSection.setVisibility(VISIBLE); + binding.uploadUrlTextInputLayout.setVisibility(GONE); } - imagePreview.setImageResource(R.drawable.ic_photo_dark); - imageNameLabel.setText(""); - imageDetailsLabel.setText(R.string.imgur_uploader_tap_to_choose_file); - uploadUrlEditText.setText(""); - uploadUrlTextWrapper.setError(null); + binding.imagePreview.setImageResource(R.drawable.ic_photo_dark); + binding.imageName.setText(""); + binding.imageDetails.setText(R.string.imgur_uploader_tap_to_choose_file); + binding.uploadUrlEdittext.setText(""); + binding.uploadUrlTextInputLayout.setError(null); uploadButton.setEnabled(false); - uploadStatus.setText(uploadSourceIsUrl ? getString(R.string.imgur_uploader_status_enter_image_url) : getString(R.string.imgur_uploader_status_choose_source_file)); - uploadProgressBar.setVisibility(GONE); + binding.uploadStatus.setText(uploadSourceIsUrl ? getString(R.string.imgur_uploader_status_enter_image_url) : getString(R.string.imgur_uploader_status_choose_source_file)); + binding.uploadProgressBar.setVisibility(GONE); break; // upload source selected (either a URL entered, or a source file chosen) case READY_TO_UPLOAD: uploadButton.setEnabled(true); - uploadStatus.setText(R.string.imgur_uploader_status_ready_to_upload); - uploadProgressBar.setVisibility(GONE); + binding.uploadStatus.setText(R.string.imgur_uploader_status_ready_to_upload); + binding.uploadProgressBar.setVisibility(GONE); break; // upload request in progress case UPLOADING: uploadButton.setEnabled(false); - uploadStatus.setText(R.string.imgur_uploader_status_upload_in_progress); - uploadProgressBar.setVisibility(VISIBLE); + binding.uploadStatus.setText(R.string.imgur_uploader_status_upload_in_progress); + binding.uploadProgressBar.setVisibility(VISIBLE); break; // error state for when we can't upload case NO_UPLOAD_CREDITS: // put on the brakes, hide everything and prevent uploads uploadButton.setEnabled(false); - uploadStatus.setText(R.string.imgur_uploader_status_no_remaining_uploads); - uploadImageSection.setVisibility(GONE); - uploadUrlTextWrapper.setVisibility(GONE); - uploadProgressBar.setVisibility(GONE); + binding.uploadStatus.setText(R.string.imgur_uploader_status_no_remaining_uploads); + binding.uploadImageSection.setVisibility(GONE); + binding.uploadUrlTextInputLayout.setVisibility(GONE); + binding.uploadProgressBar.setVisibility(GONE); break; } } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/search/SearchFragment.kt b/Awful.apk/src/main/java/com/ferg/awfulapp/search/SearchFragment.kt index 88ade42f0..1c59b9b4e 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/search/SearchFragment.kt +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/search/SearchFragment.kt @@ -64,7 +64,7 @@ import java.util.* class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshlayout.library.SwipyRefreshLayout.OnRefreshListener { - private val mSearchQuery by lazy { view!!.findViewById(R.id.search_query) as EditText } + private val mSearchQuery by lazy { requireView().findViewById(R.id.search_query) as EditText } private var mQueryId: Int = 0 private var mMaxPageQueried: Int = 0 @@ -74,7 +74,7 @@ class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshl private var mDialog: ProgressDialog? = null private val mSearchResultList: RecyclerView by lazy { - (view!!.findViewById(R.id.search_results) as RecyclerView) + (requireView().findViewById(R.id.search_results) as RecyclerView) .apply { adapter = SearchResultAdapter() layoutManager = @@ -84,7 +84,7 @@ class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshl private var mSearchResults: MutableList = mutableListOf() private val mSRL: SwipyRefreshLayout by lazy { - (view!!.findViewById(R.id.search_srl) as SwipyRefreshLayout) + (requireView().findViewById(R.id.search_srl) as SwipyRefreshLayout) .apply { setOnRefreshListener(this@SearchFragment) setColorSchemeResources(*ColorProvider.getSRLProgressColors(null)) @@ -136,7 +136,7 @@ class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshl private fun search() { mDialog = ProgressDialog.show(activity, getString(R.string.search_forums_active_dialog_title), getString(R.string.search_forums_active_dialog_message), true, false) val searchForumsPrimitive = ArrayUtils.toPrimitive(searchForums.toTypedArray()) - NetworkUtils.queueRequest(SearchRequest(this.context!!, mSearchQuery.text.toString().toLowerCase(), searchForumsPrimitive) + NetworkUtils.queueRequest(SearchRequest(this.requireContext(), mSearchQuery.text.toString().toLowerCase(), searchForumsPrimitive) .build(null, object : AwfulRequest.AwfulResultCallback { override fun success(result: AwfulSearchResult) { removeLoadingDialog() @@ -189,7 +189,7 @@ class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshl R.id.select_forums -> SearchForumsFragment(this) .apply { setStyle(DialogFragment.STYLE_NO_TITLE, 0) } - .show(fragmentManager!!, "searchforums") + .show(requireFragmentManager(), "searchforums") else -> return super.onOptionsItemSelected(item) } return true @@ -218,7 +218,7 @@ class SearchFragment : AwfulFragment(), com.orangegangsters.github.swipyrefreshl override fun onRefresh(direction: SwipyRefreshLayoutDirection) { Timber.i("onRefresh: %s", mMaxPageQueried) val preItemCount = mSearchResultList.adapter?.itemCount ?: 0 - NetworkUtils.queueRequest(SearchResultPageRequest(this.context!!, mQueryId, mMaxPageQueried + 1).build(null, object : AwfulRequest.AwfulResultCallback> { + NetworkUtils.queueRequest(SearchResultPageRequest(this.requireContext(), mQueryId, mMaxPageQueried + 1).build(null, object : AwfulRequest.AwfulResultCallback> { // TODO: combine this with #search since they share functionality - maybe a SearchQuery object for the current query that holds this state we're changing override fun success(result: ArrayList) { diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/task/AwfulRequest.kt b/Awful.apk/src/main/java/com/ferg/awfulapp/task/AwfulRequest.kt index c2b393a5e..e26a13ecd 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/task/AwfulRequest.kt +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/task/AwfulRequest.kt @@ -20,7 +20,6 @@ import com.ferg.awfulapp.preferences.AwfulPreferences import com.ferg.awfulapp.task.AwfulRequest.Parameters.GetParams import com.ferg.awfulapp.task.AwfulRequest.Parameters.PostParams import com.ferg.awfulapp.util.AwfulError -import com.google.firebase.crashlytics.FirebaseCrashlytics import org.apache.http.HttpEntity import org.apache.http.entity.ContentType import org.apache.http.entity.mime.MultipartEntityBuilder @@ -259,14 +258,6 @@ abstract class AwfulRequest(protected val context: Context, private val baseU return Response.success(result, HttpHeaderParser.parseCacheHeaders(response)) } catch (ae: AwfulError) { return Response.error(ae) - } catch (e: OutOfMemoryError) { - if (AwfulApplication.crashlyticsEnabled()) { - val crashlytics: FirebaseCrashlytics = FirebaseCrashlytics.getInstance() - - crashlytics.setCustomKey("Response URL", url) - crashlytics.setCustomKey("Response data size", response.data.size.toLong()) - } - throw e } catch (e: Exception) { // TODO: find out what else this is meant to be catching, because it's swallowing every exception Timber.e(e, "Failed parse: $url") diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/task/ImgurUploadRequest.java b/Awful.apk/src/main/java/com/ferg/awfulapp/task/ImgurUploadRequest.java index c339bc908..4f8ae1420 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/task/ImgurUploadRequest.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/task/ImgurUploadRequest.java @@ -146,7 +146,7 @@ public ImgurUploadRequest(@NonNull InputStream imageStream, @NonNull Response.Listener jsonResponseListener, @Nullable Response.ErrorListener errorListener) { this(true, jsonResponseListener, errorListener); - attachParams.addBinaryBody("image", imageStream); + attachParams.addBinaryBody("image", imageStream, ContentType.DEFAULT_BINARY, "Awful image"); httpEntity = attachParams.build(); } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/util/AwfulUtils.java b/Awful.apk/src/main/java/com/ferg/awfulapp/util/AwfulUtils.java index 8d0170f19..2338d8047 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/util/AwfulUtils.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/util/AwfulUtils.java @@ -25,14 +25,12 @@ import com.ToxicBakery.viewpager.transforms.ZoomInTransformer; import com.ToxicBakery.viewpager.transforms.ZoomOutSlideTransformer; import com.ToxicBakery.viewpager.transforms.ZoomOutTransformer; -import com.ferg.awfulapp.AwfulApplication; import com.ferg.awfulapp.constants.Constants; import com.ferg.awfulapp.preferences.AwfulPreferences; import com.ferg.awfulapp.provider.DatabaseHelper; import com.ferg.awfulapp.thread.AwfulEmote; import com.ferg.awfulapp.thread.AwfulPost; import com.ferg.awfulapp.thread.AwfulThread; -import com.google.firebase.crashlytics.FirebaseCrashlytics; import java.util.HashMap; @@ -165,10 +163,6 @@ public static boolean contains(int[] intArray, int value) { */ public static void failSilently(@NonNull Exception e) { Timber.e(e); - if (AwfulApplication.crashlyticsEnabled()) { - FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); - crashlytics.log(e.getMessage()); - } if (Constants.DEBUG) { throw new RuntimeException(e); } diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/PageBar.java b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/PageBar.java index c2f8399f9..918c5bf72 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/PageBar.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/PageBar.java @@ -14,13 +14,10 @@ import android.widget.TextView; import com.ferg.awfulapp.R; +import com.ferg.awfulapp.databinding.PageBarBinding; import java.util.Locale; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; - /** * Created by baka kaba on 25/05/2016. *

    @@ -31,16 +28,7 @@ public class PageBar extends FrameLayout { public static final int FIRST_PAGE = 1; - @BindView(R.id.page_count_text) - TextView mPageCountText; - @BindView(R.id.next_page) - ImageButton nextPageButton; - @BindView(R.id.prev_page) - ImageButton prevPageButton; - @BindView(R.id.refresh) - ImageButton refreshButton; - @BindView(R.id.refresh_alt) - ImageButton altRefreshButton; + PageBarBinding binding; private PageBarCallbacks listener = null; @@ -67,9 +55,13 @@ public PageBar(Context context, AttributeSet attrs, int defStyleAttr, int defSty private void init() { - View pageBar = LayoutInflater.from(getContext()).inflate(R.layout.page_bar, this, true); - ButterKnife.bind(pageBar); + binding = PageBarBinding.inflate(LayoutInflater.from(getContext()), this, true); updatePagePosition(FIRST_PAGE, FIRST_PAGE); + onRefreshClicked(binding.refresh); + onRefreshClicked(binding.refreshAlt); + onNavButtonClicked(binding.nextPage); + onNavButtonClicked(binding.prevPage); + onPageNumberClicked(binding.pageCountText); } /** @@ -102,7 +94,7 @@ public void updatePagePosition(int currentPage, int lastPage) { private void updateDisplay(int currentPage, int lastPage, @NonNull PageType pageType, boolean hasPageCount) { String template = hasPageCount ? "%d / %d" : "%d"; - mPageCountText.setText(String.format(Locale.getDefault(), template, currentPage, lastPage)); + binding.pageCountText.setText(String.format(Locale.getDefault(), template, currentPage, lastPage)); /* hide and show the appropriate icons for each state: - don't show the prev/next arrow on the first/last page @@ -112,28 +104,28 @@ private void updateDisplay(int currentPage, int lastPage, @NonNull PageType page */ switch (pageType) { case SINGLE: - prevPageButton.setVisibility(GONE); - nextPageButton.setVisibility(GONE); - altRefreshButton.setVisibility(GONE); - refreshButton.setVisibility(VISIBLE); + binding.prevPage.setVisibility(GONE); + binding.nextPage.setVisibility(GONE); + binding.refreshAlt.setVisibility(GONE); + binding.refresh.setVisibility(VISIBLE); break; case FIRST_OF_MANY: - prevPageButton.setVisibility(GONE); - altRefreshButton.setVisibility(GONE); - refreshButton.setVisibility(VISIBLE); - nextPageButton.setVisibility(VISIBLE); + binding.prevPage.setVisibility(GONE); + binding.refreshAlt.setVisibility(GONE); + binding.refresh.setVisibility(VISIBLE); + binding.nextPage.setVisibility(VISIBLE); break; case ONE_OF_MANY: - altRefreshButton.setVisibility(GONE); - prevPageButton.setVisibility(VISIBLE); - refreshButton.setVisibility(VISIBLE); - nextPageButton.setVisibility(VISIBLE); + binding.refreshAlt.setVisibility(GONE); + binding.prevPage.setVisibility(VISIBLE); + binding.refresh.setVisibility(VISIBLE); + binding.nextPage.setVisibility(VISIBLE); break; case LAST_OF_MANY: - nextPageButton.setVisibility(GONE); - refreshButton.setVisibility(GONE); - prevPageButton.setVisibility(VISIBLE); - altRefreshButton.setVisibility(VISIBLE); + binding.nextPage.setVisibility(GONE); + binding.refresh.setVisibility(GONE); + binding.prevPage.setVisibility(VISIBLE); + binding.refreshAlt.setVisibility(VISIBLE); } } @@ -145,26 +137,38 @@ public void setListener(@Nullable PageBarCallbacks listener) { this.listener = listener; } - @OnClick({R.id.refresh, R.id.refresh_alt}) - public void onRefreshClicked() { - if (listener != null) { - listener.onRefreshClicked(); - } + public void onRefreshClicked(ImageButton button) { + button.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onRefreshClicked(); + } + } + }); } - @OnClick({R.id.next_page, R.id.prev_page}) - public void onNavButtonClicked(View view) { - if (listener != null) { - listener.onPageNavigation(view.getId() == R.id.next_page); - } + public void onNavButtonClicked(ImageButton button) { + button.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onPageNavigation(button.getId() == R.id.next_page); + } + } + }); } + public void onPageNumberClicked(TextView pageNumber) { + pageNumber.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onPageNumberClicked(); + } + } + }); - @OnClick({R.id.page_count_text}) - public void onPageNumberClicked() { - if (listener != null) { - listener.onPageNumberClicked(); - } } // TODO: probably best to add a setter for the stuff that uses this @@ -174,11 +178,11 @@ public void onPageNumberClicked() { */ @NonNull public View getTextView() { - return mPageCountText; + return binding.pageCountText; } public void setTextColour(@ColorInt int textColour) { - mPageCountText.setTextColor(textColour); + binding.pageCountText.setTextColor(textColour); } private enum PageType {SINGLE, FIRST_OF_MANY, LAST_OF_MANY, ONE_OF_MANY} diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ProbationBar.java b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ProbationBar.java index 7e10e24bd..2de9ed31b 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ProbationBar.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ProbationBar.java @@ -11,14 +11,11 @@ import android.widget.TextView; import com.ferg.awfulapp.R; +import com.ferg.awfulapp.databinding.ProbationBarBinding; import java.text.DateFormat; import java.util.Date; -import butterknife.BindString; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; /** * Created by baka kaba on 25/05/2016. @@ -30,10 +27,7 @@ */ public class ProbationBar extends LinearLayout { - @BindView(R.id.probation_message) - TextView mProbationMessageView; - @BindString(R.string.probation_message) - String probationMessage; + ProbationBarBinding binding; @Nullable private Callbacks listener = null; @@ -60,8 +54,15 @@ public ProbationBar(Context context, AttributeSet attrs, int defStyleAttr, int d } private void init() { - View probationBar = LayoutInflater.from(getContext()).inflate(R.layout.probation_bar, this, true); - ButterKnife.bind(probationBar); + binding = ProbationBarBinding.inflate(LayoutInflater.from(getContext())); + binding.goToLC.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (listener != null) { + listener.onProbationButtonClicked(); + } + } + }); } @@ -82,19 +83,12 @@ public void setListener(@Nullable Callbacks listener) { */ public void setProbation(@Nullable Long probationTime) { if (probationTime == null) { - setVisibility(View.GONE); + this.setVisibility(View.GONE); return; } - setVisibility(VISIBLE); + this.setVisibility(VISIBLE); String probeEnd = DateFormat.getDateTimeInstance().format(new Date(probationTime)); - mProbationMessageView.setText(String.format(probationMessage, probeEnd)); - } - - @OnClick(R.id.go_to_LC) - public void onProbationButtonClicked() { - if (listener != null) { - listener.onProbationButtonClicked(); - } + binding.probationMessage.setText(String.format(binding.getRoot().getResources().getString(R.string.probation_message), probeEnd)); } public interface Callbacks { diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/StatusFrog.java b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/StatusFrog.java index c3aa7f0ac..576fdc907 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/StatusFrog.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/StatusFrog.java @@ -15,8 +15,6 @@ import com.ferg.awfulapp.R; -import butterknife.BindView; -import butterknife.ButterKnife; /** * Created by baka kaba on 14/08/2017. @@ -30,9 +28,9 @@ */ public class StatusFrog extends RelativeLayout { - @BindView(R.id.status_message) + TextView statusMessage; - @BindView(R.id.status_progress_bar) + ProgressBar progressBar; public StatusFrog(Context context) { @@ -59,7 +57,9 @@ public StatusFrog(Context context, AttributeSet attrs, int defStyleAttr, int def private void init(Context context, @Nullable AttributeSet attrs) { View view = LayoutInflater.from(context).inflate(R.layout.status_frog, this, true); - ButterKnife.bind(this, view); + statusMessage = view.findViewById(R.id.status_message); + progressBar = view.findViewById(R.id.status_progress_bar); + // handle any custom XML attributes if (attrs != null) { TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.StatusFrog, 0, 0); diff --git a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ThreadIconPicker.java b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ThreadIconPicker.java index 38e552a8b..4089e3cf6 100644 --- a/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ThreadIconPicker.java +++ b/Awful.apk/src/main/java/com/ferg/awfulapp/widget/ThreadIconPicker.java @@ -31,10 +31,6 @@ import java.util.Iterator; import java.util.List; -import butterknife.BindView; -import butterknife.ButterKnife; -import butterknife.OnClick; -import butterknife.OnLongClick; import static com.ferg.awfulapp.constants.Constants.POST_ICON_REQUEST_TYPES.FORUM_POST; import static com.ferg.awfulapp.constants.Constants.POST_ICON_REQUEST_TYPES.PM; @@ -64,7 +60,6 @@ public class ThreadIconPicker extends Fragment { private static final int PM_FORUM_ID = -324546; private static final SparseArray> iconsCache = new SparseArray<>(); - @BindView(R.id.selected_icon) ImageView selectedIconView; private AwfulPostIcon currentIcon = BLANK_ICON; @Nullable @@ -75,7 +70,20 @@ public class ThreadIconPicker extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.icon_picker, container, true); - ButterKnife.bind(this, view); + selectedIconView = view.findViewById(R.id.selected_icon); + selectedIconView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + showPicker(); + } + }); + selectedIconView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + secretForumCycler(); + return true; + } + }); return view; } @@ -118,7 +126,6 @@ public void usePrivateMessageIcons() { * If an icon source hasn't been selected through {@link #useForumIcons(int)} or * {@link #usePrivateMessageIcons()}, this will do nothing. */ - @OnClick(R.id.selected_icon) public void showPicker() { if (currentForumId == null) { Log.w(TAG, "The user tried to select an icon before a source forum was set!\nYou should prevent this or initialise with one"); @@ -227,7 +234,6 @@ private Menu generatePostIconMenu(@NonNull List postIcons) { Iterator allTheForums = null; - @OnLongClick(R.id.selected_icon) public boolean secretForumCycler() { if (allTheForums == null || !allTheForums.hasNext()) { ForumRepository repo = ForumRepository.getInstance(getContext()); diff --git a/Awful.apk/src/main/res/layout/forum_index_item.xml b/Awful.apk/src/main/res/layout/forum_index_item.xml index d4b9d9bb6..ca80f872d 100644 --- a/Awful.apk/src/main/res/layout/forum_index_item.xml +++ b/Awful.apk/src/main/res/layout/forum_index_item.xml @@ -44,10 +44,10 @@ android:scaleType="fitCenter" android:scaleX="1.3" android:scaleY="1.3" - android:tint="?primaryPostFontColor" android:visibility="visible" app:srcCompat="@drawable/ic_expand_more" - tools:ignore="MissingPrefix" /> + tools:ignore="MissingPrefix" + app:tint="?primaryPostFontColor" /> diff --git a/Awful.apk/src/main/res/layout/private_message_activity.xml b/Awful.apk/src/main/res/layout/private_message_activity.xml index 212431e94..0be382d84 100644 --- a/Awful.apk/src/main/res/layout/private_message_activity.xml +++ b/Awful.apk/src/main/res/layout/private_message_activity.xml @@ -1,6 +1,7 @@ + tools:ignore="ContentDescription" + app:tint="?attr/secondaryPostFontColor" /> + tools:visibility="visible" + app:tint="?attr/iconColorDark" /> diff --git a/README.md b/README.md index 3744736d7..77d15d19c 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,7 @@ Or take a look at [our issues][issues] and set up your own fork to quash some bu 2. [Fork Awful.apk on Github][github-fork-howto]. 3. Download your fork's Git repository and open the project in Android Studio. * Quick way: from the welcome screen, choose `Get from VCS` and enter the Github URL for your new fork. -4. Create your own `google-services.json`. - 1. [Create your own Firebase project][firebase-console] for Awful. - 2. Add an Android app to your Firebase project. - 3. For Android package name, enter `com.ferg.awfulapp.debug`. - 4. Download the `google-services.json` config file. - 5. Place `google-services.json` in the inner `/Awful.apk/` folder. -5. __(Optional)__ If you'd like to be able to upload images to Imgur: +4. __(Optional)__ If you'd like to be able to upload images to Imgur: 1. [Register a new application for the Imgur API][imgur-api-docs]. 2. Create the file [`secrets.xml`][secrets-example] in `/Awful.apk/src/main/res/values/`. 3. Place the client ID in `secrets.xml`, like so: diff --git a/build.gradle b/build.gradle index 495c5038e..589c9043f 100644 --- a/build.gradle +++ b/build.gradle @@ -1 +1,20 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + ext { + agp_version = '8.2.0' + } + repositories { + google() + jcenter() + maven { url 'https://jitpack.io' } + } + dependencies { + classpath "com.android.tools.build:gradle:$agp_version" + } +} +plugins { + id 'com.android.application' version '8.2.0' apply false + id 'com.android.library' version '8.2.0' apply false + id 'org.jetbrains.kotlin.android' version '1.9.21' apply false + id 'com.google.devtools.ksp' version '1.9.21-1.0.15' +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 72849b52a..f1d85932f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,5 @@ org.gradle.jvmargs=-Xmx2048m org.gradle.caching=true android.useAndroidX=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +android.nonFinalResIds = false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7e5645e7d..cadc0ed7c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sun Dec 17 12:34:58 CET 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index f89cea603..2302aa9a5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,16 @@ +pluginManagement { + repositories { + gradlePluginPortal() + google() + maven { url 'https://jitpack.io' } + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} include ':Awful.apk'