mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-19 22:39:18 +01:00
Store total chapters from MAL and automatically set as completed if it's the last chapter. Other minor changes
This commit is contained in:
parent
f26a60f1ba
commit
f9a97631f2
@ -110,6 +110,7 @@ public class MyAnimeList extends MangaSyncService {
|
|||||||
MangaSync manga = MangaSync.create(this);
|
MangaSync manga = MangaSync.create(this);
|
||||||
manga.title = entry.select("title").first().text();
|
manga.title = entry.select("title").first().text();
|
||||||
manga.remote_id = Integer.parseInt(entry.select("id").first().text());
|
manga.remote_id = Integer.parseInt(entry.select("id").first().text());
|
||||||
|
manga.total_chapters = Integer.parseInt(entry.select("chapters").first().text());
|
||||||
return manga;
|
return manga;
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
@ -141,6 +142,8 @@ public class MyAnimeList extends MangaSyncService {
|
|||||||
// MAL doesn't support score with decimals
|
// MAL doesn't support score with decimals
|
||||||
manga.score = Integer.parseInt(
|
manga.score = Integer.parseInt(
|
||||||
entry.select("my_score").first().text());
|
entry.select("my_score").first().text());
|
||||||
|
manga.total_chapters = Integer.parseInt(
|
||||||
|
entry.select("series_chapters").first().text());
|
||||||
return manga;
|
return manga;
|
||||||
})
|
})
|
||||||
.toList();
|
.toList();
|
||||||
@ -155,6 +158,9 @@ public class MyAnimeList extends MangaSyncService {
|
|||||||
|
|
||||||
public Observable<Response> update(MangaSync manga) {
|
public Observable<Response> update(MangaSync manga) {
|
||||||
try {
|
try {
|
||||||
|
if (manga.total_chapters != 0 && manga.last_chapter_read == manga.total_chapters) {
|
||||||
|
manga.status = COMPLETED;
|
||||||
|
}
|
||||||
RequestBody payload = getMangaPostPayload(manga);
|
RequestBody payload = getMangaPostPayload(manga);
|
||||||
return networkService.postData(getUpdateUrl(manga), payload, headers);
|
return networkService.postData(getUpdateUrl(manga), payload, headers);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -81,10 +81,15 @@ public class LibraryFragment extends BaseRxFragment<LibraryPresenter>
|
|||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
appBar.removeView(tabs);
|
appBar.removeView(tabs);
|
||||||
EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class);
|
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
EventBus.getDefault().removeStickyEvent(LibraryMangasEvent.class);
|
||||||
|
super.onPause();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle bundle) {
|
public void onSaveInstanceState(Bundle bundle) {
|
||||||
activeCategory = viewPager.getCurrentItem();
|
activeCategory = viewPager.getCurrentItem();
|
||||||
|
@ -2,21 +2,29 @@ package eu.kanade.mangafeed.ui.manga.myanimelist;
|
|||||||
|
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.text.Editable;
|
||||||
import android.view.LayoutInflater;
|
import android.text.TextUtils;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
|
import rx.Subscription;
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.subjects.PublishSubject;
|
||||||
import uk.co.ribot.easyadapter.EasyAdapter;
|
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||||
import uk.co.ribot.easyadapter.ItemViewHolder;
|
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||||
import uk.co.ribot.easyadapter.PositionInfo;
|
import uk.co.ribot.easyadapter.PositionInfo;
|
||||||
@ -26,61 +34,108 @@ import uk.co.ribot.easyadapter.annotations.ViewId;
|
|||||||
public class MyAnimeListDialogFragment extends DialogFragment {
|
public class MyAnimeListDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
@Bind(R.id.myanimelist_search_field) EditText searchText;
|
@Bind(R.id.myanimelist_search_field) EditText searchText;
|
||||||
@Bind(R.id.myanimelist_search_button) Button searchButton;
|
|
||||||
@Bind(R.id.myanimelist_search_results) ListView searchResults;
|
@Bind(R.id.myanimelist_search_results) ListView searchResults;
|
||||||
|
@Bind(R.id.progress) ProgressBar progressBar;
|
||||||
|
|
||||||
private EasyAdapter<MangaSync> adapter;
|
private EasyAdapter<MangaSync> adapter;
|
||||||
private MyAnimeListFragment fragment;
|
|
||||||
private MyAnimeListPresenter presenter;
|
|
||||||
private MangaSync selectedItem;
|
private MangaSync selectedItem;
|
||||||
|
|
||||||
public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) {
|
private Subscription searchSubscription;
|
||||||
MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment();
|
|
||||||
dialog.fragment = parentFragment;
|
public static MyAnimeListDialogFragment newInstance() {
|
||||||
dialog.presenter = parentFragment.getPresenter();
|
return new MyAnimeListDialogFragment();
|
||||||
return dialog;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedState) {
|
public Dialog onCreateDialog(Bundle savedState) {
|
||||||
// Inflate and bind view
|
MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
|
||||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
.customView(R.layout.dialog_myanimelist_search, false)
|
||||||
View view = inflater.inflate(R.layout.dialog_myanimelist_search, null);
|
.positiveText(R.string.button_ok)
|
||||||
ButterKnife.bind(this, view);
|
.negativeText(R.string.button_cancel)
|
||||||
|
.onPositive((dialog1, which) -> onPositiveButtonClick())
|
||||||
|
.build();
|
||||||
|
|
||||||
// Build dialog
|
ButterKnife.bind(this, dialog.getView());
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
|
||||||
builder.setView(view)
|
|
||||||
.setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick())
|
|
||||||
.setNegativeButton(R.string.button_cancel, (dialog, which) -> {});
|
|
||||||
|
|
||||||
// Create adapter
|
// Create adapter
|
||||||
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
|
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
|
||||||
searchResults.setAdapter(adapter);
|
searchResults.setAdapter(adapter);
|
||||||
|
|
||||||
// Set listeners
|
// Set listeners
|
||||||
searchButton.setOnClickListener(v ->
|
|
||||||
presenter.searchManga(searchText.getText().toString()));
|
|
||||||
|
|
||||||
searchResults.setOnItemClickListener((parent, viewList, position, id) ->
|
searchResults.setOnItemClickListener((parent, viewList, position, id) ->
|
||||||
selectedItem = adapter.getItem(position));
|
selectedItem = adapter.getItem(position));
|
||||||
|
|
||||||
// Do an initial search based on the manga's title
|
// Do an initial search based on the manga's title
|
||||||
presenter.searchManga(presenter.manga.title);
|
if (savedState == null) {
|
||||||
return builder.create();
|
String title = getPresenter().manga.title;
|
||||||
|
searchText.append(title);
|
||||||
|
search(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
PublishSubject<String> querySubject = PublishSubject.create();
|
||||||
|
searchText.addTextChangedListener(new SimpleTextChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
querySubject.onNext(s.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen to text changes
|
||||||
|
searchSubscription = querySubject.debounce(1, TimeUnit.SECONDS)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(this::search);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPause() {
|
||||||
|
if (searchSubscription != null) {
|
||||||
|
searchSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
super.onPause();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPositiveButtonClick() {
|
private void onPositiveButtonClick() {
|
||||||
if (adapter != null && selectedItem != null) {
|
if (adapter != null && selectedItem != null) {
|
||||||
presenter.registerManga(selectedItem);
|
getPresenter().registerManga(selectedItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResults(List<MangaSync> results) {
|
private void search(String query) {
|
||||||
|
if (!TextUtils.isEmpty(query)) {
|
||||||
|
searchResults.setVisibility(View.GONE);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
getPresenter().searchManga(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSearchResults(List<MangaSync> results) {
|
||||||
selectedItem = null;
|
selectedItem = null;
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
searchResults.setVisibility(View.VISIBLE);
|
||||||
adapter.setItems(results);
|
adapter.setItems(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onSearchResultsError() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
searchResults.setVisibility(View.VISIBLE);
|
||||||
|
adapter.getItems().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyAnimeListFragment getMALFragment() {
|
||||||
|
return (MyAnimeListFragment) getParentFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyAnimeListPresenter getPresenter() {
|
||||||
|
return getMALFragment().getPresenter();
|
||||||
|
}
|
||||||
|
|
||||||
@LayoutId(R.layout.dialog_myanimelist_search_item)
|
@LayoutId(R.layout.dialog_myanimelist_search_item)
|
||||||
public static class ResultViewHolder extends ItemViewHolder<MangaSync> {
|
public static class ResultViewHolder extends ItemViewHolder<MangaSync> {
|
||||||
|
|
||||||
@ -96,4 +151,22 @@ public class MyAnimeListDialogFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class SimpleTextChangeListener implements 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) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
|||||||
|
|
||||||
private DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
private DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||||
|
|
||||||
|
private final static String SEARCH_FRAGMENT_TAG = "mal_search";
|
||||||
|
|
||||||
public static MyAnimeListFragment newInstance() {
|
public static MyAnimeListFragment newInstance() {
|
||||||
return new MyAnimeListFragment();
|
return new MyAnimeListFragment();
|
||||||
}
|
}
|
||||||
@ -53,21 +55,36 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSearchDialog() {
|
public void setSearchResults(List<MangaSync> results) {
|
||||||
if (dialog == null)
|
findSearchFragmentIfNeeded();
|
||||||
dialog = MyAnimeListDialogFragment.newInstance(this);
|
|
||||||
|
|
||||||
dialog.show(getActivity().getSupportFragmentManager(), "search");
|
if (dialog != null) {
|
||||||
|
dialog.onSearchResults(results);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSearchResults(List<MangaSync> results) {
|
public void setSearchResultsError() {
|
||||||
if (dialog != null)
|
findSearchFragmentIfNeeded();
|
||||||
dialog.setResults(results);
|
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog.onSearchResultsError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findSearchFragmentIfNeeded() {
|
||||||
|
if (dialog == null) {
|
||||||
|
dialog = (MyAnimeListDialogFragment) getChildFragmentManager()
|
||||||
|
.findFragmentByTag(SEARCH_FRAGMENT_TAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.myanimelist_title_layout)
|
@OnClick(R.id.myanimelist_title_layout)
|
||||||
void onTitleClick() {
|
void onTitleClick() {
|
||||||
showSearchDialog();
|
if (dialog == null)
|
||||||
|
dialog = MyAnimeListDialogFragment.newInstance();
|
||||||
|
|
||||||
|
getPresenter().restartSearch();
|
||||||
|
dialog.show(getChildFragmentManager(), SEARCH_FRAGMENT_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.myanimelist_status_layout)
|
@OnClick(R.id.myanimelist_status_layout)
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.mangafeed.ui.manga.myanimelist;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -55,9 +56,10 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
|||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread()),
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
(view, results) -> {
|
(view, results) -> {
|
||||||
view.onSearchResults(results);
|
view.setSearchResults(results);
|
||||||
}, (view, error) -> {
|
}, (view, error) -> {
|
||||||
Timber.e(error.getMessage());
|
Timber.e(error.getMessage());
|
||||||
|
view.setSearchResultsError();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -100,10 +102,18 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void searchManga(String query) {
|
public void searchManga(String query) {
|
||||||
|
if (TextUtils.isEmpty(query) || query.equals(this.query))
|
||||||
|
return;
|
||||||
|
|
||||||
this.query = query;
|
this.query = query;
|
||||||
start(GET_SEARCH_RESULTS);
|
start(GET_SEARCH_RESULTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void restartSearch() {
|
||||||
|
this.query = null;
|
||||||
|
stop(GET_SEARCH_RESULTS);
|
||||||
|
}
|
||||||
|
|
||||||
public void registerManga(MangaSync manga) {
|
public void registerManga(MangaSync manga) {
|
||||||
manga.manga_id = this.manga.id;
|
manga.manga_id = this.manga.id;
|
||||||
add(myAnimeList.bind(manga)
|
add(myAnimeList.bind(manga)
|
||||||
|
BIN
app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 254 B |
BIN
app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-ldpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 231 B |
BIN
app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 191 B |
BIN
app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 411 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_clear_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 565 B |
@ -1,36 +1,54 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingLeft="@dimen/margin_left"
|
||||||
|
android:paddingRight="@dimen/margin_right"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<EditText
|
<EditText
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:id="@+id/myanimelist_search_field"/>
|
android:id="@+id/myanimelist_search_field"
|
||||||
|
android:hint="@string/title_hint" />
|
||||||
|
|
||||||
<Button
|
<!--
|
||||||
|
<ImageButton
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/action_search"
|
android:background="@drawable/ic_clear_grey600_24dp"/>
|
||||||
android:id="@+id/myanimelist_search_button"/>
|
-->
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:paddingTop="32dp"
|
||||||
|
android:paddingBottom="32dp"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
<ListView
|
<ListView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/myanimelist_search_results"
|
android:id="@+id/myanimelist_search_results"
|
||||||
|
android:scrollbarStyle="outsideOverlay"
|
||||||
|
android:divider="@null"
|
||||||
|
android:dividerHeight="0dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
android:choiceMode="singleChoice"
|
android:choiceMode="singleChoice"
|
||||||
android:listSelector="@color/list_choice_pressed_bg_light">
|
android:listSelector="@color/list_choice_pressed_bg_light"
|
||||||
|
android:visibility="gone"/>
|
||||||
</ListView>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -141,6 +141,7 @@
|
|||||||
<string name="on_hold">On hold</string>
|
<string name="on_hold">On hold</string>
|
||||||
<string name="plan_to_read">Plan to read</string>
|
<string name="plan_to_read">Plan to read</string>
|
||||||
<string name="score">Score</string>
|
<string name="score">Score</string>
|
||||||
|
<string name="title_hint">Title…</string>
|
||||||
|
|
||||||
<!-- Reader activity -->
|
<!-- Reader activity -->
|
||||||
<string name="downloading">Downloading…</string>
|
<string name="downloading">Downloading…</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user