Merge branch 'develop' into feature/yashk2000/1823-update-tab-color-in-night-mode

This commit is contained in:
Yash Khare 2020-03-26 01:26:12 +05:30 committed by GitHub
commit 3c874e8644
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 2360 additions and 2289 deletions

View File

@ -10,9 +10,6 @@
</value>
</option>
<option name="LINE_SEPARATOR" value="&#10;" />
<AndroidXmlCodeStyleSettings>
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings>
<GroovyCodeStyleSettings>
<option name="ALIGN_MULTILINE_LIST_OR_MAP" value="false" />
<option name="ALIGN_NAMED_ARGS_IN_MAP" value="false" />

View File

@ -43,9 +43,6 @@
<ID>ReturnCount:Fat32Checker.kt$Fat32Checker$private fun canCreate4GbFile(storage: String): Boolean</ID>
<ID>ReturnCount:LanguageActivity.kt$LanguageActivity$override fun onOptionsItemSelected(item: MenuItem): Boolean</ID>
<ID>ReturnCount:LibraryFragment.kt$LibraryFragment$private fun onBookItemClick(item: BookItem)</ID>
<ID>SpreadOperator:LanguageAdapter.kt$LanguageAdapter$(*delegates)</ID>
<ID>SpreadOperator:LibraryAdapter.kt$LibraryAdapter$( *delegates )</ID>
<ID>SpreadOperator:ZimManageViewModel.kt$ZimManageViewModel$(*disposables())</ID>
<ID>TooGenericExceptionCaught:FileWritingFileSystemChecker.kt$FileWritingFileSystemChecker$e: Exception</ID>
<ID>TooGenericExceptionCaught:KiwixMainActivity.kt$KiwixMainActivity$e: Exception</ID>
<ID>TooGenericExceptionThrown:ActivityExtensions.kt$throw RuntimeException( """ applicationContext is ${applicationContext::class.java.simpleName} application is ${application::class.java.simpleName} """.trimIndent() )</ID>

File diff suppressed because it is too large Load Diff

View File

@ -33,13 +33,13 @@ import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.main.WebViewCallback
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_ZIM_FILE
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_ARTICLES
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_FILE
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_POSITIONS
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_TAB
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_KIWIX_MOBILE
import org.kiwix.kiwixmobile.core.utils.EXTRA_ZIM_FILE
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_ARTICLES
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_POSITIONS
import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_TAB
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
import org.kiwix.kiwixmobile.core.utils.UpdateUtils.reformatProviderUrl
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
import org.kiwix.kiwixmobile.kiwixActivityComponent

View File

@ -29,7 +29,7 @@ import androidx.annotation.NonNull;
import androidx.core.app.NotificationCompat;
import javax.inject.Inject;
import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.core.utils.Constants;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.HOTSPOT_SERVICE_CHANNEL_ID;
import org.kiwix.kiwixmobile.webserver.ZimHostActivity;
public class HotspotNotificationManager {
@ -50,7 +50,7 @@ public class HotspotNotificationManager {
private void hotspotNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel hotspotServiceChannel = new NotificationChannel(
Constants.HOTSPOT_SERVICE_CHANNEL_ID,
HOTSPOT_SERVICE_CHANNEL_ID,
context.getString(R.string.hotspot_service_channel_name),
NotificationManager.IMPORTANCE_DEFAULT);
hotspotServiceChannel.setDescription(context.getString(R.string.hotspot_channel_description));
@ -81,7 +81,7 @@ public class HotspotNotificationManager {
.addAction(R.drawable.ic_close_white_24dp,
context.getString(R.string.stop),
stopHotspot)
.setChannelId(Constants.HOTSPOT_SERVICE_CHANNEL_ID)
.setChannelId(HOTSPOT_SERVICE_CHANNEL_ID)
.build();
}

View File

@ -40,7 +40,7 @@ import org.kiwix.kiwixmobile.core.base.BaseActivity
import org.kiwix.kiwixmobile.core.base.BaseFragment
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.viewModel
import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_STORAGE_PERMISSION
import org.kiwix.kiwixmobile.core.utils.REQUEST_STORAGE_PERMISSION
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BookOnDiskDelegate.BookDelegate

View File

@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@ -42,6 +48,7 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_secondary"
android:layout_gravity="start"
tools:text="Description" />
@ -56,13 +63,15 @@
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
android:orientation="horizontal"
android:layout_marginBottom="10dp">
<TextView
android:id="@+id/downloadState"
style="@style/list_item_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
android:layout_weight="1"
tools:text="In Progress" />
@ -71,6 +80,7 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
tools:text="1min 10secs" />
</LinearLayout>
</LinearLayout>
@ -93,3 +103,4 @@
app:srcCompat="@drawable/ic_stop_24dp" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@ -1,7 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin"
xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraint_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
@ -40,6 +48,9 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:textColor="@color/text_secondary"
android:maxLines="2"
android:ellipsize="end"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/libraryBookTitle"
app:layout_constraintTop_toBottomOf="@+id/libraryBookTitle"
@ -50,17 +61,23 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@+id/libraryBookDescription"
android:textColor="@color/text_tertiary"
app:layout_constraintStart_toStartOf="@+id/libraryBookTitle"
app:layout_constraintTop_toBottomOf="@+id/libraryBookDescription"
tools:text="File Size" />
<TextView
android:id="@+id/libraryBookCreator"
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
android:gravity="start"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintStart_toStartOf="@+id/libraryBookSize"
app:layout_constraintTop_toBottomOf="@+id/libraryBookSize"
app:layout_constraintEnd_toStartOf="@id/libraryBookDate"
tools:text="Author" />
<TextView
@ -68,6 +85,7 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
android:paddingBottom="@dimen/activity_horizontal_margin"
app:layout_constraintStart_toStartOf="@+id/libraryBookCreator"
app:layout_constraintTop_toBottomOf="@+id/libraryBookCreator"
@ -79,6 +97,7 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/libraryBookSize"
@ -89,6 +108,8 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
android:layout_marginStart="50dp"
app:layout_constraintEnd_toEndOf="@+id/libraryBookDate"
app:layout_constraintTop_toBottomOf="@+id/libraryBookDate"
tools:text="Language" />
@ -98,6 +119,7 @@
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
app:layout_constraintEnd_toEndOf="@+id/libraryBookLanguage"
app:layout_constraintTop_toBottomOf="@+id/libraryBookLanguage"
tools:text="File Name" />
@ -108,7 +130,7 @@
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/libraryBookTitle"
app:layout_constraintTop_toBottomOf="@id/libraryBookFileName" />
app:layout_constraintTop_toBottomOf="@id/libraryBookPublisher" />
<View
@ -117,10 +139,12 @@
android:layout_height="0dp"
android:alpha=".5"
android:background="@color/pure_grey"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="@id/constraint_layout"
app:layout_constraintEnd_toEndOf="@id/constraint_layout"
app:layout_constraintStart_toStartOf="@id/constraint_layout"
app:layout_constraintTop_toTopOf="@id/constraint_layout"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@ -15,7 +15,6 @@
<ID>MagicNumber:KiloByte.kt$KiloByte$1024.0</ID>
<ID>MagicNumber:MainMenu.kt$MainMenu$99</ID>
<ID>MagicNumber:SearchResultGenerator.kt$ZimSearchResultGenerator$200</ID>
<ID>MagicNumber:SearchViewModel.kt$SearchViewModel$100</ID>
<ID>MagicNumber:Seconds.kt$Seconds$24</ID>
<ID>MagicNumber:Seconds.kt$Seconds$60</ID>
<ID>MagicNumber:Seconds.kt$Seconds$60.0</ID>
@ -37,10 +36,6 @@
<ID>ReturnCount:FileUtils.kt$FileUtils$@JvmStatic fun hasPart(file: File): Boolean</ID>
<ID>ReturnCount:FileUtils.kt$FileUtils$@Synchronized private fun deleteZimFileParts(path: String): Boolean</ID>
<ID>ReturnCount:ImageUtils.kt$ImageUtils$private fun getBitmapFromView(width: Int, height: Int, viewToDrawFrom: View): Bitmap?</ID>
<ID>SpreadOperator:AlertDialogShower.kt$AlertDialogShower$(dialog.message, *bodyArguments(dialog))</ID>
<ID>SpreadOperator:BooksOnDiskAdapter.kt$BooksOnDiskAdapter$( *delegates )</ID>
<ID>SpreadOperator:FileSearch.kt$FileSearch$(*zimFileExtensions)</ID>
<ID>SpreadOperator:SearchAdapter.kt$SearchAdapter$(*delegates)</ID>
<ID>TooGenericExceptionThrown:AbstractContentProvider.kt$AbstractContentProvider$throw RuntimeException("Operation not supported")</ID>
<ID>TooGenericExceptionThrown:AdapterDelegateManager.kt$AdapterDelegateManager$throw RuntimeException("No delegate registered for $item")</ID>
<ID>TooGenericExceptionThrown:Bytes.kt$Bytes$throw RuntimeException("impossible value $size")</ID>
@ -52,6 +47,7 @@
<ID>TooManyFunctions:CoreComponent.kt$CoreComponent$CoreComponent</ID>
<ID>TooManyFunctions:FetchDownloadMonitor.kt$FetchDownloadMonitor$&lt;no name provided&gt; : FetchListener</ID>
<ID>TooManyFunctions:FileUtils.kt$FileUtils$FileUtils</ID>
<ID>TooManyFunctions:MainMenu.kt$MainMenu$MainMenu</ID>
<ID>TooManyFunctions:NewBookDao.kt$NewBookDao$NewBookDao</ID>
<ID>TooManyFunctions:Repository.kt$Repository$Repository</ID>
<ID>TooManyFunctions:ZimFileReader.kt$ZimFileReader$ZimFileReader</ID>

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -15,30 +15,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.base;
package org.kiwix.kiwixmobile.core.base
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.CompositeDisposable
import org.kiwix.kiwixmobile.core.base.BaseContract.Presenter
import org.kiwix.kiwixmobile.core.base.BaseContract.View
/**
* All presenters should inherit from this presenter.
*/
abstract class BasePresenter<T : View<*>?> : Presenter<T> {
@JvmField val compositeDisposable = CompositeDisposable()
@JvmField var view: T? = null
public abstract class BasePresenter<T extends BaseContract.View>
implements BaseContract.Presenter<T> {
protected final CompositeDisposable compositeDisposable = new CompositeDisposable();
protected T view;
@Override
public void attachView(T view) {
this.view = view;
override fun attachView(view: T) {
this.view = view
}
@Override
public void detachView() {
view = null;
if (!compositeDisposable.isDisposed()) {
compositeDisposable.dispose();
override fun detachView() {
view = null
if (!compositeDisposable.isDisposed) {
compositeDisposable.dispose()
}
}
}

View File

@ -51,9 +51,9 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.utils.DialogShower;
import org.kiwix.kiwixmobile.core.utils.KiwixDialog;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_TITLE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_URL;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_TITLE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_URL;
public class BookmarksActivity extends BaseActivity implements BookmarksContract.View,
BookmarksAdapter.OnItemClickListener {
@ -85,6 +85,7 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_context_delete, menu);
bookmarksSwitch.setEnabled(false);
return true;
}
@ -97,6 +98,7 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
refreshAdapter = false;
if (item.getItemId() == R.id.menu_context_delete) {
dialogShower.show(KiwixDialog.DeleteBookmarks.INSTANCE,(Function0<Unit>)() ->{
allBookmarks.removeAll(deleteList);
for (BookmarkItem bookmark : deleteList) {
int position = bookmarksList.indexOf(bookmark);
@ -106,6 +108,8 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
}
presenter.deleteBookmarks(new ArrayList<>(deleteList));
mode.finish();
return Unit.INSTANCE;
});
return true;
}
return false;
@ -120,6 +124,7 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
if (refreshAdapter) {
bookmarksAdapter.notifyDataSetChanged();
}
bookmarksSwitch.setEnabled(true);
}
};

View File

@ -45,7 +45,7 @@ import org.kiwix.kiwixmobile.core.data.local.entity.NetworkLanguageDatabaseEntit
import org.kiwix.kiwixmobile.core.data.local.entity.RecentSearch;
import org.kiwix.kiwixmobile.core.utils.UpdateUtils;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
@Singleton
@Deprecated //delete once migrations are no longer needed

View File

@ -45,7 +45,7 @@ fun Book.buildSearchableText(bookUtils: BookUtils): String =
append(NetworkUtils.parseURL(CoreApp.getInstance(), url))
append("|")
if (bookUtils.localeMap.containsKey(language)) {
append(bookUtils.localeMap[language]!!.displayLanguage)
append(bookUtils.localeMap[language]?.displayLanguage)
append("|")
}
}.toString()

View File

@ -33,7 +33,7 @@ import org.kiwix.kiwixmobile.core.base.BaseActivity;
import org.kiwix.kiwixmobile.core.di.components.CoreComponent;
import org.kiwix.kiwixmobile.core.utils.LanguageUtils;
import static org.kiwix.kiwixmobile.core.utils.Constants.CONTACT_EMAIL_ADDRESS;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.CONTACT_EMAIL_ADDRESS;
public class HelpActivity extends BaseActivity {

View File

@ -53,8 +53,8 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.utils.DialogShower;
import org.kiwix.kiwixmobile.core.utils.KiwixDialog;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_URL;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_URL;
public class HistoryActivity extends BaseActivity implements HistoryContract.View,
HistoryAdapter.OnItemClickListener {
@ -88,6 +88,7 @@ public class HistoryActivity extends BaseActivity implements HistoryContract.Vie
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_context_delete, menu);
historySwitch.setEnabled(false);
return true;
}
@ -137,6 +138,7 @@ public class HistoryActivity extends BaseActivity implements HistoryContract.Vie
if (refreshAdapter) {
historyAdapter.notifyDataSetChanged();
}
historySwitch.setEnabled(true);
}
};

