diff options
author | H. Lehmann <ByteHamster@users.noreply.github.com> | 2019-10-02 15:46:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-02 15:46:29 +0200 |
commit | f9fd9c32827dee1e45505d9edcee74aba525cd97 (patch) | |
tree | 68ff29feb9f39428f5a83c8ca0b79a3abb419a50 /app | |
parent | 8f5ff42f6a1a1a7d47e6c25bf9cc11e4b44b86f7 (diff) | |
parent | 6967e9c8902b789079c7dee6a78d835410716d60 (diff) | |
download | AntennaPod-f9fd9c32827dee1e45505d9edcee74aba525cd97.zip |
Merge pull request #3426 from ByteHamster/feedinfo-fragment
Feedinfo page animation
Diffstat (limited to 'app')
15 files changed, 435 insertions, 450 deletions
diff --git a/app/build.gradle b/app/build.gradle index 3996d7ba5..0fdfd153e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -139,10 +139,6 @@ dependencies { implementation "com.android.support:recyclerview-v7:$supportVersion" compileOnly 'com.google.android.wearable:wearable:2.2.0' - // ViewModel and LiveData - implementation "android.arch.lifecycle:extensions:$lifecycle_version" - annotationProcessor "android.arch.lifecycle:compiler:$lifecycle_version" - implementation "org.apache.commons:commons-lang3:$commonslangVersion" implementation "commons-io:commons-io:$commonsioVersion" implementation "org.jsoup:jsoup:$jsoupVersion" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index aa9dc96c4..bfef37f71 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -105,17 +105,6 @@ android:value="de.danoeh.antennapod.activity.MainActivity"/> </activity> - <activity - android:name=".activity.FeedInfoActivity" - android:label="@string/feed_info_label"> - </activity> - - <activity - android:name=".activity.FeedSettingsActivity" - android:windowSoftInputMode="stateHidden" - android:label="@string/feed_settings_label"> - </activity> - <service android:name=".core.service.PlayerWidgetJobService" android:permission="android.permission.BIND_JOB_SERVICE" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java deleted file mode 100644 index 26e360bd3..000000000 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java +++ /dev/null @@ -1,225 +0,0 @@ -package de.danoeh.antennapod.activity; - -import android.content.ClipData; -import android.content.Context; -import android.content.Intent; -import android.graphics.LightingColorFilter; -import android.net.Uri; -import android.os.Bundle; -import android.support.v7.app.AppCompatActivity; -import android.text.TextUtils; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; -import com.joanzapata.iconify.Iconify; - -import org.apache.commons.lang3.StringUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.glide.FastBlurTransformation; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DownloadRequestException; -import de.danoeh.antennapod.core.util.IntentUtils; -import de.danoeh.antennapod.core.util.LangUtils; -import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; -import de.danoeh.antennapod.menuhandler.FeedMenuHandler; -import io.reactivex.Maybe; -import io.reactivex.MaybeOnSubscribe; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -/** - * Displays information about a feed. - */ -public class FeedInfoActivity extends AppCompatActivity { - - public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; - private static final String TAG = "FeedInfoActivity"; - private Feed feed; - - private ImageView imgvCover; - private TextView txtvTitle; - private TextView txtvDescription; - private TextView lblLanguage; - private TextView txtvLanguage; - private TextView lblAuthor; - private TextView txtvAuthor; - private TextView txtvUrl; - - private Disposable disposable; - - - private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { - @Override - public void onClick(View v) { - if(feed != null && feed.getDownload_url() != null) { - String url = feed.getDownload_url(); - ClipData clipData = ClipData.newPlainText(url, url); - android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this - .getSystemService(Context.CLIPBOARD_SERVICE); - cm.setPrimaryClip(clipData); - Toast t = Toast.makeText(FeedInfoActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT); - t.show(); - } - } - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - setTheme(UserPreferences.getTheme()); - super.onCreate(savedInstanceState); - setContentView(R.layout.feedinfo); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1); - - imgvCover = findViewById(R.id.imgvCover); - txtvTitle = findViewById(R.id.txtvTitle); - TextView txtvAuthorHeader = findViewById(R.id.txtvAuthor); - ImageView imgvBackground = findViewById(R.id.imgvBackground); - findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); - findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); - // https://github.com/bumptech/glide/issues/529 - imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); - - - txtvDescription = findViewById(R.id.txtvDescription); - lblLanguage = findViewById(R.id.lblLanguage); - txtvLanguage = findViewById(R.id.txtvLanguage); - lblAuthor = findViewById(R.id.lblAuthor); - txtvAuthor = findViewById(R.id.txtvDetailsAuthor); - txtvUrl = findViewById(R.id.txtvUrl); - - txtvUrl.setOnClickListener(copyUrlToClipboard); - - disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> { - Feed feed = DBReader.getFeed(feedId); - if (feed != null) { - emitter.onSuccess(feed); - } else { - emitter.onComplete(); - } - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - feed = result; - Log.d(TAG, "Language is " + feed.getLanguage()); - Log.d(TAG, "Author is " + feed.getAuthor()); - Log.d(TAG, "URL is " + feed.getDownload_url()); - Glide.with(FeedInfoActivity.this) - .load(feed.getImageLocation()) - .apply(new RequestOptions() - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate()) - .into(imgvCover); - Glide.with(FeedInfoActivity.this) - .load(feed.getImageLocation()) - .apply(new RequestOptions() - .placeholder(R.color.image_readability_tint) - .error(R.color.image_readability_tint) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .transform(new FastBlurTransformation()) - .dontAnimate()) - .into(imgvBackground); - - txtvTitle.setText(feed.getTitle()); - - String description = feed.getDescription(); - if(description != null) { - if(Feed.TYPE_ATOM1.equals(feed.getType())) { - HtmlToPlainText formatter = new HtmlToPlainText(); - Document feedDescription = Jsoup.parse(feed.getDescription()); - description = StringUtils.trim(formatter.getPlainText(feedDescription)); - } - } else { - description = ""; - } - txtvDescription.setText(description); - - if (!TextUtils.isEmpty(feed.getAuthor())) { - txtvAuthor.setText(feed.getAuthor()); - txtvAuthorHeader.setText(feed.getAuthor()); - } else { - lblAuthor.setVisibility(View.GONE); - txtvAuthor.setVisibility(View.GONE); - } - if (!TextUtils.isEmpty(feed.getLanguage())) { - txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage())); - } else { - lblLanguage.setVisibility(View.GONE); - txtvLanguage.setVisibility(View.GONE); - } - txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}"); - Iconify.addIcons(txtvUrl); - - supportInvalidateOptionsMenu(); - }, error -> { - Log.d(TAG, Log.getStackTraceString(error)); - finish(); - }, () -> { - Log.e(TAG, "Activity was started with invalid arguments"); - finish(); - }); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (disposable != null) { - disposable.dispose(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.feedinfo, menu); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null); - menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null && - IntentUtils.isCallable(this, new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink())))); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - try { - return FeedMenuHandler.onOptionsItemClicked(this, item, feed); - } catch (DownloadRequestException e) { - e.printStackTrace(); - DownloadRequestErrorDialogCreator.newRequestErrorDialog(this, - e.getMessage()); - } - return super.onOptionsItemSelected(item); - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java deleted file mode 100644 index fbd19f88a..000000000 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java +++ /dev/null @@ -1,130 +0,0 @@ -package de.danoeh.antennapod.activity; - -import android.arch.lifecycle.ViewModelProviders; -import android.graphics.LightingColorFilter; -import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentTransaction; -import android.support.v7.app.AppCompatActivity; -import android.text.TextUtils; -import android.util.Log; -import android.view.MenuItem; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.glide.FastBlurTransformation; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.fragment.FeedSettingsFragment; -import de.danoeh.antennapod.viewmodel.FeedSettingsViewModel; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -/** - * Displays information about a feed. - */ -public class FeedSettingsActivity extends AppCompatActivity { - public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; - private static final String TAG = "FeedSettingsActivity"; - private Feed feed; - private Disposable disposable; - private ImageView imgvCover; - private TextView txtvTitle; - private ImageView imgvBackground; - private TextView txtvAuthorHeader; - - @Override - protected void onCreate(Bundle savedInstanceState) { - setTheme(UserPreferences.getTheme()); - super.onCreate(savedInstanceState); - setContentView(R.layout.feedsettings); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - imgvCover = findViewById(R.id.imgvCover); - txtvTitle = findViewById(R.id.txtvTitle); - txtvAuthorHeader = findViewById(R.id.txtvAuthor); - imgvBackground = findViewById(R.id.imgvBackground); - findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); - findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); - // https://github.com/bumptech/glide/issues/529 - imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); - - long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1); - disposable = ViewModelProviders.of(this).get(FeedSettingsViewModel.class).getFeed(feedId) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - feed = result; - showFragment(); - showHeader(); - }, error -> { - Log.d(TAG, Log.getStackTraceString(error)); - finish(); - }, () -> { - Log.e(TAG, "Activity was started with invalid arguments"); - finish(); - }); - } - - private void showFragment() { - FeedSettingsFragment fragment = new FeedSettingsFragment(); - fragment.setArguments(getIntent().getExtras()); - - FragmentManager fragmentManager = getSupportFragmentManager(); - FragmentTransaction fragmentTransaction = - fragmentManager.beginTransaction(); - fragmentTransaction.replace(R.id.settings_fragment_container, fragment); - fragmentTransaction.commit(); - } - - private void showHeader() { - txtvTitle.setText(feed.getTitle()); - - if (!TextUtils.isEmpty(feed.getAuthor())) { - txtvAuthorHeader.setText(feed.getAuthor()); - } - - Glide.with(FeedSettingsActivity.this) - .load(feed.getImageLocation()) - .apply(new RequestOptions() - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate()) - .into(imgvCover); - Glide.with(FeedSettingsActivity.this) - .load(feed.getImageLocation()) - .apply(new RequestOptions() - .placeholder(R.color.image_readability_tint) - .error(R.color.image_readability_tint) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .transform(new FastBlurTransformation()) - .dontAnimate()) - .into(imgvBackground); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (disposable != null) { - disposable.dispose(); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - finish(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index b028f7983..b778fe77e 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -69,6 +69,7 @@ import de.danoeh.antennapod.fragment.FeedItemlistFragment; import de.danoeh.antennapod.fragment.PlaybackHistoryFragment; import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; +import de.danoeh.antennapod.fragment.TransitionEffect; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; import de.danoeh.antennapod.preferences.PreferenceUpgrader; import io.reactivex.Observable; @@ -377,15 +378,34 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi } } - public void loadChildFragment(Fragment fragment) { + public void loadChildFragment(Fragment fragment, TransitionEffect transition) { Validate.notNull(fragment); - FragmentManager fm = getSupportFragmentManager(); - fm.beginTransaction() - .replace(R.id.main_view, fragment, "main") + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + switch (transition) { + case FADE: + transaction.setCustomAnimations(R.anim.fade_in, R.anim.fade_out); + break; + case FLIP: + transaction.setCustomAnimations( + R.anim.card_flip_left_in, + R.anim.card_flip_left_out, + R.anim.card_flip_right_in, + R.anim.card_flip_right_out); + break; + } + + transaction + .hide(getSupportFragmentManager().findFragmentByTag("main")) + .add(R.id.main_view, fragment, "main") .addToBackStack(null) .commit(); } + public void loadChildFragment(Fragment fragment) { + loadChildFragment(fragment, TransitionEffect.NONE); + } + public void dismissChildFragment() { getSupportFragmentManager().popBackStack(); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java new file mode 100644 index 000000000..a1df6c428 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java @@ -0,0 +1,234 @@ +package de.danoeh.antennapod.fragment; + +import android.content.ClipData; +import android.content.Context; +import android.content.Intent; +import android.graphics.LightingColorFilter; +import android.net.Uri; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.text.TextUtils; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.joanzapata.iconify.Iconify; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.glide.ApGlideSettings; +import de.danoeh.antennapod.core.glide.FastBlurTransformation; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DownloadRequestException; +import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.core.util.LangUtils; +import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; +import de.danoeh.antennapod.menuhandler.FeedMenuHandler; +import io.reactivex.Maybe; +import io.reactivex.MaybeOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; +import org.apache.commons.lang3.StringUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; + +/** + * Displays information about a feed. + */ +public class FeedInfoFragment extends Fragment { + + private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; + private static final String TAG = "FeedInfoActivity"; + + private Feed feed; + private Disposable disposable; + private ImageView imgvCover; + private TextView txtvTitle; + private TextView txtvDescription; + private TextView lblLanguage; + private TextView txtvLanguage; + private TextView lblAuthor; + private TextView txtvAuthor; + private TextView txtvUrl; + private TextView txtvAuthorHeader; + private ImageView imgvBackground; + + public static FeedInfoFragment newInstance(Feed feed) { + FeedInfoFragment fragment = new FeedInfoFragment(); + Bundle arguments = new Bundle(); + arguments.putLong(EXTRA_FEED_ID, feed.getId()); + fragment.setArguments(arguments); + return fragment; + } + + private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { + @Override + public void onClick(View v) { + if(feed != null && feed.getDownload_url() != null) { + String url = feed.getDownload_url(); + ClipData clipData = ClipData.newPlainText(url, url); + android.content.ClipboardManager cm = (android.content.ClipboardManager) getContext() + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(clipData); + Toast t = Toast.makeText(getContext(), R.string.copied_url_msg, Toast.LENGTH_SHORT); + t.show(); + } + } + }; + + @Override + public void onResume() { + super.onResume(); + ((MainActivity)getActivity()).getSupportActionBar().setTitle(R.string.feed_info_label); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.feedinfo, null); + setHasOptionsMenu(true); + + imgvCover = root.findViewById(R.id.imgvCover); + txtvTitle = root.findViewById(R.id.txtvTitle); + txtvAuthorHeader = root.findViewById(R.id.txtvAuthor); + imgvBackground = root.findViewById(R.id.imgvBackground); + root.findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); + root.findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); + // https://github.com/bumptech/glide/issues/529 + imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); + + + txtvDescription = root.findViewById(R.id.txtvDescription); + lblLanguage = root.findViewById(R.id.lblLanguage); + txtvLanguage = root.findViewById(R.id.txtvLanguage); + lblAuthor = root.findViewById(R.id.lblAuthor); + txtvAuthor = root.findViewById(R.id.txtvDetailsAuthor); + txtvUrl = root.findViewById(R.id.txtvUrl); + + txtvUrl.setOnClickListener(copyUrlToClipboard); + postponeEnterTransition(); + return root; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + long feedId = getArguments().getLong(EXTRA_FEED_ID); + disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> { + Feed feed = DBReader.getFeed(feedId); + if (feed != null) { + emitter.onSuccess(feed); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + feed = result; + showFeed(); + }, error -> Log.d(TAG, Log.getStackTraceString(error)), + this::startPostponedEnterTransition); + } + + private void showFeed() { + Log.d(TAG, "Language is " + feed.getLanguage()); + Log.d(TAG, "Author is " + feed.getAuthor()); + Log.d(TAG, "URL is " + feed.getDownload_url()); + Glide.with(getContext()) + .load(feed.getImageLocation()) + .apply(new RequestOptions() + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate()) + .into(imgvCover); + Glide.with(getContext()) + .load(feed.getImageLocation()) + .apply(new RequestOptions() + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation()) + .dontAnimate()) + .into(imgvBackground); + + txtvTitle.setText(feed.getTitle()); + + String description = feed.getDescription(); + if(description != null) { + if(Feed.TYPE_ATOM1.equals(feed.getType())) { + HtmlToPlainText formatter = new HtmlToPlainText(); + Document feedDescription = Jsoup.parse(feed.getDescription()); + description = StringUtils.trim(formatter.getPlainText(feedDescription)); + } + } else { + description = ""; + } + txtvDescription.setText(description); + + if (!TextUtils.isEmpty(feed.getAuthor())) { + txtvAuthor.setText(feed.getAuthor()); + txtvAuthorHeader.setText(feed.getAuthor()); + } else { + lblAuthor.setVisibility(View.GONE); + txtvAuthor.setVisibility(View.GONE); + } + if (!TextUtils.isEmpty(feed.getLanguage())) { + txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage())); + } else { + lblLanguage.setVisibility(View.GONE); + txtvLanguage.setVisibility(View.GONE); + } + txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}"); + Iconify.addIcons(txtvUrl); + + getActivity().invalidateOptionsMenu(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (disposable != null) { + disposable.dispose(); + } + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.feedinfo, menu); + } + + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null); + menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null && + IntentUtils.isCallable(getContext(), new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink())))); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + boolean handled = false; + try { + handled = FeedMenuHandler.onOptionsItemClicked(getContext(), item, feed); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(getContext(), e.getMessage()); + } + return handled || super.onOptionsItemSelected(item); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java index 8fe0883b2..745404aeb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedItemlistFragment.java @@ -38,8 +38,6 @@ import org.greenrobot.eventbus.ThreadMode; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.FeedInfoActivity; -import de.danoeh.antennapod.activity.FeedSettingsActivity; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.FeedItemlistAdapter; import de.danoeh.antennapod.core.asynctask.FeedRemover; @@ -141,37 +139,33 @@ public class FeedItemlistFragment extends ListFragment { } @Override - public void onStart() { - super.onStart(); + public void onHiddenChanged(boolean hidden) { + super.onHiddenChanged(hidden); + if (!hidden && getActivity() != null) { + ((MainActivity) getActivity()).getSupportActionBar().setTitle(""); + } + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + registerForContextMenu(getListView()); + EventDistributor.getInstance().register(contentUpdate); EventBus.getDefault().register(this); loadItems(); } @Override - public void onResume() { - super.onResume(); - ((MainActivity)getActivity()).getSupportActionBar().setTitle(""); - updateProgressBarVisibility(); - } + public void onDestroyView() { + super.onDestroyView(); - @Override - public void onStop() { - super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); EventBus.getDefault().unregister(this); - if(disposable != null) { + if (disposable != null) { disposable.dispose(); } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - resetViewState(); - } - - private void resetViewState() { adapter = null; listFooter = null; } @@ -345,13 +339,6 @@ public class FeedItemlistFragment extends ListFragment { } @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - registerForContextMenu(getListView()); - } - - @Override public void onListItemClick(ListView l, View v, int position, long id) { if(adapter == null) { return; @@ -429,8 +416,9 @@ public class FeedItemlistFragment extends ListFragment { } - private void onFragmentLoaded() { - if(!isVisible()) { + private void displayList() { + if (getView() == null) { + Log.e(TAG, "Required root view is not yet created. Stop binding data to UI."); return; } if (adapter == null) { @@ -514,10 +502,8 @@ public class FeedItemlistFragment extends ListFragment { imgvCover.setOnClickListener(v -> showFeedInfo()); butShowSettings.setOnClickListener(v -> { if (feed != null) { - Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class); - startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID, - feed.getId()); - startActivity(startIntent); + FeedSettingsFragment fragment = FeedSettingsFragment.newInstance(feed); + ((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.FLIP); } }); headerCreated = true; @@ -525,10 +511,8 @@ public class FeedItemlistFragment extends ListFragment { private void showFeedInfo() { if (feed != null) { - Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); - startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, - feed.getId()); - startActivity(startIntent); + FeedInfoFragment fragment = FeedInfoFragment.newInstance(feed); + ((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.FLIP); } } @@ -634,7 +618,7 @@ public class FeedItemlistFragment extends ListFragment { .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { feed = result.orElse(null); - onFragmentLoaded(); + displayList(); }, error -> Log.e(TAG, Log.getStackTraceString(error))); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java index 4fb3d90f5..f9564336d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java @@ -1,39 +1,66 @@ package de.danoeh.antennapod.fragment; -import android.arch.lifecycle.ViewModelProviders; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.ListPreference; import android.support.v7.preference.PreferenceFragmentCompat; +import android.util.Log; import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedFilter; import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.dialog.AuthenticationDialog; import de.danoeh.antennapod.dialog.EpisodeFilterDialog; -import de.danoeh.antennapod.viewmodel.FeedSettingsViewModel; - -import static de.danoeh.antennapod.activity.FeedSettingsActivity.EXTRA_FEED_ID; +import io.reactivex.Maybe; +import io.reactivex.MaybeOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.schedulers.Schedulers; public class FeedSettingsFragment extends PreferenceFragmentCompat { private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter"; + private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; + private static final String TAG = "FeedSettingsFragment"; + private Feed feed; + private Disposable disposable; private FeedPreferences feedPreferences; + public static FeedSettingsFragment newInstance(Feed feed) { + FeedSettingsFragment fragment = new FeedSettingsFragment(); + Bundle arguments = new Bundle(); + arguments.putLong(EXTRA_FEED_ID, feed.getId()); + fragment.setArguments(arguments); + return fragment; + } + @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.feed_settings); + postponeEnterTransition(); long feedId = getArguments().getLong(EXTRA_FEED_ID); - ViewModelProviders.of(getActivity()).get(FeedSettingsViewModel.class).getFeed(feedId) + disposable = Maybe.create((MaybeOnSubscribe<Feed>) emitter -> { + Feed feed = DBReader.getFeed(feedId); + if (feed != null) { + emitter.onSuccess(feed); + } else { + emitter.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { feed = result; feedPreferences = feed.getPreferences(); + ((MainActivity) getActivity()).getSupportActionBar().setSubtitle(feed.getTitle()); setupAutoDownloadPreference(); setupKeepUpdatedPreference(); @@ -43,7 +70,31 @@ public class FeedSettingsFragment extends PreferenceFragmentCompat { updateAutoDeleteSummary(); updateAutoDownloadEnabled(); - }).dispose(); + }, error -> Log.d(TAG, Log.getStackTraceString(error)), + this::startPostponedEnterTransition); + } + + @Override + public void onResume() { + super.onResume(); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.feed_settings_label); + if (feed != null) { + ((MainActivity) getActivity()).getSupportActionBar().setSubtitle(feed.getTitle()); + } + } + + @Override + public void onStop() { + super.onStop(); + ((MainActivity) getActivity()).getSupportActionBar().setSubtitle(null); + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (disposable != null) { + disposable.dispose(); + } } private void setupEpisodeFilterPreference() { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/TransitionEffect.java b/app/src/main/java/de/danoeh/antennapod/fragment/TransitionEffect.java new file mode 100644 index 000000000..461fa9da3 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/TransitionEffect.java @@ -0,0 +1,5 @@ +package de.danoeh.antennapod.fragment; + +public enum TransitionEffect { + NONE, FLIP, FADE +} diff --git a/app/src/main/java/de/danoeh/antennapod/viewmodel/FeedSettingsViewModel.java b/app/src/main/java/de/danoeh/antennapod/viewmodel/FeedSettingsViewModel.java deleted file mode 100644 index fe11a645c..000000000 --- a/app/src/main/java/de/danoeh/antennapod/viewmodel/FeedSettingsViewModel.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.danoeh.antennapod.viewmodel; - -import android.arch.lifecycle.ViewModel; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.storage.DBReader; -import io.reactivex.Maybe; - -public class FeedSettingsViewModel extends ViewModel { - private Feed feed; - - public Maybe<Feed> getFeed(long feedId) { - if (feed == null) { - return loadFeed(feedId); - } else { - return Maybe.just(feed); - } - } - - private Maybe<Feed> loadFeed(long feedId) { - return Maybe.create(emitter -> { - Feed feed = DBReader.getFeed(feedId); - if (feed != null) { - this.feed = feed; - emitter.onSuccess(feed); - } else { - emitter.onComplete(); - } - }); - } -} diff --git a/app/src/main/res/anim/card_flip_left_in.xml b/app/src/main/res/anim/card_flip_left_in.xml new file mode 100644 index 000000000..0ffc85aec --- /dev/null +++ b/app/src/main/res/anim/card_flip_left_in.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Before rotating, immediately set the alpha to 0. --> + <objectAnimator + android:valueFrom="1.0" + android:valueTo="0.0" + android:propertyName="alpha" + android:duration="0" /> + + <!-- Rotate. --> + <objectAnimator + android:valueFrom="-180" + android:valueTo="0" + android:propertyName="rotationY" + android:interpolator="@android:interpolator/accelerate_decelerate" + android:duration="@integer/card_flip_time_full" /> + + <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> + <objectAnimator + android:valueFrom="0.0" + android:valueTo="1.0" + android:propertyName="alpha" + android:startOffset="@integer/card_flip_time_half" + android:duration="1" /> +</set>
\ No newline at end of file diff --git a/app/src/main/res/anim/card_flip_left_out.xml b/app/src/main/res/anim/card_flip_left_out.xml new file mode 100644 index 000000000..817f0d3fc --- /dev/null +++ b/app/src/main/res/anim/card_flip_left_out.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Rotate. --> + <objectAnimator + android:valueFrom="0" + android:valueTo="180" + android:propertyName="rotationY" + android:interpolator="@android:interpolator/accelerate_decelerate" + android:duration="@integer/card_flip_time_full" /> + + <!-- Half-way through the rotation (see startOffset), set the alpha to 0. --> + <objectAnimator + android:valueFrom="1.0" + android:valueTo="0.0" + android:propertyName="alpha" + android:startOffset="@integer/card_flip_time_half" + android:duration="1" /> +</set>
\ No newline at end of file diff --git a/app/src/main/res/anim/card_flip_right_in.xml b/app/src/main/res/anim/card_flip_right_in.xml new file mode 100644 index 000000000..31ff1dde5 --- /dev/null +++ b/app/src/main/res/anim/card_flip_right_in.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Before rotating, immediately set the alpha to 0. --> + <objectAnimator + android:valueFrom="1.0" + android:valueTo="0.0" + android:propertyName="alpha" + android:duration="0" /> + + <!-- Rotate. --> + <objectAnimator + android:valueFrom="180" + android:valueTo="0" + android:propertyName="rotationY" + android:interpolator="@android:interpolator/accelerate_decelerate" + android:duration="@integer/card_flip_time_full" /> + + <!-- Half-way through the rotation (see startOffset), set the alpha to 1. --> + <objectAnimator + android:valueFrom="0.0" + android:valueTo="1.0" + android:propertyName="alpha" + android:startOffset="@integer/card_flip_time_half" + android:duration="1" /> +</set>
\ No newline at end of file diff --git a/app/src/main/res/anim/card_flip_right_out.xml b/app/src/main/res/anim/card_flip_right_out.xml new file mode 100644 index 000000000..b57113fea --- /dev/null +++ b/app/src/main/res/anim/card_flip_right_out.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<set xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Rotate. --> + <objectAnimator + android:valueFrom="0" + android:valueTo="-180" + android:propertyName="rotationY" + android:interpolator="@android:interpolator/accelerate_decelerate" + android:duration="@integer/card_flip_time_full" /> + + <!-- Half-way through the rotation (see startOffset), set the alpha to 0. --> + <objectAnimator + android:valueFrom="1.0" + android:valueTo="0.0" + android:propertyName="alpha" + android:startOffset="@integer/card_flip_time_half" + android:duration="1" /> +</set>
\ No newline at end of file diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 000000000..8c444ee8b --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <integer name="card_flip_time_full">400</integer> + <integer name="card_flip_time_half">200</integer> +</resources>
\ No newline at end of file |