diff --git a/folioreader/res/layout/item_styled_text.xml b/folioreader/res/layout/item_styled_text.xml new file mode 100644 index 000000000..2d50c317d --- /dev/null +++ b/folioreader/res/layout/item_styled_text.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/folioreader/res/layout/progress_dialog.xml b/folioreader/res/layout/progress_dialog.xml index 0d823fe0e..7f7d5ee62 100644 --- a/folioreader/res/layout/progress_dialog.xml +++ b/folioreader/res/layout/progress_dialog.xml @@ -14,7 +14,7 @@ android:id="@+id/loading" android:layout_width="wrap_content" android:layout_height="wrap_content" - style="?android:attr/android:progressBarStyle" /> + style="?android:attr/progressBarStyle" /> + app:srcCompat="@drawable/icon_sun_sel" + tools:ignore="MissingConstraints" /> + app:srcCompat="@drawable/icon_moon_sel" + tools:ignore="MissingConstraints" /> - - - - - - - + app:layout_constraintTop_toBottomOf="@+id/view_config_font_spinner" /> T getBundleItem(Bundle bundle, String key, T defaultValue) { + if (bundle.containsKey(key)) { + return (T) bundle.get(key); + } + return defaultValue; } public Config() { } - public Config(JSONObject jsonObject) { - font = jsonObject.optInt(CONFIG_FONT); - fontSize = jsonObject.optInt(CONFIG_FONT_SIZE); - nightMode = jsonObject.optBoolean(CONFIG_IS_NIGHT_MODE); - themeColor = getValidColorInt(jsonObject.optInt(CONFIG_THEME_COLOR_INT)); - showTts = jsonObject.optBoolean(CONFIG_IS_TTS); - allowedDirection = getAllowedDirectionFromString(LOG_TAG, - jsonObject.optString(CONFIG_ALLOWED_DIRECTION)); - direction = getDirectionFromString(LOG_TAG, jsonObject.optString(CONFIG_DIRECTION)); + public Config(JSONObject obj) { + font = getJsonItem(obj, CONFIG_FONT, "Roboto"); + fontSize = getJsonItem(obj, CONFIG_FONT_SIZE, 2); + nightMode = getJsonItem(obj, CONFIG_IS_NIGHT_MODE, false); + themeColor = getValidColorInt(getJsonItem(obj, CONFIG_THEME_COLOR_INT, DEFAULT_THEME_COLOR_INT)); + nightThemeColor = getValidColorInt(getJsonItem(obj, CONFIG_NIGHT_THEME_COLOR_INT, DEFAULT_THEME_COLOR_INT)); + showTts = getJsonItem(obj, CONFIG_IS_TTS, true); + allowedDirection = getAllowedDirectionFromString( + LOG_TAG, + getJsonItem(obj, CONFIG_ALLOWED_DIRECTION, DEFAULT_ALLOWED_DIRECTION.toString()) + ); + direction = getDirectionFromString( + LOG_TAG, + getJsonItem(obj, CONFIG_DIRECTION, DEFAULT_DIRECTION.toString()) + ); + showRemainingIndicator = getJsonItem(obj, CONFIG_REMAINING_INDICATOR, false); + } + + @SuppressWarnings("unchecked") + private T getJsonItem(JSONObject object, String key, T defaultValue) { + if (object.has(key)) { + return (T) object.opt(key); + } + return defaultValue; } public static Direction getDirectionFromString(final String LOG_TAG, String directionString) { @@ -137,11 +203,11 @@ public static AllowedDirection getAllowedDirectionFromString(final String LOG_TA } } - public int getFont() { + public String getFont() { return font; } - public Config setFont(int font) { + public Config setFont(String font) { this.font = font; return this; } @@ -164,6 +230,11 @@ public Config setNightMode(boolean nightMode) { return this; } + @ColorInt + public int getCurrentThemeColor() { + return isNightMode() ? getNightThemeColor() : getThemeColor(); + } + @ColorInt private int getValidColorInt(@ColorInt int colorInt) { if (colorInt >= 0) { @@ -179,6 +250,11 @@ public int getThemeColor() { return themeColor; } + @ColorInt + public int getNightThemeColor() { + return nightThemeColor; + } + public Config setThemeColorRes(@ColorRes int colorResId) { try { this.themeColor = ContextCompat.getColor(AppContext.get(), colorResId); @@ -196,6 +272,23 @@ public Config setThemeColorInt(@ColorInt int colorInt) { return this; } + public Config setNightThemeColorRes(@ColorRes int colorResId) { + try { + this.nightThemeColor = ContextCompat.getColor(AppContext.get(), colorResId); + } catch (Resources.NotFoundException e) { + Log.w(LOG_TAG, "-> setNightThemeColorRes -> " + e); + Log.w(LOG_TAG, "-> setNightThemeColorRes -> Defaulting themeColor to " + + DEFAULT_THEME_COLOR_INT); + this.nightThemeColor = DEFAULT_THEME_COLOR_INT; + } + return this; + } + + public Config setNightThemeColorInt(@ColorInt int colorInt) { + this.nightThemeColor = getValidColorInt(colorInt); + return this; + } + public boolean isShowTts() { return showTts; } @@ -280,6 +373,19 @@ public Config setDirection(Direction direction) { return this; } + public boolean isShowRemainingIndicator() { + return showRemainingIndicator; + } + + /** + * Sets the remaining indicator to be visible while reading + * + * @param showRemainingIndicator true to show the indicator while reading, otherwise false. + */ + public void setShowRemainingIndicator(boolean showRemainingIndicator) { + this.showRemainingIndicator = showRemainingIndicator; + } + @Override public String toString() { return "Config{" + @@ -287,9 +393,11 @@ public String toString() { ", fontSize=" + fontSize + ", nightMode=" + nightMode + ", themeColor=" + themeColor + + ", nightThemeColor=" + nightThemeColor + ", showTts=" + showTts + ", allowedDirection=" + allowedDirection + ", direction=" + direction + + ", remainingIndicator=" + showRemainingIndicator + '}'; } } diff --git a/folioreader/src/main/java/com/folioreader/FolioReader.java b/folioreader/src/main/java/com/folioreader/FolioReader.java index d02a16d90..8e4f3af64 100644 --- a/folioreader/src/main/java/com/folioreader/FolioReader.java +++ b/folioreader/src/main/java/com/folioreader/FolioReader.java @@ -6,8 +6,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.os.Parcelable; + import androidx.annotation.Nullable; import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import com.folioreader.model.HighLight; import com.folioreader.model.HighlightImpl; import com.folioreader.model.locators.ReadLocator; @@ -19,14 +21,15 @@ import com.folioreader.ui.base.SaveReceivedHighlightTask; import com.folioreader.util.OnHighlightListener; import com.folioreader.util.ReadLocatorListener; + +import java.util.List; +import java.util.concurrent.TimeUnit; + import okhttp3.OkHttpClient; import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.jackson.JacksonConverterFactory; -import java.util.List; -import java.util.concurrent.TimeUnit; - /** * Created by avez raj on 9/13/2017. */ diff --git a/folioreader/src/main/java/com/folioreader/Font.java b/folioreader/src/main/java/com/folioreader/Font.java deleted file mode 100644 index a54dc4802..000000000 --- a/folioreader/src/main/java/com/folioreader/Font.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2016 Pedro Paulo de Amorim - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.folioreader; - -public class Font { - - String name; - - public Font(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - -} diff --git a/folioreader/src/main/java/com/folioreader/mediaoverlay/MediaController.java b/folioreader/src/main/java/com/folioreader/mediaoverlay/MediaController.java index be9d2ee90..8db793312 100644 --- a/folioreader/src/main/java/com/folioreader/mediaoverlay/MediaController.java +++ b/folioreader/src/main/java/com/folioreader/mediaoverlay/MediaController.java @@ -7,12 +7,15 @@ import android.os.Handler; import android.speech.tts.TextToSpeech; import android.util.Log; + import androidx.appcompat.app.AppCompatActivity; + import com.folioreader.Constants; import com.folioreader.model.event.MediaOverlayPlayPauseEvent; import com.folioreader.model.event.MediaOverlaySpeedEvent; import com.folioreader.model.media_overlay.OverlayItems; import com.folioreader.util.UiUtil; + import org.readium.r2.shared.Clip; import org.readium.r2.shared.MediaOverlays; @@ -104,25 +107,29 @@ public void setTextToSpeech(final Context context) { mTextToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { - if (status != TextToSpeech.ERROR) { - mTextToSpeech.setLanguage(Locale.UK); - mTextToSpeech.setSpeechRate(0.70f); - } + try { + if (status != TextToSpeech.ERROR) { + mTextToSpeech.setLanguage(Locale.UK); + mTextToSpeech.setSpeechRate(0.70f); + } - mTextToSpeech.setOnUtteranceCompletedListener( - new TextToSpeech.OnUtteranceCompletedListener() { - @Override - public void onUtteranceCompleted(String utteranceId) { - ((AppCompatActivity) context).runOnUiThread(new Runnable() { - @Override - public void run() { - if (mIsSpeaking) { - callbacks.highLightTTS(); + mTextToSpeech.setOnUtteranceCompletedListener( + new TextToSpeech.OnUtteranceCompletedListener() { + @Override + public void onUtteranceCompleted(String utteranceId) { + ((AppCompatActivity) context).runOnUiThread(new Runnable() { + @Override + public void run() { + if (mIsSpeaking) { + callbacks.highLightTTS(); + } } - } - }); - } - }); + }); + } + }); + } catch (NullPointerException e) { + System.out.println("Failed to create TextToSpeech"); + } } }); } diff --git a/folioreader/src/main/java/com/folioreader/model/TOCLinkWrapper.java b/folioreader/src/main/java/com/folioreader/model/TOCLinkWrapper.java index c1fed2fb7..3c0b4b408 100644 --- a/folioreader/src/main/java/com/folioreader/model/TOCLinkWrapper.java +++ b/folioreader/src/main/java/com/folioreader/model/TOCLinkWrapper.java @@ -1,6 +1,7 @@ package com.folioreader.model; import com.folioreader.util.MultiLevelExpIndListAdapter; + import org.readium.r2.shared.Link; import java.util.ArrayList; diff --git a/folioreader/src/main/java/com/folioreader/model/sqlite/HighLightTable.java b/folioreader/src/main/java/com/folioreader/model/sqlite/HighLightTable.java index 29a4462fc..fc8645876 100644 --- a/folioreader/src/main/java/com/folioreader/model/sqlite/HighLightTable.java +++ b/folioreader/src/main/java/com/folioreader/model/sqlite/HighLightTable.java @@ -4,13 +4,18 @@ import android.database.Cursor; import android.text.TextUtils; import android.util.Log; + import com.folioreader.Constants; import com.folioreader.model.HighLight; import com.folioreader.model.HighlightImpl; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.UUID; @SuppressWarnings("PMD.AvoidDuplicateLiterals") public class HighLightTable { diff --git a/folioreader/src/main/java/com/folioreader/network/QualifiedTypeConverterFactory.kt b/folioreader/src/main/java/com/folioreader/network/QualifiedTypeConverterFactory.kt index 87b6f06bd..f32912835 100644 --- a/folioreader/src/main/java/com/folioreader/network/QualifiedTypeConverterFactory.kt +++ b/folioreader/src/main/java/com/folioreader/network/QualifiedTypeConverterFactory.kt @@ -43,7 +43,9 @@ class QualifiedTypeConverterFactory : Converter.Factory { override fun requestBodyConverter( type: Type, - parameterAnnotations: Array, methodAnnotations: Array, retrofit: Retrofit + parameterAnnotations: Array, + methodAnnotations: Array, + retrofit: Retrofit ): Converter<*, RequestBody>? { for (annotation in parameterAnnotations) { diff --git a/folioreader/src/main/java/com/folioreader/network/R2StreamerApi.kt b/folioreader/src/main/java/com/folioreader/network/R2StreamerApi.kt index e543b67d6..1f491452c 100644 --- a/folioreader/src/main/java/com/folioreader/network/R2StreamerApi.kt +++ b/folioreader/src/main/java/com/folioreader/network/R2StreamerApi.kt @@ -7,6 +7,10 @@ import retrofit2.http.Query interface R2StreamerApi { - @GET("search") @Gson - fun search(@Query("spineIndex") spineIndex: Int, @Query("query") query: String): Call> + @GET("search") + @Gson + fun search( + @Query("spineIndex") spineIndex: Int, + @Query("query") query: String + ): Call> } \ No newline at end of file diff --git a/folioreader/src/main/java/com/folioreader/network/TLSSocketFactory.java b/folioreader/src/main/java/com/folioreader/network/TLSSocketFactory.java index 897665782..3d277c6ea 100644 --- a/folioreader/src/main/java/com/folioreader/network/TLSSocketFactory.java +++ b/folioreader/src/main/java/com/folioreader/network/TLSSocketFactory.java @@ -6,9 +6,6 @@ package com.folioreader.network; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; @@ -16,6 +13,10 @@ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + /** * @author fkrauthan */ diff --git a/folioreader/src/main/java/com/folioreader/ui/activity/ContentHighlightActivity.java b/folioreader/src/main/java/com/folioreader/ui/activity/ContentHighlightActivity.java index 2c320e731..5d8932d54 100644 --- a/folioreader/src/main/java/com/folioreader/ui/activity/ContentHighlightActivity.java +++ b/folioreader/src/main/java/com/folioreader/ui/activity/ContentHighlightActivity.java @@ -7,9 +7,11 @@ import android.view.View; import android.widget.ImageView; import android.widget.TextView; + import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentTransaction; + import com.folioreader.Config; import com.folioreader.Constants; import com.folioreader.FolioReader; @@ -18,6 +20,7 @@ import com.folioreader.ui.fragment.TableOfContentFragment; import com.folioreader.util.AppUtil; import com.folioreader.util.UiUtil; + import org.readium.r2.shared.Publication; public class ContentHighlightActivity extends AppCompatActivity { @@ -43,21 +46,21 @@ protected void onCreate(Bundle savedInstanceState) { private void initViews() { - UiUtil.setColorIntToDrawable(mConfig.getThemeColor(), ((ImageView) findViewById(R.id.btn_close)).getDrawable()); - findViewById(R.id.layout_content_highlights).setBackgroundDrawable(UiUtil.getShapeDrawable(mConfig.getThemeColor())); + UiUtil.setColorIntToDrawable(mConfig.getCurrentThemeColor(), ((ImageView) findViewById(R.id.btn_close)).getDrawable()); + findViewById(R.id.layout_content_highlights).setBackgroundDrawable(UiUtil.getShapeDrawable(mConfig.getCurrentThemeColor())); if (mIsNightMode) { findViewById(R.id.toolbar).setBackgroundColor(Color.BLACK); - findViewById(R.id.btn_contents).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getThemeColor(), ContextCompat.getColor(this, R.color.black))); - findViewById(R.id.btn_highlights).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getThemeColor(), ContextCompat.getColor(this, R.color.black))); - ((TextView) findViewById(R.id.btn_contents)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.black), mConfig.getThemeColor())); - ((TextView) findViewById(R.id.btn_highlights)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.black), mConfig.getThemeColor())); + findViewById(R.id.btn_contents).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getCurrentThemeColor(), ContextCompat.getColor(this, R.color.black))); + findViewById(R.id.btn_highlights).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getCurrentThemeColor(), ContextCompat.getColor(this, R.color.black))); + ((TextView) findViewById(R.id.btn_contents)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.black), mConfig.getCurrentThemeColor())); + ((TextView) findViewById(R.id.btn_highlights)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.black), mConfig.getCurrentThemeColor())); } else { - ((TextView) findViewById(R.id.btn_contents)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.white), mConfig.getThemeColor())); - ((TextView) findViewById(R.id.btn_highlights)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.white), mConfig.getThemeColor())); - findViewById(R.id.btn_contents).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getThemeColor(), ContextCompat.getColor(this, R.color.white))); - findViewById(R.id.btn_highlights).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getThemeColor(), ContextCompat.getColor(this, R.color.white))); + ((TextView) findViewById(R.id.btn_contents)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.white), mConfig.getCurrentThemeColor())); + ((TextView) findViewById(R.id.btn_highlights)).setTextColor(UiUtil.getColorList(ContextCompat.getColor(this, R.color.white), mConfig.getCurrentThemeColor())); + findViewById(R.id.btn_contents).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getCurrentThemeColor(), ContextCompat.getColor(this, R.color.white))); + findViewById(R.id.btn_highlights).setBackgroundDrawable(UiUtil.createStateDrawable(mConfig.getCurrentThemeColor(), ContextCompat.getColor(this, R.color.white))); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivity.kt b/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivity.kt index 8df26fbe8..2c7d0ceaa 100644 --- a/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivity.kt +++ b/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivity.kt @@ -83,6 +83,7 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle private var actionBar: ActionBar? = null private var appBarLayout: FolioAppBarLayout? = null private var toolbar: Toolbar? = null + private var createdMenu: Menu? = null private var distractionFreeMode: Boolean = false private var handler: Handler? = null @@ -139,7 +140,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle if (action != null && action == FolioReader.ACTION_CLOSE_FOLIOREADER) { try { - val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + val activityManager = + context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val tasks = activityManager.runningAppProcesses taskImportance = tasks[0].importance } catch (e: Exception) { @@ -147,7 +149,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle } val closeIntent = Intent(applicationContext, FolioActivity::class.java) - closeIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP + closeIntent.flags = + Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP closeIntent.action = FolioReader.ACTION_CLOSE_FOLIOREADER this@FolioActivity.startActivity(closeIntent) } @@ -267,11 +270,13 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle if (savedInstanceState != null) { searchAdapterDataBundle = savedInstanceState.getBundle(SearchAdapter.DATA_BUNDLE) - searchQuery = savedInstanceState.getCharSequence(SearchActivity.BUNDLE_SAVE_SEARCH_QUERY) + searchQuery = + savedInstanceState.getCharSequence(SearchActivity.BUNDLE_SAVE_SEARCH_QUERY) } mBookId = intent.getStringExtra(FolioReader.EXTRA_BOOK_ID) - mEpubSourceType = intent.extras!!.getSerializable(FolioActivity.INTENT_EPUB_SOURCE_TYPE) as EpubSourceType + mEpubSourceType = + intent.extras!!.getSerializable(FolioActivity.INTENT_EPUB_SOURCE_TYPE) as EpubSourceType if (mEpubSourceType == EpubSourceType.RAW) { mEpubRawId = intent.extras!!.getInt(FolioActivity.INTENT_EPUB_SOURCE_PATH) } else { @@ -307,7 +312,7 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle val config = AppUtil.getSavedConfig(applicationContext)!! val drawable = ContextCompat.getDrawable(this, R.drawable.ic_drawer) - UiUtil.setColorIntToDrawable(config.themeColor, drawable!!) + UiUtil.setColorIntToDrawable(config.currentThemeColor, drawable!!) toolbar!!.navigationIcon = drawable if (config.isNightMode) { @@ -340,7 +345,22 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle actionBar!!.setBackgroundDrawable( ColorDrawable(ContextCompat.getColor(this, R.color.white)) ) + toolbar!!.setTitleTextColor(ContextCompat.getColor(this, R.color.black)) + + val config = AppUtil.getSavedConfig(applicationContext)!! + + // Update drawer color + val newNavIcon = toolbar!!.navigationIcon + UiUtil.setColorIntToDrawable(config.themeColor, newNavIcon) + toolbar!!.navigationIcon = newNavIcon + + // Update toolbar colors + createdMenu?.let { m -> + UiUtil.setColorIntToDrawable(config.themeColor, m.findItem(R.id.itemSearch).icon) + UiUtil.setColorIntToDrawable(config.themeColor, m.findItem(R.id.itemConfig).icon) + UiUtil.setColorIntToDrawable(config.themeColor, m.findItem(R.id.itemTts).icon) + } } override fun setNightMode() { @@ -349,7 +369,22 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle actionBar!!.setBackgroundDrawable( ColorDrawable(ContextCompat.getColor(this, R.color.black)) ) + toolbar!!.setTitleTextColor(ContextCompat.getColor(this, R.color.night_title_text_color)) + + val config = AppUtil.getSavedConfig(applicationContext)!! + + // Update drawer color + val newNavIcon = toolbar!!.navigationIcon + UiUtil.setColorIntToDrawable(config.nightThemeColor, newNavIcon) + toolbar!!.navigationIcon = newNavIcon + + // Update toolbar colors + createdMenu?.let { m -> + UiUtil.setColorIntToDrawable(config.nightThemeColor, m.findItem(R.id.itemSearch).icon) + UiUtil.setColorIntToDrawable(config.nightThemeColor, m.findItem(R.id.itemConfig).icon) + UiUtil.setColorIntToDrawable(config.nightThemeColor, m.findItem(R.id.itemTts).icon) + } } private fun initMediaController() { @@ -359,12 +394,13 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle } override fun onCreateOptionsMenu(menu: Menu): Boolean { + createdMenu = menu menuInflater.inflate(R.menu.menu_main, menu) val config = AppUtil.getSavedConfig(applicationContext)!! - UiUtil.setColorIntToDrawable(config.themeColor, menu.findItem(R.id.itemSearch).icon) - UiUtil.setColorIntToDrawable(config.themeColor, menu.findItem(R.id.itemConfig).icon) - UiUtil.setColorIntToDrawable(config.themeColor, menu.findItem(R.id.itemTts).icon) + UiUtil.setColorIntToDrawable(config.currentThemeColor, menu.findItem(R.id.itemSearch).icon) + UiUtil.setColorIntToDrawable(config.currentThemeColor, menu.findItem(R.id.itemConfig).icon) + UiUtil.setColorIntToDrawable(config.currentThemeColor, menu.findItem(R.id.itemTts).icon) if (!config.isShowTts) menu.findItem(R.id.itemTts).isVisible = false @@ -485,7 +521,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle } } - portNumber = intent.getIntExtra(FolioReader.EXTRA_PORT_NUMBER, Constants.DEFAULT_PORT_NUMBER) + portNumber = + intent.getIntExtra(FolioReader.EXTRA_PORT_NUMBER, Constants.DEFAULT_PORT_NUMBER) portNumber = AppUtil.getAvailablePortNumber(portNumber) r2StreamerServer = Server(portNumber) @@ -538,7 +575,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle override fun getStreamerUrl(): String { if (streamerUri == null) { - streamerUri = Uri.parse(String.format(STREAMER_URL_TEMPLATE, LOCALHOST, portNumber, bookFileName)) + streamerUri = + Uri.parse(String.format(STREAMER_URL_TEMPLATE, LOCALHOST, portNumber, bookFileName)) } return streamerUri.toString() } @@ -575,7 +613,8 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle hideSystemUI() showSystemUI() - distractionFreeMode = savedInstanceState != null && savedInstanceState.getBoolean(BUNDLE_DISTRACTION_FREE_MODE) + distractionFreeMode = + savedInstanceState != null && savedInstanceState.getBoolean(BUNDLE_DISTRACTION_FREE_MODE) } override fun onPostCreate(savedInstanceState: Bundle?) { @@ -785,6 +824,7 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) if (requestCode == RequestCode.SEARCH.value) { Log.v(LOG_TAG, "-> onActivityResult -> " + RequestCode.SEARCH) @@ -855,8 +895,14 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle mFolioPageViewPager = findViewById(R.id.folioPageViewPager) // Replacing with addOnPageChangeListener(), onPageSelected() is not invoked - mFolioPageViewPager!!.setOnPageChangeListener(object : DirectionalViewpager.OnPageChangeListener { - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {} + mFolioPageViewPager!!.setOnPageChangeListener(object : + DirectionalViewpager.OnPageChangeListener { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + } override fun onPageSelected(position: Int) { Log.v(LOG_TAG, "-> onPageSelected -> DirectionalViewpager -> position = $position") @@ -879,14 +925,16 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle "position = " + position ) - var folioPageFragment = mFolioPageFragmentAdapter!!.getItem(position - 1) as FolioPageFragment? + var folioPageFragment = + mFolioPageFragmentAdapter!!.getItem(position - 1) as FolioPageFragment? if (folioPageFragment != null) { folioPageFragment.scrollToLast() if (folioPageFragment.mWebview != null) folioPageFragment.mWebview!!.dismissPopupWindow() } - folioPageFragment = mFolioPageFragmentAdapter!!.getItem(position + 1) as FolioPageFragment? + folioPageFragment = + mFolioPageFragmentAdapter!!.getItem(position + 1) as FolioPageFragment? if (folioPageFragment != null) { folioPageFragment.scrollToFirst() if (folioPageFragment.mWebview != null) @@ -1027,12 +1075,20 @@ class FolioActivity : AppCompatActivity(), FolioActivityCallback, MediaControlle ) } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { when (requestCode) { Constants.WRITE_EXTERNAL_STORAGE_REQUEST -> if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { setupBook() } else { - Toast.makeText(this, getString(R.string.cannot_access_epub_message), Toast.LENGTH_LONG).show() + Toast.makeText( + this, + getString(R.string.cannot_access_epub_message), + Toast.LENGTH_LONG + ).show() finish() } } diff --git a/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivityCallback.java b/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivityCallback.java index 502a54cfa..aa380f9ae 100644 --- a/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivityCallback.java +++ b/folioreader/src/main/java/com/folioreader/ui/activity/FolioActivityCallback.java @@ -1,6 +1,7 @@ package com.folioreader.ui.activity; import android.graphics.Rect; + import com.folioreader.Config; import com.folioreader.model.DisplayUnit; import com.folioreader.model.locators.ReadLocator; diff --git a/folioreader/src/main/java/com/folioreader/ui/activity/SearchActivity.kt b/folioreader/src/main/java/com/folioreader/ui/activity/SearchActivity.kt index 01cf904a5..7decddaf2 100644 --- a/folioreader/src/main/java/com/folioreader/ui/activity/SearchActivity.kt +++ b/folioreader/src/main/java/com/folioreader/ui/activity/SearchActivity.kt @@ -64,34 +64,35 @@ class SearchActivity : AppCompatActivity(), OnItemClickListener { private lateinit var searchViewModel: SearchViewModel // To get collapseButtonView from toolbar for any click events - private val toolbarOnLayoutChangeListener: View.OnLayoutChangeListener = object : View.OnLayoutChangeListener { - override fun onLayoutChange( - v: View?, left: Int, top: Int, right: Int, bottom: Int, - oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int - ) { - - for (i in 0 until toolbar.childCount) { - - val view: View = toolbar.getChildAt(i) - val contentDescription: String? = view.contentDescription as String? - if (TextUtils.isEmpty(contentDescription)) - continue - - if (contentDescription == "Collapse") { - Log.v(LOG_TAG, "-> initActionBar -> mCollapseButtonView found") - collapseButtonView = view as ImageButton - - collapseButtonView?.setOnClickListener { - Log.v(LOG_TAG, "-> onClick -> collapseButtonView") - navigateBack() + private val toolbarOnLayoutChangeListener: View.OnLayoutChangeListener = + object : View.OnLayoutChangeListener { + override fun onLayoutChange( + v: View?, left: Int, top: Int, right: Int, bottom: Int, + oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int + ) { + + for (i in 0 until toolbar.childCount) { + + val view: View = toolbar.getChildAt(i) + val contentDescription: String? = view.contentDescription as String? + if (TextUtils.isEmpty(contentDescription)) + continue + + if (contentDescription == "Collapse") { + Log.v(LOG_TAG, "-> initActionBar -> mCollapseButtonView found") + collapseButtonView = view as ImageButton + + collapseButtonView?.setOnClickListener { + Log.v(LOG_TAG, "-> onClick -> collapseButtonView") + navigateBack() + } + + toolbar.removeOnLayoutChangeListener(this) + return } - - toolbar.removeOnLayoutChangeListener(this) - return } } } - } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -121,7 +122,7 @@ class SearchActivity : AppCompatActivity(), OnItemClickListener { val fieldCollapseIcon: Field = Toolbar::class.java.getDeclaredField("mCollapseIcon") fieldCollapseIcon.isAccessible = true val collapseIcon: Drawable = fieldCollapseIcon.get(toolbar) as Drawable - UiUtil.setColorIntToDrawable(config.themeColor, collapseIcon) + UiUtil.setColorIntToDrawable(config.currentThemeColor, collapseIcon) } catch (e: Exception) { Log.e(LOG_TAG, "-> ", e) } @@ -175,7 +176,10 @@ class SearchActivity : AppCompatActivity(), OnItemClickListener { val query: String = intent.getStringExtra(SearchManager.QUERY) val newDataBundle = Bundle() - newDataBundle.putString(ListViewType.KEY, ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString()) + newDataBundle.putString( + ListViewType.KEY, + ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString() + ) newDataBundle.putParcelableArrayList("DATA", ArrayList()) searchViewModel.liveAdapterDataBundle.value = newDataBundle @@ -221,7 +225,7 @@ class SearchActivity : AppCompatActivity(), OnItemClickListener { val config: Config = AppUtil.getSavedConfig(applicationContext)!! val itemSearch: MenuItem = menu.findItem(R.id.itemSearch) - UiUtil.setColorIntToDrawable(config.themeColor, itemSearch.icon) + UiUtil.setColorIntToDrawable(config.currentThemeColor, itemSearch.icon) searchView = itemSearch.actionView as FolioSearchView searchView.init(componentName, config) @@ -316,7 +320,10 @@ class SearchActivity : AppCompatActivity(), OnItemClickListener { linearLayoutManager.findFirstVisibleItemPosition() ) intent.putExtra(SearchAdapter.DATA_BUNDLE, searchAdapterDataBundle) - intent.putExtra(FolioActivity.EXTRA_SEARCH_ITEM, viewHolder.searchLocator as Parcelable) + intent.putExtra( + FolioActivity.EXTRA_SEARCH_ITEM, + viewHolder.searchLocator as Parcelable + ) intent.putExtra(BUNDLE_SAVE_SEARCH_QUERY, searchView.query) setResult(ResultCode.ITEM_SELECTED.value, intent) finish() diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/DictionaryAdapter.java b/folioreader/src/main/java/com/folioreader/ui/adapter/DictionaryAdapter.java index b524e6904..e26c9e079 100644 --- a/folioreader/src/main/java/com/folioreader/ui/adapter/DictionaryAdapter.java +++ b/folioreader/src/main/java/com/folioreader/ui/adapter/DictionaryAdapter.java @@ -9,11 +9,17 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; + import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.Config; import com.folioreader.R; -import com.folioreader.model.dictionary.*; +import com.folioreader.model.dictionary.Audio; +import com.folioreader.model.dictionary.DictionaryResults; +import com.folioreader.model.dictionary.Example; +import com.folioreader.model.dictionary.Pronunciations; +import com.folioreader.model.dictionary.Senses; import com.folioreader.ui.base.DictionaryCallBack; import com.folioreader.util.AppUtil; diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/FolioPageFragmentAdapter.java b/folioreader/src/main/java/com/folioreader/ui/adapter/FolioPageFragmentAdapter.java index ba4caa8ca..24890e5c3 100644 --- a/folioreader/src/main/java/com/folioreader/ui/adapter/FolioPageFragmentAdapter.java +++ b/folioreader/src/main/java/com/folioreader/ui/adapter/FolioPageFragmentAdapter.java @@ -3,10 +3,13 @@ import android.os.Bundle; import android.util.Log; import android.view.ViewGroup; + import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; + import com.folioreader.ui.fragment.FolioPageFragment; + import org.readium.r2.shared.Link; import java.lang.reflect.Field; diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.java b/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.java deleted file mode 100644 index 69db5e9b4..000000000 --- a/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2016 Pedro Paulo de Amorim - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.folioreader.ui.adapter; - -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import androidx.recyclerview.widget.RecyclerView; -import com.folioreader.Font; -import com.folioreader.R; - -import java.util.ArrayList; - -public class FontAdapter extends RecyclerView.Adapter { - - private ArrayList mFonts = null; - - @Override - public FontAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int i) { - return new ViewHolder(LayoutInflater.from(parent.getContext()) - .inflate(R.layout.row_font, parent, false)); - } - - @Override - public void onBindViewHolder(ViewHolder viewHolder, int i) { - viewHolder.mName.setText(mFonts.get(i).getName()); - } - - @Override - public int getItemCount() { - return mFonts != null ? mFonts.size() : 0; - } - - public void setFonts(ArrayList mFonts) { - this.mFonts = mFonts; - } - - public static class ViewHolder extends RecyclerView.ViewHolder { - - private TextView mName; - - public ViewHolder(View v) { - super(v); - mName = (TextView) v.findViewById(R.id.name); - } - } -} diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.kt b/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.kt new file mode 100644 index 000000000..d0febf620 --- /dev/null +++ b/folioreader/src/main/java/com/folioreader/ui/adapter/FontAdapter.kt @@ -0,0 +1,72 @@ +package com.folioreader.ui.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Typeface +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.TextView +import androidx.core.content.ContextCompat +import com.folioreader.Config +import com.folioreader.R +import com.folioreader.util.FontFinder +import java.io.File + +class FontAdapter( + private val config: Config, + context: Context, + private val userFonts: Map = FontFinder.getUserFonts(), + private val systemFonts: Map = FontFinder.getSystemFonts(), + val fontKeyList: List = + ArrayList(userFonts.keys.toTypedArray().sorted()) + + ArrayList(systemFonts.keys.toTypedArray().sorted()) +) : ArrayAdapter(context, android.R.layout.simple_spinner_dropdown_item, fontKeyList) { + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = createTextView(position) + + if (config.isNightMode) { + view.setTextColor(ContextCompat.getColor(context, R.color.night_default_font_color)) + } else { + view.setTextColor(ContextCompat.getColor(context, R.color.day_default_font_color)) + } + + return view + } + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = createTextView(position) + + if (config.isNightMode) { + view.setBackgroundResource(R.color.night_background_color) + view.setTextColor(ContextCompat.getColor(context, R.color.night_default_font_color)) + } else { + view.setBackgroundResource(R.color.day_background_color) + view.setTextColor(ContextCompat.getColor(context, R.color.day_default_font_color)) + } + + return view + } + + @SuppressLint("ViewHolder", "InflateParams") + private fun createTextView(position: Int): TextView { + val inflater = + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + + val view = inflater.inflate(R.layout.item_styled_text, null) as TextView + + val fontKey = fontKeyList[position] + + view.text = fontKey + + if (userFonts.containsKey(fontKey)) { + view.typeface = Typeface.createFromFile(userFonts[fontKey]) + } else if (systemFonts.containsKey(fontKey)) { + view.typeface = Typeface.createFromFile(systemFonts[fontKey]) + } + + return view + } +} \ No newline at end of file diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/HighlightAdapter.java b/folioreader/src/main/java/com/folioreader/ui/adapter/HighlightAdapter.java index 4ffdc2ae2..c177b6d62 100644 --- a/folioreader/src/main/java/com/folioreader/ui/adapter/HighlightAdapter.java +++ b/folioreader/src/main/java/com/folioreader/ui/adapter/HighlightAdapter.java @@ -5,10 +5,16 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.*; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.Config; import com.folioreader.R; import com.folioreader.model.HighlightImpl; diff --git a/folioreader/src/main/java/com/folioreader/ui/adapter/TOCAdapter.java b/folioreader/src/main/java/com/folioreader/ui/adapter/TOCAdapter.java index 1abd330ad..d81a079ba 100644 --- a/folioreader/src/main/java/com/folioreader/ui/adapter/TOCAdapter.java +++ b/folioreader/src/main/java/com/folioreader/ui/adapter/TOCAdapter.java @@ -8,8 +8,10 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; + import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.Config; import com.folioreader.R; import com.folioreader.model.TOCLinkWrapper; @@ -113,7 +115,7 @@ public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { R.color.black)); } if (tocLinkWrapper.getTocLink().getHref().equals(selectedHref)) { - viewHolder.sectionTitle.setTextColor(mConfig.getThemeColor()); + viewHolder.sectionTitle.setTextColor(mConfig.getCurrentThemeColor()); } } diff --git a/folioreader/src/main/java/com/folioreader/ui/base/DictionaryTask.java b/folioreader/src/main/java/com/folioreader/ui/base/DictionaryTask.java index 0b8ad5a3e..6185e49f8 100644 --- a/folioreader/src/main/java/com/folioreader/ui/base/DictionaryTask.java +++ b/folioreader/src/main/java/com/folioreader/ui/base/DictionaryTask.java @@ -3,18 +3,20 @@ import android.os.AsyncTask; import android.os.Build; import android.util.Log; + import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.folioreader.model.dictionary.Dictionary; import com.folioreader.network.TLSSocketFactory; import com.folioreader.util.AppUtil; -import javax.net.ssl.HttpsURLConnection; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; +import javax.net.ssl.HttpsURLConnection; + /** * @author gautam chibde on 4/7/17. */ diff --git a/folioreader/src/main/java/com/folioreader/ui/base/HtmlTask.java b/folioreader/src/main/java/com/folioreader/ui/base/HtmlTask.java index d844a1dfd..f6bbf4246 100644 --- a/folioreader/src/main/java/com/folioreader/ui/base/HtmlTask.java +++ b/folioreader/src/main/java/com/folioreader/ui/base/HtmlTask.java @@ -2,6 +2,7 @@ import android.os.AsyncTask; import android.util.Log; + import com.folioreader.util.AppUtil; import java.io.BufferedReader; diff --git a/folioreader/src/main/java/com/folioreader/ui/base/HtmlUtil.java b/folioreader/src/main/java/com/folioreader/ui/base/HtmlUtil.java index 733bf5098..86ba637e9 100644 --- a/folioreader/src/main/java/com/folioreader/ui/base/HtmlUtil.java +++ b/folioreader/src/main/java/com/folioreader/ui/base/HtmlUtil.java @@ -1,9 +1,12 @@ package com.folioreader.ui.base; import android.content.Context; + import com.folioreader.Config; -import com.folioreader.Constants; import com.folioreader.R; +import com.folioreader.util.FontFinder; + +import java.io.File; /** * @author gautam chibde on 14/6/17. @@ -56,26 +59,34 @@ public static String getHtmlContent(Context context, String htmlContent, Config jsPath = jsPath + ""; - String toInject = "\n" + cssPath + "\n" + jsPath + "\n"; + String fontName = config.getFont(); + + System.out.println("Font family: " + fontName); + + // Inject CSS & user font style + String toInject = "\n" + cssPath + "\n" + jsPath + "\n"; + + File userFontFile = FontFinder.getFontFile(fontName); + if (userFontFile != null) { + System.out.println("Injected user font into CSS"); + System.out.println(" - path: " + userFontFile.getAbsolutePath()); + System.out.println(" - family: '" + fontName + "'"); + toInject += ""; + } + + toInject += ""; + htmlContent = htmlContent.replace("", toInject); - String classes = ""; - switch (config.getFont()) { - case Constants.FONT_ANDADA: - classes = "andada"; - break; - case Constants.FONT_LATO: - classes = "lato"; - break; - case Constants.FONT_LORA: - classes = "lora"; - break; - case Constants.FONT_RALEWAY: - classes = "raleway"; - break; - default: - break; - } + String classes = "custom-font"; if (config.isNightMode()) { classes += " nightMode"; @@ -101,8 +112,12 @@ public static String getHtmlContent(Context context, String htmlContent, Config break; } - htmlContent = htmlContent.replace("(R.id.pagesLeft) as TextView mMinutesLeftTextView = mRootView!!.findViewById(R.id.minutesLeft) as TextView @@ -169,6 +177,7 @@ class FolioPageFragment : Fragment(), mConfig = AppUtil.getSavedConfig(context) loadingView = mRootView!!.findViewById(R.id.loadingView) + setIndicatorVisibility() initSeekbar() initAnimations() initWebView() @@ -218,13 +227,18 @@ class FolioPageFragment : Fragment(), if (isAdded) { when (event.style) { MediaOverlayHighlightStyleEvent.Style.DEFAULT -> highlightStyle = - HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.Normal) + HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.Normal) MediaOverlayHighlightStyleEvent.Style.UNDERLINE -> highlightStyle = - HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.DottetUnderline) + HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.DottetUnderline) MediaOverlayHighlightStyleEvent.Style.BACKGROUND -> highlightStyle = - HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.TextColor) + HighlightImpl.HighlightStyle.classForStyle(HighlightImpl.HighlightStyle.TextColor) } - mWebview!!.loadUrl(String.format(getString(R.string.setmediaoverlaystyle), highlightStyle)) + mWebview!!.loadUrl( + String.format( + getString(R.string.setmediaoverlaystyle), + highlightStyle + ) + ) } } @@ -362,7 +376,8 @@ class FolioPageFragment : Fragment(), setupScrollBar() mWebview!!.addOnLayoutChangeListener { view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> - val height = Math.floor((mWebview!!.contentHeight * mWebview!!.scale).toDouble()).toInt() + val height = + Math.floor((mWebview!!.contentHeight * mWebview!!.scale).toDouble()).toInt() val webViewHeight = mWebview!!.measuredHeight mScrollSeekbar!!.maximum = height - webViewHeight } @@ -381,7 +396,7 @@ class FolioPageFragment : Fragment(), mWebview!!.setScrollListener(object : FolioWebView.ScrollListener { override fun onScrollChange(percent: Int) { - + setIndicatorVisibility() mScrollSeekbar!!.setProgressAndThumb(percent) updatePagesLeftText(percent) } @@ -466,7 +481,8 @@ class FolioPageFragment : Fragment(), readLocator = mActivityCallback!!.entryReadLocator } else { Log.v(LOG_TAG, "-> onPageFinished -> took from bundle") - readLocator = savedInstanceState!!.getParcelable(BUNDLE_READ_LOCATOR_CONFIG_CHANGE) + readLocator = + savedInstanceState!!.getParcelable(BUNDLE_READ_LOCATOR_CONFIG_CHANGE) savedInstanceState!!.remove(BUNDLE_READ_LOCATOR_CONFIG_CHANGE) } @@ -520,7 +536,10 @@ class FolioPageFragment : Fragment(), // prevent favicon.ico to be loaded automatically @SuppressLint("NewApi") - override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest + ): WebResourceResponse? { if (!request.isForMainFrame && request.url.path != null && request.url.path!!.endsWith("/favicon.ico") @@ -546,7 +565,12 @@ class FolioPageFragment : Fragment(), override fun onProgressChanged(view: WebView, progress: Int) {} - override fun onJsAlert(view: WebView, url: String, message: String, result: JsResult): Boolean { + override fun onJsAlert( + view: WebView, + url: String, + message: String, + result: JsResult + ): Boolean { // Check if this `if` block can be dropped? if (!this@FolioPageFragment.isVisible) @@ -561,7 +585,8 @@ class FolioPageFragment : Fragment(), } else { // to handle TTS playback when highlight is deleted. - val p = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}") + val p = + Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}") if (!p.matcher(message).matches() && message != "undefined" && isCurrentFragment) { mediaController!!.speakAudio(message) } @@ -636,9 +661,9 @@ class FolioPageFragment : Fragment(), } private fun setupScrollBar() { - UiUtil.setColorIntToDrawable(mConfig!!.themeColor, mScrollSeekbar!!.progressDrawable) + UiUtil.setColorIntToDrawable(mConfig!!.currentThemeColor, mScrollSeekbar!!.progressDrawable) val thumbDrawable = ContextCompat.getDrawable(activity!!, R.drawable.icons_sroll) - UiUtil.setColorIntToDrawable(mConfig!!.themeColor, thumbDrawable!!) + UiUtil.setColorIntToDrawable(mConfig!!.currentThemeColor, thumbDrawable!!) mScrollSeekbar!!.thumb = thumbDrawable } @@ -652,6 +677,18 @@ class FolioPageFragment : Fragment(), ) } + private fun setIndicatorVisibility() { + if (mConfig != null) { + mRootView?.findViewById(R.id.indicatorLayout)?.let { layout -> + layout.visibility = if (mConfig!!.isShowRemainingIndicator) { + View.VISIBLE + } else { + View.GONE + } + } + } + } + private fun updatePagesLeftTextBg() { if (mConfig!!.isNightMode) { @@ -665,8 +702,9 @@ class FolioPageFragment : Fragment(), private fun updatePagesLeftText(scrollY: Int) { try { - val currentPage = (Math.ceil(scrollY.toDouble() / mWebview!!.webViewHeight) + 1).toInt() - val totalPages = Math.ceil(mWebview!!.contentHeightVal.toDouble() / mWebview!!.webViewHeight).toInt() + val currentPage = (ceil(scrollY.toDouble() / mWebview!!.webViewHeight) + 1).toInt() + val totalPages = + ceil(mWebview!!.contentHeightVal.toDouble() / mWebview!!.webViewHeight).toInt() val pagesRemaining = totalPages - currentPage val pagesRemainingStrFormat = if (pagesRemaining > 1) getString(R.string.pages_left) @@ -677,20 +715,21 @@ class FolioPageFragment : Fragment(), pagesRemainingStrFormat, pagesRemaining ) - val minutesRemaining = Math.ceil((pagesRemaining * mTotalMinutes).toDouble() / totalPages).toInt() + val minutesRemaining = + ceil((pagesRemaining * mTotalMinutes).toDouble() / totalPages).toInt() val minutesRemainingStr: String - if (minutesRemaining > 1) { - minutesRemainingStr = String.format( + minutesRemainingStr = if (minutesRemaining > 1) { + String.format( Locale.US, getString(R.string.minutes_left), minutesRemaining ) } else if (minutesRemaining == 1) { - minutesRemainingStr = String.format( + String.format( Locale.US, getString(R.string.minute_left), minutesRemaining ) } else { - minutesRemainingStr = getString(R.string.less_than_minute) + getString(R.string.less_than_minute) } mMinutesLeftTextView!!.text = minutesRemainingStr diff --git a/folioreader/src/main/java/com/folioreader/ui/fragment/HighlightFragment.java b/folioreader/src/main/java/com/folioreader/ui/fragment/HighlightFragment.java index e4c8a9d16..9a1a154b2 100644 --- a/folioreader/src/main/java/com/folioreader/ui/fragment/HighlightFragment.java +++ b/folioreader/src/main/java/com/folioreader/ui/fragment/HighlightFragment.java @@ -11,12 +11,14 @@ import android.view.Window; import android.widget.EditText; import android.widget.Toast; + import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.Config; import com.folioreader.Constants; import com.folioreader.FolioReader; @@ -28,6 +30,7 @@ import com.folioreader.ui.adapter.HighlightAdapter; import com.folioreader.util.AppUtil; import com.folioreader.util.HighlightUtil; + import org.greenrobot.eventbus.EventBus; public class HighlightFragment extends Fragment implements HighlightAdapter.HighLightAdapterCallback { diff --git a/folioreader/src/main/java/com/folioreader/ui/fragment/MediaControllerFragment.kt b/folioreader/src/main/java/com/folioreader/ui/fragment/MediaControllerFragment.kt index 0e486f51e..50cca17bf 100644 --- a/folioreader/src/main/java/com/folioreader/ui/fragment/MediaControllerFragment.kt +++ b/folioreader/src/main/java/com/folioreader/ui/fragment/MediaControllerFragment.kt @@ -171,13 +171,17 @@ class MediaControllerFragment : BottomSheetDialogFragment() { config = AppUtil.getSavedConfig(context)!! if (Build.VERSION.SDK_INT >= 24) { - btnOneAndHalfSpeed?.text = Html.fromHtml(context!!.getString(R.string.one_and_half_speed), 0) + btnOneAndHalfSpeed?.text = + Html.fromHtml(context!!.getString(R.string.one_and_half_speed), 0) btnHalfSpeed?.text = Html.fromHtml(context!!.getString(R.string.half_speed_text), 0) - btnTextUnderlineStyle?.text = Html.fromHtml(context!!.getString(R.string.style_underline), 0) + btnTextUnderlineStyle?.text = + Html.fromHtml(context!!.getString(R.string.style_underline), 0) } else { - btnOneAndHalfSpeed?.text = Html.fromHtml(context!!.getString(R.string.one_and_half_speed)) + btnOneAndHalfSpeed?.text = + Html.fromHtml(context!!.getString(R.string.one_and_half_speed)) btnHalfSpeed?.text = Html.fromHtml(context!!.getString(R.string.half_speed_text)) - btnTextUnderlineStyle?.text = Html.fromHtml(context!!.getString(R.string.style_underline)) + btnTextUnderlineStyle?.text = + Html.fromHtml(context!!.getString(R.string.style_underline)) } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) @@ -193,31 +197,31 @@ class MediaControllerFragment : BottomSheetDialogFragment() { btnHalfSpeed?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) btnOneAndHalfSpeed?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) btnTwoXSpeed?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) btnOneXSpeed?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) btnTextUnderlineStyle?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) @@ -229,31 +233,41 @@ class MediaControllerFragment : BottomSheetDialogFragment() { ) btnBackColorStyle?.setBackgroundDrawable( UiUtil.createStateDrawable( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, android.R.color.transparent) ) ) btnTextColorStyle?.setTextColor( UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) ) - UiUtil.setColorIntToDrawable(config.themeColor, playPauseButton?.drawable) - UiUtil.setColorIntToDrawable(config.themeColor, nextButton?.drawable) - UiUtil.setColorIntToDrawable(config.themeColor, prevButton?.drawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, playPauseButton?.drawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, nextButton?.drawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, prevButton?.drawable) } private fun initListeners() { playPauseButton?.setOnClickListener { if (isPlaying) { - playPauseButton?.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_play)) - UiUtil.setColorIntToDrawable(config.themeColor, playPauseButton?.drawable) + playPauseButton?.setImageDrawable( + ContextCompat.getDrawable( + context!!, + R.drawable.ic_play + ) + ) + UiUtil.setColorIntToDrawable(config.currentThemeColor, playPauseButton?.drawable) callback.pause() } else { - playPauseButton?.setImageDrawable(ContextCompat.getDrawable(context!!, R.drawable.ic_pause)) - UiUtil.setColorIntToDrawable(config.themeColor, playPauseButton?.drawable) + playPauseButton?.setImageDrawable( + ContextCompat.getDrawable( + context!!, + R.drawable.ic_pause + ) + ) + UiUtil.setColorIntToDrawable(config.currentThemeColor, playPauseButton?.drawable) callback.play() } isPlaying = !isPlaying @@ -271,7 +285,8 @@ class MediaControllerFragment : BottomSheetDialogFragment() { btnOneAndHalfSpeed?.setOnClickListener { toggleSpeedControlButtons(false, false, true, false) - EventBus.getDefault().post(MediaOverlaySpeedEvent(MediaOverlaySpeedEvent.Speed.ONE_HALF)) + EventBus.getDefault() + .post(MediaOverlaySpeedEvent(MediaOverlaySpeedEvent.Speed.ONE_HALF)) } btnTwoXSpeed?.setOnClickListener { @@ -281,12 +296,14 @@ class MediaControllerFragment : BottomSheetDialogFragment() { btnBackColorStyle?.setOnClickListener { toggleTextStyle(true, false, false) - EventBus.getDefault().post(MediaOverlayHighlightStyleEvent(MediaOverlayHighlightStyleEvent.Style.DEFAULT)) + EventBus.getDefault() + .post(MediaOverlayHighlightStyleEvent(MediaOverlayHighlightStyleEvent.Style.DEFAULT)) } btnTextUnderlineStyle?.setOnClickListener { toggleTextStyle(false, true, false) - EventBus.getDefault().post(MediaOverlayHighlightStyleEvent(MediaOverlayHighlightStyleEvent.Style.UNDERLINE)) + EventBus.getDefault() + .post(MediaOverlayHighlightStyleEvent(MediaOverlayHighlightStyleEvent.Style.UNDERLINE)) } btnTextColorStyle?.setOnClickListener { @@ -302,7 +319,12 @@ class MediaControllerFragment : BottomSheetDialogFragment() { btnTextColorStyle?.isSelected = textColor } - private fun toggleSpeedControlButtons(half: Boolean, one: Boolean, oneHalf: Boolean, two: Boolean) { + private fun toggleSpeedControlButtons( + half: Boolean, + one: Boolean, + oneHalf: Boolean, + two: Boolean + ) { btnHalfSpeed?.isSelected = half btnOneXSpeed?.isSelected = one btnOneAndHalfSpeed?.isSelected = oneHalf diff --git a/folioreader/src/main/java/com/folioreader/ui/fragment/TableOfContentFragment.java b/folioreader/src/main/java/com/folioreader/ui/fragment/TableOfContentFragment.java index 5fdbebce2..5f3f54978 100644 --- a/folioreader/src/main/java/com/folioreader/ui/fragment/TableOfContentFragment.java +++ b/folioreader/src/main/java/com/folioreader/ui/fragment/TableOfContentFragment.java @@ -7,24 +7,31 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; + import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.DividerItemDecoration; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.Config; import com.folioreader.R; import com.folioreader.model.TOCLinkWrapper; import com.folioreader.ui.adapter.TOCAdapter; import com.folioreader.util.AppUtil; + import org.readium.r2.shared.Link; import org.readium.r2.shared.Publication; import java.util.ArrayList; import java.util.List; -import static com.folioreader.Constants.*; +import static com.folioreader.Constants.BOOK_TITLE; +import static com.folioreader.Constants.CHAPTER_SELECTED; +import static com.folioreader.Constants.PUBLICATION; +import static com.folioreader.Constants.SELECTED_CHAPTER_POSITION; +import static com.folioreader.Constants.TYPE; public class TableOfContentFragment extends Fragment implements TOCAdapter.TOCCallback { private TOCAdapter mTOCAdapter; diff --git a/folioreader/src/main/java/com/folioreader/ui/view/ConfigBottomSheetDialogFragment.kt b/folioreader/src/main/java/com/folioreader/ui/view/ConfigBottomSheetDialogFragment.kt index 0118a612e..ae945bb86 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/ConfigBottomSheetDialogFragment.kt +++ b/folioreader/src/main/java/com/folioreader/ui/view/ConfigBottomSheetDialogFragment.kt @@ -3,21 +3,23 @@ package com.folioreader.ui.view import android.animation.Animator import android.animation.ArgbEvaluator import android.animation.ValueAnimator +import android.graphics.PorterDuff import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.AdapterView import android.widget.FrameLayout import android.widget.SeekBar import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.folioreader.Config -import com.folioreader.Constants import com.folioreader.R import com.folioreader.model.event.ReloadDataEvent import com.folioreader.ui.activity.FolioActivity import com.folioreader.ui.activity.FolioActivityCallback +import com.folioreader.ui.adapter.FontAdapter import com.folioreader.ui.fragment.MediaControllerFragment import com.folioreader.util.AppUtil import com.folioreader.util.UiUtil @@ -34,6 +36,7 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { companion object { const val FADE_DAY_NIGHT_MODE = 500 + @JvmField val LOG_TAG: String = ConfigBottomSheetDialogFragment::class.java.simpleName } @@ -42,7 +45,11 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { private var isNightMode = false private lateinit var activityCallback: FolioActivityCallback - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { return inflater.inflate(R.layout.view_config, container) } @@ -86,12 +93,18 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { if (isNightMode) { view_config_ib_day_mode.isSelected = false view_config_ib_night_mode.isSelected = true - UiUtil.setColorIntToDrawable(config.themeColor, view_config_ib_night_mode.drawable) + UiUtil.setColorIntToDrawable( + config.currentThemeColor, + view_config_ib_night_mode.drawable + ) UiUtil.setColorResToDrawable(R.color.app_gray, view_config_ib_day_mode.drawable) } else { view_config_ib_day_mode.isSelected = true view_config_ib_night_mode.isSelected = false - UiUtil.setColorIntToDrawable(config.themeColor, view_config_ib_day_mode!!.drawable) + UiUtil.setColorIntToDrawable( + config.currentThemeColor, + view_config_ib_day_mode!!.drawable + ) UiUtil.setColorResToDrawable(R.color.app_gray, view_config_ib_night_mode.drawable) } } @@ -112,7 +125,8 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { setToolBarColor() setAudioPlayerBackground() UiUtil.setColorResToDrawable(R.color.app_gray, view_config_ib_night_mode.drawable) - UiUtil.setColorIntToDrawable(config.themeColor, view_config_ib_day_mode.drawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, view_config_ib_day_mode.drawable) + dialog?.hide() } view_config_ib_night_mode.setOnClickListener { @@ -121,9 +135,13 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { view_config_ib_day_mode.isSelected = false view_config_ib_night_mode.isSelected = true UiUtil.setColorResToDrawable(R.color.app_gray, view_config_ib_day_mode.drawable) - UiUtil.setColorIntToDrawable(config.themeColor, view_config_ib_night_mode.drawable) + UiUtil.setColorIntToDrawable( + config.currentThemeColor, + view_config_ib_night_mode.drawable + ) setToolBarColor() setAudioPlayerBackground() + dialog?.hide() } if (activityCallback.direction == Config.Direction.HORIZONTAL) { @@ -154,43 +172,55 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { private fun configFonts() { val colorStateList = UiUtil.getColorList( - config.themeColor, + config.currentThemeColor, ContextCompat.getColor(context!!, R.color.grey_color) ) + buttonVertical.setTextColor(colorStateList) buttonHorizontal.setTextColor(colorStateList) - view_config_font_andada.setTextColor(colorStateList) - view_config_font_lato.setTextColor(colorStateList) - view_config_font_lora.setTextColor(colorStateList) - view_config_font_raleway.setTextColor(colorStateList) - - view_config_font_andada.setOnClickListener { selectFont(Constants.FONT_ANDADA, true) } - view_config_font_lato.setOnClickListener { selectFont(Constants.FONT_LATO, true) } - view_config_font_lora.setOnClickListener { selectFont(Constants.FONT_LORA, true) } - view_config_font_raleway.setOnClickListener { selectFont(Constants.FONT_RALEWAY, true) } + + val adapter = FontAdapter(config, context!!) + + view_config_font_spinner.adapter = adapter + + view_config_font_spinner.background.setColorFilter( + if (config.isNightMode) { + R.color.night_default_font_color + } else { + R.color.day_default_font_color + }, + PorterDuff.Mode.SRC_ATOP + ) + + val fontIndex = adapter.fontKeyList.indexOf(config.font) + view_config_font_spinner.setSelection(if (fontIndex < 0) 0 else fontIndex) + + view_config_font_spinner.onItemSelectedListener = + object : AdapterView.OnItemSelectedListener { + override fun onItemSelected( + parent: AdapterView<*>?, + view: View?, + position: Int, + id: Long + ) { + selectFont(adapter.fontKeyList[position], true) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + } + } } - private fun selectFont(selectedFont: Int, isReloadNeeded: Boolean) { - when (selectedFont) { - Constants.FONT_ANDADA -> setSelectedFont(true, false, false, false) - Constants.FONT_LATO -> setSelectedFont(false, true, false, false) - Constants.FONT_LORA -> setSelectedFont(false, false, true, false) - Constants.FONT_RALEWAY -> setSelectedFont(false, false, false, true) - } + private fun selectFont(selectedFont: String, isReloadNeeded: Boolean) { + // parse font from name config.font = selectedFont + if (isAdded && isReloadNeeded) { AppUtil.saveConfig(activity, config) EventBus.getDefault().post(ReloadDataEvent()) } } - private fun setSelectedFont(andada: Boolean, lato: Boolean, lora: Boolean, raleway: Boolean) { - view_config_font_andada.isSelected = andada - view_config_font_lato.isSelected = lato - view_config_font_lora.isSelected = lora - view_config_font_raleway.isSelected = raleway - } - private fun toggleBlackTheme() { val day = ContextCompat.getColor(context!!, R.color.white) @@ -254,11 +284,15 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { private fun configSeekBar() { val thumbDrawable = ContextCompat.getDrawable(activity!!, R.drawable.seekbar_thumb) - UiUtil.setColorIntToDrawable(config.themeColor, thumbDrawable) - UiUtil.setColorResToDrawable(R.color.grey_color, view_config_font_size_seek_bar.progressDrawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, thumbDrawable) + UiUtil.setColorResToDrawable( + R.color.grey_color, + view_config_font_size_seek_bar.progressDrawable + ) view_config_font_size_seek_bar.thumb = thumbDrawable - view_config_font_size_seek_bar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { + view_config_font_size_seek_bar.setOnSeekBarChangeListener(object : + SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { config.fontSize = progress AppUtil.saveConfig(activity, config) @@ -281,8 +315,9 @@ class ConfigBottomSheetDialogFragment : BottomSheetDialogFragment() { private fun setAudioPlayerBackground() { - var mediaControllerFragment: Fragment? = fragmentManager?.findFragmentByTag(MediaControllerFragment.LOG_TAG) - ?: return + var mediaControllerFragment: Fragment? = + fragmentManager?.findFragmentByTag(MediaControllerFragment.LOG_TAG) + ?: return mediaControllerFragment = mediaControllerFragment as MediaControllerFragment if (isNightMode) { mediaControllerFragment.setDayMode() diff --git a/folioreader/src/main/java/com/folioreader/ui/view/DirectionalViewpager.java b/folioreader/src/main/java/com/folioreader/ui/view/DirectionalViewpager.java index a47067860..6abf9f596 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/DirectionalViewpager.java +++ b/folioreader/src/main/java/com/folioreader/ui/view/DirectionalViewpager.java @@ -12,24 +12,44 @@ import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.*; +import android.os.Build; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; -import android.view.*; +import android.view.FocusFinder; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; import android.view.accessibility.AccessibilityEvent; import android.view.animation.Interpolator; import android.widget.Scroller; + import androidx.annotation.CallSuper; import androidx.annotation.DrawableRes; import androidx.core.os.ParcelableCompat; import androidx.core.os.ParcelableCompatCreatorCallbacks; -import androidx.core.view.*; +import androidx.core.view.AccessibilityDelegateCompat; +import androidx.core.view.MotionEventCompat; +import androidx.core.view.VelocityTrackerCompat; +import androidx.core.view.ViewCompat; +import androidx.core.view.ViewConfigurationCompat; +import androidx.core.view.WindowInsetsCompat; import androidx.core.view.accessibility.AccessibilityEventCompat; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.core.view.accessibility.AccessibilityRecordCompat; import androidx.core.widget.EdgeEffectCompat; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; + import com.folioreader.Config; import com.folioreader.R; diff --git a/folioreader/src/main/java/com/folioreader/ui/view/FolioSearchView.kt b/folioreader/src/main/java/com/folioreader/ui/view/FolioSearchView.kt index 706502956..a50899d7d 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/FolioSearchView.kt +++ b/folioreader/src/main/java/com/folioreader/ui/view/FolioSearchView.kt @@ -27,12 +27,17 @@ class FolioSearchView : SearchView { constructor(context: Context?) : super(context) constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) fun init(componentName: ComponentName, config: Config) { Log.v(LOG_TAG, "-> init") - val searchManager: SearchManager = context.getSystemService(Context.SEARCH_SERVICE) as SearchManager + val searchManager: SearchManager = + context.getSystemService(Context.SEARCH_SERVICE) as SearchManager setSearchableInfo(searchManager.getSearchableInfo(componentName)) setIconifiedByDefault(false) @@ -56,17 +61,33 @@ class FolioSearchView : SearchView { Log.v(LOG_TAG, "-> applyTheme") val searchCloseButton: ImageView = findViewById(R.id.search_close_btn) - UiUtil.setColorIntToDrawable(config.themeColor, searchCloseButton.drawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, searchCloseButton.drawable) searchAutoComplete = findViewById(R.id.search_src_text) - UiUtil.setEditTextCursorColor(searchAutoComplete, config.themeColor) - UiUtil.setEditTextHandleColor(searchAutoComplete, config.themeColor) - searchAutoComplete.highlightColor = ColorUtils.setAlphaComponent(config.themeColor, 85) + UiUtil.setEditTextCursorColor(searchAutoComplete, config.currentThemeColor) + UiUtil.setEditTextHandleColor(searchAutoComplete, config.currentThemeColor) + searchAutoComplete.highlightColor = + ColorUtils.setAlphaComponent(config.currentThemeColor, 85) if (config.isNightMode) { - searchAutoComplete.setTextColor(ContextCompat.getColor(context, R.color.night_title_text_color)) - searchAutoComplete.setHintTextColor(ContextCompat.getColor(context, R.color.night_text_color)) + searchAutoComplete.setTextColor( + ContextCompat.getColor( + context, + R.color.night_title_text_color + ) + ) + searchAutoComplete.setHintTextColor( + ContextCompat.getColor( + context, + R.color.night_text_color + ) + ) } else { - searchAutoComplete.setHintTextColor(ContextCompat.getColor(context, R.color.edit_text_hint_color)) + searchAutoComplete.setHintTextColor( + ContextCompat.getColor( + context, + R.color.edit_text_hint_color + ) + ) } } diff --git a/folioreader/src/main/java/com/folioreader/ui/view/FolioWebView.kt b/folioreader/src/main/java/com/folioreader/ui/view/FolioWebView.kt index e6416d52f..5ddcab6aa 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/FolioWebView.kt +++ b/folioreader/src/main/java/com/folioreader/ui/view/FolioWebView.kt @@ -41,6 +41,7 @@ import kotlinx.android.synthetic.main.text_selection.view.* import org.json.JSONObject import org.springframework.util.ReflectionUtils import java.lang.ref.WeakReference +import kotlin.math.floor /** * @author by mahavir on 3/31/16. @@ -105,15 +106,19 @@ class FolioWebView : WebView { private var lastTouchAction: Int = 0 private var destroyed: Boolean = false private var handleHeight: Int = 0 + private var calculatedProgress = 0.0 private var lastScrollType: LastScrollType? = null val contentHeightVal: Int - get() = Math.floor((this.contentHeight * this.scale).toDouble()).toInt() + get() = floor((this.contentHeight * this.scale).toDouble()).toInt() val webViewHeight: Int get() = this.measuredHeight + val currentProgress: Double + get() = calculatedProgress + private enum class LastScrollType { USER, PROGRAMMATIC } @@ -156,13 +161,23 @@ class FolioWebView : WebView { private inner class HorizontalGestureListener : GestureDetector.SimpleOnGestureListener() { - override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean { + override fun onScroll( + e1: MotionEvent?, + e2: MotionEvent?, + distanceX: Float, + distanceY: Float + ): Boolean { //Log.d(LOG_TAG, "-> onScroll -> e1 = " + e1 + ", e2 = " + e2 + ", distanceX = " + distanceX + ", distanceY = " + distanceY); lastScrollType = LastScrollType.USER return false } - override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { + override fun onFling( + e1: MotionEvent?, + e2: MotionEvent?, + velocityX: Float, + velocityY: Float + ): Boolean { //Log.d(LOG_TAG, "-> onFling -> e1 = " + e1 + ", e2 = " + e2 + ", velocityX = " + velocityX + ", velocityY = " + velocityY); if (!webViewPager.isScrolling) { @@ -171,7 +186,7 @@ class FolioWebView : WebView { //Log.d(LOG_TAG, "-> onFling -> completing scroll"); uiHandler.postDelayed({ // Delayed to avoid inconsistency of scrolling in WebView - scrollTo(getScrollXPixelsForPage(webViewPager!!.currentItem), 0) + scrollTo(getScrollXPixelsForPage(webViewPager.currentItem), 0) }, 100) } @@ -212,13 +227,28 @@ class FolioWebView : WebView { private inner class VerticalGestureListener : GestureDetector.SimpleOnGestureListener() { - override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean { - //Log.v(LOG_TAG, "-> onScroll -> e1 = " + e1 + ", e2 = " + e2 + ", distanceX = " + distanceX + ", distanceY = " + distanceY); + override fun onScroll( + e1: MotionEvent?, + e2: MotionEvent?, + distanceX: Float, + distanceY: Float + ): Boolean { +// Log.v(LOG_TAG, "-> onScroll -> e1 = " + e1 + ", e2 = " + e2 + ", distanceX = " + distanceX + ", distanceY = " + distanceY); + parentFragment.mWebview?.let { wv -> + calculatedProgress = (wv.scrollY.toDouble() / wv.contentHeightVal.toDouble()) * 100.0 +// val fmtProgress = "%.2f".format(calculatedProgress) +// println("VProgress: $fmtProgress%") + } lastScrollType = LastScrollType.USER return false } - override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { + override fun onFling( + e1: MotionEvent?, + e2: MotionEvent?, + velocityX: Float, + velocityY: Float + ): Boolean { //Log.v(LOG_TAG, "-> onFling -> e1 = " + e1 + ", e2 = " + e2 + ", velocityX = " + velocityX + ", velocityY = " + velocityY); lastScrollType = LastScrollType.USER return false @@ -227,7 +257,11 @@ class FolioWebView : WebView { constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet) : super(context, attrs) - constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) private fun init() { Log.v(LOG_TAG, "-> init") @@ -315,7 +349,8 @@ class FolioWebView : WebView { R.id.copySelection -> { Log.v(LOG_TAG, "-> onTextSelectionItemClicked -> copySelection -> $selectedText") UiUtil.copyToClipboard(context, selectedText) - Toast.makeText(context, context.getString(R.string.copied), Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.copied), Toast.LENGTH_SHORT) + .show() } R.id.shareSelection -> { Log.v(LOG_TAG, "-> onTextSelectionItemClicked -> shareSelection -> $selectedText") @@ -336,7 +371,10 @@ class FolioWebView : WebView { val bundle = Bundle() bundle.putString(Constants.SELECTED_WORD, selectedText?.trim()) dictionaryFragment.arguments = bundle - dictionaryFragment.show(parentFragment.fragmentManager!!, DictionaryFragment::class.java.name) + dictionaryFragment.show( + parentFragment.fragmentManager!!, + DictionaryFragment::class.java.name + ) } private fun onHighlightColorItemsClicked(style: HighlightStyle, isAlreadyCreated: Boolean) { @@ -443,6 +481,14 @@ class FolioWebView : WebView { override fun scrollTo(x: Int, y: Int) { super.scrollTo(x, y) //Log.d(LOG_TAG, "-> scrollTo -> x = " + x); + + if (getDirection() == "HORIZONTAL") { // should always be true + calculatedProgress = + (webViewPager.currentItem.toDouble() / webViewPager.horizontalPageCount.toDouble()) * 100.0 +// val fmtProgress = "%.2f".format(calculatedProgress) +// println("HProgress: $fmtProgress%") + } + lastScrollType = LastScrollType.PROGRAMMATIC } @@ -580,7 +626,8 @@ class FolioWebView : WebView { if (Build.VERSION.SDK_INT < 23) { val folioActivityRef: WeakReference = folioActivityCallback.activity - val mWindowManagerField = ReflectionUtils.findField(FolioActivity::class.java, "mWindowManager") + val mWindowManagerField = + ReflectionUtils.findField(FolioActivity::class.java, "mWindowManager") mWindowManagerField.isAccessible = true val mWindowManager = mWindowManagerField.get(folioActivityRef.get()) @@ -596,19 +643,21 @@ class FolioWebView : WebView { val config = AppUtil.getSavedConfig(context)!! for (view in mViews) { - val handleViewClass = Class.forName("com.android.org.chromium.content.browser.input.HandleView") + val handleViewClass = + Class.forName("com.android.org.chromium.content.browser.input.HandleView") if (handleViewClass.isInstance(view)) { val mDrawableField = ReflectionUtils.findField(handleViewClass, "mDrawable") mDrawableField.isAccessible = true val mDrawable = mDrawableField.get(view) as BitmapDrawable - UiUtil.setColorIntToDrawable(config.themeColor, mDrawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, mDrawable) } } } else { val folioActivityRef: WeakReference = folioActivityCallback.activity - val mWindowManagerField = ReflectionUtils.findField(FolioActivity::class.java, "mWindowManager") + val mWindowManagerField = + ReflectionUtils.findField(FolioActivity::class.java, "mWindowManager") mWindowManagerField.isAccessible = true val mWindowManager = mWindowManagerField.get(folioActivityRef.get()) @@ -624,7 +673,8 @@ class FolioWebView : WebView { val config = AppUtil.getSavedConfig(context)!! for (view in mViews) { - val popupDecorViewClass = Class.forName("android.widget.PopupWindow\$PopupDecorView") + val popupDecorViewClass = + Class.forName("android.widget.PopupWindow\$PopupDecorView") if (!popupDecorViewClass.isInstance(view)) continue @@ -636,7 +686,10 @@ class FolioWebView : WebView { //val pathClassLoader = PathClassLoader("/system/app/Chrome/Chrome.apk", ClassLoader.getSystemClassLoader()) val pathClassLoader = - PathClassLoader("/system/app/Chrome/Chrome.apk", folioActivityRef.get()?.classLoader) + PathClassLoader( + "/system/app/Chrome/Chrome.apk", + folioActivityRef.get()?.classLoader + ) val popupTouchHandleDrawableClass = Class.forName( "org.chromium.android_webview.PopupTouchHandleDrawable", @@ -646,10 +699,11 @@ class FolioWebView : WebView { //if (!popupTouchHandleDrawableClass.isInstance(mChildren[0])) // continue - val mDrawableField = ReflectionUtils.findField(popupTouchHandleDrawableClass, "mDrawable") + val mDrawableField = + ReflectionUtils.findField(popupTouchHandleDrawableClass, "mDrawable") mDrawableField.isAccessible = true val mDrawable = mDrawableField.get(mChildren[0]) as Drawable - UiUtil.setColorIntToDrawable(config.themeColor, mDrawable) + UiUtil.setColorIntToDrawable(config.currentThemeColor, mDrawable) } } } diff --git a/folioreader/src/main/java/com/folioreader/ui/view/LoadingView.java b/folioreader/src/main/java/com/folioreader/ui/view/LoadingView.java index ae650d968..3c0ca0271 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/LoadingView.java +++ b/folioreader/src/main/java/com/folioreader/ui/view/LoadingView.java @@ -7,8 +7,10 @@ import android.view.LayoutInflater; import android.webkit.JavascriptInterface; import android.widget.ProgressBar; + import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.content.ContextCompat; + import com.folioreader.Config; import com.folioreader.R; import com.folioreader.util.AppUtil; @@ -75,7 +77,7 @@ public void updateTheme() { Config config = AppUtil.getSavedConfig(getContext()); if (config == null) config = new Config(); - UiUtil.setColorIntToDrawable(config.getThemeColor(), progressBar.getIndeterminateDrawable()); + UiUtil.setColorIntToDrawable(config.getCurrentThemeColor(), progressBar.getIndeterminateDrawable()); if (config.isNightMode()) { setBackgroundColor(ContextCompat.getColor(getContext(), R.color.night_background_color)); } else { diff --git a/folioreader/src/main/java/com/folioreader/ui/view/StyleableTextView.java b/folioreader/src/main/java/com/folioreader/ui/view/StyleableTextView.java index 00944fd95..06a3c5271 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/StyleableTextView.java +++ b/folioreader/src/main/java/com/folioreader/ui/view/StyleableTextView.java @@ -2,7 +2,9 @@ import android.content.Context; import android.util.AttributeSet; + import androidx.appcompat.widget.AppCompatTextView; + import com.folioreader.R; import com.folioreader.util.UiUtil; diff --git a/folioreader/src/main/java/com/folioreader/ui/view/UnderlinedTextView.java b/folioreader/src/main/java/com/folioreader/ui/view/UnderlinedTextView.java index 80d0ab8cf..46d314d6f 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/UnderlinedTextView.java +++ b/folioreader/src/main/java/com/folioreader/ui/view/UnderlinedTextView.java @@ -7,7 +7,9 @@ import android.graphics.Rect; import android.text.Layout; import android.util.AttributeSet; + import androidx.appcompat.widget.AppCompatTextView; + import com.folioreader.R; /** diff --git a/folioreader/src/main/java/com/folioreader/ui/view/VerticalSeekbar.java b/folioreader/src/main/java/com/folioreader/ui/view/VerticalSeekbar.java index cf9e4be74..8704a7bb8 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/VerticalSeekbar.java +++ b/folioreader/src/main/java/com/folioreader/ui/view/VerticalSeekbar.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; + import androidx.appcompat.widget.AppCompatSeekBar; /** diff --git a/folioreader/src/main/java/com/folioreader/ui/view/WebViewPager.kt b/folioreader/src/main/java/com/folioreader/ui/view/WebViewPager.kt index e81f1a692..0b7c1954f 100644 --- a/folioreader/src/main/java/com/folioreader/ui/view/WebViewPager.kt +++ b/folioreader/src/main/java/com/folioreader/ui/view/WebViewPager.kt @@ -18,7 +18,7 @@ class WebViewPager : ViewPager { val LOG_TAG: String = WebViewPager::class.java.simpleName } - private var horizontalPageCount: Int = 0 + internal var horizontalPageCount: Int = 0 private var folioWebView: FolioWebView? = null private var takeOverScrolling: Boolean = false var isScrolling: Boolean = false @@ -42,15 +42,20 @@ class WebViewPager : ViewPager { uiHandler = Handler() gestureDetector = GestureDetectorCompat(context, GestureListener()) - addOnPageChangeListener(object : ViewPager.OnPageChangeListener { - override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { + addOnPageChangeListener(object : OnPageChangeListener { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { // Log.d(LOG_TAG, "-> onPageScrolled -> position = " + position + // ", positionOffset = " + positionOffset + ", positionOffsetPixels = " + positionOffsetPixels); isScrolling = true if (takeOverScrolling && folioWebView != null) { - val scrollX = folioWebView!!.getScrollXPixelsForPage(position) + positionOffsetPixels + val scrollX = + folioWebView!!.getScrollXPixelsForPage(position) + positionOffsetPixels //Log.d(LOG_TAG, "-> onPageScrolled -> scrollX = " + scrollX); folioWebView!!.scrollTo(scrollX, 0) } @@ -128,13 +133,23 @@ class WebViewPager : ViewPager { lastGestureType = LastGestureType.OnLongPress } - override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean { + override fun onScroll( + e1: MotionEvent?, + e2: MotionEvent?, + distanceX: Float, + distanceY: Float + ): Boolean { //Log.v(LOG_TAG, "-> onScroll -> e1 = " + e1 + ", e2 = " + e2 + ", distanceX = " + distanceX + ", distanceY = " + distanceY); lastGestureType = LastGestureType.OnScroll return false } - override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean { + override fun onFling( + e1: MotionEvent?, + e2: MotionEvent?, + velocityX: Float, + velocityY: Float + ): Boolean { //Log.d(LOG_TAG, "-> onFling -> e1 = " + e1 + ", e2 = " + e2 + ", velocityX = " + velocityX + ", velocityY = " + velocityY); lastGestureType = LastGestureType.OnFling return false diff --git a/folioreader/src/main/java/com/folioreader/util/AppUtil.kt b/folioreader/src/main/java/com/folioreader/util/AppUtil.kt index 9b7958f44..f2f2df72b 100644 --- a/folioreader/src/main/java/com/folioreader/util/AppUtil.kt +++ b/folioreader/src/main/java/com/folioreader/util/AppUtil.kt @@ -62,7 +62,8 @@ class AppUtil { fun charsetNameForURLConnection(connection: URLConnection): String { // see https://stackoverflow.com/a/3934280/1027646 val contentType = connection.contentType - val values = contentType.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val values = + contentType.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() var charset: String? = null for (_value in values) { @@ -94,9 +95,11 @@ class AppUtil { obj.put(Config.CONFIG_FONT_SIZE, config.fontSize) obj.put(Config.CONFIG_IS_NIGHT_MODE, config.isNightMode) obj.put(Config.CONFIG_THEME_COLOR_INT, config.themeColor) + obj.put(Config.CONFIG_NIGHT_THEME_COLOR_INT, config.nightThemeColor) obj.put(Config.CONFIG_IS_TTS, config.isShowTts) obj.put(Config.CONFIG_ALLOWED_DIRECTION, config.allowedDirection.toString()) obj.put(Config.CONFIG_DIRECTION, config.direction.toString()) + obj.put(Config.CONFIG_REMAINING_INDICATOR, config.isShowRemainingIndicator) SharedPreferenceUtil.putSharedPreferencesString( context, Config.INTENT_CONFIG, obj.toString() @@ -111,12 +114,12 @@ class AppUtil { fun getSavedConfig(context: Context?): Config? { val json = getSharedPreferencesString(context, Config.INTENT_CONFIG, null) if (json != null) { - try { + return try { val jsonObject = JSONObject(json) - return Config(jsonObject) + Config(jsonObject) } catch (e: JSONException) { Log.e(LOG_TAG, e.message) - return null + null } } @@ -143,7 +146,8 @@ class AppUtil { } } - val index = action and MotionEvent.ACTION_POINTER_INDEX_MASK shr MotionEvent.ACTION_POINTER_INDEX_SHIFT + val index = + action and MotionEvent.ACTION_POINTER_INDEX_MASK shr MotionEvent.ACTION_POINTER_INDEX_SHIFT when (action and MotionEvent.ACTION_MASK) { MotionEvent.ACTION_POINTER_DOWN -> return "ACTION_POINTER_DOWN($index)" MotionEvent.ACTION_POINTER_UP -> return "ACTION_POINTER_UP($index)" diff --git a/folioreader/src/main/java/com/folioreader/util/FileUtil.java b/folioreader/src/main/java/com/folioreader/util/FileUtil.java index 64b488a77..2e6a9ab2a 100644 --- a/folioreader/src/main/java/com/folioreader/util/FileUtil.java +++ b/folioreader/src/main/java/com/folioreader/util/FileUtil.java @@ -6,10 +6,15 @@ import android.os.Environment; import android.text.TextUtils; import android.util.Log; + import com.folioreader.Constants; import com.folioreader.ui.activity.FolioActivity; -import java.io.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** * Created by Mahavir on 12/15/16. diff --git a/folioreader/src/main/java/com/folioreader/util/FontFinder.kt b/folioreader/src/main/java/com/folioreader/util/FontFinder.kt new file mode 100644 index 000000000..4c5a63b73 --- /dev/null +++ b/folioreader/src/main/java/com/folioreader/util/FontFinder.kt @@ -0,0 +1,79 @@ +package com.folioreader.util + +import android.os.Environment +import java.io.File + +/** + * @author Tyler Sedlar + */ +object FontFinder { + + private var sysFonts: Map? = null + + @JvmStatic + fun getSystemFonts(): Map { + if (sysFonts != null) { + return sysFonts!! + } + + val fonts = HashMap() + + val sysFontDir = File("/system/fonts/") + val fontSuffix = ".ttf" + + // Collect system fonts + for (fontFile in sysFontDir.listFiles()) { + val fontName: String = fontFile.name + if (fontName.endsWith(fontSuffix)) { + val key = fontName.subSequence(0, fontName.lastIndexOf(fontSuffix)).toString() + fonts[key] = fontFile + } + } + + sysFonts = fonts + + return fonts + } + + @JvmStatic + fun getUserFonts(): Map { + val fonts = HashMap() + + val fontDirs = arrayOf( + File(Environment.getExternalStorageDirectory(), "Fonts/") + ) + val fontSuffix = ".ttf" + + fontDirs.forEach { fontDir -> + // Collect user fonts + if (fontDir.exists() && fontDir.isDirectory) { + fontDir.walkTopDown() + .filter { f -> f.name.endsWith(fontSuffix) } + .forEach { fontFile -> + val fontName = fontFile.name + val key = + fontName.subSequence(0, fontName.lastIndexOf(fontSuffix)).toString() + fonts[key] = fontFile + } + } + } + return fonts + } + + @JvmStatic + fun getFontFile(key: String): File? { + val system = getSystemFonts() + val user = getUserFonts() + + return when { + system.containsKey(key) -> system[key] + user.containsKey(key) -> user[key] + else -> null + } + } + + @JvmStatic + fun isSystemFont(key: String): Boolean { + return getSystemFonts().containsKey(key) + } +} \ No newline at end of file diff --git a/folioreader/src/main/java/com/folioreader/util/HighlightUtil.java b/folioreader/src/main/java/com/folioreader/util/HighlightUtil.java index 2e2564a83..d6db36232 100644 --- a/folioreader/src/main/java/com/folioreader/util/HighlightUtil.java +++ b/folioreader/src/main/java/com/folioreader/util/HighlightUtil.java @@ -4,10 +4,13 @@ import android.content.Intent; import android.os.Bundle; import android.util.Log; + import androidx.localbroadcastmanager.content.LocalBroadcastManager; + import com.folioreader.model.HighLight; import com.folioreader.model.HighlightImpl; import com.folioreader.model.sqlite.HighLightTable; + import org.json.JSONException; import org.json.JSONObject; diff --git a/folioreader/src/main/java/com/folioreader/util/MultiLevelExpIndListAdapter.java b/folioreader/src/main/java/com/folioreader/util/MultiLevelExpIndListAdapter.java index 2fa049b07..ac27fcd75 100644 --- a/folioreader/src/main/java/com/folioreader/util/MultiLevelExpIndListAdapter.java +++ b/folioreader/src/main/java/com/folioreader/util/MultiLevelExpIndListAdapter.java @@ -1,6 +1,7 @@ package com.folioreader.util; import androidx.recyclerview.widget.RecyclerView; + import com.folioreader.model.TOCLinkWrapper; import java.util.ArrayList; diff --git a/folioreader/src/main/java/com/folioreader/util/ProgressDialog.java b/folioreader/src/main/java/com/folioreader/util/ProgressDialog.java index 1b3790286..344584a54 100644 --- a/folioreader/src/main/java/com/folioreader/util/ProgressDialog.java +++ b/folioreader/src/main/java/com/folioreader/util/ProgressDialog.java @@ -3,6 +3,7 @@ import android.app.Dialog; import android.content.Context; import android.widget.TextView; + import com.folioreader.R; public class ProgressDialog { diff --git a/folioreader/src/main/java/com/folioreader/util/SMILParser.java b/folioreader/src/main/java/com/folioreader/util/SMILParser.java index 247c53d95..97d17ac56 100644 --- a/folioreader/src/main/java/com/folioreader/util/SMILParser.java +++ b/folioreader/src/main/java/com/folioreader/util/SMILParser.java @@ -1,6 +1,7 @@ package com.folioreader.util; import com.folioreader.model.media_overlay.OverlayItems; + import org.w3c.dom.Element; import org.w3c.dom.Node; diff --git a/folioreader/src/main/java/com/folioreader/util/StyleableTextView.java b/folioreader/src/main/java/com/folioreader/util/StyleableTextView.java index 1d7f817d5..7d69da330 100644 --- a/folioreader/src/main/java/com/folioreader/util/StyleableTextView.java +++ b/folioreader/src/main/java/com/folioreader/util/StyleableTextView.java @@ -2,7 +2,9 @@ import android.content.Context; import android.util.AttributeSet; + import androidx.appcompat.widget.AppCompatTextView; + import com.folioreader.R; public class StyleableTextView extends AppCompatTextView { diff --git a/folioreader/src/main/java/com/folioreader/util/UiUtil.java b/folioreader/src/main/java/com/folioreader/util/UiUtil.java index 8bdb3cb80..015997573 100644 --- a/folioreader/src/main/java/com/folioreader/util/UiUtil.java +++ b/folioreader/src/main/java/com/folioreader/util/UiUtil.java @@ -26,12 +26,15 @@ import android.widget.Button; import android.widget.EditText; import android.widget.TextView; + import androidx.annotation.ColorInt; import androidx.annotation.ColorRes; import androidx.core.content.ContextCompat; + import com.folioreader.AppContext; import com.folioreader.R; import com.folioreader.ui.view.UnderlinedTextView; + import org.json.JSONException; import org.json.JSONObject; @@ -66,14 +69,14 @@ public static boolean setCustomFont(View view, Context ctx, String asset) { ((Button) view).setTypeface(tf); } } catch (Exception e) { - Log.e("AppUtil", "Could not get typface " + asset); + Log.e("AppUtil", "Could not get typeface " + asset); return false; } return true; } - private static final Hashtable> fontCache = new Hashtable>(); + private static final Hashtable> fontCache = new Hashtable<>(); public static Typeface getFont(Context c, String name) { synchronized (fontCache) { diff --git a/folioreader/src/main/java/com/folioreader/viewmodels/SearchViewModel.kt b/folioreader/src/main/java/com/folioreader/viewmodels/SearchViewModel.kt index 446077cb8..25a445fe3 100644 --- a/folioreader/src/main/java/com/folioreader/viewmodels/SearchViewModel.kt +++ b/folioreader/src/main/java/com/folioreader/viewmodels/SearchViewModel.kt @@ -93,11 +93,15 @@ class SearchViewModel : ViewModel() { ++successSearchCallCount val responseList: MutableList = bundle.getParcelableArrayList("DATA")!! - var liveList: MutableList = liveAdapterDataBundle.value!!.getParcelableArrayList("DATA")!! + var liveList: MutableList = + liveAdapterDataBundle.value!!.getParcelableArrayList("DATA")!! liveList = liveList.toMutableList() if (liveList.isEmpty()) { - bundle.putString(ListViewType.KEY, ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString()) + bundle.putString( + ListViewType.KEY, + ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString() + ) liveAdapterDataBundle.value = bundle } else { @@ -110,7 +114,10 @@ class SearchViewModel : ViewModel() { liveList.addAll(responseList) val dataBundle = Bundle() - dataBundle.putString(ListViewType.KEY, ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString()) + dataBundle.putString( + ListViewType.KEY, + ListViewType.PAGINATION_IN_PROGRESS_VIEW.toString() + ) dataBundle.putParcelableArrayList("DATA", ArrayList(liveList)) liveAdapterDataBundle.value = dataBundle } @@ -122,19 +129,21 @@ class SearchViewModel : ViewModel() { } if (--searchCallCount == 0) { - val liveList: MutableList = liveAdapterDataBundle.value!!.getParcelableArrayList("DATA")!! + val liveList: MutableList = + liveAdapterDataBundle.value!!.getParcelableArrayList("DATA")!! val dataBundle = Bundle() dataBundle.putParcelableArrayList("DATA", ArrayList(liveList)) - val liveListViewType: ListViewType = if (liveList.isEmpty() && errorSearchCallCount > 0) { - ListViewType.FAILURE_VIEW + val liveListViewType: ListViewType = + if (liveList.isEmpty() && errorSearchCallCount > 0) { + ListViewType.FAILURE_VIEW - } else if (liveList.isEmpty()) { - ListViewType.EMPTY_VIEW + } else if (liveList.isEmpty()) { + ListViewType.EMPTY_VIEW - } else { - ListViewType.NORMAL_VIEW - } + } else { + ListViewType.NORMAL_VIEW + } dataBundle.putString(ListViewType.KEY, liveListViewType.toString()) liveAdapterDataBundle.value = dataBundle diff --git a/folioreader/src/test/java/com/folioreader/android/EncoderDecoderUnitTest.kt b/folioreader/src/test/java/com/folioreader/android/EncoderDecoderUnitTest.kt index 16e27be30..bcbee4d80 100644 --- a/folioreader/src/test/java/com/folioreader/android/EncoderDecoderUnitTest.kt +++ b/folioreader/src/test/java/com/folioreader/android/EncoderDecoderUnitTest.kt @@ -18,8 +18,10 @@ class EncoderDecoderUnitTest { // We have "/OEBPS/Text/Chapter%201.html" in spine link of Publication model. val case1FilePath = "OEBPS/Text/Chapter 1.html" - val case1Encoding1 = URI(null, null, case1FilePath, null).toString() // OEBPS/Text/Chapter%201.html - val case1Encoding2 = URLEncoder.encode(case1FilePath, "UTF-8") // OEBPS%2FText%2FChapter+1.html + val case1Encoding1 = + URI(null, null, case1FilePath, null).toString() // OEBPS/Text/Chapter%201.html + val case1Encoding2 = + URLEncoder.encode(case1FilePath, "UTF-8") // OEBPS%2FText%2FChapter+1.html // So in Case 1, we need to pick case1Encoding1 // This logic can is implemented in Publication.isLinkWithHrefURIDecoded() @@ -33,9 +35,16 @@ class EncoderDecoderUnitTest { // We have "/OEBPS/Text/%E4%BA%B2%E5%AD%902018%E5%B9%B44%E6%9C%88%E5%88%8A_0001.xhtml" in spine link of Publication model. val case2FilePath = "OEBPS/Text/亲子2018年4月刊_0001.xhtml" - val case2LinkHref = "/OEBPS/Text/%E4%BA%B2%E5%AD%902018%E5%B9%B44%E6%9C%88%E5%88%8A_0001.xhtml" - val case2Decoding1 = URI(null, null, case2LinkHref, null).toString() // /OEBPS/Text/%25E4%25BA%25B2%25E5%25AD%25902018%25E5%25B9%25B44%25E6%259C%2588%25E5%2588%258A_0001.xhtml - val case2Decoding2 = URLDecoder.decode(case2LinkHref, "UTF-8") // /OEBPS/Text/亲子2018年4月刊_0001.xhtml + val case2LinkHref = + "/OEBPS/Text/%E4%BA%B2%E5%AD%902018%E5%B9%B44%E6%9C%88%E5%88%8A_0001.xhtml" + val case2Decoding1 = URI( + null, + null, + case2LinkHref, + null + ).toString() // /OEBPS/Text/%25E4%25BA%25B2%25E5%25AD%25902018%25E5%25B9%25B44%25E6%259C%2588%25E5%2588%258A_0001.xhtml + val case2Decoding2 = + URLDecoder.decode(case2LinkHref, "UTF-8") // /OEBPS/Text/亲子2018年4月刊_0001.xhtml // So in Case 2, we need to pick case2Decoding2 // This logic can is implemented in Publication.isLinkWithLinkHrefURLDecoded() @@ -49,9 +58,16 @@ class EncoderDecoderUnitTest { // We have "/OEBPS/Text/%D8%A7%D9%84%D9%85%D8%A7%D8%B6%D9%8A%20%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%82%D8%A8%D9%84.html" in spine link of Publication model. val case3FilePath = "OEBPS/Text/الماضي والمستقبل.html" - val case3LinkHref = "/OEBPS/Text/%D8%A7%D9%84%D9%85%D8%A7%D8%B6%D9%8A%20%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%82%D8%A8%D9%84.html" - val case3Decoding1 = URI(null, null, case3LinkHref, null).toString() // /OEBPS/Text/%25D8%25A7%25D9%2584%25D9%2585%25D8%25A7%25D8%25B6%25D9%258A%2520%25D9%2588%25D8%25A7%25D9%2584%25D9%2585%25D8%25B3%25D8%25AA%25D9%2582%25D8%25A8%25D9%2584.html - val case3Decoding2 = URLDecoder.decode(case3LinkHref, "UTF-8") // /OEBPS/Text/الماضي والمستقبل.html + val case3LinkHref = + "/OEBPS/Text/%D8%A7%D9%84%D9%85%D8%A7%D8%B6%D9%8A%20%D9%88%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%82%D8%A8%D9%84.html" + val case3Decoding1 = URI( + null, + null, + case3LinkHref, + null + ).toString() // /OEBPS/Text/%25D8%25A7%25D9%2584%25D9%2585%25D8%25A7%25D8%25B6%25D9%258A%2520%25D9%2588%25D8%25A7%25D9%2584%25D9%2585%25D8%25B3%25D8%25AA%25D9%2582%25D8%25A8%25D9%2584.html + val case3Decoding2 = + URLDecoder.decode(case3LinkHref, "UTF-8") // /OEBPS/Text/الماضي والمستقبل.html // So in Case 3, we need to pick case3Decoding2 // This logic can is implemented in Publication.isLinkWithLinkHrefURLDecoded() diff --git a/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java b/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java index 25c63427d..8cf949443 100644 --- a/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java +++ b/sample/src/main/java/com/folioreader/android/sample/HomeActivity.java @@ -15,6 +15,7 @@ */ package com.folioreader.android.sample; +import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.View; @@ -82,6 +83,9 @@ public void onClick(View v) { config = new Config(); config.setAllowedDirection(Config.AllowedDirection.VERTICAL_AND_HORIZONTAL); + config.setNightThemeColorInt(Color.parseColor("#FFFFFF")); + config.setShowRemainingIndicator(true); + folioReader.setReadLocator(readLocator); folioReader.setConfig(config, true) .openBook("file:///android_asset/TheSilverChair.epub");