View File

@ -136,8 +136,8 @@ public class AddNoteDialog extends DialogFragment
toolbar.setTitle(R.string.note);
toolbar.setNavigationIcon(R.drawable.ic_close_white_24dp);
toolbar.setNavigationOnClickListener(v -> {
closeKeyboard();
exitAddNoteDialog();
closeKeyboard();
});
toolbar.setOnMenuItemClickListener(item -> {

View File

@ -125,27 +125,27 @@ import static org.kiwix.kiwixmobile.core.downloader.fetch.FetchDownloadNotificat
import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.DocumentSection;
import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.TableClickListener;
import static org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate;
import static org.kiwix.kiwixmobile.core.utils.Constants.BOOKMARK_CHOSEN_REQUEST;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_TITLE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_URL;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_EXTERNAL_LINK;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_IS_WIDGET_VOICE;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_SEARCH;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_ZIM_FILE;
import static org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_FILE_SELECT;
import static org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_HISTORY_ITEM_CHOSEN;
import static org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_PREFERENCES;
import static org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_STORAGE_PERMISSION;
import static org.kiwix.kiwixmobile.core.utils.Constants.REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE;
import static org.kiwix.kiwixmobile.core.utils.Constants.RESULT_HISTORY_CLEARED;
import static org.kiwix.kiwixmobile.core.utils.Constants.RESULT_RESTART;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_ARTICLES;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_FILE;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_POSITIONS;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_CURRENT_TAB;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_FILE_SEARCHED;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.BOOKMARK_CHOSEN_REQUEST;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_FILE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_TITLE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_CHOSE_X_URL;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_EXTERNAL_LINK;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_IS_WIDGET_VOICE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_SEARCH;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_ZIM_FILE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_FILE_SELECT;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_HISTORY_ITEM_CHOSEN;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_PREFERENCES;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_STORAGE_PERMISSION;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.RESULT_HISTORY_CLEARED;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.RESULT_RESTART;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_CURRENT_ARTICLES;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_CURRENT_FILE;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_CURRENT_POSITIONS;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_CURRENT_TAB;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_FILE_SEARCHED;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.LanguageUtils.getResourceString;
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_KIWIX_MOBILE;
@ -413,7 +413,7 @@ public abstract class CoreMainActivity extends BaseActivity
private void handleIntentExtras(Intent intent) {
if (intent.hasExtra(TAG_FILE_SEARCHED)) {
searchForTitle(intent.getStringExtra(TAG_FILE_SEARCHED));
searchForTitle(intent.getStringExtra(TAG_FILE_SEARCHED), mainMenu.isInTabSwitcher());
selectTab(webViewList.size() - 1);
}
if (intent.hasExtra(EXTRA_CHOSE_X_URL)) {
@ -849,6 +849,9 @@ public abstract class CoreMainActivity extends BaseActivity
private void closeTab(int index) {
tempForUndo = webViewList.get(index);
webViewList.remove(index);
if (index <= currentWebViewIndex && currentWebViewIndex > 0) {
currentWebViewIndex--;
}
tabsAdapter.notifyItemRemoved(index);
tabsAdapter.notifyDataSetChanged();
Snackbar.make(tabSwitcherRoot, R.string.tab_closed, Snackbar.LENGTH_LONG)
@ -1277,6 +1280,12 @@ public abstract class CoreMainActivity extends BaseActivity
painter.update(getCurrentWebView(), videoView);
}
private void openFullScreenIfEnabled() {
if (isInFullScreenMode()) {
openFullScreen();
}
}
private void updateBottomToolbarVisibility() {
if (checkNull(bottomToolbar)) {
if (!urlIsInvalid()
@ -1367,6 +1376,13 @@ public abstract class CoreMainActivity extends BaseActivity
alertDialogShower.show(KiwixDialog.ContentsDrawerHint.INSTANCE);
}
private void openArticleInNewTab(String articleUrl) {
if (articleUrl != null) {
createNewTab();
loadUrlWithCurrentWebview(redirectOrOriginal(contentUrl(articleUrl)));
}
}
private void openArticle(String articleUrl) {
if (articleUrl != null) {
loadUrlWithCurrentWebview(redirectOrOriginal(contentUrl(articleUrl)));
@ -1413,7 +1429,7 @@ public abstract class CoreMainActivity extends BaseActivity
tabRecyclerView.setAdapter(tabsAdapter);
}
private void searchForTitle(String title) {
private void searchForTitle(String title, boolean openInNewTab) {
String articleUrl;
if (title.startsWith("A/")) {
@ -1421,17 +1437,21 @@ public abstract class CoreMainActivity extends BaseActivity
} else {
articleUrl = zimReaderContainer.getPageUrlFromTitle(title);
}
if (openInNewTab) {
openArticleInNewTab(articleUrl);
} else {
openArticle(articleUrl);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
hideTabSwitcher();
Log.i(TAG_KIWIX, "Intent data: " + data);
switch (requestCode) {
case MainMenuKt.REQUEST_FILE_SEARCH:
if (resultCode == RESULT_OK) {
boolean wasFromTabSwitcher = mainMenu.isInTabSwitcher();
hideTabSwitcher();
String title =
data.getStringExtra(TAG_FILE_SEARCHED).replace("<b>", "").replace("</b>", "");
boolean isSearchInText =
@ -1446,7 +1466,7 @@ public abstract class CoreMainActivity extends BaseActivity
compatCallback.findAll();
compatCallback.showSoftInput();
} else {
searchForTitle(title);
searchForTitle(title, wasFromTabSwitcher);
}
} else if (resultCode == RESULT_CANCELED) {
Log.w(TAG_KIWIX, "Search cancelled or exited");
@ -1456,6 +1476,7 @@ public abstract class CoreMainActivity extends BaseActivity
}
break;
case REQUEST_PREFERENCES:
hideTabSwitcher();
if (resultCode == RESULT_RESTART) {
recreate();
}
@ -1470,6 +1491,7 @@ public abstract class CoreMainActivity extends BaseActivity
case BOOKMARK_CHOSEN_REQUEST:
case REQUEST_FILE_SELECT:
case REQUEST_HISTORY_ITEM_CHOSEN:
hideTabSwitcher();
if (resultCode == RESULT_OK) {
if (data.getBooleanExtra(HistoryActivity.USER_CLEARED_HISTORY, false)) {
for (KiwixWebView kiwixWebView : webViewList) {
@ -1542,9 +1564,7 @@ public abstract class CoreMainActivity extends BaseActivity
backToTopButton.hide();
}
if (isInFullScreenMode()) {
openFullScreen();
}
openFullScreenIfEnabled();
painter.update(getCurrentWebView(), videoView);
}
@ -1611,6 +1631,7 @@ public abstract class CoreMainActivity extends BaseActivity
presenter.saveHistory(history);
}
updateBottomToolbarVisibility();
openFullScreenIfEnabled();
painter.update(getCurrentWebView(), videoView);
}

View File

@ -34,8 +34,8 @@ import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil;
import static org.kiwix.kiwixmobile.core.main.CoreMainActivity.HOME_URL;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_EXTERNAL_LINK;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_EXTERNAL_LINK;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
public abstract class CoreWebViewClient extends WebViewClient {
private static final HashMap<String, String> DOCUMENT_TYPES = new HashMap<String, String>() {{

View File

@ -42,7 +42,7 @@ import org.kiwix.kiwixmobile.core.extensions.ContextExtensionsKt;
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.utils.LanguageUtils;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
public class KiwixTextToSpeech {

View File

@ -32,8 +32,10 @@ import org.kiwix.kiwixmobile.core.history.HistoryActivity
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import org.kiwix.kiwixmobile.core.search.SearchActivity
import org.kiwix.kiwixmobile.core.settings.CoreSettingsActivity
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_ZIM_FILE
import org.kiwix.kiwixmobile.core.utils.EXTRA_ZIM_FILE
import org.kiwix.kiwixmobile.core.utils.TAG_FROM_TAB_SWITCHER
import org.kiwix.kiwixmobile.core.utils.REQUEST_HISTORY_ITEM_CHOSEN
import org.kiwix.kiwixmobile.core.utils.REQUEST_PREFERENCES
const val REQUEST_FILE_SEARCH = 1236
@ -91,6 +93,7 @@ class MainMenu(
private val help = menu.findItem(R.id.menu_help)
private val settings = menu.findItem(R.id.menu_settings)
private val supportKiwix = menu.findItem(R.id.menu_support_kiwix)
private var isInTabSwitcher: Boolean = false
init {
if (disableReadAloud) {
@ -114,13 +117,13 @@ class MainMenu(
settings.menuItemClickListener {
activity.startActivityForResult(
internal(CoreSettingsActivity::class.java),
Constants.REQUEST_PREFERENCES
REQUEST_PREFERENCES
)
}
history.menuItemClickListener {
activity.startActivityForResult(
activity.intent<HistoryActivity>(),
Constants.REQUEST_HISTORY_ITEM_CHOSEN
REQUEST_HISTORY_ITEM_CHOSEN
)
}
hostBooks.menuItemClickListener { menuClickListener.onHostBooksMenuClicked() }
@ -155,10 +158,12 @@ class MainMenu(
}
fun showTabSwitcherOptions() {
setVisibility(false, randomArticle, search, readAloud, addNote, fullscreen)
isInTabSwitcher = true
setVisibility(false, randomArticle, readAloud, addNote, fullscreen)
}
fun showWebViewOptions(urlIsValid: Boolean) {
isInTabSwitcher = false
fullscreen.isVisible = true
setVisibility(urlIsValid, randomArticle, search, readAloud, addNote)
}
@ -171,6 +176,7 @@ class MainMenu(
activity.startActivityForResult(
activity.intent<SearchActivity> {
putExtra(EXTRA_ZIM_FILE, zimFileReader.zimFile.absolutePath)
putExtra(TAG_FROM_TAB_SWITCHER, isInTabSwitcher)
},
REQUEST_FILE_SEARCH
)
@ -195,6 +201,8 @@ class MainMenu(
zimFileReader?.let(::navigateToSearch)
}
}
fun isInTabSwitcher(): Boolean = isInTabSwitcher
}
private fun MenuItem?.menuItemClickListener(function: (MenuItem) -> Unit) {

View File

@ -31,7 +31,7 @@ import org.kiwix.kiwixlib.JNIKiwix;
import org.kiwix.kiwixmobile.core.CoreApp;
import org.kiwix.kiwixmobile.core.data.AbstractContentProvider;
import static org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
public class ZimContentProvider extends AbstractContentProvider {

View File

@ -50,6 +50,7 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ExitedSearch
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemLongClick
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchViewModel
import org.kiwix.kiwixmobile.core.search.viewmodel.State
import org.kiwix.kiwixmobile.core.search.viewmodel.State.NoResults
@ -131,7 +132,9 @@ class SearchActivity : BaseActivity() {
return true
}
private fun render(state: State) = when (state) {
private fun render(state: State) {
searchInTextMenuItem.isVisible = state.searchOrigin == FromWebView
when (state) {
is Results -> {
searchViewAnimator.setDistinctDisplayedChild(0)
searchAdapter.items = state.values
@ -142,6 +145,7 @@ class SearchActivity : BaseActivity() {
render(state.searchString)
}
}
}
private fun render(searchString: String) {
searchInTextMenuItem.isEnabled = searchString.isNotBlank()

View File

@ -30,6 +30,7 @@ sealed class Action {
data class OnItemClick(val searchListItem: SearchListItem) : Action()
data class OnItemLongClick(val searchListItem: SearchListItem) : Action()
data class Filter(val term: String) : Action()
data class ScreenWasStartedFrom(val searchOrigin: SearchOrigin) : Action()
data class ConfirmedDelete(val searchListItem: SearchListItem) : Action()
data class CreatedWithIntent(val intent: Intent?) : Action()
data class ActivityResultReceived(val requestCode: Int, val resultCode: Int, val data: Intent?) :

View File

@ -22,7 +22,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import io.reactivex.Flowable
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.Function3
import io.reactivex.functions.Function4
import io.reactivex.processors.BehaviorProcessor
import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers
@ -40,7 +40,9 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemLongClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.StartSpeechInputFailed
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.search.viewmodel.State.NoResults
import org.kiwix.kiwixmobile.core.search.viewmodel.State.Results
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.DeleteRecentSearch
@ -61,10 +63,11 @@ class SearchViewModel @Inject constructor(
private val searchResultGenerator: SearchResultGenerator
) : ViewModel() {
val state = MutableLiveData<State>().apply { value = NoResults("") }
val state = MutableLiveData<State>().apply { value = NoResults("", FromWebView) }
val effects = PublishProcessor.create<SideEffect<*>>()
val actions = PublishProcessor.create<Action>()
private val filter = BehaviorProcessor.createDefault("")
private val searchOrigin = BehaviorProcessor.createDefault(FromWebView)
private val compositeDisposable = CompositeDisposable()
@ -93,6 +96,7 @@ class SearchViewModel @Inject constructor(
StartSpeechInputFailed -> effects.offer(ShowToast(R.string.speech_not_supported))
is ActivityResultReceived ->
effects.offer(ProcessActivityResult(it.requestCode, it.resultCode, it.data, actions))
is ScreenWasStartedFrom -> searchOrigin.offer(it.searchOrigin)
}
}.subscribe(
{},
@ -125,19 +129,21 @@ class SearchViewModel @Inject constructor(
recentSearchDao.recentSearches(zimReaderContainer.id),
searchResultsFromZimReader(),
filter,
Function3(this::reduce)
searchOrigin,
Function4(this::reduce)
).subscribe(state::postValue, Throwable::printStackTrace)
private fun reduce(
recentSearchResults: List<SearchListItem>,
zimSearchResults: List<SearchListItem>,
searchString: String
searchString: String,
searchOrigin: SearchOrigin
) = when {
searchString.isNotEmpty() && zimSearchResults.isNotEmpty() ->
Results(searchString, zimSearchResults)
Results(searchString, zimSearchResults, searchOrigin)
searchString.isEmpty() && recentSearchResults.isNotEmpty() ->
Results(searchString, recentSearchResults)
else -> NoResults(searchString)
Results(searchString, recentSearchResults, searchOrigin)
else -> NoResults(searchString, searchOrigin)
}
private fun searchResultsFromZimReader() = filter

View File

@ -20,9 +20,21 @@ package org.kiwix.kiwixmobile.core.search.viewmodel
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
enum class SearchOrigin {
FromWebView,
FromTabView
}
sealed class State {
abstract val searchString: String
abstract val searchOrigin: SearchOrigin
data class Results(override val searchString: String, val values: List<SearchListItem>) : State()
data class NoResults(override val searchString: String) : State()
data class Results(
override val searchString: String,
val values: List<SearchListItem>,
override val searchOrigin: SearchOrigin
) : State()
data class NoResults(override val searchString: String, override val searchOrigin: SearchOrigin) :
State()
}

View File

@ -23,13 +23,13 @@ import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
data class OpenSearchItem(private val searchListItem: SearchListItem) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
activity.setResult(
Activity.RESULT_OK,
Intent().putExtra(Constants.TAG_FILE_SEARCHED, searchListItem.value)
Intent().putExtra(TAG_FILE_SEARCHED, searchListItem.value)
)
activity.finish()
}

View File

@ -22,7 +22,7 @@ import android.app.Activity
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
data class SearchInPreviousScreen(private val searchString: String) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
@ -30,7 +30,7 @@ data class SearchInPreviousScreen(private val searchString: String) : SideEffect
Activity.RESULT_OK,
Intent().apply {
putExtra(EXTRA_SEARCH_IN_TEXT, true)
putExtra(Constants.TAG_FILE_SEARCHED, searchString)
putExtra(TAG_FILE_SEARCHED, searchString)
}
)
activity.finish()

View File

@ -27,7 +27,12 @@ import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.utils.EXTRA_SEARCH
import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE
import org.kiwix.kiwixmobile.core.utils.TAG_FROM_TAB_SWITCHER
data class SearchIntentProcessing(
private val intent: Intent?,
@ -35,14 +40,20 @@ data class SearchIntentProcessing(
) : SideEffect<Unit> {
@TargetApi(VERSION_CODES.M)
override fun invokeWith(activity: AppCompatActivity) {
if (intent != null) {
if (intent.hasExtra(Intent.EXTRA_PROCESS_TEXT)) {
actions.offer(Filter(intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT)))
intent?.let {
actions.offer(
ScreenWasStartedFrom(
if (it.getBooleanExtra(TAG_FROM_TAB_SWITCHER, false)) FromTabView
else FromWebView
)
)
if (it.hasExtra(Intent.EXTRA_PROCESS_TEXT)) {
actions.offer(Filter(it.getStringExtra(Intent.EXTRA_PROCESS_TEXT)))
}
if (intent.hasExtra(Constants.EXTRA_SEARCH)) {
actions.offer(Filter(intent.getStringExtra(Constants.EXTRA_SEARCH)))
if (intent.hasExtra(EXTRA_SEARCH)) {
actions.offer(Filter(intent.getStringExtra(EXTRA_SEARCH)))
}
if (intent.getBooleanExtra(Constants.EXTRA_IS_WIDGET_VOICE, false)) {
if (intent.getBooleanExtra(EXTRA_IS_WIDGET_VOICE, false)) {
actions.offer(ReceivedPromptForSpeechInput)
}
}

View File

@ -55,7 +55,7 @@ import org.kiwix.kiwixmobile.core.utils.KiwixDialog;
import org.kiwix.kiwixmobile.core.utils.LanguageUtils;
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil;
import static org.kiwix.kiwixmobile.core.utils.Constants.RESULT_RESTART;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.RESULT_RESTART;
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_NIGHT_MODE;
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_STORAGE;
import static org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.PREF_ZOOM;

View File

@ -25,8 +25,8 @@ import androidx.appcompat.widget.Toolbar;
import org.kiwix.kiwixmobile.core.R;
import org.kiwix.kiwixmobile.core.base.BaseActivity;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_WEBVIEWS_LIST;
import static org.kiwix.kiwixmobile.core.utils.Constants.RESULT_HISTORY_CLEARED;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.EXTRA_WEBVIEWS_LIST;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.RESULT_HISTORY_CLEARED;
public abstract class CoreSettingsActivity extends BaseActivity {

View File

@ -1,60 +0,0 @@
/*
* Kiwix Android
* Copyright (c) 2019 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.utils;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* Created by mhutti1 on 19/04/17.
*/
public class BookUtils {
public final Map<String, Locale> localeMap;
// Create a map of ISO 369-2 language codes
public BookUtils() {
String[] languages = Locale.getISOLanguages();
localeMap = new HashMap<>(languages.length);
for (String language : languages) {
Locale locale = new Locale(language);
localeMap.put(locale.getISO3Language(), locale);
}
}
// Get the language from the language codes of the parsed xml stream
public String getLanguage(String languageCode) {
if (languageCode == null) {
return "";
}
if (languageCode.length() == 2) {
return new LanguageContainer(languageCode).getLanguageName();
} else if (languageCode.length() == 3) {
try {
return localeMap.get(languageCode).getDisplayLanguage();
} catch (Exception e) {
return "";
}
}
return "";
}
}

View File

@ -0,0 +1,38 @@
/*
* Kiwix Android
* Copyright (c) 2020 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.utils
import java.util.Locale
/**
* Created by mhutti1 on 19/04/17.
*/
class BookUtils {
val localeMap = Locale.getISOLanguages().map(::Locale).associateBy { it.isO3Language }
// Get the language from the language codes of the parsed xml stream
@Suppress("MagicNumber")
fun getLanguage(languageCode: String?): String {
return when {
languageCode == null -> ""
languageCode.length == 2 -> LanguageContainer(languageCode).languageName
languageCode.length == 3 -> localeMap[languageCode]?.displayLanguage.orEmpty()
else -> ""
}
}
}

View File

@ -1,77 +0,0 @@
/*
* Kiwix Android
* Copyright (c) 2019 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.utils;
public final class Constants {
public static final String TAG_KIWIX = "kiwix";
public static final String CONTACT_EMAIL_ADDRESS = "android@kiwix.org";
// Request stuff
public static final int REQUEST_STORAGE_PERMISSION = 1;
public static final int REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE = 3;
public static final int REQUEST_HISTORY_ITEM_CHOSEN = 99;
public static final int REQUEST_FILE_SELECT = 1234;
public static final int REQUEST_PREFERENCES = 1235;
public static final int BOOKMARK_CHOSEN_REQUEST = 1;
// Result stuff
public static final int RESULT_RESTART = 1236;
public static final int RESULT_HISTORY_CLEARED = 1239;
// Tags
public static final String TAG_FILE_SEARCHED = "searchedarticle";
public static final String TAG_CURRENT_FILE = "currentzimfile";
public static final String TAG_CURRENT_ARTICLES = "currentarticles";
public static final String TAG_CURRENT_POSITIONS = "currentpositions";
public static final String TAG_CURRENT_TAB = "currenttab";
// Extras
public static final String EXTRA_ZIM_FILE = "zimFile";
public static final String EXTRA_CHOSE_X_URL = "choseXURL";
public static final String EXTRA_CHOSE_X_TITLE = "choseXTitle";
public static final String EXTRA_CHOSE_X_FILE = "choseXFile";
public static final String EXTRA_EXTERNAL_LINK = "external_link";
public static final String EXTRA_SEARCH = "search";
public static final String EXTRA_IS_WIDGET_VOICE = "isWidgetVoice";
public static final String HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService";
public static final String EXTRA_WEBVIEWS_LIST = "webviewsList";
public static final String EXTRA_SEARCH_TEXT = "searchText";
public static final String OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base";
}

View File

@ -0,0 +1,53 @@
/*
* Kiwix Android
* Copyright (c) 2020 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.utils
const val TAG_KIWIX = "kiwix"
const val CONTACT_EMAIL_ADDRESS = "android@kiwix.org"
// Request stuff
const val REQUEST_STORAGE_PERMISSION = 1
const val REQUEST_WRITE_STORAGE_PERMISSION_ADD_NOTE = 3
const val REQUEST_HISTORY_ITEM_CHOSEN = 99
const val REQUEST_FILE_SELECT = 1234
const val REQUEST_PREFERENCES = 1235
const val BOOKMARK_CHOSEN_REQUEST = 1
// Result stuff
const val RESULT_RESTART = 1236
const val RESULT_HISTORY_CLEARED = 1239
// Tags
const val TAG_FILE_SEARCHED = "searchedarticle"
const val TAG_CURRENT_FILE = "currentzimfile"
const val TAG_CURRENT_ARTICLES = "currentarticles"
const val TAG_CURRENT_POSITIONS = "currentpositions"
const val TAG_CURRENT_TAB = "currenttab"
const val TAG_FROM_TAB_SWITCHER = "fromtabswitcher"
// Extras
const val EXTRA_ZIM_FILE = "zimFile"
const val EXTRA_CHOSE_X_URL = "choseXURL"
const val EXTRA_CHOSE_X_TITLE = "choseXTitle"
const val EXTRA_CHOSE_X_FILE = "choseXFile"
const val EXTRA_EXTERNAL_LINK = "external_link"
const val EXTRA_SEARCH = "search"
const val EXTRA_IS_WIDGET_VOICE = "isWidgetVoice"
const val HOTSPOT_SERVICE_CHANNEL_ID = "hotspotService"
const val EXTRA_WEBVIEWS_LIST = "webviewsList"
const val OLD_PROVIDER_DOMAIN = "org.kiwix.zim.base"

View File

@ -110,16 +110,14 @@ sealed class KiwixDialog(
R.string.did_you_know,
R.string.hint_contents_drawer_message,
R.string.got_it,
null,
icon = R.drawable.icon_question
null
)
object ExternalLinkPopup : KiwixDialog(
R.string.external_link_popup_dialog_title,
R.string.external_link_popup_dialog_message,
android.R.string.yes,
android.R.string.no,
icon = R.drawable.ic_warning,
R.string.yes,
R.string.no,
neutralMessage = R.string.do_not_ask_anymore
)
@ -141,17 +139,15 @@ sealed class KiwixDialog(
object ClearAllHistory : KiwixDialog(
R.string.clear_all_history_dialog_title,
R.string.clear_recent_and_tabs_history_dialog,
R.string.yes,
R.string.no,
icon = R.drawable.ic_warning
positiveMessage = R.string.delete,
negativeMessage = R.string.cancel
)
object ClearAllNotes : KiwixDialog(
R.string.delete_notes_confirmation_msg,
message = null,
positiveMessage = R.string.yes,
negativeMessage = R.string.no,
icon = R.drawable.ic_warning
positiveMessage = R.string.delete,
negativeMessage = R.string.cancel
)
data class OpenCredits(val customGetView: (() -> View)?) : KiwixDialog(
@ -187,17 +183,17 @@ sealed class KiwixDialog(
}
object DeleteHistory : KiwixDialog(
null,
R.string.delete_history,
R.string.yes,
R.string.no
null,
positiveMessage = R.string.delete,
negativeMessage = R.string.cancel
)
object DeleteBookmarks : KiwixDialog(
null,
R.string.delete_bookmarks,
R.string.yes,
R.string.no
null,
positiveMessage = R.string.delete,
negativeMessage = R.string.cancel
)
}

View File

@ -32,7 +32,6 @@ import android.view.View
import android.widget.TextView
import androidx.core.os.ConfigurationCompat
import org.kiwix.kiwixmobile.core.extensions.locale
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX
import org.kiwix.kiwixmobile.core.utils.files.FileUtils
import java.text.Collator
import java.util.Locale

View File

@ -25,6 +25,8 @@ import android.util.Log;
import java.util.UUID;
import org.kiwix.kiwixmobile.core.R;
import static org.kiwix.kiwixmobile.core.utils.ConstantsKt.TAG_KIWIX;
public class NetworkUtils {
/**
* check availability of any network
@ -115,7 +117,7 @@ public class NetworkUtils {
details = details.trim().replaceAll(" +", " ");
return details;
} catch (Exception e) {
Log.d(Constants.TAG_KIWIX, "Context invalid url: " + url, e);
Log.d(TAG_KIWIX, "Context invalid url: " + url, e);
return "";
}
}

View File

@ -19,7 +19,6 @@
package org.kiwix.kiwixmobile.core.utils
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.utils.Constants.OLD_PROVIDER_DOMAIN
object UpdateUtils {
@JvmStatic

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24dp">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24dp">
<path
android:fillColor="#FF000000"
android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z" />
</vector>

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24dp">
<path
android:fillColor="#2DA369"
android:pathData="M11,18h2v-2h-2v2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM12,6c-2.21,0 -4,1.79 -4,4h2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2c0,2 -3,1.75 -3,5h2c0,-2.25 3,-2.5 3,-5 0,-2.21 -1.79,-4 -4,-4z" />
</vector>

View File

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
tools:ignore="Overdraw">
android:layout_margin="@dimen/card_margin">
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/horizontal_padding"
@ -54,13 +57,28 @@
app:layout_constraintTop_toBottomOf="@+id/vertical_padding"
tools:text="Wikipedia" />
<TextView
android:id="@+id/item_book_description"
style="@style/list_item_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/text_secondary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/item_book_title"
app:layout_constraintTop_toBottomOf="@id/item_book_title"
tools:text="All wikipedia articles" />
<TextView
android:id="@+id/item_book_date"
style="@style/list_item_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/text_tertiary"
app:layout_constraintStart_toStartOf="@id/item_book_title"
app:layout_constraintTop_toBottomOf="@id/item_book_title"
app:layout_constraintTop_toBottomOf="@id/item_book_description"
tools:text="1 Jan 2018" />
<TextView
@ -70,6 +88,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:textColor="@color/text_tertiary"
app:layout_constraintStart_toEndOf="@id/item_book_date"
app:layout_constraintTop_toTopOf="@id/item_book_date"
tools:text="20 GB" />
@ -81,36 +100,18 @@
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:textColor="@color/text_tertiary"
app:layout_constraintStart_toEndOf="@id/item_book_size"
app:layout_constraintTop_toTopOf="@id/item_book_size"
tools:text="10.1 K articles" />
<TextView
android:id="@+id/item_book_description"
style="@style/list_item_body"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@id/item_book_title"
app:layout_constraintTop_toBottomOf="@id/item_book_date"
tools:text="All wikipedia articles" />
<org.kiwix.kiwixmobile.core.zim_manager.TagsView
android:id="@+id/tags"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/item_book_description"
app:layout_constraintTop_toBottomOf="@id/item_book_description" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="?android:attr/dividerVertical"
app:layout_constraintStart_toStartOf="@id/item_book_title"
app:layout_constraintTop_toBottomOf="@id/tags" />
app:layout_constraintTop_toBottomOf="@id/item_book_date" />
<View
android:id="@+id/item_book_clickable_area"
@ -118,8 +119,11 @@
android:layout_height="0dp"
android:background="?android:attr/selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

View File

@ -34,6 +34,7 @@
android:layout_height="wrap_content"
android:paddingTop="@dimen/activity_vertical_margin"
android:visibility="gone"
android:textColor="@color/text_secondary"
app:layout_constraintTop_toBottomOf="@id/item_help_title"
tools:text="@string/help_3"
tools:visibility="visible" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background" />
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -13,4 +13,7 @@
<color name="color_on_primary">@color/white</color>
<color name="color_on_surface">@color/white</color>
<color name="color_on_error">@color/white</color>
<color name="text_secondary">@color/gray500</color>
<color name="text_tertiary">@color/gray700</color>
</resources>

View File

@ -12,7 +12,10 @@
<color name="blue800">#1565c0</color>
<color name="pink300">#f06292</color>
<color name="actionModeBackground">#4285F4</color>
<color name="gray500">#9E9E9E</color>
<color name="gray700">#616161</color>
<color name="text_secondary">@color/gray700</color>
<color name="text_tertiary">@color/gray500</color>
<!--Material Components Colors-->

View File

@ -27,4 +27,6 @@
<!-- Workaround to store floats in dimen -->
<item format="float" name="material_light_hint_alpha" type="dimen">0.38</item>
<item format="float" name="material_dark_hint_pressed_alpha" type="dimen">0.70</item>
<dimen name="card_margin">5dp</dimen>
</resources>

View File

@ -73,10 +73,11 @@
<string name="all_history_cleared">All History Cleared</string>
<string name="pref_clear_all_bookmarks_title">Clear bookmarks</string>
<string name="all_bookmarks_cleared">All Bookmarks Cleared</string>
<string name="clear_all_history_dialog_title">Clear All History</string>
<string name="clear_all_history_dialog_title">Clear All History?</string>
<string name="share">Share</string>
<string name="selected_file_cab_app_chooser_title" tools:keep="@string/selected_file_cab_app_chooser_title">Share ZIM files with:</string>
<string name="delete">Delete</string>
<string name="cancel">Cancel</string>
<string name="delete_specific_search_toast">Recent search removed</string>
<string name="hint_contents_drawer_message">You can swipe left to view the contents of this article</string>
<string name="got_it">Got it</string>
@ -153,7 +154,7 @@
<string name="time_yesterday">Yesterday</string>
<string name="pref_external_link_popup_title">Warn when entering external links</string>
<string name="pref_external_link_popup_summary">Display popup to warn about additional costs or not working in offline links.</string>
<string name="external_link_popup_dialog_title">Entering External Link</string>
<string name="external_link_popup_dialog_title">Entering External Link!</string>
<string name="external_link_popup_dialog_message">You are entering an external link. This could lead to additional costs for data transfer or will just not work when you are offline. Do you want to continue?</string>
<string name="do_not_ask_anymore">Do not ask anymore</string>
<string name="your_languages" tools:keep="@string/your_languages">Selected languages:</string>

View File

@ -1,109 +0,0 @@
/*
* Kiwix Android
* Copyright (c) 2019 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.entity;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
public class MetaLinkNetworkEntityTest {
private static Matcher<MetaLinkNetworkEntity.Url> url(
String location, int priority, String value) {
return new UrlMatcher(location, priority, value);
}
@Test
public void testDeserialize() throws Exception {
Serializer serializer = new Persister();
final MetaLinkNetworkEntity result = serializer.read(
MetaLinkNetworkEntity.class,
MetaLinkNetworkEntityTest.class.getClassLoader().getResourceAsStream(
"wikipedia_af_all_nopic_2016-05.zim.meta4"
));
Assert.assertThat(result.getUrls().size(), CoreMatchers.is(5));
Assert.assertThat(result.getUrls(), CoreMatchers.hasItems(
url("us", 1,
"http://ftpmirror.your.org/pub/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
url("gb", 2,
"http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
url("us", 3,
"http://download.wikimedia.org/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
url("de", 4,
"http://mirror.netcologne.de/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"),
url("fr", 5, "http://mirror3.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim")
));
// Basic file attributes
Assert.assertThat(result.getFile().getName(),
CoreMatchers.is("wikipedia_af_all_nopic_2016-05.zim"));
Assert.assertThat(result.getFile().getSize(), CoreMatchers.is(63973123L));
// File hashes
Assert.assertThat(result.getFile().getHash("md5"),
CoreMatchers.is("6f06866b61c4a921b57f28cfd4307220"));
Assert.assertThat(result.getFile().getHash("sha-1"),
CoreMatchers.is("8aac4c7f89e3cdd45b245695e19ecde5aac59593"));
Assert.assertThat(result.getFile().getHash("sha-256"),
CoreMatchers.is("83126775538cf588a85edb10db04d6e012321a2025278a08a084b258849b3a5c"));
// Pieces
Assert.assertThat(result.getFile().getPieceHashType(), CoreMatchers.is("sha-1"));
Assert.assertThat(result.getFile().getPieceLength(), CoreMatchers.is(1048576));
// Check only the first and the last elements of the piece hashes
Assert.assertThat(result.getFile().getPieceHashes().size(), CoreMatchers.is(62));
Assert.assertThat(result.getFile().getPieceHashes().get(0),
CoreMatchers.is("f36815d904d4fd563aaef4ee6ef2600fb1fd70b2"));
Assert.assertThat(result.getFile().getPieceHashes().get(61),
CoreMatchers.is("8055e515aa6e78f2810bbb0e0cd07330838b8920"));
}
/**
* Implemented as a matcher only to avoid putting extra code into {@code MetaLinkNetworkEntity}.
* However in case {@code equals} and {@code hashCode} methods are added to
* {@code MetaLinkNetworkEntity.Url} class itself, this Matcher should be deleted.
*/
private static class UrlMatcher extends TypeSafeMatcher<MetaLinkNetworkEntity.Url> {
private String location;
private int priority;
private String value;
public UrlMatcher(String location, int priority, String value) {
this.location = location;
this.priority = priority;
this.value = value;
}
@Override
protected boolean matchesSafely(MetaLinkNetworkEntity.Url item) {
return location.equals(item.getLocation()) && priority == item.getPriority()
&& value.equals(item.getValue());
}
@Override
public void describeTo(Description description) {
description.appendText(String.format(
"Url (location=%s, priority=%d, value=%s", location, priority, value));
}
}
}

View File

@ -0,0 +1,133 @@
/*
* Kiwix Android
* Copyright (c) 2019 Kiwix <android.kiwix.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.kiwix.kiwixmobile.core.entity
import org.assertj.core.api.AbstractAssert
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.simpleframework.xml.core.Persister
class MetaLinkNetworkEntityTest {
@Test
@Throws(Exception::class)
fun testDeserialize() {
val serializer = Persister()
val result = serializer.read(
MetaLinkNetworkEntity::class.java,
MetaLinkNetworkEntityTest::class.java.classLoader.getResourceAsStream(
"wikipedia_af_all_nopic_2016-05.zim.meta4"
)
)
MetaLinkNetworkEntityUrlAssert(result.urls).hasItems(
listOf(
DummyUrl(
"us",
1,
"http://ftpmirror.your.org/pub/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
),
DummyUrl(
"gb",
2,
"http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim" // ktlint-disable
),
DummyUrl(
"us",
3,
"http://download.wikimedia.org/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
),
DummyUrl(
"de",
4,
"http://mirror.netcologne.de/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
),
DummyUrl(
"fr",
5,
"http://mirror3.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
)
)
)
// Basic file attributes
assertThat(result.getFile().getName()).isEqualTo("wikipedia_af_all_nopic_2016-05.zim")
assertThat(result.getFile().size).isEqualTo(63973123L)
// File hashes
assertThat(result.getFile().getHash("md5")).isEqualTo("6f06866b61c4a921b57f28cfd4307220")
assertThat(
result.getFile().getHash("sha-1")
).isEqualTo("8aac4c7f89e3cdd45b245695e19ecde5aac59593")
assertThat(
result.getFile().getHash("sha-256")
).isEqualTo("83126775538cf588a85edb10db04d6e012321a2025278a08a084b258849b3a5c")
// Pieces
assertThat(result.getFile().pieceHashType).isEqualTo("sha-1")
assertThat(result.getFile().pieceLength).isEqualTo(1048576)
// Check only the first and the last elements of the piece hashes
assertThat(result.getFile().pieceHashes.size).isEqualTo(62)
assertThat(
result.getFile().pieceHashes[0]
)
.isEqualTo("f36815d904d4fd563aaef4ee6ef2600fb1fd70b2")
assertThat(
result.getFile().pieceHashes[61]
)
.isEqualTo("8055e515aa6e78f2810bbb0e0cd07330838b8920")
}
data class DummyUrl(val location: String, val priority: Int, val value: String)
/**
* Implemented as a matcher only to avoid putting extra code into {@code MetaLinkNetworkEntity}.
* However in case {@code equals} and {@code hashCode} methods are added to
* {@code MetaLinkNetworkEntity.Url} class itself, this Matcher should be deleted.
*/
class MetaLinkNetworkEntityUrlAssert(
actual: List<MetaLinkNetworkEntity.Url>
) :
AbstractAssert<MetaLinkNetworkEntityUrlAssert, List<MetaLinkNetworkEntity.Url>>(
actual,
MetaLinkNetworkEntityUrlAssert::class.java
) {
private fun <S, T> intersectionWith(
first: List<S>,
second: List<T>,
function: (S, T) -> Boolean
): Boolean {
val filtered = first.filter { a -> second.any { b -> function(a, b) } }
if (filtered.isNotEmpty())
return true
return false
}
fun hasItems(items: List<DummyUrl>): Boolean {
return intersectionWith(actual, items) { a, b ->
a.location == b.location && a.priority == b.priority && a.value == b.value
}
}
}
companion object {
fun assertThat(actual: List<MetaLinkNetworkEntity.Url>): MetaLinkNetworkEntityUrlAssert =
MetaLinkNetworkEntityUrlAssert(actual)
}
}

View File

@ -47,6 +47,9 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.OnItemLongClick
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.StartSpeechInputFailed
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.search.viewmodel.State.NoResults
import org.kiwix.kiwixmobile.core.search.viewmodel.State.Results
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.DeleteRecentSearch
@ -98,19 +101,21 @@ internal class SearchViewModelTest {
inner class StateTests {
@Test
fun `initial state is Initialising`() {
viewModel.state.test().assertValue(NoResults(""))
viewModel.state.test().assertValue(NoResults("", FromWebView))
}
@Test
fun `non empty search term with search results shows Results`() {
val item = ZimSearchResultListItem("")
val searchTerm = "searchTerm"
val searchOrigin = FromWebView
emissionOf(
searchTerm = searchTerm,
searchResults = listOf(item),
databaseResults = listOf(RecentSearchListItem(""))
databaseResults = listOf(RecentSearchListItem("")),
searchOrigin = searchOrigin
)
resultsIn(Results(searchTerm, listOf(item)))
resultsIn(Results(searchTerm, listOf(item), searchOrigin))
}
@Test
@ -118,9 +123,10 @@ internal class SearchViewModelTest {
emissionOf(
searchTerm = "a",
searchResults = emptyList(),
databaseResults = listOf(RecentSearchListItem(""))
databaseResults = listOf(RecentSearchListItem("")),
searchOrigin = FromWebView
)
resultsIn(NoResults("a"))
resultsIn(NoResults("a", FromWebView))
}
@Test
@ -129,9 +135,10 @@ internal class SearchViewModelTest {
emissionOf(
searchTerm = "",
searchResults = listOf(ZimSearchResultListItem("")),
databaseResults = listOf(item)
databaseResults = listOf(item),
searchOrigin = FromWebView
)
resultsIn(Results("", listOf(item)))
resultsIn(Results("", listOf(item), FromWebView))
}
@Test
@ -139,9 +146,10 @@ internal class SearchViewModelTest {
emissionOf(
searchTerm = "",
searchResults = listOf(ZimSearchResultListItem("")),
databaseResults = emptyList()
databaseResults = emptyList(),
searchOrigin = FromWebView
)
resultsIn(NoResults(""))
resultsIn(NoResults("", FromWebView))
}
@Test
@ -151,12 +159,16 @@ internal class SearchViewModelTest {
emissionOf(
searchTerm = searchString,
searchResults = listOf(item),
databaseResults = emptyList()
databaseResults = emptyList(),
searchOrigin = FromWebView
)
viewModel.actions.offer(Filter(searchString))
viewModel.state.test()
.also { testScheduler.advanceTimeBy(100, MILLISECONDS) }
.assertValueHistory(NoResults(""), Results(searchString, listOf(item)))
.assertValueHistory(
NoResults("", FromWebView),
Results(searchString, listOf(item), FromWebView)
)
}
@Test
@ -165,16 +177,40 @@ internal class SearchViewModelTest {
emissionOf(
searchTerm = "a",
searchResults = listOf(item),
databaseResults = emptyList()
databaseResults = emptyList(),
searchOrigin = FromWebView
)
emissionOf(
searchTerm = "b",
searchResults = listOf(item),
databaseResults = emptyList()
databaseResults = emptyList(),
searchOrigin = FromWebView
)
viewModel.state.test()
.also { testScheduler.advanceTimeBy(100, MILLISECONDS) }
.assertValueHistory(NoResults(""), Results("b", listOf(item)))
.assertValueHistory(NoResults("", FromWebView), Results("b", listOf(item), FromWebView))
}
@Test
fun `webView search origin leads to webView in NoResults`() {
emissionOf(
searchTerm = "",
searchResults = listOf(ZimSearchResultListItem("")),
databaseResults = emptyList(),
searchOrigin = FromWebView
)
resultsIn(NoResults("", FromWebView))
}
@Test
fun `tabView search origin leads to tabView in Results`() {
emissionOf(
searchTerm = "",
searchResults = listOf(ZimSearchResultListItem("")),
databaseResults = emptyList(),
searchOrigin = FromTabView
)
resultsIn(NoResults("", FromTabView))
}
}
@ -272,10 +308,12 @@ internal class SearchViewModelTest {
private fun emissionOf(
searchTerm: String,
searchResults: List<ZimSearchResultListItem>,
databaseResults: List<RecentSearchListItem>
databaseResults: List<RecentSearchListItem>,
searchOrigin: SearchOrigin
) {
every { searchResultGenerator.generateSearchResults(searchTerm) } returns searchResults
viewModel.actions.offer(Filter(searchTerm))
recentsFromDb.offer(databaseResults)
viewModel.actions.offer(ScreenWasStartedFrom(searchOrigin))
}
}

View File

@ -27,7 +27,7 @@ import io.mockk.mockkConstructor
import io.mockk.verify
import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.RecentSearchListItem
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
internal class OpenSearchItemTest {
@ -38,7 +38,7 @@ internal class OpenSearchItemTest {
mockkConstructor(Intent::class)
val intent = mockk<Intent>()
every {
anyConstructed<Intent>().putExtra(Constants.TAG_FILE_SEARCHED, searchListItem.value)
anyConstructed<Intent>().putExtra(TAG_FILE_SEARCHED, searchListItem.value)
} returns intent
OpenSearchItem(searchListItem).invokeWith(activity)
verify {

View File

@ -25,7 +25,7 @@ import io.mockk.mockk
import io.mockk.mockkConstructor
import io.mockk.verify
import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED
internal class SearchInPreviousScreenTest {
@ -37,7 +37,7 @@ internal class SearchInPreviousScreenTest {
SearchInPreviousScreen(searchString).invokeWith(activity)
verify {
anyConstructed<Intent>().putExtra(SearchInPreviousScreen.EXTRA_SEARCH_IN_TEXT, true)
anyConstructed<Intent>().putExtra(Constants.TAG_FILE_SEARCHED, searchString)
anyConstructed<Intent>().putExtra(TAG_FILE_SEARCHED, searchString)
activity.setResult(Activity.RESULT_OK, any())
activity.finish()
}

View File

@ -32,7 +32,12 @@ import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.search.viewmodel.Action
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.Filter
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ReceivedPromptForSpeechInput
import org.kiwix.kiwixmobile.core.utils.Constants
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ScreenWasStartedFrom
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromTabView
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchOrigin.FromWebView
import org.kiwix.kiwixmobile.core.utils.TAG_FROM_TAB_SWITCHER
import org.kiwix.kiwixmobile.core.utils.EXTRA_SEARCH
import org.kiwix.kiwixmobile.core.utils.EXTRA_IS_WIDGET_VOICE
internal class SearchIntentProcessingTest {
@ -59,22 +64,49 @@ internal class SearchIntentProcessingTest {
every { intent.hasExtra(Intent.EXTRA_PROCESS_TEXT) } returns true
every { intent.getStringExtra(Intent.EXTRA_PROCESS_TEXT) } returns extra
SearchIntentProcessing(intent, actions).invokeWith(activity)
verifySequence { actions.offer(Filter(extra)) }
verifySequence {
actions.offer(any<ScreenWasStartedFrom>())
actions.offer(Filter(extra))
}
}
@Test
fun `invoke with offers action when EXTRA_SEARCH present`() {
val extra = ""
every { intent.hasExtra(Constants.EXTRA_SEARCH) } returns true
every { intent.getStringExtra(Constants.EXTRA_SEARCH) } returns extra
every { intent.hasExtra(EXTRA_SEARCH) } returns true
every { intent.getStringExtra(EXTRA_SEARCH) } returns extra
SearchIntentProcessing(intent, actions).invokeWith(activity)
verifySequence { actions.offer(Filter(extra)) }
verifySequence {
actions.offer(any<ScreenWasStartedFrom>())
actions.offer(Filter(extra))
}
}
@Test
fun `invoke with offers action when EXTRA_IS_WIDGET_VOICE present`() {
every { intent.getBooleanExtra(Constants.EXTRA_IS_WIDGET_VOICE, false) } returns true
every { intent.getBooleanExtra(EXTRA_IS_WIDGET_VOICE, false) } returns true
SearchIntentProcessing(intent, actions).invokeWith(activity)
verifySequence { actions.offer(ReceivedPromptForSpeechInput) }
verifySequence {
actions.offer(any<ScreenWasStartedFrom>())
actions.offer(ReceivedPromptForSpeechInput)
}
}
@Test
fun `invoke with offers action when TAG_FROM_TAB_SWITCHER present`() {
every { intent.getBooleanExtra(TAG_FROM_TAB_SWITCHER, false) } returns true
SearchIntentProcessing(intent, actions).invokeWith(activity)
verifySequence {
actions.offer(ScreenWasStartedFrom(FromTabView))
}
}
@Test
fun `invoke with offers action when TAG_FROM_TAB_SWITCHER not present`() {
every { intent.getBooleanExtra(TAG_FROM_TAB_SWITCHER, false) } returns false
SearchIntentProcessing(intent, actions).invokeWith(activity)
verifySequence {
actions.offer(ScreenWasStartedFrom(FromWebView))
}
}
}

View File

@ -7,7 +7,7 @@
errorLine1=" &lt;string name=&quot;retry&quot;>Retry&lt;/string>"
errorLine2=" ~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
file="src\main\res\values\strings.xml"
line="4"
column="11"/>
</issue>
@ -18,18 +18,18 @@
errorLine1=" &lt;string name=&quot;download&quot;>Download&lt;/string>"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
file="src\main\res\values\strings.xml"
line="5"
column="11"/>
</issue>
<issue
id="MissingTranslation"
message="&quot;invalid_installation&quot; is not translated in &quot;fi&quot; (Finnish), &quot;zgh&quot; (Standard Moroccan Tamazight), &quot;skr&quot;, &quot;ml&quot; (Malayalam), &quot;qq&quot;, &quot;sv&quot; (Swedish), &quot;it&quot; (Italian), &quot;es&quot; (Spanish), &quot;et&quot; (Estonian), &quot;cs&quot; (Czech), &quot;tg&quot; (Tajik), &quot;lb&quot; (Luxembourgish), &quot;da&quot; (Danish)"
message="&quot;invalid_installation&quot; is not translated in &quot;fi&quot; (Finnish), &quot;zgh&quot; (Standard Moroccan Tamazight), &quot;skr&quot;, &quot;ml&quot; (Malayalam), &quot;qq&quot;, &quot;sv&quot; (Swedish), &quot;it&quot; (Italian), &quot;es&quot; (Spanish), &quot;et&quot; (Estonian), &quot;cs&quot; (Czech), &quot;tg&quot; (Tajik), &quot;lb&quot; (Luxembourgish), &quot;ne&quot; (Nepali), &quot;ckb&quot;, &quot;da&quot; (Danish)"
errorLine1=" &lt;string name=&quot;invalid_installation&quot;>Invalid Install. Please Download Zim.\n Ensure WiFi is on and you have enough storage&lt;/string>"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/values/strings.xml"
file="src\main\res\values\strings.xml"
line="6"
column="11"/>
</issue>
@ -40,7 +40,7 @@
errorLine1=" &lt;application"
errorLine2=" ^">
<location
file="src/main/AndroidManifest.xml"
file="src\main\AndroidManifest.xml"
line="6"
column="3"/>
</issue>
@ -51,7 +51,7 @@
errorLine1=" &lt;TextView"
errorLine2=" ~~~~~~~~">
<location
file="src/main/res/layout/layout_custom_download_error.xml"
file="src\main\res\layout\layout_custom_download_error.xml"
line="10"
column="4"/>
</issue>
@ -62,7 +62,7 @@
errorLine1=" &lt;TextView"
errorLine2=" ~~~~~~~~">
<location
file="src/main/res/layout/layout_custom_download_in_progress.xml"
file="src\main\res\layout\layout_custom_download_in_progress.xml"
line="8"
column="4"/>
</issue>
@ -73,7 +73,7 @@
errorLine1=" &lt;TextView"
errorLine2=" ~~~~~~~~">
<location
file="src/main/res/layout/layout_custom_download_in_progress.xml"
file="src\main\res\layout\layout_custom_download_in_progress.xml"
line="28"
column="4"/>
</issue>
@ -84,7 +84,7 @@
errorLine1="class CustomMainActivity : CoreMainActivity() {"
errorLine2=" ~~~~~~~~~~~~~~~~~~">
<location
file="src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt"
file="src\main\java\org\kiwix\kiwixmobile\custom\main\CustomMainActivity.kt"
line="55"
column="7"/>
</issue>
@ -95,7 +95,7 @@
errorLine1=" &lt;ImageView"
errorLine2=" ~~~~~~~~~">
<location
file="src/main/res/layout/activity_custom_download.xml"
file="src\main\res\layout\activity_custom_download.xml"
line="9"
column="4"/>
</issue>

View File

@ -22,7 +22,7 @@ import android.webkit.WebView
import org.kiwix.kiwixmobile.core.main.CoreWebViewClient
import org.kiwix.kiwixmobile.core.main.WebViewCallback
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
import org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX
import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX
class CustomWebViewClient internal constructor(
callback: WebViewCallback,