├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── .idea
├── .gitignore
├── .name
├── compiler.xml
├── deploymentTargetDropDown.xml
├── deploymentTargetSelector.xml
├── gradle.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── migrations.xml
├── misc.xml
├── runConfigurations.xml
└── vcs.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
├── release
│ ├── Bookwyrm-v1.3.8.apk
│ └── output-metadata.json
└── src
│ ├── androidTest
│ └── java
│ │ └── nl
│ │ └── privacydragon
│ │ └── bookwyrm
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── ic_launcher-playstore.png
│ ├── java
│ │ └── nl
│ │ │ └── privacydragon
│ │ │ └── bookwyrm
│ │ │ ├── HandlerActivity.java
│ │ │ ├── MainActivity.java
│ │ │ └── StartActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ └── activity_start.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ ├── ic_launcher_round.xml
│ │ ├── ic_launcher_wyrm.xml
│ │ └── ic_launcher_wyrm_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.webp
│ │ ├── ic_launcher_wyrm.png
│ │ ├── ic_launcher_wyrm_foreground.png
│ │ └── ic_launcher_wyrm_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.webp
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.webp
│ │ ├── ic_launcher_wyrm.png
│ │ ├── ic_launcher_wyrm_foreground.png
│ │ └── ic_launcher_wyrm_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.webp
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.webp
│ │ ├── ic_launcher_wyrm.png
│ │ ├── ic_launcher_wyrm_foreground.png
│ │ └── ic_launcher_wyrm_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.webp
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.webp
│ │ ├── ic_launcher_wyrm.png
│ │ ├── ic_launcher_wyrm_foreground.png
│ │ └── ic_launcher_wyrm_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.webp
│ │ ├── ic_launcher_foreground.png
│ │ ├── ic_launcher_round.webp
│ │ ├── ic_launcher_wyrm.png
│ │ ├── ic_launcher_wyrm_foreground.png
│ │ └── ic_launcher_wyrm_round.png
│ │ ├── values
│ │ ├── colors.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_launcher_wyrm_background.xml
│ │ ├── strings.xml
│ │ ├── theme_overlays.xml
│ │ └── themes.xml
│ │ └── xml
│ │ └── backup_rules.xml
│ └── test
│ └── java
│ └── nl
│ └── privacydragon
│ └── bookwyrm
│ └── ExampleUnitTest.java
├── build.gradle
├── fastlane
└── metadata
│ └── android
│ └── en-US
│ ├── changelogs
│ ├── 10.txt
│ ├── 11.txt
│ ├── 12.txt
│ ├── 13.txt
│ ├── 14.txt
│ ├── 15.txt
│ ├── 6.txt
│ ├── 7.txt
│ ├── 8.txt
│ └── 9.txt
│ ├── full_description.txt
│ ├── images
│ ├── icon.png
│ └── phoneScreenshots
│ │ ├── 1.png
│ │ ├── 2.png
│ │ ├── 3.png
│ │ ├── 4.png
│ │ └── 5.png
│ ├── short_description.txt
│ └── title.txt
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Experiencing a bug? Report it so it can be caught!
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **How to reproduce**
14 | Steps to reproduce the behaviour:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behaviour**
21 | A clear and concise description of what you expected to happen (unless that is so obvious that it would be particularly hard to miss).
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **System details**
27 | - Android version [e.g. Android 7]
28 | - App version [e.g. 1.3.8]
29 |
30 | **Additional context**
31 | Add any other context about the problem here.
32 |
33 | **Relevant?**
34 | - [ ] This is an issue specifically with the Android app
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | Bookwyrm
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetDropDown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/deploymentTargetSelector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/migrations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2022, Privacy_Dragon
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bookwyrm-android
2 | An Android application for Bookwyrm. Basically, it is just bookwyrm put into a 'webview' element.
3 | What it does? It enables you to use BookWyrm on your Android phone without having to use a browser to go to it every time.
4 | It can also open links to userpages of Bookwyrm users and it can scan ISBN codes.
5 |
6 | This application works on: Android 6 and above.
7 |
8 | And if you want to know, I am [`@StoryDragon@books.storydragon.nl`](https://books.storydragon.nl/user/storydragon) on BookWyrm.
9 |
10 | For the ISBN-scanning I use the library zxing-android-embedded.
11 | The barcode icon that is added for instances that do not have ISBN-scanning by default comes from the Remix Icon project.
12 |
13 | [
](https://f-droid.org/packages/nl.privacydragon.bookwyrm/)
16 |
17 | Or download the latest APK from the [Releases Section](https://github.com/PrivacyDragon/Bookwyrm_Android/releases/latest).
18 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdk 34
7 |
8 | defaultConfig {
9 | applicationId "nl.privacydragon.bookwyrm"
10 | minSdk 23
11 | targetSdk 34
12 | versionCode 15
13 | versionName "1.3.8"
14 |
15 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
16 | }
17 |
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | vcsInfo.include false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | namespace 'nl.privacydragon.bookwyrm'
30 | dependenciesInfo {
31 | includeInApk false
32 | includeInBundle false
33 | }
34 | }
35 |
36 | dependencies {
37 |
38 | implementation 'androidx.appcompat:appcompat:1.7.0'
39 | implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
40 | implementation 'com.google.android.material:material:1.12.0'
41 | implementation platform('org.jetbrains.kotlin:kotlin-bom:2.1.0')
42 | testImplementation 'junit:junit:4.13.2'
43 | androidTestImplementation 'androidx.test.ext:junit:1.2.1'
44 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
45 | implementation 'com.google.zxing:core:3.5.3'
46 | implementation 'com.journeyapps:zxing-android-embedded:4.3.0@aar'
47 | implementation 'org.conscrypt:conscrypt-android:2.5.2'
48 | implementation 'com.squareup.okhttp3:okhttp:4.12.0'
49 |
50 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/release/Bookwyrm-v1.3.8.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/release/Bookwyrm-v1.3.8.apk
--------------------------------------------------------------------------------
/app/release/output-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "artifactType": {
4 | "type": "APK",
5 | "kind": "Directory"
6 | },
7 | "applicationId": "nl.privacydragon.bookwyrm",
8 | "variantName": "release",
9 | "elements": [
10 | {
11 | "type": "SINGLE",
12 | "filters": [],
13 | "attributes": [],
14 | "versionCode": 15,
15 | "versionName": "1.3.8",
16 | "outputFile": "app-release.apk"
17 | }
18 | ],
19 | "elementType": "File",
20 | "baselineProfiles": [
21 | {
22 | "minApi": 28,
23 | "maxApi": 30,
24 | "baselineProfiles": [
25 | "baselineProfiles/1/app-release.dm"
26 | ]
27 | },
28 | {
29 | "minApi": 31,
30 | "maxApi": 2147483647,
31 | "baselineProfiles": [
32 | "baselineProfiles/0/app-release.dm"
33 | ]
34 | }
35 | ],
36 | "minSdkVersionForDexing": 23
37 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/nl/privacydragon/bookwyrm/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package nl.privacydragon.bookwyrm;
2 |
3 | import android.content.Context;
4 | import androidx.test.InstrumentationRegistry;
5 | import androidx.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
23 | assertEquals("nl.privacydragon.bookwyrm", appContext.getPackageName());
24 | }
25 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
22 |
23 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
759 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
--------------------------------------------------------------------------------
/app/src/main/ic_launcher-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/ic_launcher-playstore.png
--------------------------------------------------------------------------------
/app/src/main/java/nl/privacydragon/bookwyrm/HandlerActivity.java:
--------------------------------------------------------------------------------
1 | package nl.privacydragon.bookwyrm;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.app.Activity;
6 | import android.content.ActivityNotFoundException;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.SharedPreferences;
10 | import android.content.pm.PackageManager;
11 | import android.graphics.Bitmap;
12 | import android.net.Uri;
13 | import android.os.Bundle;
14 | import android.view.KeyEvent;
15 | import android.view.View;
16 | import android.webkit.JavascriptInterface;
17 | import android.webkit.ValueCallback;
18 | import android.webkit.WebChromeClient;
19 | import android.webkit.WebResourceRequest;
20 | import android.webkit.WebView;
21 | import android.webkit.WebViewClient;
22 | import android.widget.ProgressBar;
23 | import android.widget.Toast;
24 |
25 | import androidx.activity.result.ActivityResultLauncher;
26 | import androidx.activity.result.contract.ActivityResultContracts;
27 | import androidx.appcompat.app.AppCompatActivity;
28 | import androidx.core.app.ActivityCompat;
29 | import androidx.core.content.ContextCompat;
30 |
31 | import com.journeyapps.barcodescanner.ScanContract;
32 | import com.journeyapps.barcodescanner.ScanOptions;
33 |
34 | public class HandlerActivity extends AppCompatActivity {
35 |
36 | WebView myWebView;
37 | ProgressBar LoadIndicator;
38 | public ValueCallback omhooglader;
39 | @SuppressLint("SetJavaScriptEnabled")
40 | @Override
41 | protected void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_start);
44 | // ATTENTION: This was auto-generated to handle app links.
45 | Intent appLinkIntent = getIntent();
46 | String appLinkAction = appLinkIntent.getAction();
47 | Uri appLinkData = appLinkIntent.getData();
48 | // End of auto-generated stuff
49 | ActivityResultLauncher voodooLauncher = registerForActivityResult(
50 | new ActivityResultContracts.StartActivityForResult(),
51 | result -> {
52 | if (result.getResultCode() == Activity.RESULT_OK) {
53 | // There are no request codes
54 | Intent data = result.getData();
55 | if (omhooglader == null)
56 | return;
57 | omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
58 | } else {
59 | omhooglader.onReceiveValue(null);
60 | }
61 | });
62 | LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
63 | myWebView = (WebView) findViewById(R.id.webview);
64 | myWebView.setVisibility(View.GONE);
65 | myWebView.getSettings().setJavaScriptEnabled(true);
66 | myWebView.getSettings().setDomStorageEnabled(true);
67 | myWebView.getSettings().setAllowFileAccess(true);
68 | myWebView.getSettings().setAllowContentAccess(true);
69 | myWebView.addJavascriptInterface(new Object()
70 | {
71 | @JavascriptInterface // For API 17+
72 | public void performClick(String what)
73 | {
74 | if (!what.contains("[object Window]")) { //For some reason the function has to be called when the event listener is attached to the button. So, by adding in 'this', it is possible to make sure to only act when the thing that called the function is NOT the window, but the button.
75 | ScanBarCode();
76 | }
77 |
78 | }
79 | }, "scan");
80 | myWebView.setWebChromeClient(new WebChromeClient() {
81 | @Override
82 | public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
83 | if (omhooglader != null) {
84 | omhooglader = null;
85 | }
86 | omhooglader = filePathCallback;
87 | Intent intent = fileChooserParams.createIntent();
88 | try {
89 | voodooLauncher.launch(intent);
90 | } catch (ActivityNotFoundException grrr){
91 | omhooglader = null;
92 | return false;
93 | }
94 | return true;
95 | }
96 | });
97 | //The name of the user's server is stored in the shared preferences, so first it has to be read from there.
98 | String defaultValue = "none";
99 | SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
100 | String server = sharedPref.getString(getString(R.string.server), defaultValue);
101 | if (server.equals("none")) {
102 | startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.MainActivity.class));
103 | }
104 | String pathMaybe = appLinkData.getPath();
105 | String toGoServer = "bla";
106 | //This bit of code regelt wanneer de webpagina wordt weergegeven. It is quite handig then om dan ook "book" toe te laten, zodat ook boeken in de app bekeken kunnen worden...
107 | if (pathMaybe.contains("user") || pathMaybe.contains("book")) {
108 | //If the path contains 'user', it is a user profile, unless it is followed by something like 'review'.
109 | if (pathMaybe.contains("review") || pathMaybe.contains("generatednote") || pathMaybe.contains("quotation") || pathMaybe.contains("comment") || pathMaybe.contains("book")) {
110 | toGoServer = "https://" + appLinkData.getHost() + pathMaybe;
111 | }
112 | else {
113 | String notAtUser = pathMaybe.substring(pathMaybe.indexOf("user") + 5); //This line gets the username.
114 | String atUser = notAtUser + "@" + appLinkData.getHost(); //This appends @[HOST] to the string, so we have the full username thing needed.
115 | toGoServer = "https://" + server + "/user/" + atUser;
116 | }
117 | } else {
118 | //If the toGoServer string remains "bla", dan zal de user when they teruggaan uitkomen op https://bla/, which is 'not allowed'.
119 | //So, maybe here, just to be sure, assign the value of the user's own server to the toGoServer variabele.
120 | //After that, since apparently I have decided that the URL the user tried to follow is not valid in my application, redirect them to StartActivity.
121 | toGoServer = "https://" + server;
122 | startActivity(new Intent(HandlerActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
123 | }
124 |
125 | //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.
126 | String finalToGoServer = toGoServer;
127 | myWebView.setWebViewClient(new HandlerActivity.MyWebViewClient() {
128 | public void onPageFinished(WebView view, String url) {
129 | LoadIndicator.setVisibility(View.GONE);
130 | myWebView.setVisibility(View.VISIBLE);
131 | view.loadUrl("javascript:(function() { if (/(review|generatednote|quotation|comment|book)/i.test(window.location.href)) {" +
132 | "blocks = document.getElementsByClassName('block');" +
133 | "for (let element of blocks){" +
134 | "if (element.localName == 'header') { " +
135 | "element.innerHTML = ` \n" +
136 | "\n" +
137 | "Back to homeserver\n" +
138 | "`;" +
139 | "break;" +
140 | "}" +
141 | "}" +
142 | "} ;})()");
143 | view.loadUrl("javascript:(function() { " +
144 | "if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
145 | "let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
146 | "ISBN_Button.replaceWith(ISBN_Button.cloneNode(true));" +
147 | "document.querySelectorAll(\"[data-modal-open]\")[0].addEventListener('click', () => {" +
148 | "scan.performClick(this);" +
149 | "});" +
150 | "} else {" +
151 | "let ISBN = document.createElement(\"div\");" +
152 | "ISBN.class = 'control';" +
153 | "ISBN.innerHTML = '';" +
154 | "nav = document.getElementsByClassName(\"field has-addons\")[0];" +
155 | "nav.appendChild(ISBN);" +
156 | "}" +
157 | ";})()");
158 | }
159 | });
160 | //Here, load the login page of the server. That actually does all that is needed.
161 | myWebView.loadUrl(toGoServer);
162 | }
163 |
164 | private final ActivityResultLauncher barcodeLanceerder = registerForActivityResult(new ScanContract(),
165 | result -> {
166 | if(result.getContents() == null) {
167 | Toast.makeText(HandlerActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
168 | } else {
169 | Toast.makeText(HandlerActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
170 | myWebView.loadUrl("Javascript:(function() {" +
171 | "try {" +
172 | "document.getElementById('tour-search').value = " + result.getContents() + ";" +
173 | "} catch {" +
174 | "document.getElementById('search_input').value = " + result.getContents() + ";" +
175 | "}" +
176 | "document.getElementsByTagName('form')[0].submit();" +
177 | ";})()");
178 | LoadIndicator.setVisibility(View.VISIBLE);
179 | }
180 | });
181 |
182 | public void ScanBarCode() {
183 | String permission = Manifest.permission.CAMERA;
184 | int grant = ContextCompat.checkSelfPermission(HandlerActivity.this, permission);
185 | if (grant != PackageManager.PERMISSION_GRANTED) {
186 | String[] permission_list = new String[1];
187 | permission_list[0] = permission;
188 | ActivityCompat.requestPermissions(HandlerActivity.this, permission_list, 1);
189 | }
190 | ScanOptions eisen = new ScanOptions();
191 | eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13);
192 | eisen.setBeepEnabled(true);
193 | eisen.setCameraId(0);
194 | eisen.setPrompt("SCAN ISBN");
195 | eisen.setBarcodeImageEnabled(false);
196 | barcodeLanceerder.launch(eisen);
197 | }
198 |
199 | @Override
200 | public boolean onKeyUp(int keyCode, KeyEvent event) {
201 | // Check if the key event was the Back button and if there's history
202 | if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
203 | myWebView.goBack();
204 | return true;
205 | }
206 | // If it wasn't the Back key or there's no web page history, bubble up to the default
207 | // system behavior (probably exit the activity)
208 | return super.onKeyUp(keyCode, event);
209 | }
210 | @Override
211 | public boolean onKeyLongPress(int keyCode, KeyEvent event) {
212 | if (keyCode == KeyEvent.KEYCODE_BACK) {
213 | finish();
214 | return true;
215 | }
216 | return super.onKeyLongPress(keyCode, event);
217 | }
218 | //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.
219 | //Yes, I used the web for this too.
220 | private class MyWebViewClient extends WebViewClient {
221 | @Override
222 | public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
223 | // ATTENTION: This was auto-generated to handle app links.
224 | Intent appLinkIntent = getIntent();
225 | String appLinkAction = appLinkIntent.getAction();
226 | Uri appLinkData = appLinkIntent.getData();
227 | // End of auto-generated stuff
228 | String strangeHost = appLinkData.getHost();
229 | SharedPreferences sharedPref = HandlerActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
230 | String defaultValue = "none";
231 | String server = sharedPref.getString(getString(R.string.server), defaultValue);
232 | if (server.equals(request.getUrl().getHost())) {
233 | //If the server is the same as the bookwyrm, load it in the webview.
234 | return false;
235 | } else if (strangeHost.equals(request.getUrl().getHost())) {
236 | return false;
237 | }
238 | // Otherwise, it should go to the default browser instead.
239 | Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
240 | startActivity(intent);
241 | return true;
242 | }
243 |
244 | @Override
245 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
246 | LoadIndicator.setVisibility(View.VISIBLE);
247 | }
248 |
249 | }
250 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/privacydragon/bookwyrm/MainActivity.java:
--------------------------------------------------------------------------------
1 | package nl.privacydragon.bookwyrm;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.SharedPreferences;
6 | import android.graphics.Color;
7 | import android.security.keystore.KeyGenParameterSpec;
8 | import android.security.keystore.KeyProperties;
9 | import android.os.Bundle;
10 | import android.util.Base64;
11 | import android.view.View;
12 | import android.widget.EditText;
13 | import android.widget.TextView;
14 |
15 | import androidx.appcompat.app.AppCompatActivity;
16 |
17 | import java.io.IOException;
18 | import java.security.InvalidAlgorithmParameterException;
19 | import java.security.InvalidKeyException;
20 | import java.security.Key;
21 | import java.security.KeyStore;
22 | import java.security.KeyStoreException;
23 | import java.security.NoSuchAlgorithmException;
24 | import java.security.NoSuchProviderException;
25 | import java.security.UnrecoverableKeyException;
26 | import java.security.cert.CertificateException;
27 | import java.util.Random;
28 |
29 | import javax.crypto.BadPaddingException;
30 | import javax.crypto.Cipher;
31 | import javax.crypto.IllegalBlockSizeException;
32 | import javax.crypto.KeyGenerator;
33 | import javax.crypto.NoSuchPaddingException;
34 | import javax.crypto.spec.GCMParameterSpec;
35 |
36 | public class MainActivity extends AppCompatActivity {
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_main);
42 | //Check whether there is something stored. Only if there is already something stored, proceed to BookWyrm.
43 | SharedPreferences sharedPref = MainActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
44 | String defaultValue = "none";
45 | String server = sharedPref.getString(getString(R.string.server), defaultValue);
46 | if (!"none".equals(server)) {
47 | startActivity(new Intent(MainActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
48 | }
49 | }
50 |
51 | private static String getRandomString() //I just copied this from internet. Yes, I am lazy :). (https://stackoverflow.com/questions/12116092/android-random-string-generator#answer-12116194)
52 | {
53 | String ALLOWED_CHARACTERS ="0123456789qwertyuiopasdfghjklzxcvbnm!@#$%^&*()_+=][{}";
54 | final Random random=new Random();
55 | final StringBuilder sb=new StringBuilder(12);
56 | for(int i = 0; i< 12; ++i) {
57 | sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
58 | }
59 | return sb.toString();
60 | }
61 |
62 | public void LogIn(View view) throws IllegalBlockSizeException, BadPaddingException, KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, UnrecoverableKeyException, NoSuchPaddingException, InvalidKeyException {
63 | //Declaring some things needed. Getting the user input.
64 | EditText serverInput = (EditText) findViewById(R.id.Instance);
65 | String server = String.valueOf(serverInput.getText());
66 | EditText passInput = (EditText) findViewById(R.id.Password);
67 | String pass = String.valueOf(passInput.getText());
68 | EditText nameInput = (EditText) findViewById(R.id.Username);
69 | String name = String.valueOf(nameInput.getText());
70 | //All fields are required, so if one of them is empty, the user should see a warning.
71 | if (server.isEmpty() || pass.isEmpty() || name.isEmpty()) {
72 | TextView ErrorMessage = (TextView) findViewById(R.id.textView5);
73 | ErrorMessage.setTextColor(Color.YELLOW);
74 | ErrorMessage.setText("ERROR: All fields are required!");
75 | } else {
76 | //Likely this will be the first time the program is run. So create a new key thing in the android key store happening.
77 | KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
78 | keyStore.load(null);
79 | if (!keyStore.containsAlias("BookWyrm")) { //Actually, the new key is made here, if it does not exist already.
80 | KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
81 | keyGenerator.init(
82 | new KeyGenParameterSpec.Builder("BookWyrm",
83 | KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
84 | .setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
85 | .setRandomizedEncryptionRequired(false)
86 | .build());
87 | keyGenerator.generateKey();
88 | }
89 | //Grab the key and initiate the encryption process stuff. For this, a random fixed IV code is generated.
90 | Key DragonLikeKey = keyStore.getKey("BookWyrm", null);
91 | Cipher c = Cipher.getInstance("AES/GCM/NoPadding");
92 | String magicCode = getRandomString();
93 | c.init(Cipher.ENCRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, magicCode.getBytes()));
94 | //And now do the encryption!
95 | byte[] passBytes = c.doFinal(pass.getBytes());
96 | String passUse = Base64.encodeToString(passBytes, Base64.DEFAULT);
97 | //And then all the things are stored in the shared preferences.
98 | //Therefore, first all the shared preferences objects are loaded.
99 | SharedPreferences sharedPref = MainActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
100 | SharedPreferences sharedPrefName = MainActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
101 | SharedPreferences sharedPrefPass = MainActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
102 | SharedPreferences sharedPrefMagic = MainActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
103 | //Then the 'edit' stuff are made for them.
104 | SharedPreferences.Editor editorName = sharedPrefName.edit();
105 | SharedPreferences.Editor editorPass = sharedPrefPass.edit();
106 | SharedPreferences.Editor editorMagic = sharedPrefMagic.edit();
107 | SharedPreferences.Editor editor = sharedPref.edit();
108 | //And finally, the values are written to them.
109 | editor.putString(getString(R.string.server), server);
110 | editor.apply();
111 | editorName.putString(getString(R.string.name), name);
112 | editorName.apply();
113 | editorPass.putString(getString(R.string.pw), passUse);
114 | editorPass.apply();
115 | editorMagic.putString(getString(R.string.q), magicCode);
116 | editorMagic.apply();
117 | //Once all that has been done, Bookwyrm can be opened and such!
118 | startActivity(new Intent(MainActivity.this, nl.privacydragon.bookwyrm.StartActivity.class));
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/app/src/main/java/nl/privacydragon/bookwyrm/StartActivity.java:
--------------------------------------------------------------------------------
1 | package nl.privacydragon.bookwyrm;
2 |
3 | import android.Manifest;
4 | import android.annotation.SuppressLint;
5 | import android.app.Activity;
6 | import android.content.ActivityNotFoundException;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.SharedPreferences;
10 | import android.content.pm.PackageManager;
11 | import android.graphics.Bitmap;
12 | import android.net.Uri;
13 | import android.os.Bundle;
14 | import android.util.Base64;
15 | import android.view.KeyEvent;
16 | import android.view.View;
17 | import android.webkit.CookieManager;
18 | import android.webkit.JavascriptInterface;
19 | import android.webkit.ValueCallback;
20 | import android.webkit.WebChromeClient;
21 | import android.webkit.WebResourceRequest;
22 | import android.webkit.WebView;
23 | import android.webkit.WebViewClient;
24 | import android.widget.ProgressBar;
25 | import android.widget.Toast;
26 |
27 | import androidx.activity.result.ActivityResultLauncher;
28 | import androidx.activity.result.contract.ActivityResultContracts;
29 | import androidx.appcompat.app.AppCompatActivity;
30 | import androidx.core.app.ActivityCompat;
31 | import androidx.core.content.ContextCompat;
32 |
33 | import com.journeyapps.barcodescanner.ScanContract;
34 | import com.journeyapps.barcodescanner.ScanOptions;
35 |
36 | import org.conscrypt.Conscrypt;
37 |
38 | import java.io.IOException;
39 | import java.io.UnsupportedEncodingException;
40 | import java.net.URLEncoder;
41 | import java.nio.charset.StandardCharsets;
42 | import java.security.InvalidAlgorithmParameterException;
43 | import java.security.InvalidKeyException;
44 | import java.security.Key;
45 | import java.security.KeyStore;
46 | import java.security.KeyStoreException;
47 | import java.security.NoSuchAlgorithmException;
48 | import java.security.Security;
49 | import java.security.UnrecoverableKeyException;
50 | import java.security.cert.CertificateException;
51 |
52 | import javax.crypto.BadPaddingException;
53 | import javax.crypto.Cipher;
54 | import javax.crypto.IllegalBlockSizeException;
55 | import javax.crypto.NoSuchPaddingException;
56 | import javax.crypto.spec.GCMParameterSpec;
57 |
58 | import okhttp3.FormBody;
59 | import okhttp3.Headers;
60 | import okhttp3.Interceptor;
61 | import okhttp3.OkHttpClient;
62 | import okhttp3.Request;
63 | import okhttp3.RequestBody;
64 | import okhttp3.Response;
65 |
66 | public class StartActivity extends AppCompatActivity {
67 | WebView myWebView;
68 | ProgressBar LoadIndicator;
69 | public ValueCallback omhooglader;
70 | String putje = "";
71 | String sessie = "";
72 | @SuppressLint("SetJavaScriptEnabled")
73 | @Override
74 | protected void onCreate(Bundle savedInstanceState) {
75 | super.onCreate(savedInstanceState);
76 | setContentView(R.layout.activity_start);
77 | LoadIndicator = (ProgressBar) findViewById(R.id.progressBar3);
78 | ActivityResultLauncher voodooLauncher = registerForActivityResult(
79 | new ActivityResultContracts.StartActivityForResult(),
80 | result -> {
81 | if (result.getResultCode() == Activity.RESULT_OK) {
82 | // There are no request codes
83 | Intent data = result.getData();
84 | if (omhooglader == null)
85 | return;
86 | omhooglader.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(result.getResultCode(), data));
87 | }
88 | else {
89 | omhooglader.onReceiveValue(null);
90 | }
91 | });
92 | myWebView = (WebView) findViewById(R.id.webview);
93 | myWebView.setVisibility(View.GONE);
94 | myWebView.getSettings().setUserAgentString(getString(R.string.gebruikersagent));
95 | myWebView.getSettings().setJavaScriptEnabled(true);
96 | myWebView.addJavascriptInterface(new Object()
97 | {
98 | @JavascriptInterface // For API 17+
99 | public void performClick(String what)
100 | {
101 | if (!what.contains("[object Window]")) { //For some reason the function has to be called when the event listener is attached to the button. So, by adding in 'this', it is possible to make sure to only act when the thing that called the function is NOT the window, but the button.
102 | ScanBarCode();
103 | }
104 |
105 | }
106 | }, "scan");
107 | myWebView.setWebChromeClient(new WebChromeClient() {
108 | @Override
109 | public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) {
110 | if (omhooglader != null) {
111 | //omhooglader.onReceiveValue(null);
112 | omhooglader = null;
113 | }
114 | omhooglader = filePathCallback;
115 | Intent intent = fileChooserParams.createIntent();
116 | try {
117 | voodooLauncher.launch(intent);
118 | } catch (ActivityNotFoundException grrr){
119 | omhooglader = null;
120 | return false;
121 | }
122 | return true;
123 | }
124 | });
125 | //The user credentials are stored in the shared preferences, so first they have to be read from there.
126 | String defaultValue = "none";
127 | SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
128 | String server = sharedPref.getString(getString(R.string.server), defaultValue);
129 | SharedPreferences sharedPrefName = StartActivity.this.getSharedPreferences(getString(R.string.name), Context.MODE_PRIVATE);
130 | String name = sharedPrefName.getString(getString(R.string.name), defaultValue);
131 | SharedPreferences sharedPrefPass = StartActivity.this.getSharedPreferences(getString(R.string.pw), Context.MODE_PRIVATE);
132 | String pass = sharedPrefPass.getString(getString(R.string.pw), defaultValue);
133 | SharedPreferences sharedPrefMagic = StartActivity.this.getSharedPreferences(getString(R.string.q), Context.MODE_PRIVATE);
134 | String codeMagic = sharedPrefMagic.getString(getString(R.string.q), defaultValue);
135 | //Then all the decryption stuff has to happen. There are a lot of try-catch stuff, because apparently that seems to be needed.
136 | //First get the keystore thing.
137 | KeyStore keyStore = null;
138 | try {
139 | keyStore = KeyStore.getInstance("AndroidKeyStore");
140 | } catch (KeyStoreException e) {
141 | e.printStackTrace();
142 | }
143 | //Then, load it. or something. To make sure that it can be used.
144 | try {
145 | keyStore.load(null);
146 | } catch (CertificateException | IOException | NoSuchAlgorithmException e) {
147 | e.printStackTrace();
148 | }
149 | //Next, retrieve the key to be used for the decryption.
150 | Key DragonLikeKey = null;
151 | try {
152 | DragonLikeKey = keyStore.getKey("BookWyrm", null);
153 | } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
154 | e.printStackTrace();
155 | }
156 | //Do something with getting the/a cipher or something.
157 | Cipher c = null;
158 | try {
159 | c = Cipher.getInstance("AES/GCM/NoPadding");
160 | } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
161 | e.printStackTrace();
162 | }
163 | //And then initiating the cipher, so it can be used.
164 | try {
165 | assert c != null;
166 | c.init(Cipher.DECRYPT_MODE, DragonLikeKey, new GCMParameterSpec(128, codeMagic.getBytes()));
167 | } catch (InvalidAlgorithmParameterException | InvalidKeyException e) {
168 | e.printStackTrace();
169 | }
170 | //Decrypt the password!
171 | byte[] truePass = null;
172 | try {
173 | truePass = c.doFinal(Base64.decode(pass, Base64.DEFAULT));
174 | } catch (BadPaddingException | IllegalBlockSizeException e) {
175 | e.printStackTrace();
176 | }
177 | //Convert the decrypted password back to a string.
178 | String passw = new String(truePass, StandardCharsets.UTF_8);
179 | //String wacht = passw.replaceAll("'", "\\\\'");
180 |
181 | //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.
182 | myWebView.setWebViewClient(new MyWebViewClient(){
183 | public void onPageFinished(WebView view, String url) {
184 | LoadIndicator.setVisibility(View.GONE);
185 | myWebView.setVisibility(View.VISIBLE);
186 | view.loadUrl("javascript:(function() { " +
187 | "if (document.querySelectorAll(\"[data-modal-open]\")[0]) {" +
188 | "let ISBN_Button = document.querySelectorAll(\"[data-modal-open]\")[0];" +
189 | "ISBN_Button.replaceWith(ISBN_Button.cloneNode(true));" +
190 | "document.querySelectorAll(\"[data-modal-open]\")[0].addEventListener('click', () => {" +
191 | "scan.performClick(this);" +
192 | "});" +
193 | "} else {" +
194 | "let ISBN = document.createElement(\"div\");" +
195 | "ISBN.class = 'control';" +
196 | "ISBN.innerHTML = '';" +
197 | "nav = document.getElementsByClassName(\"field has-addons\")[0];" +
198 | "nav.appendChild(ISBN);" +
199 | "}" +
200 | ";})()"); //This lines replace the ISBN-scan button event listener with one that points to the on-device scanning implementation, if it is available on the instance. If not, the button is added.
201 |
202 | }
203 | });
204 | CookieManager oven = CookieManager.getInstance();
205 | String koek = oven.getCookie("https://" + server);
206 | if (koek != null) {
207 | if (koek.indexOf("sessionid") != -1) {
208 | myWebView.loadUrl("https://" + server);
209 | } else {
210 | //This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
211 | try {
212 | getMiddleWareTokenAndLogIn(server, name, passw);
213 | } catch (IOException e) {
214 | throw new RuntimeException(e);
215 | }
216 | }
217 | } else {
218 | //This should get the login page, retreive the csrf-middlewaretoken, and then log the user in using a POST-request.
219 | try {
220 | getMiddleWareTokenAndLogIn(server, name, passw);
221 | } catch (IOException e) {
222 | throw new RuntimeException(e);
223 | }
224 | }
225 |
226 |
227 | }
228 |
229 | public void getMiddleWareTokenAndLogIn(String server, String name, String passw) throws IOException {
230 | //Het idee is dat deze functie de loginpagina van de server laadt en dan de 'csrfmiddlewaretoken' uit het inlogformulier haalt,
231 | //Zodat dat dan gebruikt kan worden bij het inloggen.
232 | //Becuase network operations cannot be done on the main/ui thread, create a new thread for this complete function. Yay!
233 | Thread draadje = new Thread(new Runnable() {
234 | @Override
235 | public void run() {
236 | try {
237 | //Load the login page, and do not forget to take some cookies.
238 | Security.insertProviderAt(Conscrypt.newProvider(), 1);
239 | String speculaas = "";
240 | String speculaasBeslag = "";
241 | //The login page loading is done using OkHttpClient.
242 | OkHttpClient client = new OkHttpClient();
243 | Request aanvraag = new Request.Builder()
244 | .url("https://" + server + "/")
245 | .header("User-Agent", getString(R.string.gebruikersagent))
246 | .build();
247 | //Get an answer!
248 | try (Response antwoord = client.newCall(aanvraag).execute()) {
249 | if (!antwoord.isSuccessful()) throw new IOException("Unexpected code " + antwoord);
250 | //Search the headers for the 'set-cookie' header so we can eat a cookie!
251 | Headers cenna = antwoord.headers();
252 | for (int i = 0; i < cenna.size(); i++) {
253 | if (cenna.name(i).equals("set-cookie")) {
254 | speculaas = cenna.value(i);
255 | speculaasBeslag = speculaas.split(";")[0];
256 | }
257 | }
258 | //And then get the HTML body.
259 | assert antwoord.body() != null;
260 | String zooi = antwoord.body().string();
261 | //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!
262 | String[] opgebroken = zooi.split("name=\"csrfmiddlewaretoken\" value=\"");
263 | //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.
264 | String[] breukjes = opgebroken[1].split("\">");
265 | //Of course, the token is then the first element in our array.
266 | String token = breukjes[0];
267 | //Log.d("botbreuk", token);
268 | String gegevens = null;
269 | //And then set the data string up for use in the POST request, with the csrf middleware token, the username, and the password.
270 | try {
271 | gegevens = "csrfmiddlewaretoken=" + URLEncoder.encode(token, "UTF-8") + "&localname=" + URLEncoder.encode(name, "UTF-8") + "&password=" + URLEncoder.encode(passw, "UTF-8");
272 | } catch (UnsupportedEncodingException e) {
273 | throw new RuntimeException(e);
274 | }
275 | RequestBody keurslijf = new FormBody.Builder()
276 | .add("csrfmiddlewaretoken", token)
277 | .add("localname", name)
278 | .add("password", passw)
279 | .build();
280 |
281 | String finalGegevens = gegevens;
282 | //Log.d("gegevens", finalGegevens);
283 | //Log.d("beslag", speculaasBeslag);
284 | String finalSpeculaas = speculaas;
285 | //Log in using a POST request, and shove the resulting web-page into a public string. (putje)
286 | //For this, we have to give the log-in function the servername, the request body, and the value of the csrf cookie.
287 | logInAndGetHTML(server, keurslijf, speculaasBeslag);
288 | //Then we have to run a bit of code on the main (UI) thread. To be able to work with the webview...
289 | runOnUiThread(new Runnable() {
290 | @Override
291 | public void run() {
292 | //First we have to get the cookie manager of the webview, so we can hand it the csrf cookie.
293 | //Without being fed the correct csrf cookie, the Wyrm will refuse our request. The wyrm is a very picky eater!
294 | CookieManager oven = CookieManager.getInstance();
295 | //Bake the cookie into the webview.
296 | oven.setCookie("https://" + server, finalSpeculaas);
297 | //And bake the session cookie as well.
298 | oven.setCookie("https://" + server, sessie);
299 | //And then finally it is time to load everything into the webview.
300 | myWebView.loadDataWithBaseURL("https://" + server, putje, null, null, "https://" + server + "/login");
301 | }
302 | });
303 |
304 | }
305 | } catch (Exception e) {
306 | throw new RuntimeException(e);
307 | }
308 | }
309 | });
310 | //^Here ends all that new Thread() code.
311 | //⇓Run all the code in the thread.
312 | draadje.start();
313 | }
314 | public void logInAndGetHTML(String server, RequestBody lichaam, String speculoos) throws IOException {
315 | Security.insertProviderAt(Conscrypt.newProvider(), 1);
316 | //Create a client using CookieMonster, so we can retrieve cookies from the redirect after sending the log-in data.
317 | OkHttpClient client = new OkHttpClient.Builder()
318 | .addNetworkInterceptor(new CookieMonster())
319 | .build();
320 | //Create the POST request.
321 | Request verzoek = new Request.Builder()
322 | .url("https://" + server + "/login?next=/")
323 | .header("User-Agent", getString(R.string.gebruikersagent))
324 | .addHeader("origin", "https://" + server)
325 | .addHeader("cookie", speculoos)
326 | .post(lichaam)
327 | .build();
328 | //And then get the response.
329 | try (Response reactie = client.newCall(verzoek).execute()) {
330 | if (!reactie.isSuccessful())
331 | throw new IOException("Unexpected code " + reactie);
332 | assert reactie.body() != null;
333 | //Shove the response body into the public string 'putje', to be used for sending the body to the webview.
334 | putje = reactie.body().string();
335 | }
336 | }
337 | private final ActivityResultLauncher barcodeLanceerder = registerForActivityResult(new ScanContract(),
338 | result -> {
339 | if(result.getContents() == null) {
340 | Toast.makeText(StartActivity.this, "Cancelled", Toast.LENGTH_LONG).show();
341 | } else {
342 | Toast.makeText(StartActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
343 | myWebView.loadUrl("Javascript:(function() {" +
344 | "try {" +
345 | "document.getElementById('tour-search').value = " + result.getContents() + ";" +
346 | "} catch {" +
347 | "document.getElementById('search_input').value = " + result.getContents() + ";" +
348 | "}" +
349 | "document.getElementsByTagName('form')[0].submit();" +
350 | ";})()");
351 | LoadIndicator.setVisibility(View.VISIBLE);
352 | }
353 | });
354 |
355 | public void ScanBarCode() {
356 | String permission = Manifest.permission.CAMERA;
357 | int grant = ContextCompat.checkSelfPermission(StartActivity.this, permission);
358 | if (grant != PackageManager.PERMISSION_GRANTED) {
359 | String[] permission_list = new String[1];
360 | permission_list[0] = permission;
361 | ActivityCompat.requestPermissions(StartActivity.this, permission_list, 1);
362 | }
363 | ScanOptions eisen = new ScanOptions();
364 | eisen.setDesiredBarcodeFormats(ScanOptions.EAN_13);
365 | eisen.setBeepEnabled(true);
366 | eisen.setCameraId(0);
367 | eisen.setPrompt("SCAN ISBN");
368 | eisen.setBarcodeImageEnabled(false);
369 | barcodeLanceerder.launch(eisen);
370 | }
371 |
372 | @Override
373 | public boolean onKeyUp(int keyCode, KeyEvent event) {
374 | // Check if the key event was the Back button and if there's history
375 | if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
376 | myWebView.goBack();
377 | return true;
378 | }
379 | // If it wasn't the Back key or there's no web page history, bubble up to the default
380 | // system behavior (probably exit the activity)
381 | return super.onKeyUp(keyCode, event);
382 | }
383 | @Override
384 | public boolean onKeyLongPress(int keyCode, KeyEvent event) {
385 | if (keyCode == KeyEvent.KEYCODE_BACK) {
386 | finish();
387 | return true;
388 | }
389 | return super.onKeyLongPress(keyCode, event);
390 | }
391 | final class CookieMonster implements Interceptor {
392 | @Override public Response intercept(Interceptor.Chain chain) throws IOException {
393 | //Om ingelogd te blijven moeten we het sessiekoekje aan kunnen bieden.
394 | //Die moeten we dan wel eerst uit het koekblik pakken!
395 | Request eersteVerzoek = chain.request();
396 | //Eerst moeten we controleren of er al een sessiekoekje is. Als dat niet zo is, dan is dit het echte eerste verzoek.
397 | if (sessie.isEmpty()) {
398 | //In dat geval halen we de reactie op om het koekje te kunnen pakken!
399 | Response eersteReactie = chain.proceed(chain.request());
400 | Headers hoofden = eersteReactie.headers();
401 | for (int i = 0; i < hoofden.size(); i++) {
402 | if (hoofden.name(i).equals("set-cookie") && hoofden.value(i).startsWith("session")) {
403 | sessie = hoofden.value(i);
404 | }
405 | }
406 | //Nadat we het koekje hebben moet de reactie doorgebriefd worden aan de 'client',
407 | //die dan het volgende verzoek zal gaan doen vanwege de 302-redirect bij het inloggen.
408 | return eersteReactie;
409 | }
410 | //Het koekje is er! Hoera!
411 | //Het nieuwe verzoek moet wel met het sessiekoekje verzonden worden, anders zijn we alsnog niet ingelogd!
412 | Request nieuwVerzoek = eersteVerzoek.newBuilder()
413 | .addHeader("cookie", sessie)
414 | .build();
415 | return chain.proceed(nieuwVerzoek);
416 | }
417 | }
418 | //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.
419 | //Yes, I used the web for this too.
420 | private class MyWebViewClient extends WebViewClient {
421 | @Override
422 | public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
423 | SharedPreferences sharedPref = StartActivity.this.getSharedPreferences(getString(R.string.server), Context.MODE_PRIVATE);
424 | String defaultValue = "none";
425 | String server = sharedPref.getString(getString(R.string.server), defaultValue);
426 | if (server.equals(request.getUrl().getHost())) {
427 | //If the server is the same as the bookwyrm, load it in the webview.
428 | return false;
429 | }
430 | // Otherwise, it should go to the default browser instead.
431 | Intent intent = new Intent(Intent.ACTION_VIEW, request.getUrl());
432 | startActivity(intent);
433 | return true;
434 | }
435 |
436 | @Override
437 | public void onPageStarted(WebView view, String url, Bitmap favicon) {
438 | LoadIndicator.setVisibility(View.VISIBLE);
439 | }
440 | }
441 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
24 |
25 |
39 |
40 |
55 |
56 |
70 |
71 |
87 |
88 |
102 |
103 |
117 |
118 |
132 |
133 |
149 |
150 |
165 |
166 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_start.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_wyrm.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_wyrm_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-hdpi/ic_launcher_wyrm_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-mdpi/ic_launcher_wyrm_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xhdpi/ic_launcher_wyrm_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxhdpi/ic_launcher_wyrm_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm_foreground.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/app/src/main/res/mipmap-xxxhdpi/ic_launcher_wyrm_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 | #FD00FF
3 | #003351
4 | #FFFFFF
5 | #074B72
6 | #CCE5FF
7 | #B8C8DA
8 | #23323F
9 | #394857
10 | #D4E4F6
11 | #D1BFE7
12 | #372A4A
13 | #4E4161
14 | #EDDCFF
15 | #FFB4AB
16 | #690005
17 | #93000A
18 | #FFDAD6
19 | #101418
20 | #E0E2E8
21 | #101418
22 | #E0E2E8
23 | #42474E
24 | #C2C7CE
25 | #8C9198
26 | #42474E
27 | #000000
28 | #E0E2E8
29 | #2D3135
30 | #2C638B
31 | #CCE5FF
32 | #001D31
33 | #99CCFA
34 | #074B72
35 | #D4E4F6
36 | #0D1D2A
37 | #B8C8DA
38 | #394857
39 | #EDDCFF
40 | #221534
41 | #D1BFE7
42 | #4E4161
43 | #101418
44 | #36393E
45 | #0B0F12
46 | #181C20
47 | #1C2024
48 | #272A2E
49 | #313539
50 | #C0E0FF
51 | #002841
52 | #6396C1
53 | #000000
54 | #CEDEF0
55 | #182734
56 | #8392A3
57 | #000000
58 | #E8D5FE
59 | #2C203E
60 | #9A8AAF
61 | #000000
62 | #FFD2CC
63 | #540003
64 | #FF5449
65 | #000000
66 | #101418
67 | #E0E2E8
68 | #101418
69 | #FFFFFF
70 | #42474E
71 | #D8DDE4
72 | #ADB2BA
73 | #8B9198
74 | #000000
75 | #E0E2E8
76 | #272A2E
77 | #0A4C73
78 | #CCE5FF
79 | #001321
80 | #99CCFA
81 | #00395A
82 | #D4E4F6
83 | #03121F
84 | #B8C8DA
85 | #293845
86 | #EDDCFF
87 | #170A28
88 | #D1BFE7
89 | #3D3050
90 | #101418
91 | #414549
92 | #05080B
93 | #1A1E22
94 | #24282C
95 | #2F3337
96 | #3A3E42
97 | #E6F1FF
98 | #000000
99 | #95C8F5
100 | #000C18
101 | #E6F1FF
102 | #000000
103 | #B4C4D6
104 | #000C18
105 | #F7ECFF
106 | #000000
107 | #CDBBE3
108 | #110522
109 | #FFECE9
110 | #000000
111 | #FFAEA4
112 | #220001
113 | #101418
114 | #E0E2E8
115 | #101418
116 | #FFFFFF
117 | #42474E
118 | #FFFFFF
119 | #EBF0F8
120 | #BEC3CB
121 | #000000
122 | #E0E2E8
123 | #000000
124 | #0A4C73
125 | #CCE5FF
126 | #000000
127 | #99CCFA
128 | #001321
129 | #D4E4F6
130 | #000000
131 | #B8C8DA
132 | #03121F
133 | #EDDCFF
134 | #000000
135 | #D1BFE7
136 | #170A28
137 | #101418
138 | #4D5055
139 | #000000
140 | #1C2024
141 | #2D3135
142 | #383C40
143 | #43474C
144 |
145 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/ic_launcher_wyrm_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Bookwyrm
3 | bla
4 | blup
5 | gloep
6 | wheeeee
7 | Bookwyrm Android/1.3.8
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/theme_overlays.xml:
--------------------------------------------------------------------------------
1 |
2 |
50 |
98 |
99 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
50 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/backup_rules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/test/java/nl/privacydragon/bookwyrm/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package nl.privacydragon.bookwyrm;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | plugins {
3 | id 'com.android.application' version '8.8.0' apply false
4 | id 'com.android.library' version '8.8.0' apply false
5 | }
6 |
7 | task clean(type: Delete) {
8 | delete rootProject.buildDir
9 | }
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/10.txt:
--------------------------------------------------------------------------------
1 | * Fixed a bug with the barcode scanning. Now you can scan barcodes again.
2 | * Dependencies have been updated to newest versions.
3 | * More Bookwyrm instances have been added.
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/11.txt:
--------------------------------------------------------------------------------
1 | The same as release 1.3.3, but not the one bug is actually fixed for real...
2 | * Fixed a bug with the barcode scanning. Now you can scan barcodes again.
3 | * Dependencies have been updated to newest versions.
4 | * More Bookwyrm instances have been added.
5 |
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/12.txt:
--------------------------------------------------------------------------------
1 | * It is finally possible to add book covers from your own device storage.
2 | * You can now return to the initial log-in screen by long-pressing the 'back' button.
3 | * Dependencies have been updated to newest versions.
4 | * Compiled for up to Android 14 now.
5 | * Deprecated pieces of code have been rewritten.
6 | * More Bookwyrm instances have been added.
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/13.txt:
--------------------------------------------------------------------------------
1 | * Fixed some log-in problems.
2 | * Changed colour of warning text to be better visible.
3 | * Disabled inclusion of dependencies info and VCS info, fixing build problems for F-Droid.
4 | * Long-press now actually works.
5 | * Other minor changes
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/14.txt:
--------------------------------------------------------------------------------
1 | * Significant log-in improvements, including better security.
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/15.txt:
--------------------------------------------------------------------------------
1 | Fixing what turned out not to work for unreleased version 1.3.7:
2 | * Significant log-in improvements, including better security.
3 | Further changes:
4 | * The app now uses a custom User-Agent string.
5 | * Two new dependencies have been added: okhttp3, and conscrypt.
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/6.txt:
--------------------------------------------------------------------------------
1 | Initial release for F-Droid.
2 |
3 | * Added support for four more BookWyrm instances.
4 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/7.txt:
--------------------------------------------------------------------------------
1 | * Added a loading bar
2 | * You can now scan ISBN's, on any instance!
3 |
4 | More technical change:
5 | * Mitigated the project to use Androidx libraries, for that is necessary for the ISBN scanning...
6 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/8.txt:
--------------------------------------------------------------------------------
1 | * Improved the loading bar.
2 | * The ISBN-scanning feature now works by simply clicking the ISBN button that is used by the instances that have scanning already available.
3 | * For instances that do not support the scanning server-side, there is now instead of the text a button for ISBN-scanning, similar to the standard one.
4 | * More bookwyrm instances added to the ones that can be opened in the app.
5 | * Small bug-fix, so now only ISBN-codes (And other EAN-13 codes) will be scanned.
6 | * Another bug-fix. The modified back button works again.
7 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/changelogs/9.txt:
--------------------------------------------------------------------------------
1 | * Changed the initial screen to dark mode.
2 | * The login screen things are now better aligned.
3 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/full_description.txt:
--------------------------------------------------------------------------------
1 | This is an Android client for BookWyrm – a federated social network for tracking your reading, talking about books, writing reviews, and discovering what to read next. It is just BookWyrm put into a webview element, nothing special – but it adds some convenience on top:
2 |
3 | * bookwyrm links can be made to open with the app (e.g. clicking on the link to someone's userprofile will open that from your own bookwyrm instance)
4 | * thanks to that, you can immediately follow them easily if you want.
5 | * it lets you easily return to your own home timeline when viewing something like posts, on another bookwyrm instance, because the 'back' button is then modified for that.
6 | * You can also search for books by scanning the ISBN, no matter what instance of Bookwyrm you use.
7 |
8 | This application is not an official client! (An official client does not exist yet, as far as I know)
9 |
10 | The ISBN scanning feature is created with the zxing-android-embedded library.
11 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/icon.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/short_description.txt:
--------------------------------------------------------------------------------
1 | A BookWyrm client for Android.
2 |
--------------------------------------------------------------------------------
/fastlane/metadata/android/en-US/title.txt:
--------------------------------------------------------------------------------
1 | BookWyrm
2 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # Enables namespacing of each library's R class so that its R class includes only the
15 | # resources declared in the library itself and none from the library's dependencies,
16 | # thereby reducing the size of the R class for that library
17 | android.nonTransitiveRClass=true
18 |
19 | android.useAndroidX=true
20 | android.enableJetifier=true
21 | android.defaults.buildfeatures.buildconfig=true
22 | android.nonFinalResIds=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrivacyDragon/Bookwyrm_Android/df65414f25fe76ae6e4298e2dd0f01ce8bbd99f0/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Feb 14 18:09:26 CET 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | gradlePluginPortal()
4 | google()
5 | mavenCentral()
6 | }
7 | }
8 | dependencyResolutionManagement {
9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
10 | repositories {
11 | google()
12 | mavenCentral()
13 | //maven { url 'https://jitpack.io' }
14 | }
15 | }
16 |
17 | rootProject.name = "Bookwyrm"
18 | include ':app'
--------------------------------------------------------------------------------