diff --git a/.gitignore b/.gitignore
index 3816578..5f7aae7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Built application files
*.apk
*.ap_
+*.aab
# Files for the ART/Dalvik VM
*.dex
@@ -32,17 +33,14 @@ proguard/
# Android Studio captures folder
captures/
-# Intellij
+# IntelliJ
*.iml
-.idea/workspace.xml
-.idea/tasks.xml
-.idea/gradle.xml
-.idea/dictionaries
-.idea/libraries
-.idea/caches/
+.idea/
# Keystore files
-*.jks
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
@@ -55,6 +53,24 @@ freeline.py
freeline/
freeline_project_description.json
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+
# Deploy files
app/upload.keystore
app/upload.json
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 9570c35..0000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,184 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- xmlns:android
- ^$
-
-
-
-
-
-
-
-
- xmlns:.*
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*:id
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- .*:name
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- name
- ^$
-
-
-
-
-
-
-
-
- style
- ^$
-
-
-
-
-
-
-
-
- .*
- ^$
-
-
- BY_NAME
-
-
-
-
-
-
- .*:layout_width
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- .*:layout_height
- http://schemas.android.com/apk/res/android
-
-
-
-
-
-
-
-
- .*:layout_.*
- http://schemas.android.com/apk/res/android
-
-
- BY_NAME
-
-
-
-
-
-
- .*:width
- http://schemas.android.com/apk/res/android
-
-
- BY_NAME
-
-
-
-
-
-
- .*:height
- http://schemas.android.com/apk/res/android
-
-
- BY_NAME
-
-
-
-
-
-
- .*
- http://schemas.android.com/apk/res/android
-
-
- BY_NAME
-
-
-
-
-
-
- .*
- .*
-
-
- BY_NAME
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index 8f1a3b7..0000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index 15a15b2..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 707ee6e..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index a7b061e..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 960078e..4ad0dfc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,7 +5,7 @@ env:
global:
- ANDROID_API=29
- EMULATOR_API=21
- - ANDROID_BUILD_TOOLS=29.0.1
+ - ANDROID_BUILD_TOOLS=29.0.2
android:
components:
- build-tools-$ANDROID_BUILD_TOOLS
diff --git a/app/build.gradle b/app/build.gradle
index 7d8f879..4189b16 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,6 +2,12 @@ plugins {
id 'com.android.application'
id 'com.github.triplet.play' version '2.4.2'
}
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+
+repositories {
+ mavenCentral()
+}
android {
applicationVariants.all { variant ->
@@ -11,13 +17,13 @@ android {
}
compileSdkVersion 29
- buildToolsVersion '29.0.1'
+ buildToolsVersion '29.0.2'
defaultConfig {
applicationId "com.jtmcn.archwiki.viewer"
minSdkVersion 21
targetSdkVersion 29
- versionCode 14
- versionName "1.0.13"
+ versionCode 15
+ versionName "1.0.14"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -53,11 +59,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
}
dependencies {
@@ -67,14 +68,17 @@ dependencies {
exclude group: 'com.android.support', module: 'support-annotations'
})
- implementation 'com.jakewharton:butterknife:10.1.0'
- annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'
-
implementation 'com.google.code.gson:gson:2.8.5'
+ implementation 'com.jakewharton.timber:timber:4.7.1'
+
+ implementation 'com.squareup.okhttp3:okhttp:3.11.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.preference:preference:1.1.0'
+ implementation 'androidx.core:core-ktx:1.1.0'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
play {
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
index 7cbbc76..0d98bb9 100644
--- a/app/proguard-rules.pro
+++ b/app/proguard-rules.pro
@@ -19,7 +19,15 @@
-keep class android.support.v7.** { *; }
-keep interface android.support.v7.** { *; }
-# butterknife
--dontwarn butterknife.internal.**
--keep class **$$ViewInjector { *; }
--keepnames class * { @butterknife.InjectView *;}
\ No newline at end of file
+# OkHttp
+# JSR 305 annotations are for embedding nullability information.
+-dontwarn javax.annotation.**
+
+# A resource is loaded with a relative path so the package of this class must be preserved.
+-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
+
+# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
+-dontwarn org.codehaus.mojo.animal_sniffer.*
+
+# OkHttp platform used only on JVM and when Conscrypt dependency is available.
+-dontwarn okhttp3.internal.platform.ConscryptPlatform
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0a33abf..2c54fca 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,9 +1,11 @@
+
-
-
-
-
-
+ android:label="@string/menu_settings"
+ android:parentActivityName=".MainActivity">
+
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/ArchWikiViewerApp.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/ArchWikiViewerApp.kt
new file mode 100644
index 0000000..3bed536
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/ArchWikiViewerApp.kt
@@ -0,0 +1,13 @@
+package com.jtmcn.archwiki.viewer
+
+import android.app.Application
+import timber.log.Timber
+import timber.log.Timber.DebugTree
+
+
+class ArchwikiViewerApp : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ Timber.plant(DebugTree())
+ }
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.java b/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.java
deleted file mode 100644
index 2721570..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-/**
- * Various constants used throughout the program.
- */
-public class Constants {
- //format types
- public static final String TEXT_HTML_MIME = "text/html";
- public static final String TEXT_PLAIN_MIME = "text/plain";
- public static final String UTF_8 = "UTF-8";
-
- //arch wiki urls
- public static final String ARCHWIKI_BASE = "https://wiki.archlinux.org/";
- public static final String ARCHWIKI_MAIN = ARCHWIKI_BASE + "index.php/Main_page";
- public static final String ARCHWIKI_SEARCH_URL = ARCHWIKI_BASE + "index.php?&search=%s";
-
- //local file paths
- public static final String ASSETS_FOLDER = "file:///android_asset/";
- public static final String LOCAL_CSS = ASSETS_FOLDER + "style.css";
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.kt
new file mode 100644
index 0000000..dcfcdba
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/Constants.kt
@@ -0,0 +1,16 @@
+package com.jtmcn.archwiki.viewer
+
+
+//format types
+const val TEXT_HTML_MIME = "text/html"
+const val TEXT_PLAIN_MIME = "text/plain"
+const val UTF_8 = "UTF-8"
+
+//arch wiki urls
+const val ARCHWIKI_BASE = "https://wiki.archlinux.org"
+const val ARCHWIKI_MAIN = "${ARCHWIKI_BASE}/index.php/Main_page"
+const val ARCHWIKI_SEARCH_URL = "${ARCHWIKI_BASE}/index.php?&search=%s"
+
+//local file paths
+const val ASSETS_FOLDER = "file:///android_asset"
+const val LOCAL_CSS = "${ASSETS_FOLDER}/style.css"
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.java b/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.java
deleted file mode 100644
index fb2b54d..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.java
+++ /dev/null
@@ -1,212 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-import android.app.SearchManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-
-import androidx.annotation.NonNull;
-import androidx.core.view.MenuItemCompat;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.SearchView;
-import androidx.appcompat.widget.Toolbar;
-import android.util.Log;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.webkit.WebSettings;
-import android.widget.ProgressBar;
-
-import com.jtmcn.archwiki.viewer.data.SearchResult;
-import com.jtmcn.archwiki.viewer.data.SearchResultsBuilder;
-import com.jtmcn.archwiki.viewer.data.WikiPage;
-import com.jtmcn.archwiki.viewer.tasks.Fetch;
-import com.jtmcn.archwiki.viewer.tasks.FetchUrl;
-import com.jtmcn.archwiki.viewer.utils.SettingsUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-
-import static com.jtmcn.archwiki.viewer.Constants.TEXT_PLAIN_MIME;
-
-public class MainActivity extends AppCompatActivity implements FetchUrl.OnFinish> {
- public static final String TAG = MainActivity.class.getSimpleName();
- @BindView(R.id.wiki_view) WikiView wikiViewer;
- @BindView(R.id.toolbar) Toolbar toolbar;
- private SearchView searchView;
- private MenuItem searchMenuItem;
- private List currentSuggestions;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- ButterKnife.bind(this);
-
- setSupportActionBar(toolbar);
-
- ProgressBar progressBar = findViewById(R.id.progress_bar);
- wikiViewer.buildView(progressBar, getSupportActionBar());
-
- handleIntent(getIntent());
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- updateWebSettings();
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- handleIntent(intent);
- }
-
- private void handleIntent(Intent intent) {
- if (intent == null) {
- return;
- }
-
- if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
- String query = intent.getStringExtra(SearchManager.QUERY);
- wikiViewer.passSearch(query);
- hideSearchView();
- } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
- final String url = intent.getDataString();
- wikiViewer.wikiClient.shouldOverrideUrlLoading(wikiViewer, url);
- }
- }
-
- /**
- * Update the font size used in the webview.
- */
- public void updateWebSettings() {
- WebSettings webSettings = wikiViewer.getSettings();
- int fontSize = SettingsUtils.getFontSize(this);
-
- //todo this setting should be changed to a slider, remove deprecated call
- // deprecated method must be used until Android API 14
- // https://developer.android.com/reference/android/webkit/WebSettings.TextSize.html#NORMAL
- switch (fontSize) {
- case 0:
- webSettings.setTextSize(WebSettings.TextSize.SMALLEST); //50%
- break;
- case 1:
- webSettings.setTextSize(WebSettings.TextSize.SMALLER); //75%
- break;
- case 2:
- webSettings.setTextSize(WebSettings.TextSize.NORMAL); //100%
- break;
- case 3:
- webSettings.setTextSize(WebSettings.TextSize.LARGER); //150%
- break;
- case 4:
- webSettings.setTextSize(WebSettings.TextSize.LARGEST); //200%
- break;
- }
- }
-
- @Override
- public boolean onPrepareOptionsMenu(Menu menu) {
- SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
- searchMenuItem = menu.findItem(R.id.menu_search);
- searchView = (SearchView) MenuItemCompat.getActionView(searchMenuItem);
- searchView.setOnQueryTextFocusChangeListener((v, hasFocus) -> {
- if (!hasFocus) {
- hideSearchView();
- }
- });
- searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
- searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
- @Override
- public boolean onQueryTextSubmit(String query) {
- wikiViewer.passSearch(query);
- return false;
- }
-
- @Override
- public boolean onQueryTextChange(String newText) {
- if (newText.isEmpty()) {
- setCursorAdapter(new ArrayList<>());
- return true;
- } else {
- String searchUrl = SearchResultsBuilder.getSearchQuery(newText);
- Fetch.search(MainActivity.this, searchUrl);
- return true;
- }
- }
- });
-
- searchView.setOnSuggestionListener(new SearchView.OnSuggestionListener() {
- @Override
- public boolean onSuggestionSelect(int position) {
- return false;
- }
-
- @Override
- public boolean onSuggestionClick(int position) {
- SearchResult searchResult = currentSuggestions.get(position);
- Log.d(TAG, "Opening '" + searchResult.getPageName() + "' from search suggestion.");
- wikiViewer.wikiClient.shouldOverrideUrlLoading(wikiViewer, searchResult.getPageURL());
- hideSearchView();
- return true;
- }
- });
- return true;
- }
-
- public void hideSearchView() {
- searchMenuItem.collapseActionView();
- wikiViewer.requestFocus(); //pass control back to the wikiview
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.menu, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(@NonNull MenuItem item) {
- switch (item.getItemId()) {
- case R.id.menu_share:
- WikiPage wikiPage = wikiViewer.getCurrentWebPage();
- if (wikiPage != null) {
- Intent sharingIntent = new Intent();
- sharingIntent.setType(TEXT_PLAIN_MIME);
- sharingIntent.setAction(Intent.ACTION_SEND);
- sharingIntent.putExtra(Intent.EXTRA_TITLE, wikiPage.getPageTitle());
- sharingIntent.putExtra(Intent.EXTRA_TEXT, wikiPage.getPageUrl());
- startActivity(Intent.createChooser(sharingIntent, null));
- }
- break;
- case R.id.refresh:
- wikiViewer.onRefresh();
- break;
- case R.id.menu_settings:
- startActivity(new Intent(this, PreferencesActivity.class));
- break;
- case R.id.exit:
- finish();
- break;
- }
- return super.onOptionsItemSelected(item);
- }
-
- @Override
- public void onFinish(List results) {
- currentSuggestions = results;
- setCursorAdapter(currentSuggestions);
- }
-
- private void setCursorAdapter(List currentSuggestions) {
- searchView.setSuggestionsAdapter(
- SearchResultsAdapter.getCursorAdapter(this, currentSuggestions)
- );
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.kt
new file mode 100644
index 0000000..30ebcb8
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/MainActivity.kt
@@ -0,0 +1,149 @@
+package com.jtmcn.archwiki.viewer
+
+import android.app.SearchManager
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.Menu
+import android.view.MenuItem
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.SearchView
+import com.jtmcn.archwiki.viewer.data.SearchResult
+import com.jtmcn.archwiki.viewer.data.getSearchQuery
+import com.jtmcn.archwiki.viewer.tasks.Fetch
+import com.jtmcn.archwiki.viewer.utils.getTextZoom
+import kotlinx.android.synthetic.main.activity_main.*
+import kotlinx.android.synthetic.main.toolbar.*
+import timber.log.Timber
+import java.util.*
+
+class MainActivity : AppCompatActivity() {
+ private lateinit var searchView: SearchView
+ private lateinit var searchMenuItem: MenuItem
+ private var currentSuggestions: List? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ setSupportActionBar(toolbar)
+
+ wikiViewer.buildView(progressBar, supportActionBar)
+
+ handleIntent(intent)
+ }
+
+ override fun onResume() {
+ super.onResume()
+ updateWebSettings()
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ handleIntent(intent)
+ }
+
+ private fun handleIntent(intent: Intent?) {
+ if (intent == null) {
+ return
+ }
+
+ if (Intent.ACTION_SEARCH == intent.action) {
+ val query = intent.getStringExtra(SearchManager.QUERY)
+ wikiViewer.passSearch(query!!)
+ hideSearchView()
+ } else if (Intent.ACTION_VIEW == intent.action) {
+ val url = intent.dataString
+ wikiViewer.wikiClient.shouldOverrideUrlLoading(wikiViewer, url!!)
+ }
+ }
+
+ /**
+ * Update the font size used in the webview.
+ */
+ private fun updateWebSettings() {
+ wikiViewer.settings.textZoom = getTextZoom(this)
+ }
+
+ override fun onPrepareOptionsMenu(menu: Menu): Boolean {
+ val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
+ searchMenuItem = menu.findItem(R.id.menu_search)
+ searchView = searchMenuItem.actionView as SearchView
+ searchView.setOnQueryTextFocusChangeListener { _, hasFocus ->
+ if (!hasFocus) {
+ hideSearchView()
+ }
+ }
+ searchView.setSearchableInfo(searchManager.getSearchableInfo(componentName))
+ searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
+ override fun onQueryTextSubmit(query: String): Boolean {
+ wikiViewer.passSearch(query)
+ return false
+ }
+
+ override fun onQueryTextChange(newText: String): Boolean {
+ if (newText.isEmpty()) {
+ setCursorAdapter(ArrayList())
+ return true
+ } else {
+ val searchUrl = getSearchQuery(newText)
+ Fetch.search({
+ currentSuggestions = it
+ setCursorAdapter(currentSuggestions)
+ }, searchUrl)
+ return true
+ }
+ }
+ })
+
+ searchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
+ override fun onSuggestionSelect(position: Int): Boolean {
+ return false
+ }
+
+ override fun onSuggestionClick(position: Int): Boolean {
+ val (pageName, pageURL) = currentSuggestions!![position]
+ Timber.d("Opening '$pageName' from search suggestion.")
+ wikiViewer.wikiClient.shouldOverrideUrlLoading(wikiViewer, pageURL)
+ hideSearchView()
+ return true
+ }
+ })
+ return true
+ }
+
+ private fun hideSearchView() {
+ searchMenuItem.collapseActionView()
+ wikiViewer.requestFocus() //pass control back to the wikiview
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ val inflater = menuInflater
+ inflater.inflate(R.menu.menu, menu)
+ return true
+ }
+
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_share -> {
+ val wikiPage = wikiViewer.currentWebPage
+ if (wikiPage != null) {
+ val sharingIntent = Intent()
+ sharingIntent.type = TEXT_PLAIN_MIME
+ sharingIntent.action = Intent.ACTION_SEND
+ sharingIntent.putExtra(Intent.EXTRA_TITLE, wikiPage.pageTitle)
+ sharingIntent.putExtra(Intent.EXTRA_TEXT, wikiPage.pageUrl)
+ startActivity(Intent.createChooser(sharingIntent, null))
+ }
+ }
+ R.id.refresh -> wikiViewer.onRefresh()
+ R.id.menu_settings -> startActivity(Intent(this, PreferencesActivity::class.java))
+ R.id.exit -> finish()
+ }
+ return super.onOptionsItemSelected(item)
+ }
+
+ private fun setCursorAdapter(currentSuggestions: List?) {
+ searchView.suggestionsAdapter = SearchResultsAdapter.getCursorAdapter(this, currentSuggestions!!)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.java b/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.java
deleted file mode 100644
index f95a3c0..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceManager;
-import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
-import androidx.appcompat.widget.Toolbar;
-import android.view.MenuItem;
-
-/**
- * The {@link PreferenceActivity} to change settings for the application.
- */
-public class PreferencesActivity extends AppCompatActivity {
- public static final String KEY_TEXT_SIZE = "textSize";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
- }
-
- @Override
- protected void onPostCreate(@Nullable Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- setContentView(R.layout.activity_preferences);
-
- getFragmentManager().beginTransaction()
- .replace(R.id.settings_content, new ApplicationPreferenceFragment())
- .commit();
-
- Toolbar toolbar = findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- setTitle(R.string.menu_settings);
-
- if (getSupportActionBar() != null) {
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
- }
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- onBackPressed();
- break;
- }
- return true;
- }
-
- /**
- * Loads the activities preferences into the fragment.
- */
- public static class ApplicationPreferenceFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- addPreferencesFromResource(R.xml.prefs);
- }
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.kt
new file mode 100644
index 0000000..43632a4
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/PreferencesActivity.kt
@@ -0,0 +1,37 @@
+package com.jtmcn.archwiki.viewer
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.preference.PreferenceFragmentCompat
+import com.jtmcn.archwiki.viewer.utils.getTextZoom
+import kotlinx.android.synthetic.main.toolbar.*
+
+class PreferencesActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_preferences)
+
+ setSupportActionBar(toolbar)
+
+ supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.settings, SettingsFragment())
+ .commit()
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+
+ getTextZoom(this)
+ }
+
+ class SettingsFragment : PreferenceFragmentCompat() {
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.preferences, rootKey)
+ }
+ }
+}
+
+object Prefs {
+ @Deprecated(message = "Should use textZoom", replaceWith = ReplaceWith("KEY_TEXT_ZOOM"))
+ const val KEY_TEXT_SIZE = "textSize"
+ const val KEY_TEXT_ZOOM = "textZoom"
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.java b/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.java
deleted file mode 100644
index 3059c5c..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-import android.app.SearchManager;
-import android.content.Context;
-import android.database.MatrixCursor;
-import android.provider.BaseColumns;
-import androidx.cursoradapter.widget.CursorAdapter;
-import androidx.cursoradapter.widget.SimpleCursorAdapter;
-
-import com.jtmcn.archwiki.viewer.data.SearchResult;
-
-import java.util.List;
-
-/**
- * Helper for creating a {@link SimpleCursorAdapter} which will
- * list the search results for a {@link android.widget.SearchView}
- */
-public class SearchResultsAdapter {
- private static final String[] columnNames = {BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1};
- private static final String[] from = {SearchManager.SUGGEST_COLUMN_TEXT_1};
- private static final int[] to = new int[]{R.id.url};
-
- /**
- * Creates a cursor adapter given a {@link List}.
- * https://stackoverflow.com/questions/11628172/converting-an-arrayadapter-to-cursoradapter-for-use-in-a-searchview/11628527#11628527
- *
- * @param results the results to be placed in the adapter.
- * @return the adapter.
- */
- public static CursorAdapter getCursorAdapter(Context context, List results) {
- int id = 0;
- MatrixCursor cursor = new MatrixCursor(columnNames);
- for (SearchResult item : results) {
- String[] temp = new String[2];
- temp[0] = String.valueOf(id); // "_id"
- temp[1] = item.getPageName(); // "title"
-
- cursor.addRow(temp);
- id++;
- }
-
- return new SimpleCursorAdapter(
- context,
- R.layout.search_suggestions_list_item,
- cursor,
- from,
- to,
- CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
- );
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.kt
new file mode 100644
index 0000000..8c32b3e
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/SearchResultsAdapter.kt
@@ -0,0 +1,49 @@
+package com.jtmcn.archwiki.viewer
+
+import android.app.SearchManager
+import android.content.Context
+import android.database.MatrixCursor
+import android.provider.BaseColumns
+import androidx.cursoradapter.widget.CursorAdapter
+import androidx.cursoradapter.widget.SimpleCursorAdapter
+
+import com.jtmcn.archwiki.viewer.data.SearchResult
+
+/**
+ * Helper for creating a [SimpleCursorAdapter] which will
+ * list the search results for a [android.widget.SearchView]
+ */
+object SearchResultsAdapter {
+ private val columnNames = arrayOf(BaseColumns._ID, SearchManager.SUGGEST_COLUMN_TEXT_1)
+ private val from = arrayOf(SearchManager.SUGGEST_COLUMN_TEXT_1)
+ private val to = intArrayOf(R.id.url)
+
+ /**
+ * Creates a cursor adapter given a [<].
+ * https://stackoverflow.com/questions/11628172/converting-an-arrayadapter-to-cursoradapter-for-use-in-a-searchview/11628527#11628527
+ *
+ * @param results the results to be placed in the adapter.
+ * @return the adapter.
+ */
+ fun getCursorAdapter(context: Context, results: List): CursorAdapter {
+ var id = 0
+ val cursor = MatrixCursor(columnNames)
+ for ((pageName) in results) {
+ val temp = arrayOfNulls(2)
+ temp[0] = id.toString() // "_id"
+ temp[1] = pageName // "title"
+
+ cursor.addRow(temp)
+ id++
+ }
+
+ return SimpleCursorAdapter(
+ context,
+ R.layout.search_suggestions_list_item,
+ cursor,
+ from,
+ to,
+ CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER
+ )
+ }
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.java b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.java
deleted file mode 100644
index c932907..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-import android.os.Handler;
-import androidx.appcompat.app.ActionBar;
-import android.util.Log;
-import android.view.View;
-import android.webkit.WebView;
-import android.webkit.WebViewClient;
-import android.widget.ProgressBar;
-
-import com.jtmcn.archwiki.viewer.data.WikiPage;
-import com.jtmcn.archwiki.viewer.tasks.Fetch;
-import com.jtmcn.archwiki.viewer.tasks.FetchUrl;
-import com.jtmcn.archwiki.viewer.utils.AndroidUtils;
-
-import java.util.HashSet;
-import java.util.Set;
-import java.util.Stack;
-
-import static com.jtmcn.archwiki.viewer.Constants.ARCHWIKI_BASE;
-import static com.jtmcn.archwiki.viewer.Constants.TEXT_HTML_MIME;
-import static com.jtmcn.archwiki.viewer.Constants.UTF_8;
-
-public class WikiClient extends WebViewClient implements FetchUrl.OnFinish {
- public static final String TAG = WikiClient.class.getSimpleName();
- private final WebView webView;
- private final Stack webPageStack = new Stack<>();
- private final ProgressBar progressBar;
- private final ActionBar actionBar;
- private Set loadedUrls = new HashSet<>(); // this is used to see if we should restore the scroll position
- private String lastLoadedUrl = null; //https://stackoverflow.com/questions/11601134/android-webview-function-onpagefinished-is-called-twice
-
- public WikiClient(ProgressBar progressBar, ActionBar actionBar, WebView wikiViewer) {
- this.progressBar = progressBar;
- this.actionBar = actionBar;
- webView = wikiViewer;
- }
-
- /*
- * Manage page history
- */
- public void addHistory(WikiPage wikiPage) {
- if (webPageStack.size() > 0) {
- Log.d(TAG, "Saving " + getCurrentWebPage().getPageTitle() + " at " + webView.getScrollY());
- getCurrentWebPage().setScrollPosition(webView.getScrollY());
- }
- webPageStack.push(wikiPage);
- Log.i(TAG, "Adding page " + wikiPage.getPageTitle() + ". Stack size= " + webPageStack.size());
- }
-
- /**
- * Loads the html from a {@link WikiPage} into the webview.
- *
- * @param wikiPage the page to be loaded.
- */
- public void loadWikiHtml(WikiPage wikiPage) {
- webView.loadDataWithBaseURL(
- wikiPage.getPageUrl(),
- wikiPage.getHtmlString(),
- TEXT_HTML_MIME,
- UTF_8,
- null
- );
-
- setSubtitle(wikiPage.getPageTitle());
- }
-
- /**
- * Intercept url when clicked. If it's part of the wiki load it here.
- * If not, open the device's default browser.
- *
- * @param view webview being loaded into
- * @param url url being loaded
- * @return true if should override url loading
- */
- @Override
- public boolean shouldOverrideUrlLoading(WebView view, String url) {
- // deprecated until min api 21 is used
- if (url.startsWith(ARCHWIKI_BASE)) {
- webView.stopLoading();
- Fetch.page(this, url);
- showProgress();
-
- return false;
- } else {
- AndroidUtils.openLink(url, view.getContext());
- return true;
- }
- }
-
- @Override
- public void onPageFinished(WebView view, String url) {
- super.onPageFinished(view, url);
- final WikiPage currentWebPage = getCurrentWebPage();
- Log.d(TAG, "Calling onPageFinished(view, " + currentWebPage.getPageTitle() + ")");
- // make sure we're loading the current page and that
- // this page's url doesn't have an anchor (only on first page load)
- if (url.equals(currentWebPage.getPageUrl()) && !url.equals(lastLoadedUrl)) {
- if (!isFirstLoad(currentWebPage)) {
- new Handler().postDelayed(() -> {
- int scrollY = currentWebPage.getScrollPosition();
- Log.d(TAG, "Restoring " + currentWebPage.getPageTitle() + " at " + scrollY);
- webView.setScrollY(scrollY);
- }, 25);
- }
-
- lastLoadedUrl = url;
- hideProgress();
- }
- }
-
- private boolean isFirstLoad(WikiPage currentWebPage) {
- if (loadedUrls.contains(currentWebPage.getPageUrl())) {
- return false;
- } else {
- loadedUrls.add(currentWebPage.getPageUrl());
- return true;
- }
- }
-
- public void showProgress() {
- progressBar.setVisibility(View.VISIBLE);
- }
-
- public void hideProgress() {
- progressBar.setVisibility(View.GONE);
- }
-
- public void setSubtitle(String title) {
- if (actionBar != null) {
- actionBar.setSubtitle(title);
- }
- }
-
- /**
- * Get the number of pages that are in the history.
- *
- * @return number of pages on the stack.
- */
- public int getHistoryStackSize() {
- return webPageStack.size();
- }
-
- /**
- * Go back to the last loaded page.
- */
- public void goBackHistory() {
- WikiPage removed = webPageStack.pop();
- loadedUrls.remove(removed.getPageUrl());
- Log.i(TAG, "Removing " + removed.getPageTitle() + " from stack");
- WikiPage newPage = webPageStack.peek();
- loadWikiHtml(newPage);
- }
-
- /**
- * Returns null or the current page.
- *
- * @return The current page
- */
- public WikiPage getCurrentWebPage() {
- return webPageStack.size() == 0 ? null : webPageStack.peek();
- }
-
- @Override
- public void onFinish(WikiPage results) {
- addHistory(results);
- loadWikiHtml(getCurrentWebPage());
- }
-
- public void refreshPage() {
- lastLoadedUrl = null; // set to null if page should restore position, otherwise start at top of page
- WikiPage currentWebPage = getCurrentWebPage();
- if (currentWebPage != null) {
- final int scrollPosition = currentWebPage.getScrollPosition();
-
- String url = currentWebPage.getPageUrl();
- showProgress();
- Fetch.page(wikiPage -> {
- webPageStack.pop();
- webPageStack.push(wikiPage);
- wikiPage.setScrollPosition(scrollPosition);
- loadWikiHtml(wikiPage);
- }, url);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.kt
new file mode 100644
index 0000000..3f05fe8
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiClient.kt
@@ -0,0 +1,159 @@
+package com.jtmcn.archwiki.viewer
+
+import android.os.Handler
+import android.view.View
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import android.widget.ProgressBar
+import androidx.appcompat.app.ActionBar
+import com.jtmcn.archwiki.viewer.data.WikiPage
+import com.jtmcn.archwiki.viewer.tasks.Fetch
+import com.jtmcn.archwiki.viewer.utils.openLink
+import timber.log.Timber
+import java.util.*
+
+
+class WikiClient(private val progressBar: ProgressBar, private val actionBar: ActionBar?, private val webView: WebView) : WebViewClient() {
+ private val webPageStack = Stack()
+ private val loadedUrls = HashSet() // this is used to see if we should restore the scroll position
+ private var lastLoadedUrl: String? = null //https://stackoverflow.com/questions/11601134/android-webview-function-onpagefinished-is-called-twice
+
+ /**
+ * Get the number of pages that are in the history.
+ *
+ * @return number of pages on the stack.
+ */
+ val historyStackSize: Int
+ get() = webPageStack.size
+
+ /**
+ * Returns null or the current page.
+ *
+ * @return The current page
+ */
+ val currentWebPage: WikiPage?
+ get() = if (webPageStack.size == 0) null else webPageStack.peek()
+
+ /*
+ * Manage page history
+ */
+ private fun addHistory(wikiPage: WikiPage) {
+ if (webPageStack.size > 0) {
+ Timber.d("Saving ${currentWebPage?.pageTitle} at ${webView.scrollY}")
+ currentWebPage!!.scrollPosition = webView.scrollY
+ }
+ webPageStack.push(wikiPage)
+ Timber.i("Adding page ${wikiPage.pageTitle}. Stack size= ${webPageStack.size}")
+ }
+
+ /**
+ * Loads the html from a [WikiPage] into the webview.
+ *
+ * @param wikiPage the page to be loaded.
+ */
+ fun loadWikiHtml(wikiPage: WikiPage) {
+ webView.loadDataWithBaseURL(
+ wikiPage.pageUrl,
+ wikiPage.htmlString,
+ TEXT_HTML_MIME,
+ UTF_8,
+ null
+ )
+
+ setSubtitle(wikiPage.pageTitle)
+ }
+
+ /**
+ * Intercept url when clicked. If it's part of the wiki load it here.
+ * If not, open the device's default browser.
+ *
+ * @param view webview being loaded into
+ * @param url url being loaded
+ * @return true if should override url loading
+ */
+ override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
+ // deprecated until min api 21 is used
+ if (url.startsWith(ARCHWIKI_BASE)) {
+ webView.stopLoading()
+ Fetch.page({
+ addHistory(it)
+ loadWikiHtml(currentWebPage!!)
+ }, url)
+ showProgress()
+
+ return false
+ } else {
+ openLink(url, view.context)
+ return true
+ }
+ }
+
+ override fun onPageFinished(view: WebView, url: String) {
+ super.onPageFinished(view, url)
+ val currentWebPage = currentWebPage
+ Timber.d("Calling onPageFinished(view, ${currentWebPage?.pageTitle})")
+ // make sure we're loading the current page and that
+ // this page's url doesn't have an anchor (only on first page load)
+ if (url == currentWebPage?.pageUrl && url != lastLoadedUrl) {
+ if (!isFirstLoad(currentWebPage)) {
+ Handler().postDelayed({
+ val scrollY = currentWebPage.scrollPosition
+ Timber.d("Restoring ${currentWebPage.pageTitle} at $scrollY")
+ webView.scrollY = scrollY
+ }, 25)
+ }
+
+ lastLoadedUrl = url
+ hideProgress()
+ }
+ }
+
+ private fun isFirstLoad(currentWebPage: WikiPage): Boolean {
+ return if (loadedUrls.contains(currentWebPage.pageUrl)) {
+ false
+ } else {
+ loadedUrls.add(currentWebPage.pageUrl)
+ true
+ }
+ }
+
+ private fun showProgress() {
+ progressBar.visibility = View.VISIBLE
+ }
+
+ private fun hideProgress() {
+ progressBar.visibility = View.GONE
+ }
+
+ private fun setSubtitle(title: String?) {
+ actionBar?.subtitle = title
+ }
+
+ /**
+ * Go back to the last loaded page.
+ */
+ fun goBackHistory() {
+ val (pageUrl, pageTitle) = webPageStack.pop()
+ loadedUrls.remove(pageUrl)
+ Timber.i("Removing $pageTitle from stack")
+ val newPage = webPageStack.peek()
+ loadWikiHtml(newPage)
+ }
+
+ fun refreshPage() {
+ lastLoadedUrl = null // set to null if page should restore position, otherwise start at top of page
+ val currentWebPage = currentWebPage
+ if (currentWebPage != null) {
+ val scrollPosition = currentWebPage.scrollPosition
+
+ val url = currentWebPage.pageUrl
+ showProgress()
+ Fetch.page({ wikiPage ->
+ webPageStack.pop()
+ webPageStack.push(wikiPage)
+ wikiPage.scrollPosition = scrollPosition
+ loadWikiHtml(wikiPage)
+ }, url)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.java b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.java
deleted file mode 100644
index 31a7f7f..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.jtmcn.archwiki.viewer;
-
-import android.content.Context;
-import android.os.Build;
-
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
-import androidx.appcompat.app.ActionBar;
-
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.webkit.WebSettings;
-import android.widget.ProgressBar;
-
-import com.github.takahirom.webview_in_coodinator_layout.NestedWebView;
-import com.jtmcn.archwiki.viewer.data.WikiPage;
-
-import static com.jtmcn.archwiki.viewer.Constants.ARCHWIKI_MAIN;
-import static com.jtmcn.archwiki.viewer.Constants.ARCHWIKI_SEARCH_URL;
-
-public class WikiView extends NestedWebView implements SwipeRefreshLayout.OnRefreshListener {
- public static final String TAG = WikiView.class.getSimpleName();
- WikiClient wikiClient;
-
- public WikiView(Context context, AttributeSet attrs) {
- super(context, attrs);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !isInEditMode()) {
- // This allows the webview to inject the css (otherwise it blocks it for security reasons)
- getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
- }
- }
-
- /**
- * Initializes the wiki client and loads the main page.
- */
- public void buildView(ProgressBar progressBar, ActionBar actionBar) {
- wikiClient = new WikiClient(progressBar, actionBar, this);
- setWebViewClient(wikiClient);
- wikiClient.shouldOverrideUrlLoading(this, ARCHWIKI_MAIN);
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK && wikiClient.getHistoryStackSize() > 1) {
- Log.i(TAG, "Loading previous page.");
- Log.d(TAG, "Position on page currently at " + getScrollY());
- wikiClient.goBackHistory();
- return true;
- } else {
- Log.d(TAG, "Passing up button press.");
- return super.onKeyDown(keyCode, event);
- }
- }
-
- /**
- * Performs a search against the wiki.
- *
- * @param query the text to search for.
- */
- public void passSearch(String query) {
- Log.d(TAG, "Searching for " + query);
- String searchUrl = String.format(ARCHWIKI_SEARCH_URL, query);
- wikiClient.shouldOverrideUrlLoading(this, searchUrl);
- }
-
- /**
- * Returns the current {@link WikiPage} being shown or null.
- *
- * @return current wiki page being shown.
- */
- public WikiPage getCurrentWebPage() {
- return wikiClient.getCurrentWebPage();
- }
-
- @Override
- public void onRefresh() {
- wikiClient.refreshPage();
- stopLoading();
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.kt
new file mode 100644
index 0000000..c747296
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/WikiView.kt
@@ -0,0 +1,69 @@
+package com.jtmcn.archwiki.viewer
+
+import android.content.Context
+import android.os.Build
+import android.util.AttributeSet
+import android.view.KeyEvent
+import android.webkit.WebSettings
+import android.widget.ProgressBar
+import androidx.appcompat.app.ActionBar
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+import com.github.takahirom.webview_in_coodinator_layout.NestedWebView
+import com.jtmcn.archwiki.viewer.data.WikiPage
+import timber.log.Timber
+
+class WikiView(context: Context, attrs: AttributeSet) : NestedWebView(context, attrs), SwipeRefreshLayout.OnRefreshListener {
+ lateinit var wikiClient: WikiClient
+
+ /**
+ * Returns the current [WikiPage] being shown or null.
+ *
+ * @return current wiki page being shown.
+ */
+ val currentWebPage: WikiPage?
+ get() = wikiClient.currentWebPage
+
+ init {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !isInEditMode) {
+ // This allows the webview to inject the css (otherwise it blocks it for security reasons)
+ settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
+ }
+ }
+
+ /**
+ * Initializes the wiki client and loads the main page.
+ */
+ fun buildView(progressBar: ProgressBar, actionBar: ActionBar?) {
+ wikiClient = WikiClient(progressBar, actionBar, this)
+ webViewClient = wikiClient
+ wikiClient.shouldOverrideUrlLoading(this, ARCHWIKI_MAIN)
+ }
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
+ if (keyCode == KeyEvent.KEYCODE_BACK && wikiClient.historyStackSize > 1) {
+ Timber.i("Loading previous page.")
+ Timber.d("Position on page currently at $scrollY")
+ wikiClient.goBackHistory()
+ return true
+ } else {
+ Timber.d("Passing up button press.")
+ return super.onKeyDown(keyCode, event)
+ }
+ }
+
+ /**
+ * Performs a search against the wiki.
+ *
+ * @param query the text to search for.
+ */
+ fun passSearch(query: String) {
+ Timber.d("Searching for $query")
+ val searchUrl = String.format(ARCHWIKI_SEARCH_URL, query)
+ wikiClient.shouldOverrideUrlLoading(this, searchUrl)
+ }
+
+ override fun onRefresh() {
+ wikiClient.refreshPage()
+ stopLoading()
+ }
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.java b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.java
deleted file mode 100644
index f54ef59..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-/**
- * A page on the wiki which only knows the name and url.
- */
-public class SearchResult {
- private final String pageName;
- private final String pageURL;
-
- /**
- * Create a search result.
- *
- * @param pageName the name of the page as shown on the wiki.
- * @param pageURL the string url on the wiki.
- */
- public SearchResult(String pageName, String pageURL) {
- this.pageName = pageName;
- this.pageURL = pageURL;
- }
-
- public String getPageName() {
- return pageName;
- }
-
- public String getPageURL() {
- return pageURL;
- }
-
- @Override
- public String toString() {
- return "SearchResult{" + "title='" + pageName + '\'' +
- ", url='" + pageURL + '\'' + '}';
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.kt
new file mode 100644
index 0000000..c562b6e
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResult.kt
@@ -0,0 +1,6 @@
+package com.jtmcn.archwiki.viewer.data
+
+/**
+ * A page on the wiki which only knows the name and url.
+ */
+data class SearchResult(val pageName: String, val pageURL: String)
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.java b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.java
deleted file mode 100644
index ee11f65..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.jtmcn.archwiki.viewer.Constants.ARCHWIKI_BASE;
-
-/**
- * Provides a simple interface to make queries against
- * and parse data from the arch wiki for searches.
- */
-public class SearchResultsBuilder {
- public static final String SEARCH_URL = ARCHWIKI_BASE + "api.php?action=opensearch" +
- "&format=json&formatversion=2&namespace=0&limit=%d" +
- "&suggest=true&search=%s";
- private static final int DEFAULT_LIMIT = 10;
-
- private SearchResultsBuilder() {
-
- }
-
- /**
- * Builds a string url to fetch search results.
- *
- * @param query the text to search for.
- * @return a url to fetch.
- */
- public static String getSearchQuery(String query) {
- return getSearchQuery(query, DEFAULT_LIMIT);
- }
-
- /**
- * Builds a string url to fetch search results.
- *
- * @param query the text to search for.
- * @param limit the maximum number of results to retrieve.
- * @return a url to fetch.
- */
- public static String getSearchQuery(String query, int limit) {
- return String.format(SEARCH_URL, limit, query);
- }
-
- /**
- * Builds a {@link List} from the result of fetching with {@link #getSearchQuery(String, int)}.
- *
- * @param jsonResult the string returned from the query.
- * @return a parsed list of the results.
- */
- public static List parseSearchResults(String jsonResult) {
- JsonParser jsonParser = new JsonParser();
- JsonElement jsonRoot = jsonParser.parse(jsonResult);
- List toReturn = new ArrayList<>();
- if (jsonRoot.isJsonArray()) {
- JsonArray jsonArray = jsonRoot.getAsJsonArray();
- if (jsonArray.size() == 4) {
- String[] listOfPageTitles = getJsonArrayAsStringArray(jsonArray.get(1).getAsJsonArray());
- String[] listOfPageUrls = getJsonArrayAsStringArray(jsonArray.get(3).getAsJsonArray());
- for (int i = 0; i < listOfPageTitles.length; i++) {
- toReturn.add(new SearchResult(listOfPageTitles[i], listOfPageUrls[i]));
- }
- }
- }
- return toReturn;
- }
-
- /**
- * Convert a {@link JsonArray} into an array of strings.
- *
- * @param jsonArray the array to be parsed.
- * @return the string array which was parsed.
- */
- private static String[] getJsonArrayAsStringArray(JsonArray jsonArray) {
- String[] s2 = new String[jsonArray.size()];
- for (int i = 0; i < jsonArray.size(); i++) {
- s2[i] = jsonArray.get(i).getAsString();
- }
- return s2;
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.kt
new file mode 100644
index 0000000..b32be63
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilder.kt
@@ -0,0 +1,36 @@
+package com.jtmcn.archwiki.viewer.data
+
+import com.google.gson.JsonParser
+import com.jtmcn.archwiki.viewer.ARCHWIKI_BASE
+
+/**
+ * Builds a string url to fetch search results.
+ *
+ * @param query the text to search for.
+ * @param limit the maximum number of results to retrieve.
+ * @return a url to fetch.
+ */
+fun getSearchQuery(query: String, limit: Int = 10): String {
+ return "${ARCHWIKI_BASE}/api.php?" +
+ "action=opensearch&format=json&formatversion=2&namespace=0&suggest=true" +
+ "&search=$query" +
+ "&limit=$limit"
+}
+
+/**
+ * Builds a [List] from the result of fetching with [getSearchQuery].
+ *
+ * @param jsonResult the string returned from the query.
+ * @return a parsed list of the results.
+ */
+fun parseSearchResults(jsonResult: String): List {
+ val jsonRoot = JsonParser().parse(jsonResult)
+ if (!jsonRoot.isJsonArray || jsonRoot.asJsonArray.size() != 4) return listOf()
+
+ val jsonArray = jsonRoot.asJsonArray
+
+ val listOfPageTitles = jsonArray.get(1).asJsonArray.mapNotNull { it.asString }
+ val listOfPageUrls = jsonArray.get(3).asJsonArray.mapNotNull { it.asString }
+
+ return listOfPageTitles.zip(listOfPageUrls).map { SearchResult(it.first, it.second) }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.java b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.java
deleted file mode 100644
index 0ecfeac..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-/**
- * Wrapper for a downloaded wiki page which holds the title and html.
- */
-public class WikiPage {
- private final String pageUrl;
- private final String pageTitle;
- private final String htmlString;
- private int scrollPosition = 0;
-
- /**
- * Store the url, title, and html of a page on the wiki.
- *
- * @param pageUrl the string url on the wiki.
- * @param pageTitle the title of the page on the wiki.
- * @param htmlString the html which should be shown to represent the page.
- */
- public WikiPage(String pageUrl, String pageTitle, String htmlString) {
- this.pageUrl = pageUrl;
- this.pageTitle = pageTitle;
- this.htmlString = htmlString;
- }
-
- public String getPageUrl() {
- return pageUrl;
- }
-
- public String getPageTitle() {
- return pageTitle;
- }
-
- public String getHtmlString() {
- return htmlString;
- }
-
- public int getScrollPosition() {
- return scrollPosition;
- }
-
- public void setScrollPosition(int scrollPosition) {
- this.scrollPosition = scrollPosition;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
-
- if (!(obj instanceof WikiPage)) {
- return false;
- }
-
- WikiPage wikiPage = (WikiPage) obj;
-
- return getPageUrl() != null ? getPageUrl().equals(wikiPage.getPageUrl()) : wikiPage.getPageUrl() == null;
- }
-
- @Override
- public int hashCode() {
- return getPageUrl() != null ? getPageUrl().hashCode() : 0;
- }
-
- @Override
- public String toString() {
- return "WikiPage{" +
- "pageUrl='" + pageUrl + '\'' +
- ", pageTitle='" + pageTitle + '\'' +
- ", htmlString='" + htmlString + '\'' +
- ", scrollPosition=" + scrollPosition +
- '}';
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.kt
new file mode 100644
index 0000000..864da17
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPage.kt
@@ -0,0 +1,8 @@
+package com.jtmcn.archwiki.viewer.data
+
+/**
+ * Wrapper for a downloaded wiki page which holds the title and html.
+ */
+data class WikiPage(val pageUrl: String, val pageTitle: String?, val htmlString: String) {
+ var scrollPosition = 0
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.java b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.java
deleted file mode 100644
index ddaa06e..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-import static com.jtmcn.archwiki.viewer.Constants.LOCAL_CSS;
-
-/**
- * Helps with creating a {@link WikiPage} by extracting content from the
- * html fetched from the ArchWiki.
- */
-public class WikiPageBuilder {
- //NOTE: spaces are allowed in ""/etc, but parsing this way should be fine
- public static final String HTML_HEAD_OPEN = "";
- public static final String HTML_HEAD_CLOSE = "";
- public static final String HTML_TITLE_OPEN = "";
- public static final String HTML_TITLE_CLOSE = "";
- public static final String HEAD_TO_INJECT = ""
- + "";
- public static final String DEFAULT_TITLE = " - ArchWiki";
-
- private WikiPageBuilder() {
-
- }
-
- /**
- * Builds a page containing the title, url, and injects local css.
- *
- * @param stringUrl url to download.
- * @param html StringBuilder containing the html of the wikipage
- * @return {@link WikiPage} containing downloaded page.
- */
- public static WikiPage buildPage(String stringUrl, StringBuilder html) {
- String pageTitle = getPageTitle(html);
- injectLocalCSS(html, LOCAL_CSS);
- return new WikiPage(stringUrl, pageTitle, html.toString());
- }
-
- /**
- * Finds the name of the page within the title block of the html.
- * The returned string removes the " - ArchWiki" if found.
- *
- * @param htmlString The html of the page as a string.
- * @return the extracted title from the page.
- */
- public static String getPageTitle(StringBuilder htmlString) {
- int titleStart = (htmlString.indexOf(HTML_TITLE_OPEN) + HTML_TITLE_OPEN.length());
- int titleEnd = htmlString.indexOf(HTML_TITLE_CLOSE, titleStart);
- if (titleStart > 0 && titleEnd > titleStart) { // if there is an html title block
- String title = htmlString.substring(titleStart, titleEnd);
- return title.replace(DEFAULT_TITLE, ""); // drop DEFAULT_TITLE from page title
- }
- //todo should be handled somewhere else when no title is found
- return "No title found";
- }
-
- /**
- * Removes the contents within the head block of the html
- * and replaces it with the a reference to a local css file.
- *
- * @param htmlString The html of the page as a string.
- * @param localCSSFilePath The path of the css file to inject.
- * @return true if the block was successfully replaced.
- */
- public static boolean injectLocalCSS(StringBuilder htmlString, String localCSSFilePath) {
- int headStart = htmlString.indexOf(HTML_HEAD_OPEN) + HTML_HEAD_OPEN.length();
- int headEnd = htmlString.indexOf(HTML_HEAD_CLOSE, headStart);
-
- if (headStart > 0 && headEnd >= headStart) {
- String injectedHeadHtml = String.format(HEAD_TO_INJECT, localCSSFilePath);
- htmlString.replace(headStart, headEnd, injectedHeadHtml);
- return true;
- }
-
- return false;
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.kt
new file mode 100644
index 0000000..517d614
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilder.kt
@@ -0,0 +1,68 @@
+package com.jtmcn.archwiki.viewer.data
+
+import com.jtmcn.archwiki.viewer.LOCAL_CSS
+
+/**
+ * Helps with creating a [WikiPage] by extracting content from the
+ * html fetched from the ArchWiki.
+ */
+
+//NOTE: spaces are allowed in ""/etc, but parsing this way should be fine
+const val HTML_HEAD_OPEN = ""
+const val HTML_HEAD_CLOSE = ""
+const val HTML_TITLE_OPEN = ""
+const val HTML_TITLE_CLOSE = ""
+private const val HEAD_TO_INJECT = "" +
+ ""
+private const val DEFAULT_TITLE = " - ArchWiki"
+
+/**
+ * Builds a page containing the title, url, and injects local css.
+ *
+ * @param url url to download.
+ * @param html [StringBuilder] containing the html of the wikipage
+ * @return [WikiPage] containing downloaded page.
+ */
+fun buildPage(url: String, html: StringBuilder): WikiPage {
+ val pageTitle = getPageTitle(html)
+ injectLocalCSS(html, LOCAL_CSS)
+ return WikiPage(url, pageTitle, html.toString())
+}
+
+/**
+ * Finds the name of the page within the title block of the html.
+ * The returned string removes the " - ArchWiki" if found.
+ *
+ * @param htmlString The html of the page as a string.
+ * @return the extracted title from the page.
+ */
+fun getPageTitle(htmlString: StringBuilder): String? {
+ val titleStart = htmlString.indexOf(HTML_TITLE_OPEN) + HTML_TITLE_OPEN.length
+ val titleEnd = htmlString.indexOf(HTML_TITLE_CLOSE, titleStart)
+ if (titleStart in 1..titleEnd) { // if there is an html title block
+ val title = htmlString.substring(titleStart, titleEnd)
+ return title.replace(DEFAULT_TITLE, "") // drop DEFAULT_TITLE from page title
+ }
+ return null
+}
+
+/**
+ * Removes the contents within the head block of the html
+ * and replaces it with the a reference to a local css file.
+ *
+ * @param htmlString The html of the page as a string.
+ * @param localCSSFilePath The path of the css file to inject.
+ * @return true if the block was successfully replaced.
+ */
+fun injectLocalCSS(htmlString: StringBuilder, localCSSFilePath: String): Boolean {
+ val headStart = htmlString.indexOf(HTML_HEAD_OPEN) + HTML_HEAD_OPEN.length
+ val headEnd = htmlString.indexOf(HTML_HEAD_CLOSE, headStart)
+
+ if (headStart in 1..headEnd) {
+ val injectedHeadHtml = String.format(HEAD_TO_INJECT, localCSSFilePath)
+ htmlString.replace(headStart, headEnd, injectedHeadHtml)
+ return true
+ }
+
+ return false
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.java b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.java
deleted file mode 100644
index 29c0cbd..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.jtmcn.archwiki.viewer.tasks;
-
-import android.os.AsyncTask;
-
-import com.jtmcn.archwiki.viewer.data.SearchResult;
-import com.jtmcn.archwiki.viewer.data.SearchResultsBuilder;
-import com.jtmcn.archwiki.viewer.data.WikiPage;
-import com.jtmcn.archwiki.viewer.data.WikiPageBuilder;
-
-import java.util.List;
-
-/**
- * Wrapper for {@link FetchUrl} which gives an easy to use interface
- * for fetching {@link SearchResult} and {@link WikiPage}.
- */
-public class Fetch {
- public static final FetchUrl.FetchUrlMapper> SEARCH_RESULTS_MAPPER =
- (url, stringBuilder) -> SearchResultsBuilder.parseSearchResults(stringBuilder.toString());
-
- public static final FetchUrl.FetchUrlMapper WIKI_PAGE_MAPPER =
- WikiPageBuilder::buildPage;
-
- private Fetch() {
-
- }
-
- /**
- * Fetches a {@link List} from the url.
- *
- * @param onFinish The listener called when search results are ready.
- * @param url The url to fetch the search results from.
- * @return the async task fetching the data.
- */
- public static AsyncTask> search(
- FetchUrl.OnFinish> onFinish,
- String url
- ) {
- return new FetchUrl<>(onFinish, SEARCH_RESULTS_MAPPER).execute(url);
- }
-
- /**
- * Fetches a {@link WikiPage} from the url.
- *
- * @param onFinish The listener called when the page is ready.
- * @param url The url to fetch the page from.
- * @return the async task fetching the data.
- */
- public static AsyncTask page(
- FetchUrl.OnFinish onFinish,
- String url
- ) {
- return new FetchUrl<>(onFinish, WIKI_PAGE_MAPPER).execute(url);
- }
-
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.kt
new file mode 100644
index 0000000..d6d5ed7
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/Fetch.kt
@@ -0,0 +1,39 @@
+package com.jtmcn.archwiki.viewer.tasks
+
+import android.os.AsyncTask
+import com.jtmcn.archwiki.viewer.data.SearchResult
+import com.jtmcn.archwiki.viewer.data.WikiPage
+import com.jtmcn.archwiki.viewer.data.buildPage
+import com.jtmcn.archwiki.viewer.data.parseSearchResults
+
+/**
+ * Wrapper for [FetchUrl] which gives an easy to use interface
+ * for fetching [SearchResult] and [WikiPage].
+ */
+object Fetch {
+ private val SEARCH_RESULTS_MAPPER = { _: String, html: StringBuilder -> parseSearchResults(html.toString()) }
+
+ private val WIKI_PAGE_MAPPER = { url: String, html: StringBuilder -> buildPage(url, html) }
+
+ /**
+ * Fetches a List from the url.
+ *
+ * @param onFinish The listener called when search results are ready.
+ * @param url The url to fetch the search results from.
+ * @return the async task fetching the data.
+ */
+ fun search(onFinish: (List) -> Unit, url: String): AsyncTask> {
+ return FetchUrl(onFinish, SEARCH_RESULTS_MAPPER).execute(url)
+ }
+
+ /**
+ * Fetches a [WikiPage] from the url.
+ *
+ * @param onFinish The listener called when the page is ready.
+ * @param url The url to fetch the page from.
+ * @return the async task fetching the data.
+ */
+ fun page(onFinish: (WikiPage) -> Unit, url: String): AsyncTask {
+ return FetchUrl(onFinish, WIKI_PAGE_MAPPER).execute(url)
+ }
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.java b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.java
deleted file mode 100644
index da0db51..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.jtmcn.archwiki.viewer.tasks;
-
-import android.os.AsyncTask;
-import android.util.Log;
-
-import com.jtmcn.archwiki.viewer.utils.NetworkUtils;
-
-import java.io.IOException;
-
-/**
- * Fetches a url, maps it to a {@link Result}, and returns it.
- *
- * @param The type which the fetched url's text will be mapped to.
- */
-public class FetchUrl extends AsyncTask {
- private static final String TAG = FetchUrl.class.getSimpleName();
- private final OnFinish onFinish;
- private final FetchUrlMapper mapper;
- private final boolean caching;
-
- public FetchUrl(OnFinish onFinish, FetchUrlMapper mapper) {
- this(onFinish, mapper, true);
- }
-
- /**
- * Fetches the first url and notifies the {@link OnFinish} listener.
- *
- * @param onFinish The function to be called when the result is ready.
- * @param mapper The function to map from the url and downloaded page to the desired type.
- * @param caching Whether or not to use cached results
- */
- public FetchUrl(OnFinish onFinish, FetchUrlMapper mapper, boolean caching) {
- this.onFinish = onFinish;
- this.mapper = mapper;
- this.caching = caching;
- }
-
- @Override
- protected Result doInBackground(String... params) {
- if (params.length >= 1) {
- String url = params[0];
- StringBuilder toAdd = getItem(url);
- return mapper.mapTo(url, toAdd);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Result values) {
- super.onPostExecute(values);
- if (onFinish != null) {
- onFinish.onFinish(values);
- }
- }
-
- /**
- * Fetches a url and returns what was downloaded or null
- *
- * @param url to query
- */
- private StringBuilder getItem(String url) {
- StringBuilder toReturn;
- try {
- toReturn = NetworkUtils.fetchURL(url, caching);
- } catch (IOException e) { //network exception
- Log.w(TAG, "Could not connect to: " + url, e);
- toReturn = new StringBuilder();
- }
-
- return toReturn;
- }
-
- /**
- * A listener which is called when {@link Result} is ready.
- *
- * @param the type of object which has been created.
- */
- public interface OnFinish {
- void onFinish(Result result);
- }
-
- /**
- * Maps the url and fetched text to {@link R}
- *
- * @param The type which the text will be mapped to.
- */
- public interface FetchUrlMapper {
- R mapTo(String url, StringBuilder sb);
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.kt
new file mode 100644
index 0000000..48263a4
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/tasks/FetchUrl.kt
@@ -0,0 +1,47 @@
+package com.jtmcn.archwiki.viewer.tasks
+
+import android.os.AsyncTask
+import com.jtmcn.archwiki.viewer.utils.fetchURL
+import timber.log.Timber
+import java.io.IOException
+
+/**
+ * Fetches a url, [mapper] maps it to a [Result], and returns it.
+ * */
+class FetchUrl(
+ private val onFinish: (Result) -> Unit,
+ private val mapper: (url: String, html: StringBuilder) -> Result
+) : AsyncTask() {
+
+ override fun doInBackground(vararg params: String): Result? {
+ if (params.isNotEmpty()) {
+ val url = params[0]
+ val toAdd = getItem(url)
+ return mapper(url, toAdd)
+ }
+ return null
+ }
+
+ override fun onPostExecute(values: Result) {
+ super.onPostExecute(values)
+ onFinish(values)
+ }
+
+ /**
+ * Fetches a url and returns what was downloaded or null
+ *
+ * @param url to query
+ */
+ private fun getItem(url: String): StringBuilder {
+ var toReturn: StringBuilder
+ try {
+ val response = fetchURL(url).execute().body()?.string() ?: ""
+ toReturn = StringBuilder(response)
+ } catch (e: IOException) { //network exception
+ Timber.w(e,"Could not connect to $url")
+ toReturn = StringBuilder()
+ }
+
+ return toReturn
+ }
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.java b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.java
deleted file mode 100644
index ee685de..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.jtmcn.archwiki.viewer.utils;
-
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-
-/**
- * Utilities class for Android specific actions.
- */
-public class AndroidUtils {
-
- private AndroidUtils() {
-
- }
-
- /**
- * Creates an intent to open a link.
- *
- * @param url The url to be opened.
- * @param context The context needed to start the intent.
- */
- public static void openLink(String url, Context context) {
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
- context.startActivity(intent);
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.kt
new file mode 100644
index 0000000..914663c
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/AndroidUtils.kt
@@ -0,0 +1,16 @@
+package com.jtmcn.archwiki.viewer.utils
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+
+/**
+ * Creates an intent to open a link.
+ *
+ * @param url The url to be opened.
+ * @param context The context needed to start the intent.
+ */
+fun openLink(url: String, context: Context) {
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ context.startActivity(intent)
+}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.java b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.java
deleted file mode 100644
index 59bb998..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.jtmcn.archwiki.viewer.utils;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Utility class for performing basic network tasks.
- */
-public class NetworkUtils {
- private static final Map downloadCache = new HashMap<>();
-
- private NetworkUtils() {
-
- }
-
- /**
- * Fetches a url with caching.
- *
- * @param stringUrl url to be fetched.
- * @return the string that was fetched.
- * @throws IOException on network failure.
- */
- public static StringBuilder fetchURL(String stringUrl) throws IOException {
- return fetchURL(stringUrl, true);
- }
-
- /**
- * Fetches a url with optional caching.
- *
- * @param stringUrl url to be fetched.
- * @param useCache whether or not it should return a cached value.
- * @return the string that was fetched.
- * @throws IOException on network failure.
- */
- public static StringBuilder fetchURL(String stringUrl, boolean useCache) throws IOException {
- StringBuilder sb = new StringBuilder();
- URL url = new URL(stringUrl);
- if (useCache && downloadCache.containsKey(url)) {
- return new StringBuilder(downloadCache.get(url));
- }
- HttpURLConnection urlConnection = (HttpURLConnection) url
- .openConnection();
-
- urlConnection.setReadTimeout(10000); // milliseconds
- urlConnection.setConnectTimeout(15000); // milliseconds
- urlConnection.setRequestMethod("GET");
-
- BufferedReader in = new BufferedReader(new InputStreamReader(
- urlConnection.getInputStream()), 8);// buffer 8k
-
- String line;
- String lineSeparator = System.getProperty("line.separator");
-
- while ((line = in.readLine()) != null) {
- sb.append(line).append(lineSeparator);
- }
-
- urlConnection.disconnect();
- in.close();
-
- downloadCache.put(url, new StringBuilder(sb));
- return sb;
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.kt
new file mode 100644
index 0000000..956b27c
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/NetworkUtils.kt
@@ -0,0 +1,19 @@
+
+package com.jtmcn.archwiki.viewer.utils
+
+import okhttp3.Call
+import okhttp3.OkHttpClient
+import okhttp3.Request
+
+
+
+private val client = OkHttpClient.Builder().build()
+private val builder = Request.Builder()
+
+/**
+ * Fetches a url with optional caching.
+ *
+ * @param url url to be fetched.
+ * @param cb callback to handle result
+ */
+fun fetchURL(url: String): Call = client.newCall(builder.url(url).build())
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.java b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.java
deleted file mode 100644
index f778506..0000000
--- a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.jtmcn.archwiki.viewer.utils;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
-import com.jtmcn.archwiki.viewer.PreferencesActivity;
-
-/**
- * Created by kevin on 6/7/2017.
- */
-
-public class SettingsUtils {
-
- public static int getFontSize(Context context) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
-
- // https://stackoverflow.com/questions/11346916/listpreference-use-string-array-as-entry-and-integer-array-as-entry-values-does
- // the value of this preference must be parsed as a string
- String fontSizePref = prefs.getString(PreferencesActivity.KEY_TEXT_SIZE, "2");
- return Integer.valueOf(fontSizePref);
-
- }
-}
diff --git a/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.kt b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.kt
new file mode 100644
index 0000000..8e33801
--- /dev/null
+++ b/app/src/main/java/com/jtmcn/archwiki/viewer/utils/SettingsUtils.kt
@@ -0,0 +1,48 @@
+package com.jtmcn.archwiki.viewer.utils
+
+import android.content.Context
+import android.content.SharedPreferences
+import androidx.preference.PreferenceManager
+import com.jtmcn.archwiki.viewer.Prefs
+
+@Deprecated("Use getTextZoom", replaceWith = ReplaceWith("getTextZoom(this)"))
+fun getTextSize(prefs: SharedPreferences): Int? {
+ if(!prefs.contains(Prefs.KEY_TEXT_SIZE)) {
+ return null
+ }
+
+ // https://stackoverflow.com/questions/11346916/listpreference-use-string-array-as-entry-and-integer-array-as-entry-values-does
+ // the value of this preference must be parsed as a string
+ val fontSizePref = prefs.getString(Prefs.KEY_TEXT_SIZE, "2")!!
+ return Integer.valueOf(fontSizePref)
+
+}
+
+@Deprecated("Use getTextZoom")
+fun textSizeToTextZoom(fontSize: Int) = when(fontSize) {
+ 0 -> 50
+ 1 -> 75
+ 2 -> 100
+ 3 -> 150
+ 4 -> 200
+ else -> 100
+}
+
+/**
+ * gets the [Prefs.KEY_TEXT_ZOOM] preference, and if needed migrates from [getTextSize=]
+ */
+fun getTextZoom(context: Context): Int {
+ val prefs = PreferenceManager.getDefaultSharedPreferences(context)
+ val textSize = getTextSize(prefs)
+ if(textSize != null) {
+ val textZoom = textSizeToTextZoom(textSize)
+ prefs.edit()
+ .putInt(Prefs.KEY_TEXT_ZOOM, textZoom)
+ .remove(Prefs.KEY_TEXT_SIZE)
+ .apply()
+
+ return textZoom
+ }
+
+ return prefs.getInt(Prefs.KEY_TEXT_ZOOM, 100)
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index ff9a183..3f15a14 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -11,7 +11,7 @@
diff --git a/app/src/main/res/layout/activity_preferences.xml b/app/src/main/res/layout/activity_preferences.xml
index cc3c025..0975e4c 100644
--- a/app/src/main/res/layout/activity_preferences.xml
+++ b/app/src/main/res/layout/activity_preferences.xml
@@ -1,20 +1,16 @@
-
-
+ android:orientation="vertical"
+ android:fitsSystemWindows="true"
+ tools:context=".PreferencesActivity" >
-
+
-
+ android:layout_height="match_parent"
+ android:layout_below="@id/settings_app_bar"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/toolbar.xml b/app/src/main/res/layout/toolbar.xml
index 5ddffa9..97347a2 100644
--- a/app/src/main/res/layout/toolbar.xml
+++ b/app/src/main/res/layout/toolbar.xml
@@ -1,5 +1,6 @@
-
-
-
-
- - Sehr klein
- - Klein
- - Normal
- - Groß
- - Sehr groß
-
-
-
diff --git a/app/src/main/res/values-fr/array.xml b/app/src/main/res/values-fr/array.xml
deleted file mode 100644
index 31155e4..0000000
--- a/app/src/main/res/values-fr/array.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- - Très petit
- - Petit
- - Normal
- - Grand
- - Très grand
-
-
-
diff --git a/app/src/main/res/values-it/array.xml b/app/src/main/res/values-it/array.xml
deleted file mode 100644
index 3484b5d..0000000
--- a/app/src/main/res/values-it/array.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- - Molto piccolo
- - Piccolo
- - Normale
- - Grande
- - Molto grande
-
-
-
diff --git a/app/src/main/res/values-iw/array.xml b/app/src/main/res/values-iw/array.xml
deleted file mode 100644
index 6fbf36b..0000000
--- a/app/src/main/res/values-iw/array.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- - הכי קטן
- - קטן
- - רגיל
- - גדול
- - הגי גדול
-
-
-
diff --git a/app/src/main/res/values-pt-rBR/array.xml b/app/src/main/res/values-pt-rBR/array.xml
deleted file mode 100644
index df068d3..0000000
--- a/app/src/main/res/values-pt-rBR/array.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- - Muito pequeno
- - Pequeno
- - Normal
- - Grande
- - Muito grande
-
-
-
diff --git a/app/src/main/res/values-sk/array.xml b/app/src/main/res/values-sk/array.xml
deleted file mode 100644
index aad0d6c..0000000
--- a/app/src/main/res/values-sk/array.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- - Najmenšia
- - Menšia
- - Normálna
- - Väčšia
- - Najväčšia
-
-
-
diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml
deleted file mode 100644
index c0b5f5a..0000000
--- a/app/src/main/res/values/array.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
- - Smallest
- - Smaller
- - Normal
- - Larger
- - Largest
-
-
-
- - 0
- - 1
- - 2
- - 3
- - 4
-
-
-
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
new file mode 100644
index 0000000..f776307
--- /dev/null
+++ b/app/src/main/res/xml/preferences.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/prefs.xml b/app/src/main/res/xml/prefs.xml
deleted file mode 100644
index 76c6ef2..0000000
--- a/app/src/main/res/xml/prefs.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.java b/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.java
deleted file mode 100644
index d630fa0..0000000
--- a/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-import org.junit.Test;
-
-import java.util.List;
-
-import static junit.framework.Assert.assertEquals;
-
-public class SearchResultsBuilderTest {
- private final String realResult = "[\"arch\", [\"Arch-based Distros\", \"Arch-based distributions\", \"Arch-chroot\", \"Arch32\", \"Arch64 FAQ\"],\n" +
- "\t[\"\", \"\", \"\", \"\", \"\"],\n" +
- "\t[\"https://wiki.archlinux.org/index.php/Arch-based_Distros\", \"https://wiki.archlinux.org/index.php/Arch-based_distributions\", \"https://wiki.archlinux.org/index.php/Arch-chroot\", \"https://wiki.archlinux.org/index.php/Arch32\", \"https://wiki.archlinux.org/index.php/Arch64_FAQ\"]\n" +
- "]";
-
- @Test
- public void parseSearchResults() throws Exception {
- List searchResults = SearchResultsBuilder.parseSearchResults(realResult);
-
- assertEquals("Arch-based Distros",searchResults.get(0).getPageName());
- assertEquals("https://wiki.archlinux.org/index.php/Arch-based_Distros", searchResults.get(0).getPageURL());
-
- assertEquals("Arch-chroot",searchResults.get(2).getPageName());
- assertEquals("https://wiki.archlinux.org/index.php/Arch-chroot", searchResults.get(2).getPageURL());
- }
-
- @Test
- public void getSearchQuery() {
- String query = SearchResultsBuilder.getSearchQuery("arch");
- assertEquals("https://wiki.archlinux.org/api.php?action=opensearch&format=json&formatversion=2&namespace=0&limit=10&suggest=true&search=arch",query);
-
- String queryWithLength = SearchResultsBuilder.getSearchQuery("arch",9);
- assertEquals("https://wiki.archlinux.org/api.php?action=opensearch&format=json&formatversion=2&namespace=0&limit=9&suggest=true&search=arch",queryWithLength);
- }
-
- @Test
- public void emptySearchCorrectFormat() throws Exception {
- String fakeResult = "[\"\", [],\n" +
- "\t[],\n" +
- "\t[]\n" +
- "]";
- List searchResults = SearchResultsBuilder.parseSearchResults(fakeResult);
- assertEquals(0,searchResults.size());
- }
-
- @Test
- public void emptyStringSearch() throws Exception {
- String fakeResult = "";
- List searchResults = SearchResultsBuilder.parseSearchResults(fakeResult);
- assertEquals(0,searchResults.size());
- }
-}
\ No newline at end of file
diff --git a/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.kt b/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.kt
new file mode 100644
index 0000000..b9728fc
--- /dev/null
+++ b/app/src/test/java/com/jtmcn/archwiki/viewer/data/SearchResultsBuilderTest.kt
@@ -0,0 +1,48 @@
+package com.jtmcn.archwiki.viewer.data
+
+import org.junit.Test
+import org.junit.Assert.*
+
+class SearchResultsBuilderTest {
+ private val realResult = """["arch", ["Arch-based Distros", "Arch-based distributions", "Arch-chroot", "Arch32", "Arch64 FAQ"],
+ ["", "", "", "", ""],
+ ["https://wiki.archlinux.org/index.php/Arch-based_Distros", "https://wiki.archlinux.org/index.php/Arch-based_distributions", "https://wiki.archlinux.org/index.php/Arch-chroot", "https://wiki.archlinux.org/index.php/Arch32", "https://wiki.archlinux.org/index.php/Arch64_FAQ"]
+]"""
+
+ @Test
+ @Throws(Exception::class)
+ fun parseSearchResultsTest() {
+ val searchResults = parseSearchResults(realResult)
+ assertEquals("Arch-based Distros", searchResults[0].pageName)
+ assertEquals("https://wiki.archlinux.org/index.php/Arch-based_Distros", searchResults[0].pageURL)
+ assertEquals("Arch-chroot", searchResults[2].pageName)
+ assertEquals("https://wiki.archlinux.org/index.php/Arch-chroot", searchResults[2].pageURL)
+ }
+
+ @Test
+ fun getSearchQuery() {
+ val query: String = getSearchQuery("arch")
+ assertEquals("https://wiki.archlinux.org/api.php?action=opensearch&format=json&formatversion=2&namespace=0&suggest=true&search=arch&limit=10", query)
+ val queryWithLength: String = getSearchQuery("arch", 9)
+ assertEquals("https://wiki.archlinux.org/api.php?action=opensearch&format=json&formatversion=2&namespace=0&suggest=true&search=arch&limit=9", queryWithLength)
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun emptySearchCorrectFormat() {
+ val fakeResult = "[\"\", [],\n" +
+ "\t[],\n" +
+ "\t[]\n" +
+ "]"
+ val searchResults = parseSearchResults(fakeResult)
+ assertEquals(0, searchResults.size)
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun emptyStringSearch() {
+ val fakeResult = ""
+ val searchResults = parseSearchResults(fakeResult)
+ assertEquals(0, searchResults.size)
+ }
+}
\ No newline at end of file
diff --git a/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.java b/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.java
deleted file mode 100644
index 3178c5e..0000000
--- a/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.jtmcn.archwiki.viewer.data;
-
-import com.jtmcn.archwiki.viewer.Constants;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-public class WikiPageBuilderTest {
- @Test
- public void getPageTitle() throws Exception {
- String fakeTitle = "fake title..1!@#!@#!";
- StringBuilder wrapped = new StringBuilder(WikiPageBuilder.HTML_TITLE_OPEN)
- .append(fakeTitle)
- .append(WikiPageBuilder.HTML_TITLE_CLOSE);
- assertEquals(fakeTitle, WikiPageBuilder.getPageTitle(wrapped));
- }
-
- @Test
- public void getEmptyTitle() throws Exception {
- assertEquals("No title found", WikiPageBuilder.getPageTitle(new StringBuilder()));
- }
-
- @Test
- public void injectLocalCSS() throws Exception {
- StringBuilder head = new StringBuilder(WikiPageBuilder.HTML_HEAD_OPEN)
- .append(WikiPageBuilder.HTML_HEAD_CLOSE);
- boolean passed = WikiPageBuilder.injectLocalCSS(head, Constants.LOCAL_CSS);
- assertTrue(passed);
- assertEquals("",
- head.toString());
- }
-
- @Test
- public void injectLocalCSSFail() throws Exception {
- String fakeHead = " ";
- StringBuilder head = new StringBuilder(fakeHead);
- boolean passed = WikiPageBuilder.injectLocalCSS(head, Constants.LOCAL_CSS);
- assertFalse(passed);
- assertEquals(fakeHead, head.toString());
- }
-
-}
\ No newline at end of file
diff --git a/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.kt b/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.kt
new file mode 100644
index 0000000..8e52ca0
--- /dev/null
+++ b/app/src/test/java/com/jtmcn/archwiki/viewer/data/WikiPageBuilderTest.kt
@@ -0,0 +1,47 @@
+package com.jtmcn.archwiki.viewer.data
+
+import com.jtmcn.archwiki.viewer.LOCAL_CSS
+import org.junit.Assert.*
+
+import org.junit.Test
+
+class WikiPageBuilderTest {
+ @Test
+ @Throws(Exception::class)
+ fun getPageTitle() {
+ val fakeTitle = "fake title..1!@#!@#!"
+ assertEquals(fakeTitle, getPageTitle(wrappedTitle(fakeTitle)))
+
+ assertEquals("", getPageTitle(wrappedTitle("")))
+ }
+
+ private fun wrappedTitle(fakeTitle: String) =
+ StringBuilder("${HTML_TITLE_OPEN}${fakeTitle}${HTML_TITLE_CLOSE}")
+
+ @Test
+ @Throws(Exception::class)
+ fun getEmptyTitle() {
+ assertNull(getPageTitle(StringBuilder()))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun injectLocalCSS() {
+ val head = StringBuilder("${HTML_HEAD_OPEN}${HTML_HEAD_CLOSE}")
+ val passed = injectLocalCSS(head, LOCAL_CSS)
+ assertTrue(passed)
+ assertEquals("",
+ head.toString())
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun injectLocalCSSFail() {
+ val fakeHead = " "
+ val head = StringBuilder(fakeHead)
+ val passed = injectLocalCSS(head, LOCAL_CSS)
+ assertFalse(passed)
+ assertEquals(fakeHead, head.toString())
+ }
+
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 532a98c..1a2e6e8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,23 +1,19 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
+ ext.kotlin_version = '1.3.61'
repositories {
jcenter()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.1'
+ classpath 'com.android.tools.build:gradle:3.5.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
jcenter()
- maven {
- url 'https://maven.google.com/'
- name 'Google'
- }
+ google()
}
}