Compare commits
No commits in common. "main" and "csrf-fix-hopefully" have entirely different histories.
main
...
csrf-fix-h
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Experiencing a bug? Report it so it can be caught!
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**How to reproduce**
|
|
||||||
Steps to reproduce the behaviour:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behaviour**
|
|
||||||
A clear and concise description of what you expected to happen (unless that is so obvious that it would be particularly hard to miss).
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**System details**
|
|
||||||
- Android version [e.g. Android 7]
|
|
||||||
- App version [e.g. 1.3.8]
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
||||||
**Relevant?**
|
|
||||||
- [ ] This is an issue specifically with the Android app
|
|
8
.idea/deploymentTargetSelector.xml
generated
8
.idea/deploymentTargetSelector.xml
generated
@ -4,14 +4,6 @@
|
|||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-01-23T18:59:40.434203416Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=ZE2224BR4Z" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
</SelectionState>
|
||||||
</selectionStates>
|
</selectionStates>
|
||||||
</component>
|
</component>
|
||||||
|
@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "nl.privacydragon.bookwyrm"
|
applicationId "nl.privacydragon.bookwyrm"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
versionCode 15
|
versionCode 13
|
||||||
versionName "1.3.8"
|
versionName "1.3.6"
|
||||||
|
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
}
|
}
|
||||||
@ -37,14 +37,11 @@ dependencies {
|
|||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||||
implementation 'com.google.android.material:material:1.12.0'
|
|
||||||
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.1.0')
|
implementation platform('org.jetbrains.kotlin:kotlin-bom:2.1.0')
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||||
implementation 'com.google.zxing:core:3.5.3'
|
implementation 'com.google.zxing:core:3.5.3'
|
||||||
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
|
implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
|
||||||
implementation 'org.conscrypt:conscrypt-android:2.5.2'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
|
||||||
|
|
||||||
}
|
}
|
BIN
app/release/Bookwyrm-v1.3.6.apk
Normal file
BIN
app/release/Bookwyrm-v1.3.6.apk
Normal file
Binary file not shown.
Binary file not shown.
@ -11,8 +11,8 @@
|
|||||||
"type": "SINGLE",
|
"type": "SINGLE",
|
||||||
"filters": [],
|
"filters": [],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
"versionCode": 15,
|
"versionCode": 13,
|
||||||
"versionName": "1.3.8",
|
"versionName": "1.3.6",
|
||||||
"outputFile": "app-release.apk"
|
"outputFile": "app-release.apk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_wyrm_round"
|
android:roundIcon="@mipmap/ic_launcher_wyrm_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme">
|
android:theme="@style/Theme.Bookwyrm">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.webkit.WebView.MetricsOptOut"
|
android:name="android.webkit.WebView.MetricsOptOut"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
|
@ -81,6 +81,7 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
|
||||||
if (omhooglader != null) {
|
if (omhooglader != null) {
|
||||||
|
//omhooglader.onReceiveValue(null);
|
||||||
omhooglader = null;
|
omhooglader = null;
|
||||||
}
|
}
|
||||||
omhooglader = filePathCallback;
|
omhooglader = filePathCallback;
|
||||||
@ -94,11 +95,19 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//The name of the user's server is stored in the shared preferences, so first it has to be read from there.
|
//myWebView.addJavascriptInterface(new HandlerActivity.WebAppInterface(this), "Android");
|
||||||
|
//The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||||
String defaultValue = "none";
|
String defaultValue = "none";
|
||||||
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||||
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||||
if (server.equals("none")) {
|
//SharedPreferences sharedPrefName = HandlerActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
|
||||||
|
//String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
|
||||||
|
//SharedPreferences sharedPrefPass = HandlerActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
|
||||||
|
//String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
|
||||||
|
//SharedPreferences sharedPrefMagic = HandlerActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
|
||||||
|
//String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
|
||||||
|
//If there is nothing configured yet, the user should be redirected to the main screen for logging in.
|
||||||
|
if (server == "none") {
|
||||||
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
|
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
|
||||||
}
|
}
|
||||||
String pathMaybe = appLinkData.getPath();
|
String pathMaybe = appLinkData.getPath();
|
||||||
@ -121,6 +130,64 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
toGoServer = "https://" + server;
|
toGoServer = "https://" + server;
|
||||||
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
|
||||||
}
|
}
|
||||||
|
//Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
|
||||||
|
//First get the keystore thing.
|
||||||
|
// KeyStore keyStore = null;
|
||||||
|
// try {
|
||||||
|
// keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
// } catch (KeyStoreException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Then, load it. or something. To make sure that it can be used.
|
||||||
|
// try {
|
||||||
|
// keyStore.load(null);
|
||||||
|
// } catch (CertificateException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (IOException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (NoSuchAlgorithmException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Next, retrieve the key to be used for the decryption.
|
||||||
|
// Key DragonLikeKey = null;
|
||||||
|
// try {
|
||||||
|
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||||
|
// } catch (KeyStoreException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (NoSuchAlgorithmException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (UnrecoverableKeyException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Do something with getting the/a cipher or something.
|
||||||
|
// Cipher c = null;
|
||||||
|
// try {
|
||||||
|
// c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
// } catch (NoSuchAlgorithmException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (NoSuchPaddingException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //And then initiating the cipher, so it can be used.
|
||||||
|
// try {
|
||||||
|
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||||
|
// } catch (InvalidAlgorithmParameterException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (InvalidKeyException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Decrypt the password!
|
||||||
|
// byte[] truePass = null;
|
||||||
|
// try {
|
||||||
|
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||||
|
// } catch (BadPaddingException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// } catch (IllegalBlockSizeException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Convert the decrypted password back to a string.
|
||||||
|
// String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||||
|
//String wacht = passw.replaceAll("'", "\\\\'");
|
||||||
|
|
||||||
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
|
//A webviewclient thing is needed for some stuff. To automatically log in, the credentials are put in the form by the javascript that is loaded once the page is fully loaded. Then it is automatically submitted if the current page is the login page.
|
||||||
String finalToGoServer = toGoServer;
|
String finalToGoServer = toGoServer;
|
||||||
@ -128,6 +195,11 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
LoadIndicator.setVisibility(View.GONE);
|
LoadIndicator.setVisibility(View.GONE);
|
||||||
myWebView.setVisibility(View.VISIBLE);
|
myWebView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
//view.loadUrl("javascript:(function() { document.getElementById('id_password').value = '" + wacht + "'; ;})()");
|
||||||
|
//view.loadUrl("javascript:(function() { document.getElementById('id_localname').value = '" + name + "'; ;})()");
|
||||||
|
view.loadUrl("javascript:(function() { if (window.location.href == '" + finalToGoServer + "' && !/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||||
|
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "') { document.getElementsByName(\"login\")[0].submit();} ;})()");
|
||||||
view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) {" +
|
view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) {" +
|
||||||
"blocks = document.getElementsByClassName('block');" +
|
"blocks = document.getElementsByClassName('block');" +
|
||||||
"for (let element of blocks){" +
|
"for (let element of blocks){" +
|
||||||
@ -150,6 +222,8 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
"} else {" +
|
"} else {" +
|
||||||
"let ISBN = document.createElement(\"div\");" +
|
"let ISBN = document.createElement(\"div\");" +
|
||||||
"ISBN.class = 'control';" +
|
"ISBN.class = 'control';" +
|
||||||
|
//"ISBN.class = 'button';" +
|
||||||
|
//"ISBN.type = 'button';" +
|
||||||
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
|
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
|
||||||
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
|
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
|
||||||
"nav.appendChild(ISBN);" +
|
"nav.appendChild(ISBN);" +
|
||||||
@ -157,6 +231,27 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
";})()");
|
";})()");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
/*myWebView.setWebChromeClient(new WebChromeClient(){
|
||||||
|
// Need to accept permissions to use the camera
|
||||||
|
@Override
|
||||||
|
public void onPermissionRequest(PermissionRequest request) {
|
||||||
|
String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||||
|
int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission);
|
||||||
|
if (grant != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
String[] permission_list = new String[1];
|
||||||
|
permission_list[0] = permission;
|
||||||
|
ActivityCompat.requestPermissions(HandlerActivity.this, permission_list, 1);
|
||||||
|
}
|
||||||
|
request.grant(request.getResources());
|
||||||
|
final String[] requestedResources = request.getResources();
|
||||||
|
for (String r : requestedResources) {
|
||||||
|
if (r.equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) {
|
||||||
|
request.grant(new String[]{PermissionRequest.RESOURCE_VIDEO_CAPTURE});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});*/
|
||||||
//Here, load the login page of the server. That actually does all that is needed.
|
//Here, load the login page of the server. That actually does all that is needed.
|
||||||
myWebView.loadUrl(toGoServer);
|
myWebView.loadUrl(toGoServer);
|
||||||
}
|
}
|
||||||
@ -194,6 +289,8 @@ public class HandlerActivity extends AppCompatActivity {
|
|||||||
eisen.setPrompt("SCAN ISBN");
|
eisen.setPrompt("SCAN ISBN");
|
||||||
eisen.setBarcodeImageEnabled(false);
|
eisen.setBarcodeImageEnabled(false);
|
||||||
barcodeLanceerder.launch(eisen);
|
barcodeLanceerder.launch(eisen);
|
||||||
|
//return "blup";
|
||||||
|
//return "bla";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,11 +10,11 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.webkit.CookieManager;
|
|
||||||
import android.webkit.JavascriptInterface;
|
import android.webkit.JavascriptInterface;
|
||||||
import android.webkit.ValueCallback;
|
import android.webkit.ValueCallback;
|
||||||
import android.webkit.WebChromeClient;
|
import android.webkit.WebChromeClient;
|
||||||
@ -33,10 +33,17 @@ import androidx.core.content.ContextCompat;
|
|||||||
import com.journeyapps.barcodescanner.ScanContract;
|
import com.journeyapps.barcodescanner.ScanContract;
|
||||||
import com.journeyapps.barcodescanner.ScanOptions;
|
import com.journeyapps.barcodescanner.ScanOptions;
|
||||||
|
|
||||||
import org.conscrypt.Conscrypt;
|
import java.io.BufferedInputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.CookieHandler;
|
||||||
|
import java.net.CookieManager;
|
||||||
|
import java.net.CookieStore;
|
||||||
|
import java.net.HttpCookie;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
@ -45,9 +52,10 @@ import java.security.Key;
|
|||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
import java.security.KeyStoreException;
|
import java.security.KeyStoreException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.Security;
|
|
||||||
import java.security.UnrecoverableKeyException;
|
import java.security.UnrecoverableKeyException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
@ -55,20 +63,10 @@ import javax.crypto.IllegalBlockSizeException;
|
|||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
|
|
||||||
import okhttp3.FormBody;
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
public class StartActivity extends AppCompatActivity {
|
public class StartActivity extends AppCompatActivity {
|
||||||
WebView myWebView;
|
WebView myWebView;
|
||||||
ProgressBar LoadIndicator;
|
ProgressBar LoadIndicator;
|
||||||
public ValueCallback<Uri[]> omhooglader;
|
public ValueCallback<Uri[]> omhooglader;
|
||||||
String putje = "";
|
|
||||||
String sessie = "";
|
|
||||||
@SuppressLint("SetJavaScriptEnabled")
|
@SuppressLint("SetJavaScriptEnabled")
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@ -91,7 +89,6 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
});
|
});
|
||||||
myWebView = (WebView) findViewById(R.id.webview);
|
myWebView = (WebView) findViewById(R.id.webview);
|
||||||
myWebView.setVisibility(View.GONE);
|
myWebView.setVisibility(View.GONE);
|
||||||
myWebView.getSettings().setUserAgentString(getString(R.string.gebruikersagent));
|
|
||||||
myWebView.getSettings().setJavaScriptEnabled(true);
|
myWebView.getSettings().setJavaScriptEnabled(true);
|
||||||
myWebView.addJavascriptInterface(new Object()
|
myWebView.addJavascriptInterface(new Object()
|
||||||
{
|
{
|
||||||
@ -114,6 +111,13 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
omhooglader = filePathCallback;
|
omhooglader = filePathCallback;
|
||||||
Intent intent = fileChooserParams.createIntent();
|
Intent intent = fileChooserParams.createIntent();
|
||||||
try {
|
try {
|
||||||
|
// String toestemming = Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||||
|
// int grant = ContextCompat.checkSelfPermission(StartActivity.this, toestemming);
|
||||||
|
// if (grant != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// String[] permission_list = new String[1];
|
||||||
|
// permission_list[0] = toestemming;
|
||||||
|
// ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
|
||||||
|
// }
|
||||||
voodooLauncher.launch(intent);
|
voodooLauncher.launch(intent);
|
||||||
} catch (ActivityNotFoundException grrr){
|
} catch (ActivityNotFoundException grrr){
|
||||||
omhooglader = null;
|
omhooglader = null;
|
||||||
@ -183,6 +187,11 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
public void onPageFinished(WebView view, String url) {
|
public void onPageFinished(WebView view, String url) {
|
||||||
LoadIndicator.setVisibility(View.GONE);
|
LoadIndicator.setVisibility(View.GONE);
|
||||||
myWebView.setVisibility(View.VISIBLE);
|
myWebView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
//view.loadUrl("javascript:(function() { document.getElementById('id_password_confirm').value = '" + wacht + "'; ;})()");
|
||||||
|
//view.loadUrl("javascript:(function() { document.getElementById('id_localname_confirm').value = '" + name + "'; ;})()");
|
||||||
|
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login') { document.getElementsByName(\"login-confirm\")[0].submit();} ;})()");
|
||||||
|
//view.loadUrl("javascript:(function() { if (window.location.href == 'https://" + server + "/login' && document.title != '403 Forbidden') { this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);} ;})()");
|
||||||
view.loadUrl("javascript:(function() { " +
|
view.loadUrl("javascript:(function() { " +
|
||||||
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
|
"if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
|
||||||
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
|
"let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
|
||||||
@ -193,6 +202,8 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
"} else {" +
|
"} else {" +
|
||||||
"let ISBN = document.createElement(\"div\");" +
|
"let ISBN = document.createElement(\"div\");" +
|
||||||
"ISBN.class = 'control';" +
|
"ISBN.class = 'control';" +
|
||||||
|
//"ISBN.class = 'button';" +
|
||||||
|
//"ISBN.type = 'button';" +
|
||||||
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
|
"ISBN.innerHTML = '<button class=\"button\" type=\"button\" onclick=\"scan.performClick(this)\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path fill=\"none\" d=\"M0 0h24v24H0z\"/><path d=\"M4 5v14h16V5H4zM3 3h18a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm3 4h3v10H6V7zm4 0h2v10h-2V7zm3 0h1v10h-1V7zm2 0h3v10h-3V7z\"/></svg><span class=\"is-sr-only\">Search</span></button>';" +
|
||||||
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
|
"nav = document.getElementsByClassName(\"field has-addons\")[0];" +
|
||||||
"nav.appendChild(ISBN);" +
|
"nav.appendChild(ISBN);" +
|
||||||
@ -201,138 +212,185 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
CookieManager oven = CookieManager.getInstance();
|
//Here, load the login page of the server. That actually does all that is needed.
|
||||||
String koek = oven.getCookie("https://" + server);
|
// try {
|
||||||
if (koek != null) {
|
// getMiddleWareToken(server, name, passw);
|
||||||
if (koek.indexOf("sessionid") != -1) {
|
// } catch (IOException e) {
|
||||||
myWebView.loadUrl("https://" + server);
|
// throw new RuntimeException(e);
|
||||||
} else {
|
// }
|
||||||
//This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
|
// String geheimeToken = null;
|
||||||
try {
|
// try {
|
||||||
getMiddleWareTokenAndLogIn(server, name, passw);
|
// geheimeToken = getMiddleWareToken(server);
|
||||||
} catch (IOException e) {
|
// } catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
// throw new RuntimeException(e);
|
||||||
}
|
// }
|
||||||
}
|
// String gegevens = null;
|
||||||
} else {
|
// try {
|
||||||
//This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
|
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(geheimeToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||||
try {
|
// } catch (UnsupportedEncodingException e) {
|
||||||
getMiddleWareTokenAndLogIn(server, name, passw);
|
// throw new RuntimeException(e);
|
||||||
} catch (IOException e) {
|
// }
|
||||||
throw new RuntimeException(e);
|
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
|
||||||
}
|
//myWebView.loadUrl("https://" + server + "/login");
|
||||||
}
|
// myWebView.setVisibility(View.GONE);
|
||||||
|
// LoadIndicator.setVisibility(View.VISIBLE);
|
||||||
|
// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||||
|
//myWebView.loadUrl("javascript:this.document.location.href = 'source://' + encodeURI(document.documentElement.outerHTML);");
|
||||||
|
try {
|
||||||
|
getMiddleWareTokenAndLogIn(server, name, passw);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// public void logIn(String lichaam) {
|
||||||
|
// //First, verkrijg the user credentials.
|
||||||
|
// //The user credentials are stored in the shared preferences, so first they have to be read from there.
|
||||||
|
// String defaultValue = "none";
|
||||||
|
// SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
|
||||||
|
// String server = sharedPref.getString(getString(R.string.server), defaultValue);
|
||||||
|
// SharedPreferences sharedPrefName = StartActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
|
||||||
|
// String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
|
||||||
|
// SharedPreferences sharedPrefPass = StartActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
|
||||||
|
// String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
|
||||||
|
// SharedPreferences sharedPrefMagic = StartActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
|
||||||
|
// String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
|
||||||
|
// //Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
|
||||||
|
// //First get the keystore thing.
|
||||||
|
// KeyStore keyStore = null;
|
||||||
|
// try {
|
||||||
|
// keyStore = KeyStore.getInstance("AndroidKeyStore");
|
||||||
|
// } catch (KeyStoreException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Then, load it. or something. To make sure that it can be used.
|
||||||
|
// try {
|
||||||
|
// keyStore.load(null);
|
||||||
|
// } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Next, retrieve the key to be used for the decryption.
|
||||||
|
// Key DragonLikeKey = null;
|
||||||
|
// try {
|
||||||
|
// DragonLikeKey = keyStore.getKey("BookWyrm", null);
|
||||||
|
// } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Do something with getting the/a cipher or something.
|
||||||
|
// Cipher c = null;
|
||||||
|
// try {
|
||||||
|
// c = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
// } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //And then initiating the cipher, so it can be used.
|
||||||
|
// try {
|
||||||
|
// assert c != null;
|
||||||
|
// c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
|
||||||
|
// } catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Decrypt the password!
|
||||||
|
// byte[] truePass = null;
|
||||||
|
// try {
|
||||||
|
// truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
|
||||||
|
// } catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// //Convert the decrypted password back to a string.
|
||||||
|
// String passw = new String(truePass, StandardCharsets.UTF_8);
|
||||||
|
// Log.d("body", lichaam);
|
||||||
|
// String[] opgebroken = lichaam.split("name=\"csrfmiddlewaretoken\" value=\"");
|
||||||
|
// String[] breukjes = opgebroken[1].split("\">");
|
||||||
|
// String middelToken = breukjes[0];
|
||||||
|
// String[] splitsing = lichaam.split("var csrf_token = '");
|
||||||
|
// String[] dilemma = splitsing[1].split("';");
|
||||||
|
// String csrf = dilemma[0];
|
||||||
|
// Log.d("tokens", "middel= " + middelToken);
|
||||||
|
// Log.d("tokens", "csrf= " + csrf);
|
||||||
|
// String gegevens = null;
|
||||||
|
// try {
|
||||||
|
// gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(middelToken, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||||
|
// } catch (UnsupportedEncodingException e) {
|
||||||
|
// throw new RuntimeException(e);
|
||||||
|
// }
|
||||||
|
//// android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||||
|
//// oven.setCookie("https://" + server, "csrftoken=" + csrf);
|
||||||
|
// myWebView.postUrl("https://" + server + "/login", gegevens.getBytes());
|
||||||
|
// }
|
||||||
public void getMiddleWareTokenAndLogIn(String server, String name, String passw) throws IOException {
|
public void getMiddleWareTokenAndLogIn(String server, String name, String passw) throws IOException {
|
||||||
//Het idee is dat deze functie de loginpagina van de server laadt en dan de 'csrfmiddlewaretoken' uit het inlogformulier haalt,
|
//Het idee is dat deze functie de loginpagina van de server laadt en dan de 'csrfmiddlewaretoken' uit het inlogformulier haalt,
|
||||||
//Zodat dat dan gebruikt kan worden bij het inloggen.
|
//Zodat dat dan gebruikt kan worden bij het inloggen.
|
||||||
//Becuase network operations cannot be done on the main/ui thread, create a new thread for this complete function. Yay!
|
|
||||||
Thread draadje = new Thread(new Runnable() {
|
Thread draadje = new Thread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
//Load the login page, and do not forget to take some cookies.
|
URL url = new URL("https://" + server + "/login");
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1);
|
CookieManager koekManager = new CookieManager();
|
||||||
String speculaas = "";
|
CookieHandler.setDefault(koekManager);
|
||||||
String speculaasBeslag = "";
|
CookieStore bakker = koekManager.getCookieStore();
|
||||||
//The login page loading is done using OkHttpClient.
|
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
|
||||||
OkHttpClient client = new OkHttpClient();
|
try {
|
||||||
Request aanvraag = new Request.Builder()
|
InputStream ina = new BufferedInputStream(urlConnection.getInputStream());
|
||||||
.url("https://" + server + "/")
|
byte[] pagina = null;
|
||||||
.header("User-Agent", getString(R.string.gebruikersagent))
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
.build();
|
pagina = ina.readAllBytes();
|
||||||
//Get an answer!
|
} else {
|
||||||
try (Response antwoord = client.newCall(aanvraag).execute()) {
|
pagina = new byte[30000];
|
||||||
if (!antwoord.isSuccessful()) throw new IOException("Unexpected code " + antwoord);
|
ina.read(pagina);
|
||||||
//Search the headers for the 'set-cookie' header so we can eat a cookie!
|
}
|
||||||
Headers cenna = antwoord.headers();
|
try {
|
||||||
for (int i = 0; i < cenna.size(); i++) {
|
ina.close();
|
||||||
if (cenna.name(i).equals("set-cookie")) {
|
} catch (IOException e) {
|
||||||
speculaas = cenna.value(i);
|
throw new RuntimeException(e);
|
||||||
speculaasBeslag = speculaas.split(";")[0];
|
}
|
||||||
|
String zooi = new String(pagina);
|
||||||
|
String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
|
||||||
|
String[] breukjes = opgebroken[1].split("\">");
|
||||||
|
String token = breukjes[0];
|
||||||
|
String gegevens = null;
|
||||||
|
|
||||||
|
String speculaas = "", THT = "";
|
||||||
|
List<HttpCookie> koektrommel = bakker.get(URI.create("https://" + server));
|
||||||
|
//Log.d("koek", koektrommel.toString());
|
||||||
|
for (int i = 0; i < koektrommel.size(); ++i) {
|
||||||
|
HttpCookie koekje = koektrommel.get(i);
|
||||||
|
if (Objects.equals(koekje.getName(), "csrftoken")) {
|
||||||
|
speculaas = koekje.toString();
|
||||||
|
THT = String.valueOf(koekje.getMaxAge());
|
||||||
|
//Log.d("domein", koekje.getDomain());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//And then get the HTML body.
|
|
||||||
assert antwoord.body() != null;
|
|
||||||
String zooi = antwoord.body().string();
|
|
||||||
//Very easy to get the token by taking the text that it is preceded by in the raw html as the regex for a split() function!
|
|
||||||
String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
|
|
||||||
//For that gives as second element the token, followed by all the following html code. Then strip that code off, using the immediately following characters as regex.
|
|
||||||
String[] breukjes = opgebroken[1].split("\">");
|
|
||||||
//Of course, the token is then the first element in our array.
|
|
||||||
String token = breukjes[0];
|
|
||||||
//Log.d("botbreuk", token);
|
|
||||||
String gegevens = null;
|
|
||||||
//And then set the data string up for use in the POST request, with the csrf middleware token, the username, and the password.
|
|
||||||
try {
|
try {
|
||||||
gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(token, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(token, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
RequestBody keurslijf = new FormBody.Builder()
|
|
||||||
.add("csrfmiddlewaretoken", token)
|
|
||||||
.add("localname", name)
|
|
||||||
.add("password", passw)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
String finalGegevens = gegevens;
|
String finalGegevens = gegevens;
|
||||||
//Log.d("gegevens", finalGegevens);
|
//Log.d("token", speculaas);
|
||||||
//Log.d("beslag", speculaasBeslag);
|
|
||||||
String finalSpeculaas = speculaas;
|
String finalSpeculaas = speculaas;
|
||||||
//Log in using a POST request, and shove the resulting web-page into a public string. (putje)
|
String finalTHT = THT;
|
||||||
//For this, we have to give the log-in function the servername, the request body, and the value of the csrf cookie.
|
|
||||||
logInAndGetHTML(server, keurslijf, speculaasBeslag);
|
|
||||||
//Then we have to run a bit of code on the main (UI) thread. To be able to work with the webview...
|
|
||||||
runOnUiThread(new Runnable() {
|
runOnUiThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
//First we have to get the cookie manager of the webview, so we can hand it the csrf cookie.
|
|
||||||
//Without being fed the correct csrf cookie, the Wyrm will refuse our request. The wyrm is a very picky eater!
|
|
||||||
CookieManager oven = CookieManager.getInstance();
|
|
||||||
//Bake the cookie into the webview.
|
|
||||||
oven.setCookie("https://" + server, finalSpeculaas);
|
|
||||||
//And bake the session cookie as well.
|
|
||||||
oven.setCookie("https://" + server, sessie);
|
|
||||||
//And then finally it is time to load everything into the webview.
|
|
||||||
myWebView.loadDataWithBaseURL("https://" + server, putje, null, null, "https://" + server + "/login");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
android.webkit.CookieManager oven = android.webkit.CookieManager.getInstance();
|
||||||
|
oven.setCookie("https://" + server, finalSpeculaas + "; Max-Age=" + finalTHT + "; Path=/; SameSite=Lax; Secure");
|
||||||
|
myWebView.postUrl("https://" + server + "/login?next=/", finalGegevens.getBytes());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
urlConnection.disconnect();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//^Here ends all that new Thread() code.
|
|
||||||
//⇓Run all the code in the thread.
|
|
||||||
draadje.start();
|
draadje.start();
|
||||||
}
|
//return token;
|
||||||
public void logInAndGetHTML(String server, RequestBody lichaam, String speculoos) throws IOException {
|
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1);
|
|
||||||
//Create a client using CookieMonster, so we can retrieve cookies from the redirect after sending the log-in data.
|
|
||||||
OkHttpClient client = new OkHttpClient.Builder()
|
|
||||||
.addNetworkInterceptor(new CookieMonster())
|
|
||||||
.build();
|
|
||||||
//Create the POST request.
|
|
||||||
Request verzoek = new Request.Builder()
|
|
||||||
.url("https://" + server + "/login?next=/")
|
|
||||||
.header("User-Agent", getString(R.string.gebruikersagent))
|
|
||||||
.addHeader("origin", "https://" + server)
|
|
||||||
.addHeader("cookie", speculoos)
|
|
||||||
.post(lichaam)
|
|
||||||
.build();
|
|
||||||
//And then get the response.
|
|
||||||
try (Response reactie = client.newCall(verzoek).execute()) {
|
|
||||||
if (!reactie.isSuccessful())
|
|
||||||
throw new IOException("Unexpected code " + reactie);
|
|
||||||
assert reactie.body() != null;
|
|
||||||
//Shove the response body into the public string 'putje', to be used for sending the body to the webview.
|
|
||||||
putje = reactie.body().string();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
|
private final ActivityResultLauncher<ScanOptions> barcodeLanceerder = registerForActivityResult(new ScanContract(),
|
||||||
result -> {
|
result -> {
|
||||||
@ -367,6 +425,8 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
eisen.setPrompt("SCAN ISBN");
|
eisen.setPrompt("SCAN ISBN");
|
||||||
eisen.setBarcodeImageEnabled(false);
|
eisen.setBarcodeImageEnabled(false);
|
||||||
barcodeLanceerder.launch(eisen);
|
barcodeLanceerder.launch(eisen);
|
||||||
|
//return "blup";
|
||||||
|
//return "bla";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -388,33 +448,6 @@ public class StartActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
return super.onKeyLongPress(keyCode, event);
|
return super.onKeyLongPress(keyCode, event);
|
||||||
}
|
}
|
||||||
final class CookieMonster implements Interceptor {
|
|
||||||
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
|
|
||||||
//Om ingelogd te blijven moeten we het sessiekoekje aan kunnen bieden.
|
|
||||||
//Die moeten we dan wel eerst uit het koekblik pakken!
|
|
||||||
Request eersteVerzoek = chain.request();
|
|
||||||
//Eerst moeten we controleren of er al een sessiekoekje is. Als dat niet zo is, dan is dit het echte eerste verzoek.
|
|
||||||
if (sessie.isEmpty()) {
|
|
||||||
//In dat geval halen we de reactie op om het koekje te kunnen pakken!
|
|
||||||
Response eersteReactie = chain.proceed(chain.request());
|
|
||||||
Headers hoofden = eersteReactie.headers();
|
|
||||||
for (int i = 0; i < hoofden.size(); i++) {
|
|
||||||
if (hoofden.name(i).equals("set-cookie") && hoofden.value(i).startsWith("session")) {
|
|
||||||
sessie = hoofden.value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Nadat we het koekje hebben moet de reactie doorgebriefd worden aan de 'client',
|
|
||||||
//die dan het volgende verzoek zal gaan doen vanwege de 302-redirect bij het inloggen.
|
|
||||||
return eersteReactie;
|
|
||||||
}
|
|
||||||
//Het koekje is er! Hoera!
|
|
||||||
//Het nieuwe verzoek moet wel met het sessiekoekje verzonden worden, anders zijn we alsnog niet ingelogd!
|
|
||||||
Request nieuwVerzoek = eersteVerzoek.newBuilder()
|
|
||||||
.addHeader("cookie", sessie)
|
|
||||||
.build();
|
|
||||||
return chain.proceed(nieuwVerzoek);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
|
//Here is code to make sure that links of the bookwyrm server are handled within the webview client, instead of having it open in the default browser.
|
||||||
//Yes, I used the web for this too.
|
//Yes, I used the web for this too.
|
||||||
private class MyWebViewClient extends WebViewClient {
|
private class MyWebViewClient extends WebViewClient {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView4"
|
android:id="@+id/textView4"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -22,7 +22,7 @@
|
|||||||
app:layout_constraintTop_toBottomOf="@+id/Username"
|
app:layout_constraintTop_toBottomOf="@+id/Username"
|
||||||
app:layout_constraintVertical_bias="0.0" />
|
app:layout_constraintVertical_bias="0.0" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<EditText
|
||||||
android:id="@+id/Instance"
|
android:id="@+id/Instance"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -37,7 +37,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<EditText
|
||||||
android:id="@+id/Username"
|
android:id="@+id/Username"
|
||||||
android:layout_width="409dp"
|
android:layout_width="409dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -53,7 +53,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/Instance" />
|
app:layout_constraintTop_toBottomOf="@+id/Instance" />
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<EditText
|
||||||
android:id="@+id/Password"
|
android:id="@+id/Password"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -68,7 +68,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/Username" />
|
app:layout_constraintTop_toBottomOf="@+id/Username" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView"
|
android:id="@+id/textView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -85,7 +85,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView2"
|
android:id="@+id/textView2"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -100,7 +100,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textView" />
|
app:layout_constraintTop_toBottomOf="@+id/textView" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView3"
|
android:id="@+id/textView3"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -115,7 +115,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/Instance" />
|
app:layout_constraintTop_toBottomOf="@+id/Instance" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView6"
|
android:id="@+id/textView6"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -130,7 +130,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/Username" />
|
app:layout_constraintTop_toBottomOf="@+id/Username" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<Button
|
||||||
android:id="@+id/button"
|
android:id="@+id/button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -147,7 +147,7 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/Password" />
|
app:layout_constraintTop_toBottomOf="@+id/Password" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/textView5"
|
android:id="@+id/textView5"
|
||||||
android:layout_width="243dp"
|
android:layout_width="243dp"
|
||||||
android:layout_height="33dp"
|
android:layout_height="33dp"
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="715dp"
|
android:layout_marginBottom="715dp"
|
||||||
android:indeterminateTint="@color/TheNewGreen"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
10
app/src/main/res/values-night/themes.xml
Normal file
10
app/src/main/res/values-night/themes.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<!-- Base application theme. -->
|
||||||
|
<style name="Theme.Bookwyrm" parent="Theme.AppCompat">
|
||||||
|
<!-- Primary brand color. -->
|
||||||
|
<item name="colorPrimary">#3298DC</item>
|
||||||
|
<item name="colorPrimaryDark">#1B557C</item>
|
||||||
|
<item name="colorAccent">@color/teal_200</item>
|
||||||
|
<!-- Customize your theme here. -->
|
||||||
|
</style>
|
||||||
|
</resources>
|
@ -1,144 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="TheNewGreen">#FD00FF</color>
|
<color name="purple_200">#FFBB86FC</color>
|
||||||
<color name="md_theme_primary">#003351</color>
|
<color name="purple_500">#FF6200EE</color>
|
||||||
<color name="md_theme_onPrimary">#FFFFFF</color>
|
<color name="purple_700">#FF3700B3</color>
|
||||||
<color name="md_theme_primaryContainer">#074B72</color>
|
<color name="teal_200">#FF03DAC5</color>
|
||||||
<color name="md_theme_onPrimaryContainer">#CCE5FF</color>
|
<color name="teal_700">#FF018786</color>
|
||||||
<color name="md_theme_secondary">#B8C8DA</color>
|
<color name="black">#FF000000</color>
|
||||||
<color name="md_theme_onSecondary">#23323F</color>
|
<color name="white">#FFFFFFFF</color>
|
||||||
<color name="md_theme_secondaryContainer">#394857</color>
|
</resources>
|
||||||
<color name="md_theme_onSecondaryContainer">#D4E4F6</color>
|
|
||||||
<color name="md_theme_tertiary">#D1BFE7</color>
|
|
||||||
<color name="md_theme_onTertiary">#372A4A</color>
|
|
||||||
<color name="md_theme_tertiaryContainer">#4E4161</color>
|
|
||||||
<color name="md_theme_onTertiaryContainer">#EDDCFF</color>
|
|
||||||
<color name="md_theme_error">#FFB4AB</color>
|
|
||||||
<color name="md_theme_onError">#690005</color>
|
|
||||||
<color name="md_theme_errorContainer">#93000A</color>
|
|
||||||
<color name="md_theme_onErrorContainer">#FFDAD6</color>
|
|
||||||
<color name="md_theme_background">#101418</color>
|
|
||||||
<color name="md_theme_onBackground">#E0E2E8</color>
|
|
||||||
<color name="md_theme_surface">#101418</color>
|
|
||||||
<color name="md_theme_onSurface">#E0E2E8</color>
|
|
||||||
<color name="md_theme_surfaceVariant">#42474E</color>
|
|
||||||
<color name="md_theme_onSurfaceVariant">#C2C7CE</color>
|
|
||||||
<color name="md_theme_outline">#8C9198</color>
|
|
||||||
<color name="md_theme_outlineVariant">#42474E</color>
|
|
||||||
<color name="md_theme_scrim">#000000</color>
|
|
||||||
<color name="md_theme_inverseSurface">#E0E2E8</color>
|
|
||||||
<color name="md_theme_inverseOnSurface">#2D3135</color>
|
|
||||||
<color name="md_theme_inversePrimary">#2C638B</color>
|
|
||||||
<color name="md_theme_primaryFixed">#CCE5FF</color>
|
|
||||||
<color name="md_theme_onPrimaryFixed">#001D31</color>
|
|
||||||
<color name="md_theme_primaryFixedDim">#99CCFA</color>
|
|
||||||
<color name="md_theme_onPrimaryFixedVariant">#074B72</color>
|
|
||||||
<color name="md_theme_secondaryFixed">#D4E4F6</color>
|
|
||||||
<color name="md_theme_onSecondaryFixed">#0D1D2A</color>
|
|
||||||
<color name="md_theme_secondaryFixedDim">#B8C8DA</color>
|
|
||||||
<color name="md_theme_onSecondaryFixedVariant">#394857</color>
|
|
||||||
<color name="md_theme_tertiaryFixed">#EDDCFF</color>
|
|
||||||
<color name="md_theme_onTertiaryFixed">#221534</color>
|
|
||||||
<color name="md_theme_tertiaryFixedDim">#D1BFE7</color>
|
|
||||||
<color name="md_theme_onTertiaryFixedVariant">#4E4161</color>
|
|
||||||
<color name="md_theme_surfaceDim">#101418</color>
|
|
||||||
<color name="md_theme_surfaceBright">#36393E</color>
|
|
||||||
<color name="md_theme_surfaceContainerLowest">#0B0F12</color>
|
|
||||||
<color name="md_theme_surfaceContainerLow">#181C20</color>
|
|
||||||
<color name="md_theme_surfaceContainer">#1C2024</color>
|
|
||||||
<color name="md_theme_surfaceContainerHigh">#272A2E</color>
|
|
||||||
<color name="md_theme_surfaceContainerHighest">#313539</color>
|
|
||||||
<color name="md_theme_primary_mediumContrast">#C0E0FF</color>
|
|
||||||
<color name="md_theme_onPrimary_mediumContrast">#002841</color>
|
|
||||||
<color name="md_theme_primaryContainer_mediumContrast">#6396C1</color>
|
|
||||||
<color name="md_theme_onPrimaryContainer_mediumContrast">#000000</color>
|
|
||||||
<color name="md_theme_secondary_mediumContrast">#CEDEF0</color>
|
|
||||||
<color name="md_theme_onSecondary_mediumContrast">#182734</color>
|
|
||||||
<color name="md_theme_secondaryContainer_mediumContrast">#8392A3</color>
|
|
||||||
<color name="md_theme_onSecondaryContainer_mediumContrast">#000000</color>
|
|
||||||
<color name="md_theme_tertiary_mediumContrast">#E8D5FE</color>
|
|
||||||
<color name="md_theme_onTertiary_mediumContrast">#2C203E</color>
|
|
||||||
<color name="md_theme_tertiaryContainer_mediumContrast">#9A8AAF</color>
|
|
||||||
<color name="md_theme_onTertiaryContainer_mediumContrast">#000000</color>
|
|
||||||
<color name="md_theme_error_mediumContrast">#FFD2CC</color>
|
|
||||||
<color name="md_theme_onError_mediumContrast">#540003</color>
|
|
||||||
<color name="md_theme_errorContainer_mediumContrast">#FF5449</color>
|
|
||||||
<color name="md_theme_onErrorContainer_mediumContrast">#000000</color>
|
|
||||||
<color name="md_theme_background_mediumContrast">#101418</color>
|
|
||||||
<color name="md_theme_onBackground_mediumContrast">#E0E2E8</color>
|
|
||||||
<color name="md_theme_surface_mediumContrast">#101418</color>
|
|
||||||
<color name="md_theme_onSurface_mediumContrast">#FFFFFF</color>
|
|
||||||
<color name="md_theme_surfaceVariant_mediumContrast">#42474E</color>
|
|
||||||
<color name="md_theme_onSurfaceVariant_mediumContrast">#D8DDE4</color>
|
|
||||||
<color name="md_theme_outline_mediumContrast">#ADB2BA</color>
|
|
||||||
<color name="md_theme_outlineVariant_mediumContrast">#8B9198</color>
|
|
||||||
<color name="md_theme_scrim_mediumContrast">#000000</color>
|
|
||||||
<color name="md_theme_inverseSurface_mediumContrast">#E0E2E8</color>
|
|
||||||
<color name="md_theme_inverseOnSurface_mediumContrast">#272A2E</color>
|
|
||||||
<color name="md_theme_inversePrimary_mediumContrast">#0A4C73</color>
|
|
||||||
<color name="md_theme_primaryFixed_mediumContrast">#CCE5FF</color>
|
|
||||||
<color name="md_theme_onPrimaryFixed_mediumContrast">#001321</color>
|
|
||||||
<color name="md_theme_primaryFixedDim_mediumContrast">#99CCFA</color>
|
|
||||||
<color name="md_theme_onPrimaryFixedVariant_mediumContrast">#00395A</color>
|
|
||||||
<color name="md_theme_secondaryFixed_mediumContrast">#D4E4F6</color>
|
|
||||||
<color name="md_theme_onSecondaryFixed_mediumContrast">#03121F</color>
|
|
||||||
<color name="md_theme_secondaryFixedDim_mediumContrast">#B8C8DA</color>
|
|
||||||
<color name="md_theme_onSecondaryFixedVariant_mediumContrast">#293845</color>
|
|
||||||
<color name="md_theme_tertiaryFixed_mediumContrast">#EDDCFF</color>
|
|
||||||
<color name="md_theme_onTertiaryFixed_mediumContrast">#170A28</color>
|
|
||||||
<color name="md_theme_tertiaryFixedDim_mediumContrast">#D1BFE7</color>
|
|
||||||
<color name="md_theme_onTertiaryFixedVariant_mediumContrast">#3D3050</color>
|
|
||||||
<color name="md_theme_surfaceDim_mediumContrast">#101418</color>
|
|
||||||
<color name="md_theme_surfaceBright_mediumContrast">#414549</color>
|
|
||||||
<color name="md_theme_surfaceContainerLowest_mediumContrast">#05080B</color>
|
|
||||||
<color name="md_theme_surfaceContainerLow_mediumContrast">#1A1E22</color>
|
|
||||||
<color name="md_theme_surfaceContainer_mediumContrast">#24282C</color>
|
|
||||||
<color name="md_theme_surfaceContainerHigh_mediumContrast">#2F3337</color>
|
|
||||||
<color name="md_theme_surfaceContainerHighest_mediumContrast">#3A3E42</color>
|
|
||||||
<color name="md_theme_primary_highContrast">#E6F1FF</color>
|
|
||||||
<color name="md_theme_onPrimary_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_primaryContainer_highContrast">#95C8F5</color>
|
|
||||||
<color name="md_theme_onPrimaryContainer_highContrast">#000C18</color>
|
|
||||||
<color name="md_theme_secondary_highContrast">#E6F1FF</color>
|
|
||||||
<color name="md_theme_onSecondary_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_secondaryContainer_highContrast">#B4C4D6</color>
|
|
||||||
<color name="md_theme_onSecondaryContainer_highContrast">#000C18</color>
|
|
||||||
<color name="md_theme_tertiary_highContrast">#F7ECFF</color>
|
|
||||||
<color name="md_theme_onTertiary_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_tertiaryContainer_highContrast">#CDBBE3</color>
|
|
||||||
<color name="md_theme_onTertiaryContainer_highContrast">#110522</color>
|
|
||||||
<color name="md_theme_error_highContrast">#FFECE9</color>
|
|
||||||
<color name="md_theme_onError_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_errorContainer_highContrast">#FFAEA4</color>
|
|
||||||
<color name="md_theme_onErrorContainer_highContrast">#220001</color>
|
|
||||||
<color name="md_theme_background_highContrast">#101418</color>
|
|
||||||
<color name="md_theme_onBackground_highContrast">#E0E2E8</color>
|
|
||||||
<color name="md_theme_surface_highContrast">#101418</color>
|
|
||||||
<color name="md_theme_onSurface_highContrast">#FFFFFF</color>
|
|
||||||
<color name="md_theme_surfaceVariant_highContrast">#42474E</color>
|
|
||||||
<color name="md_theme_onSurfaceVariant_highContrast">#FFFFFF</color>
|
|
||||||
<color name="md_theme_outline_highContrast">#EBF0F8</color>
|
|
||||||
<color name="md_theme_outlineVariant_highContrast">#BEC3CB</color>
|
|
||||||
<color name="md_theme_scrim_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_inverseSurface_highContrast">#E0E2E8</color>
|
|
||||||
<color name="md_theme_inverseOnSurface_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_inversePrimary_highContrast">#0A4C73</color>
|
|
||||||
<color name="md_theme_primaryFixed_highContrast">#CCE5FF</color>
|
|
||||||
<color name="md_theme_onPrimaryFixed_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_primaryFixedDim_highContrast">#99CCFA</color>
|
|
||||||
<color name="md_theme_onPrimaryFixedVariant_highContrast">#001321</color>
|
|
||||||
<color name="md_theme_secondaryFixed_highContrast">#D4E4F6</color>
|
|
||||||
<color name="md_theme_onSecondaryFixed_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_secondaryFixedDim_highContrast">#B8C8DA</color>
|
|
||||||
<color name="md_theme_onSecondaryFixedVariant_highContrast">#03121F</color>
|
|
||||||
<color name="md_theme_tertiaryFixed_highContrast">#EDDCFF</color>
|
|
||||||
<color name="md_theme_onTertiaryFixed_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_tertiaryFixedDim_highContrast">#D1BFE7</color>
|
|
||||||
<color name="md_theme_onTertiaryFixedVariant_highContrast">#170A28</color>
|
|
||||||
<color name="md_theme_surfaceDim_highContrast">#101418</color>
|
|
||||||
<color name="md_theme_surfaceBright_highContrast">#4D5055</color>
|
|
||||||
<color name="md_theme_surfaceContainerLowest_highContrast">#000000</color>
|
|
||||||
<color name="md_theme_surfaceContainerLow_highContrast">#1C2024</color>
|
|
||||||
<color name="md_theme_surfaceContainer_highContrast">#2D3135</color>
|
|
||||||
<color name="md_theme_surfaceContainerHigh_highContrast">#383C40</color>
|
|
||||||
<color name="md_theme_surfaceContainerHighest_highContrast">#43474C</color>
|
|
||||||
</resources>
|
|
@ -4,5 +4,4 @@
|
|||||||
<string name="name">blup</string>
|
<string name="name">blup</string>
|
||||||
<string name="pw">gloep</string>
|
<string name="pw">gloep</string>
|
||||||
<string name="q">wheeeee</string>
|
<string name="q">wheeeee</string>
|
||||||
<string name="gebruikersagent">Bookwyrm Android/1.3.8</string>
|
|
||||||
</resources>
|
</resources>
|
@ -1,98 +0,0 @@
|
|||||||
<resources>
|
|
||||||
<style name="ThemeOverlay.AppTheme.MediumContrast" parent="Theme.Material3.Dark.NoActionBar">
|
|
||||||
<item name="colorPrimary">@color/md_theme_primary_mediumContrast</item>
|
|
||||||
<item name="colorOnPrimary">@color/md_theme_onPrimary_mediumContrast</item>
|
|
||||||
<item name="colorPrimaryContainer">@color/md_theme_primaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorSecondary">@color/md_theme_secondary_mediumContrast</item>
|
|
||||||
<item name="colorOnSecondary">@color/md_theme_onSecondary_mediumContrast</item>
|
|
||||||
<item name="colorSecondaryContainer">@color/md_theme_secondaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorTertiary">@color/md_theme_tertiary_mediumContrast</item>
|
|
||||||
<item name="colorOnTertiary">@color/md_theme_onTertiary_mediumContrast</item>
|
|
||||||
<item name="colorTertiaryContainer">@color/md_theme_tertiaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorOnTertiaryContainer">@color/md_theme_onTertiaryContainer_mediumContrast</item>
|
|
||||||
<item name="colorError">@color/md_theme_error_mediumContrast</item>
|
|
||||||
<item name="colorOnError">@color/md_theme_onError_mediumContrast</item>
|
|
||||||
<item name="colorErrorContainer">@color/md_theme_errorContainer_mediumContrast</item>
|
|
||||||
<item name="colorOnErrorContainer">@color/md_theme_onErrorContainer_mediumContrast</item>
|
|
||||||
<item name="android:colorBackground">@color/md_theme_background_mediumContrast</item>
|
|
||||||
<item name="colorOnBackground">@color/md_theme_onBackground_mediumContrast</item>
|
|
||||||
<item name="colorSurface">@color/md_theme_surface_mediumContrast</item>
|
|
||||||
<item name="colorOnSurface">@color/md_theme_onSurface_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceVariant">@color/md_theme_surfaceVariant_mediumContrast</item>
|
|
||||||
<item name="colorOnSurfaceVariant">@color/md_theme_onSurfaceVariant_mediumContrast</item>
|
|
||||||
<item name="colorOutline">@color/md_theme_outline_mediumContrast</item>
|
|
||||||
<item name="colorOutlineVariant">@color/md_theme_outlineVariant_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceInverse">@color/md_theme_inverseSurface_mediumContrast</item>
|
|
||||||
<item name="colorOnSurfaceInverse">@color/md_theme_inverseOnSurface_mediumContrast</item>
|
|
||||||
<item name="colorPrimaryInverse">@color/md_theme_inversePrimary_mediumContrast</item>
|
|
||||||
<item name="colorPrimaryFixed">@color/md_theme_primaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorOnPrimaryFixed">@color/md_theme_onPrimaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorPrimaryFixedDim">@color/md_theme_primaryFixedDim_mediumContrast</item>
|
|
||||||
<item name="colorOnPrimaryFixedVariant">@color/md_theme_onPrimaryFixedVariant_mediumContrast</item>
|
|
||||||
<item name="colorSecondaryFixed">@color/md_theme_secondaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorOnSecondaryFixed">@color/md_theme_onSecondaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorSecondaryFixedDim">@color/md_theme_secondaryFixedDim_mediumContrast</item>
|
|
||||||
<item name="colorOnSecondaryFixedVariant">@color/md_theme_onSecondaryFixedVariant_mediumContrast</item>
|
|
||||||
<item name="colorTertiaryFixed">@color/md_theme_tertiaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorOnTertiaryFixed">@color/md_theme_onTertiaryFixed_mediumContrast</item>
|
|
||||||
<item name="colorTertiaryFixedDim">@color/md_theme_tertiaryFixedDim_mediumContrast</item>
|
|
||||||
<item name="colorOnTertiaryFixedVariant">@color/md_theme_onTertiaryFixedVariant_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceDim">@color/md_theme_surfaceDim_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceBright">@color/md_theme_surfaceBright_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceContainerLowest">@color/md_theme_surfaceContainerLowest_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceContainerLow">@color/md_theme_surfaceContainerLow_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceContainer">@color/md_theme_surfaceContainer_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceContainerHigh">@color/md_theme_surfaceContainerHigh_mediumContrast</item>
|
|
||||||
<item name="colorSurfaceContainerHighest">@color/md_theme_surfaceContainerHighest_mediumContrast</item>
|
|
||||||
</style>
|
|
||||||
<style name="ThemeOverlay.AppTheme.HighContrast" parent="Theme.Material3.Dark.NoActionBar">
|
|
||||||
<item name="colorPrimary">@color/md_theme_primary_highContrast</item>
|
|
||||||
<item name="colorOnPrimary">@color/md_theme_onPrimary_highContrast</item>
|
|
||||||
<item name="colorPrimaryContainer">@color/md_theme_primaryContainer_highContrast</item>
|
|
||||||
<item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer_highContrast</item>
|
|
||||||
<item name="colorSecondary">@color/md_theme_secondary_highContrast</item>
|
|
||||||
<item name="colorOnSecondary">@color/md_theme_onSecondary_highContrast</item>
|
|
||||||
<item name="colorSecondaryContainer">@color/md_theme_secondaryContainer_highContrast</item>
|
|
||||||
<item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer_highContrast</item>
|
|
||||||
<item name="colorTertiary">@color/md_theme_tertiary_highContrast</item>
|
|
||||||
<item name="colorOnTertiary">@color/md_theme_onTertiary_highContrast</item>
|
|
||||||
<item name="colorTertiaryContainer">@color/md_theme_tertiaryContainer_highContrast</item>
|
|
||||||
<item name="colorOnTertiaryContainer">@color/md_theme_onTertiaryContainer_highContrast</item>
|
|
||||||
<item name="colorError">@color/md_theme_error_highContrast</item>
|
|
||||||
<item name="colorOnError">@color/md_theme_onError_highContrast</item>
|
|
||||||
<item name="colorErrorContainer">@color/md_theme_errorContainer_highContrast</item>
|
|
||||||
<item name="colorOnErrorContainer">@color/md_theme_onErrorContainer_highContrast</item>
|
|
||||||
<item name="android:colorBackground">@color/md_theme_background_highContrast</item>
|
|
||||||
<item name="colorOnBackground">@color/md_theme_onBackground_highContrast</item>
|
|
||||||
<item name="colorSurface">@color/md_theme_surface_highContrast</item>
|
|
||||||
<item name="colorOnSurface">@color/md_theme_onSurface_highContrast</item>
|
|
||||||
<item name="colorSurfaceVariant">@color/md_theme_surfaceVariant_highContrast</item>
|
|
||||||
<item name="colorOnSurfaceVariant">@color/md_theme_onSurfaceVariant_highContrast</item>
|
|
||||||
<item name="colorOutline">@color/md_theme_outline_highContrast</item>
|
|
||||||
<item name="colorOutlineVariant">@color/md_theme_outlineVariant_highContrast</item>
|
|
||||||
<item name="colorSurfaceInverse">@color/md_theme_inverseSurface_highContrast</item>
|
|
||||||
<item name="colorOnSurfaceInverse">@color/md_theme_inverseOnSurface_highContrast</item>
|
|
||||||
<item name="colorPrimaryInverse">@color/md_theme_inversePrimary_highContrast</item>
|
|
||||||
<item name="colorPrimaryFixed">@color/md_theme_primaryFixed_highContrast</item>
|
|
||||||
<item name="colorOnPrimaryFixed">@color/md_theme_onPrimaryFixed_highContrast</item>
|
|
||||||
<item name="colorPrimaryFixedDim">@color/md_theme_primaryFixedDim_highContrast</item>
|
|
||||||
<item name="colorOnPrimaryFixedVariant">@color/md_theme_onPrimaryFixedVariant_highContrast</item>
|
|
||||||
<item name="colorSecondaryFixed">@color/md_theme_secondaryFixed_highContrast</item>
|
|
||||||
<item name="colorOnSecondaryFixed">@color/md_theme_onSecondaryFixed_highContrast</item>
|
|
||||||
<item name="colorSecondaryFixedDim">@color/md_theme_secondaryFixedDim_highContrast</item>
|
|
||||||
<item name="colorOnSecondaryFixedVariant">@color/md_theme_onSecondaryFixedVariant_highContrast</item>
|
|
||||||
<item name="colorTertiaryFixed">@color/md_theme_tertiaryFixed_highContrast</item>
|
|
||||||
<item name="colorOnTertiaryFixed">@color/md_theme_onTertiaryFixed_highContrast</item>
|
|
||||||
<item name="colorTertiaryFixedDim">@color/md_theme_tertiaryFixedDim_highContrast</item>
|
|
||||||
<item name="colorOnTertiaryFixedVariant">@color/md_theme_onTertiaryFixedVariant_highContrast</item>
|
|
||||||
<item name="colorSurfaceDim">@color/md_theme_surfaceDim_highContrast</item>
|
|
||||||
<item name="colorSurfaceBright">@color/md_theme_surfaceBright_highContrast</item>
|
|
||||||
<item name="colorSurfaceContainerLowest">@color/md_theme_surfaceContainerLowest_highContrast</item>
|
|
||||||
<item name="colorSurfaceContainerLow">@color/md_theme_surfaceContainerLow_highContrast</item>
|
|
||||||
<item name="colorSurfaceContainer">@color/md_theme_surfaceContainer_highContrast</item>
|
|
||||||
<item name="colorSurfaceContainerHigh">@color/md_theme_surfaceContainerHigh_highContrast</item>
|
|
||||||
<item name="colorSurfaceContainerHighest">@color/md_theme_surfaceContainerHighest_highContrast</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
@ -1,50 +1,10 @@
|
|||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<style name="AppTheme" parent="Theme.Material3.Dark.NoActionBar">
|
<!-- Base application theme. -->
|
||||||
<item name="colorPrimary">@color/md_theme_primary</item>
|
<style name="Theme.Bookwyrm" parent="Theme.AppCompat">
|
||||||
<item name="colorOnPrimary">@color/md_theme_onPrimary</item>
|
<!-- Primary brand color. -->
|
||||||
<item name="colorPrimaryContainer">@color/md_theme_primaryContainer</item>
|
<item name="colorPrimary">#3298DC</item>
|
||||||
<item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer</item>
|
<item name="colorPrimaryDark">#1B557C</item>
|
||||||
<item name="colorSecondary">@color/md_theme_secondary</item>
|
<item name="colorAccent">@color/teal_200</item>
|
||||||
<item name="colorOnSecondary">@color/md_theme_onSecondary</item>
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorSecondaryContainer">@color/md_theme_secondaryContainer</item>
|
|
||||||
<item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer</item>
|
|
||||||
<item name="colorTertiary">@color/md_theme_tertiary</item>
|
|
||||||
<item name="colorOnTertiary">@color/md_theme_onTertiary</item>
|
|
||||||
<item name="colorTertiaryContainer">@color/md_theme_tertiaryContainer</item>
|
|
||||||
<item name="colorOnTertiaryContainer">@color/md_theme_onTertiaryContainer</item>
|
|
||||||
<item name="colorError">@color/md_theme_error</item>
|
|
||||||
<item name="colorOnError">@color/md_theme_onError</item>
|
|
||||||
<item name="colorErrorContainer">@color/md_theme_errorContainer</item>
|
|
||||||
<item name="colorOnErrorContainer">@color/md_theme_onErrorContainer</item>
|
|
||||||
<item name="android:colorBackground">@color/md_theme_background</item>
|
|
||||||
<item name="colorOnBackground">@color/md_theme_onBackground</item>
|
|
||||||
<item name="colorSurface">@color/md_theme_surface</item>
|
|
||||||
<item name="colorOnSurface">@color/md_theme_onSurface</item>
|
|
||||||
<item name="colorSurfaceVariant">@color/md_theme_surfaceVariant</item>
|
|
||||||
<item name="colorOnSurfaceVariant">@color/md_theme_onSurfaceVariant</item>
|
|
||||||
<item name="colorOutline">@color/md_theme_outline</item>
|
|
||||||
<item name="colorOutlineVariant">@color/md_theme_outlineVariant</item>
|
|
||||||
<item name="colorSurfaceInverse">@color/md_theme_inverseSurface</item>
|
|
||||||
<item name="colorOnSurfaceInverse">@color/md_theme_inverseOnSurface</item>
|
|
||||||
<item name="colorPrimaryInverse">@color/md_theme_inversePrimary</item>
|
|
||||||
<item name="colorPrimaryFixed">@color/md_theme_primaryFixed</item>
|
|
||||||
<item name="colorOnPrimaryFixed">@color/md_theme_onPrimaryFixed</item>
|
|
||||||
<item name="colorPrimaryFixedDim">@color/md_theme_primaryFixedDim</item>
|
|
||||||
<item name="colorOnPrimaryFixedVariant">@color/md_theme_onPrimaryFixedVariant</item>
|
|
||||||
<item name="colorSecondaryFixed">@color/md_theme_secondaryFixed</item>
|
|
||||||
<item name="colorOnSecondaryFixed">@color/md_theme_onSecondaryFixed</item>
|
|
||||||
<item name="colorSecondaryFixedDim">@color/md_theme_secondaryFixedDim</item>
|
|
||||||
<item name="colorOnSecondaryFixedVariant">@color/md_theme_onSecondaryFixedVariant</item>
|
|
||||||
<item name="colorTertiaryFixed">@color/md_theme_tertiaryFixed</item>
|
|
||||||
<item name="colorOnTertiaryFixed">@color/md_theme_onTertiaryFixed</item>
|
|
||||||
<item name="colorTertiaryFixedDim">@color/md_theme_tertiaryFixedDim</item>
|
|
||||||
<item name="colorOnTertiaryFixedVariant">@color/md_theme_onTertiaryFixedVariant</item>
|
|
||||||
<item name="colorSurfaceDim">@color/md_theme_surfaceDim</item>
|
|
||||||
<item name="colorSurfaceBright">@color/md_theme_surfaceBright</item>
|
|
||||||
<item name="colorSurfaceContainerLowest">@color/md_theme_surfaceContainerLowest</item>
|
|
||||||
<item name="colorSurfaceContainerLow">@color/md_theme_surfaceContainerLow</item>
|
|
||||||
<item name="colorSurfaceContainer">@color/md_theme_surfaceContainer</item>
|
|
||||||
<item name="colorSurfaceContainerHigh">@color/md_theme_surfaceContainerHigh</item>
|
|
||||||
<item name="colorSurfaceContainerHighest">@color/md_theme_surfaceContainerHighest</item>
|
|
||||||
</style>
|
</style>
|
||||||
</resources>
|
</resources>
|
@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '8.8.0' apply false
|
id 'com.android.application' version '8.7.3' apply false
|
||||||
id 'com.android.library' version '8.8.0' apply false
|
id 'com.android.library' version '8.7.3' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
* Significant log-in improvements, including better security.
|
|
@ -1,5 +0,0 @@
|
|||||||
Fixing what turned out not to work for unreleased version 1.3.7:
|
|
||||||
* Significant log-in improvements, including better security.
|
|
||||||
Further changes:
|
|
||||||
* The app now uses a custom User-Agent string.
|
|
||||||
* Two new dependencies have been added: okhttp3, and conscrypt.
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Mon Feb 14 18:09:26 CET 2022
|
#Mon Feb 14 18:09:26 CET 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
Loading…
x
Reference in New Issue
Block a user