Merge pull request #91 from NoodleMage/change_cover
Can now manually set cover pictures. #79
This commit is contained in:
commit
38bb0b61d4
@ -130,12 +130,15 @@ dependencies {
|
||||
compile('com.mikepenz:materialdrawer:4.6.4@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
//Google material icons SVG.
|
||||
compile 'com.mikepenz:google-material-typeface:2.1.0.1.original@aar'
|
||||
|
||||
compile('com.github.afollestad.material-dialogs:core:0.8.5.3@aar') {
|
||||
transitive = true
|
||||
}
|
||||
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.assertj:assertj-core:2.3.0'
|
||||
testCompile "org.mockito:mockito-core:$MOCKITO_VERSION"
|
||||
|
@ -11,6 +11,7 @@ import com.bumptech.glide.load.model.GlideUrl;
|
||||
import com.bumptech.glide.load.model.LazyHeaders;
|
||||
import com.bumptech.glide.request.animation.GlideAnimation;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.signature.StringSignature;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@ -119,7 +120,7 @@ public class CoverCache {
|
||||
* @param source the cover image.
|
||||
* @throws IOException exception returned
|
||||
*/
|
||||
private void copyToLocalCache(String thumbnailUrl, File source) throws IOException {
|
||||
public void copyToLocalCache(String thumbnailUrl, File source) throws IOException {
|
||||
// Create cache directory if needed.
|
||||
createCacheDir();
|
||||
|
||||
@ -200,11 +201,12 @@ public class CoverCache {
|
||||
* @param imageView imageView where picture should be displayed.
|
||||
* @param file file to load. Must exist!.
|
||||
*/
|
||||
private void loadFromCache(ImageView imageView, File file) {
|
||||
public void loadFromCache(ImageView imageView, File file) {
|
||||
Glide.with(context)
|
||||
.load(file)
|
||||
.diskCacheStrategy(DiskCacheStrategy.RESULT)
|
||||
.centerCrop()
|
||||
.signature(new StringSignature(String.valueOf(file.lastModified())))
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,6 @@ public interface AppComponent {
|
||||
void inject(LibraryUpdateService libraryUpdateService);
|
||||
void inject(DownloadService downloadService);
|
||||
void inject(UpdateMangaSyncService updateMangaSyncService);
|
||||
|
||||
Application application();
|
||||
|
||||
}
|
||||
|
110
app/src/main/java/eu/kanade/tachiyomi/io/IOHandler.java
Normal file
110
app/src/main/java/eu/kanade/tachiyomi/io/IOHandler.java
Normal file
@ -0,0 +1,110 @@
|
||||
package eu.kanade.tachiyomi.io;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class IOHandler {
|
||||
/**
|
||||
* Get full filepath of build in Android File picker.
|
||||
* If Google Drive (or other Cloud service) throw exception and download before loading
|
||||
*/
|
||||
public static String getFilePath(Uri uri, ContentResolver resolver, Context context) {
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
String filePath = "";
|
||||
String wholeID = DocumentsContract.getDocumentId(uri);
|
||||
|
||||
//Ugly work around. In sdk version Kitkat or higher external getDocumentId request will have no content://
|
||||
if (wholeID.split(":").length == 1)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
// Split at colon, use second item in the array
|
||||
String id = wholeID.split(":")[1];
|
||||
|
||||
String[] column = {MediaStore.Images.Media.DATA};
|
||||
|
||||
// where id is equal to
|
||||
String sel = MediaStore.Images.Media._ID + "=?";
|
||||
|
||||
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
|
||||
column, sel, new String[]{id}, null);
|
||||
|
||||
int columnIndex = cursor != null ? cursor.getColumnIndex(column[0]) : 0;
|
||||
|
||||
if (cursor != null ? cursor.moveToFirst() : false) {
|
||||
filePath = cursor.getString(columnIndex);
|
||||
}
|
||||
cursor.close();
|
||||
return filePath;
|
||||
} else {
|
||||
String[] fields = {MediaStore.Images.Media.DATA};
|
||||
|
||||
Cursor cursor = resolver.query(uri, fields, null, null, null);
|
||||
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
cursor.moveToFirst();
|
||||
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
|
||||
cursor.close();
|
||||
|
||||
return path;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
//This exception is thrown when Google Drive. Try to download file
|
||||
return downloadMediaAndReturnPath(uri, resolver, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getTempFilename(Context context) throws IOException {
|
||||
File outputDir = context.getCacheDir();
|
||||
File outputFile = File.createTempFile("temp_cover", "0", outputDir);
|
||||
return outputFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
private static String downloadMediaAndReturnPath(Uri uri, ContentResolver resolver, Context context) {
|
||||
if (uri == null) return null;
|
||||
FileInputStream input = null;
|
||||
FileOutputStream output = null;
|
||||
try {
|
||||
ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r");
|
||||
FileDescriptor fd = pfd != null ? pfd.getFileDescriptor() : null;
|
||||
input = new FileInputStream(fd);
|
||||
|
||||
String tempFilename = getTempFilename(context);
|
||||
output = new FileOutputStream(tempFilename);
|
||||
|
||||
int read;
|
||||
byte[] bytes = new byte[4096];
|
||||
while ((read = input.read(bytes)) != -1) {
|
||||
output.write(bytes, 0, read);
|
||||
}
|
||||
return tempFilename;
|
||||
} catch (IOException ignored) {
|
||||
} finally {
|
||||
if (input != null) try {
|
||||
input.close();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
if (output != null) try {
|
||||
output.close();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,11 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.info;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -10,6 +15,11 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.bumptech.glide.load.model.LazyHeaders;
|
||||
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.ButterKnife;
|
||||
@ -17,14 +27,16 @@ import eu.kanade.tachiyomi.R;
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache;
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga;
|
||||
import eu.kanade.tachiyomi.data.source.base.Source;
|
||||
import eu.kanade.tachiyomi.io.IOHandler;
|
||||
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment;
|
||||
import eu.kanade.tachiyomi.util.ToastUtil;
|
||||
import nucleus.factory.RequiresPresenter;
|
||||
|
||||
@RequiresPresenter(MangaInfoPresenter.class)
|
||||
public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
|
||||
private static final int REQUEST_IMAGE_OPEN = 101;
|
||||
@Bind(R.id.swipe_refresh) SwipeRefreshLayout swipeRefresh;
|
||||
|
||||
@Bind(R.id.manga_artist) TextView artist;
|
||||
@Bind(R.id.manga_author) TextView author;
|
||||
@Bind(R.id.manga_chapters) TextView chapterCount;
|
||||
@ -33,9 +45,8 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
@Bind(R.id.manga_source) TextView source;
|
||||
@Bind(R.id.manga_summary) TextView description;
|
||||
@Bind(R.id.manga_cover) ImageView cover;
|
||||
|
||||
@Bind(R.id.action_favorite) Button favoriteBtn;
|
||||
|
||||
@Bind(R.id.fab_edit) FloatingActionButton fabEdit;
|
||||
|
||||
public static MangaInfoFragment newInstance() {
|
||||
return new MangaInfoFragment();
|
||||
@ -54,9 +65,20 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
View view = inflater.inflate(R.layout.fragment_manga_info, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
favoriteBtn.setOnClickListener(v -> {
|
||||
getPresenter().toggleFavorite();
|
||||
});
|
||||
//Create edit drawable with size 24dp (google guidelines)
|
||||
IconicsDrawable edit = new IconicsDrawable(this.getContext())
|
||||
.icon(GoogleMaterial.Icon.gmd_edit)
|
||||
.color(ContextCompat.getColor(this.getContext(), R.color.white))
|
||||
.sizeDp(24);
|
||||
|
||||
// Update image of fab buttons
|
||||
fabEdit.setImageDrawable(edit);
|
||||
|
||||
// Set listener.
|
||||
fabEdit.setOnClickListener(v -> MangaInfoFragment.this.selectImage());
|
||||
|
||||
favoriteBtn.setOnClickListener(v -> getPresenter().toggleFavorite());
|
||||
|
||||
swipeRefresh.setOnRefreshListener(this::fetchMangaFromSource);
|
||||
|
||||
return view;
|
||||
@ -71,6 +93,12 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the info of the manga
|
||||
*
|
||||
* @param manga manga object containing information about manga
|
||||
* @param mangaSource the source of the manga
|
||||
*/
|
||||
private void setMangaInfo(Manga manga, Source mangaSource) {
|
||||
artist.setText(manga.artist);
|
||||
author.setText(manga.author);
|
||||
@ -99,7 +127,7 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
chapterCount.setText(String.valueOf(count));
|
||||
}
|
||||
|
||||
public void setFavoriteText(boolean isFavorite) {
|
||||
private void setFavoriteText(boolean isFavorite) {
|
||||
favoriteBtn.setText(!isFavorite ? R.string.add_to_library : R.string.remove_from_library);
|
||||
}
|
||||
|
||||
@ -108,6 +136,45 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
||||
getPresenter().fetchMangaFromSource();
|
||||
}
|
||||
|
||||
private void selectImage() {
|
||||
if (getPresenter().getManga().favorite) {
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setType("image/*");
|
||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||
startActivityForResult(Intent.createChooser(intent,
|
||||
getString(R.string.file_select_cover)), REQUEST_IMAGE_OPEN);
|
||||
} else {
|
||||
ToastUtil.showShort(getContext(), R.string.notification_first_add_to_library);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
if (requestCode == REQUEST_IMAGE_OPEN) {
|
||||
// Get the file's content URI from the incoming Intent
|
||||
Uri selectedImageUri = data.getData();
|
||||
|
||||
// Convert to absolute path to prevent FileNotFoundException
|
||||
String result = IOHandler.getFilePath(selectedImageUri, this.getContext().getContentResolver(), this.getContext());
|
||||
|
||||
// Get file from filepath
|
||||
File picture = new File(result != null ? result : "");
|
||||
|
||||
|
||||
try {
|
||||
// Update cover to selected file
|
||||
getPresenter().editCoverWithLocalFile(picture, cover);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onFetchMangaDone() {
|
||||
setRefreshing(false);
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.info;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -19,17 +23,42 @@ import rx.schedulers.Schedulers;
|
||||
|
||||
public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
|
||||
@Inject DatabaseHelper db;
|
||||
@Inject SourceManager sourceManager;
|
||||
@Inject CoverCache coverCache;
|
||||
|
||||
protected Source source;
|
||||
private Manga manga;
|
||||
private int count = -1;
|
||||
|
||||
/**
|
||||
* The id of the restartable.
|
||||
*/
|
||||
private static final int GET_MANGA = 1;
|
||||
/**
|
||||
* The id of the restartable.
|
||||
*/
|
||||
private static final int GET_CHAPTER_COUNT = 2;
|
||||
/**
|
||||
* The id of the restartable.
|
||||
*/
|
||||
private static final int FETCH_MANGA_INFO = 3;
|
||||
/**
|
||||
* Source information
|
||||
*/
|
||||
protected Source source;
|
||||
/**
|
||||
* Used to connect to database
|
||||
*/
|
||||
@Inject DatabaseHelper db;
|
||||
/**
|
||||
* Used to connect to different manga sources
|
||||
*/
|
||||
@Inject SourceManager sourceManager;
|
||||
/**
|
||||
* Used to connect to cache
|
||||
*/
|
||||
@Inject CoverCache coverCache;
|
||||
/**
|
||||
* Selected manga information
|
||||
*/
|
||||
private Manga manga;
|
||||
/**
|
||||
* Count of chapters
|
||||
*/
|
||||
private int count = -1;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedState) {
|
||||
@ -39,22 +68,29 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
onProcessRestart();
|
||||
}
|
||||
|
||||
// Update manga cache
|
||||
restartableLatestCache(GET_MANGA,
|
||||
() -> Observable.just(manga),
|
||||
(view, manga) -> view.onNextManga(manga, source));
|
||||
|
||||
// Update chapter count
|
||||
restartableLatestCache(GET_CHAPTER_COUNT,
|
||||
() -> Observable.just(count),
|
||||
MangaInfoFragment::setChapterCount);
|
||||
|
||||
// Fetch manga info from source
|
||||
restartableFirst(FETCH_MANGA_INFO,
|
||||
this::fetchMangaObs,
|
||||
(view, manga) -> view.onFetchMangaDone(),
|
||||
(view, error) -> view.onFetchMangaError());
|
||||
|
||||
// onEventMainThread receives an event thanks to this line.
|
||||
registerForStickyEvents();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when savedState not null
|
||||
*/
|
||||
private void onProcessRestart() {
|
||||
stop(GET_MANGA);
|
||||
stop(GET_CHAPTER_COUNT);
|
||||
@ -82,6 +118,9 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch manga info from source
|
||||
*/
|
||||
public void fetchMangaFromSource() {
|
||||
if (isUnsubscribed(FETCH_MANGA_INFO)) {
|
||||
start(FETCH_MANGA_INFO);
|
||||
@ -107,6 +146,16 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
refreshManga();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update cover with local file
|
||||
*/
|
||||
public void editCoverWithLocalFile(File file, ImageView imageView) throws IOException {
|
||||
if (manga.favorite) {
|
||||
coverCache.copyToLocalCache(manga.thumbnail_url, file);
|
||||
coverCache.loadFromCache(imageView, file);
|
||||
}
|
||||
}
|
||||
|
||||
private void onMangaFavoriteChange(boolean isFavorite) {
|
||||
if (isFavorite) {
|
||||
coverCache.save(manga.thumbnail_url, source.getGlideHeaders());
|
||||
@ -115,8 +164,12 @@ public class MangaInfoPresenter extends BasePresenter<MangaInfoFragment> {
|
||||
}
|
||||
}
|
||||
|
||||
public Manga getManga() {
|
||||
return manga;
|
||||
}
|
||||
|
||||
// Used to refresh the view
|
||||
private void refreshManga() {
|
||||
protected void refreshManga() {
|
||||
start(GET_MANGA);
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context="eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment">
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context="eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment">
|
||||
|
||||
|
||||
<!-- It seems I have to wrap everything in SwipeRefreshLayout because it always take the entire height
|
||||
@ -16,8 +17,8 @@
|
||||
<android.support.v4.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipe_refresh"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
@ -50,7 +51,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:scaleType="fitXY"
|
||||
android:visibility="visible" />
|
||||
android:visibility="visible"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -72,7 +73,7 @@
|
||||
android:layout_marginTop="5dp"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/author" />
|
||||
android:text="@string/author"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_author"
|
||||
@ -85,7 +86,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist_label"
|
||||
@ -97,7 +98,7 @@
|
||||
android:layout_below="@id/manga_author_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/artist" />
|
||||
android:text="@string/artist"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_artist"
|
||||
@ -110,7 +111,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters_label"
|
||||
@ -121,7 +122,7 @@
|
||||
android:layout_below="@id/manga_artist_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/chapters" />
|
||||
android:text="@string/chapters"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_chapters"
|
||||
@ -134,7 +135,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status_label"
|
||||
@ -146,7 +147,7 @@
|
||||
android:layout_below="@id/manga_chapters_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/status" />
|
||||
android:text="@string/status"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_status"
|
||||
@ -159,7 +160,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source_label"
|
||||
@ -170,7 +171,7 @@
|
||||
android:layout_below="@id/manga_status_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/source" />
|
||||
android:text="@string/source"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_source"
|
||||
@ -183,7 +184,7 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_genres_label"
|
||||
@ -194,7 +195,7 @@
|
||||
android:layout_below="@id/manga_source_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:text="@string/genres" />
|
||||
android:text="@string/genres"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_genres"
|
||||
@ -204,7 +205,7 @@
|
||||
android:layout_below="@id/manga_genres_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:singleLine="false" />
|
||||
android:singleLine="false"/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
@ -221,7 +222,7 @@
|
||||
android:id="@+id/action_favorite"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/add_to_library" />
|
||||
android:text="@string/add_to_library"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@ -238,24 +239,43 @@
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:singleLine="false"
|
||||
android:text="@string/description" />
|
||||
android:text="@string/description"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/manga_detail_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:singleLine="false" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/manga_summary"
|
||||
style="@style/manga_detail_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:singleLine="false"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="10dp"
|
||||
android:gravity="bottom">
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_edit"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:backgroundTint="@color/colorPrimary"
|
||||
app:layout_behavior="eu.kanade.tachiyomi.ui.base.fab.ScrollAwareFABBehavior"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
@ -11,6 +11,7 @@
|
||||
<color name="primary">@color/colorPrimary</color>
|
||||
<color name="primary_dark">@color/colorPrimaryDark</color>
|
||||
<color name="primary_light">@color/colorPrimaryLight</color>
|
||||
<color name="color_ripple">#E9F1FF</color>
|
||||
|
||||
<color name="divider">@color/md_light_dividers</color>
|
||||
|
||||
|
@ -205,5 +205,9 @@
|
||||
<string name="notification_no_new_chapters">No new chapters found</string>
|
||||
<string name="notification_new_chapters">New chapters found for:</string>
|
||||
<string name="notification_manga_update_failed">Failed to update manga:</string>
|
||||
<string name="notification_first_add_to_library">Please add the manga to your library before doing this</string>
|
||||
|
||||
<!-- File Picker Titles -->
|
||||
<string name="file_select_cover">Select cover image</string>
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user