1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2025-09-09 18:29:47 +02:00

Compare commits

...

464 commits

Author SHA1 Message Date
Gregor Santner
774c5bec59 Merge dandelion news and FAQ content all into markdown files in the dandelion repository 2023-02-11 03:07:41 +01:00
Gregor Santner
c65aab3840 Update translations, project info 2023-01-28 17:21:07 +01:00
Gregor Santner
c2bea7bec0 Crowdin add Estonian, Update translations (PR #297) 2022-12-08 14:16:52 +01:00
Gregor Santner
36bd1af0b9 Translations: Add bulgarian 2022-07-13 01:51:31 +02:00
Gregor Santner
67b0bbbfd2
Update translations (PR #294) 2022-05-28 19:03:18 +00:00
Gregor Santner
b80cc3ab04 Add croatian & thai language to translation system 2022-05-28 20:55:42 +02:00
Gregor Santner
37f586912f
Change link to domain podupti.me -> diaspora.fediverse.observer, closes #295, by @gsantner 2021-10-09 20:17:11 +02:00
Gregor Santner
de378b8adc Add language Odia/Oriya (India), Update translations (#293) 2021-10-02 13:04:29 +02:00
Gregor Santner
8161353de7
New Crowdin updates (#292) 2021-09-09 22:46:37 +02:00
Gregor Santner
c42b4995b3 Update crowdin config 2021-09-09 22:43:58 +02:00
Gregor Santner
5a5d1d66b3 Update CHANGELOG 2021-08-01 14:31:44 +02:00
Gregor Santner
ceb0002546 Update translations (PR #286) 2021-08-01 14:12:24 +02:00
James Addison
0cf003ea38
Update README screenshot references (PR #291) 2021-08-01 13:38:59 +02:00
Gregor Santner
904f2af20a
Update gs/opoc utilities 2021-08-01 13:30:21 +02:00
Gregor Santner
d923630b42
Update README badges, remove IRC 2021-05-19 20:48:50 +02:00
Gregor Santner
a76a463cd4
Add language Esperanto, by @gsantner 2021-03-13 14:25:09 +01:00
Gregor Santner
c9c10a6fd4
Add language Sinhala (Sri Lanka) 2021-02-28 22:09:03 +01:00
Gregor Santner
e5866ffb2b
Update opoc 2021-01-18 21:32:50 +01:00
Gregor Santner
97d9bf434e
Various additions & improvements to opoc utils 2021-01-12 20:23:10 +01:00
Gregor Santner
f1464b5f8f
ci add comment for cleanup as github has no delete-all button 2020-12-23 14:45:38 +01:00
Gregor Santner
369abf14a5
CI/CD: Remove special junit/lint jobs 2020-12-22 03:39:33 +01:00
Gregor Santner
ceb98c4258
gh actions pull_request action 2020-12-21 23:50:58 +01:00
Gregor Santner
4ebd393250
Update v1.3.5 (translations/libs only) 2020-12-09 12:08:05 +01:00
Gregor Santner
f3b3c6a160
disable AndroidSupportMeWrapper 2020-12-09 11:59:36 +01:00
Gregor Santner
ff62aa5a07 Add Makefile; CI: Remove Circle/Travis, add GitHub Actions 2020-12-09 01:07:24 +01:00
Gregor Santner
6fbd399a4b
Update gsantner/opoc libs/utils 2020-12-09 00:57:31 +01:00
Gregor Santner
fa7e37ccba
Remove Travis CI - Open Source love is gone 2020-12-08 08:41:38 +01:00
Gregor Santner
20d75acd39
New Crowdin updates (#276) 2020-12-05 22:08:40 +01:00
Gregor Santner
7b1897b2e0 crowdin: Add macedonian 2020-11-13 21:56:27 +01:00
Gregor Santner
93aadae64b
[ci skip] Crowdin translation bot: New translations for Swedish (#272) 2020-09-24 23:18:12 +02:00
Gregor Santner
a7dd4a6166
New Crowdin translations (#267) 2020-05-29 21:27:09 +00:00
Gregor Santner
cf1f0100ba
Update crowdin bot commit message template 2020-05-29 23:22:35 +02:00
Gregor Santner
875f613cd9
Update supportme link to https 2020-04-20 02:01:40 +02:00
Gregor Santner
ea1ee6bc40 Update opoc 2020-03-29 19:53:32 +02:00
Gregor Santner
a66d7bf3b2 New Crowdin translations (#264) 2020-03-29 19:33:19 +02:00
Gregor Santner
c5849d7d6a Release v1.3.4 2020-02-09 13:12:59 +01:00
Gregor Santner
cc16b84011 Add seconds to 'save picture' date format, closes #262 2020-02-09 13:12:07 +01:00
Gregor Santner
0f6b1c3ec3
Update opoc 2020-02-09 12:49:26 +01:00
Gregor Santner
a686fea141 Bump junit from 4.12 to 4.13 (#261); New Crowdin translations (#260, #263) 2020-02-09 12:46:29 +01:00
Gregor Santner
f9951f3b16 Release v1.3.3 2019-12-23 21:21:10 +01:00
Gregor Santner
073a688db9
New Crowdin translations (#259) 2019-12-23 20:18:54 +00:00
Gregor Santner
1f3cde9326
Add albanian / Tamil 2019-12-23 21:11:39 +01:00
Gregor Santner
8326c2196c
Update tools 2019-12-06 22:02:24 +01:00
Gregor Santner
7361d4bc3f
Update opoc
Update shared helper utilities of my projects to latest state
2019-11-20 00:34:10 +01:00
Gregor Santner
1948c28cff
Crowdin: Update language mapping 2019-11-04 14:18:40 +01:00
Gregor Santner
d1be7f5215 Bump gradle from 3.5.0 to 3.5.1 (#254) 2019-10-04 01:38:43 +02:00
Gregor Santner
8d019b6c3b
New Crowdin translations (#253) 2019-09-22 13:55:33 +00:00
Gregor Santner
0708fcb02b
Update list of languages for crowdin 2019-09-22 13:35:33 +02:00
Gregor Santner
c5e3a42005
Update opoc 2019-09-07 21:54:08 +02:00
Gregor Santner
8c3c7da2ab
Release v1.3.2 2019-08-25 14:19:19 +02:00
Gregor Santner
3bc6afad03
Fix getDateOfDaysAgo 2019-08-25 14:07:07 +02:00
Gregor Santner
194fbf6927 Rename test flavor to atest (so it's default dev flavor when starting android studio) 2019-08-24 14:54:25 +02:00
dependabot-preview[bot]
6d45620181 Bump gradle from 3.4.2 to 3.5.0 (#250) 2019-08-21 12:22:56 +00:00
Gregor Santner
c9d3693515
New Crowdin translations (#245) 2019-07-26 01:28:14 +00:00
Gregor Santner
a618da97d8
Update opoc 2019-07-26 03:19:28 +02:00
imgbot[bot]
3ec8ab89c6 [ImgBot] Optimize images (#247)
*Total -- 1,011.84kb -> 914.41kb (9.63%)

/app/src/flavorTest/res/drawable-ldpi/ic_launcher.png -- 1.50kb -> 1.24kb (17.35%)
/app/src/main/res/drawable-ldpi/ic_launcher.png -- 1.67kb -> 1.40kb (16.03%)
/metadata/en-US/promoGraphic.png -- 3.58kb -> 3.04kb (15.17%)
/app/src/flavorDandelior/ic_launcher-web.png -- 29.94kb -> 26.33kb (12.05%)
/metadata/en-US/featureGraphic.png -- 861.38kb -> 773.90kb (10.16%)
/app/src/flavorDandelior/res/drawable-xhdpi/ic_launcher.png -- 9.28kb -> 8.74kb (5.83%)
/app/src/flavorDandelior/res/drawable-xhdpi/ic_launcher_round.png -- 9.28kb -> 8.74kb (5.83%)
/app/src/flavorDandelior/res/drawable-hdpi/ic_launcher_round.png -- 8.01kb -> 7.58kb (5.36%)
/app/src/flavorDandelior/res/drawable-hdpi/ic_launcher.png -- 8.01kb -> 7.58kb (5.36%)
/app/src/flavorDandelior/res/drawable-xxhdpi/ic_launcher_round.png -- 11.90kb -> 11.28kb (5.19%)
/app/src/flavorDandelior/res/drawable-xxhdpi/ic_launcher.png -- 11.90kb -> 11.28kb (5.19%)
/app/src/flavorDandelior/res/drawable-xxxhdpi/ic_launcher_round.png -- 14.72kb -> 14.08kb (4.31%)
/app/src/flavorDandelior/res/drawable-xxxhdpi/ic_launcher.png -- 14.72kb -> 14.08kb (4.31%)
/app/src/flavorDandelior/res/drawable-mdpi/ic_launcher_round.png -- 6.80kb -> 6.58kb (3.33%)
/app/src/flavorDandelior/res/drawable-mdpi/ic_launcher.png -- 6.80kb -> 6.58kb (3.33%)
/app/src/flavorDandelior/res/drawable-ldpi/ic_launcher_round.png -- 6.17kb -> 5.99kb (2.96%)
/app/src/flavorDandelior/res/drawable-ldpi/ic_launcher.png -- 6.17kb -> 5.99kb (2.96%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2019-07-26 00:35:39 +00:00
Gregor Santner
938a54fc74
Release v1.3.1 2019-04-26 00:55:53 +02:00
Gregor Santner
0732fe1b91
New Crowdin translations (#243) 2019-04-25 22:53:54 +00:00
Gregor Santner
a7054d3ff8 Update metadata 2019-04-21 15:57:49 +02:00
25020c1692
Merge pull request #240 from vanitasvitae/de_metadata
German translation of metadata
2019-03-11 15:51:39 +01:00
b1fb5d646a
German translation of metadata 2019-03-11 14:10:35 +01:00
Gregor Santner
51c3f68f22 Release v1.3.0 2019-03-08 14:49:29 +01:00
Gregor Santner
a80f6ebb45 New Crowdin translations (#238) 2019-03-08 14:45:02 +01:00
Gregor Santner
49c6a97ce7 Add AndroidSupportMeWrapper 2019-03-08 12:32:10 +01:00
Gregor Santner
4f44d1acd3
New Crowdin translations (#231) 2019-02-07 09:38:41 +00:00
Gregor Santner
24571f6921
Auto reformat code 2019-02-07 10:31:18 +01:00
massimilianoLe
fb8eb60974 pullRefresh as option + Shortcut to settings @themesettings (#226)
* pull to refresh page

* Make youtube links open external

* corrected a bit but still not able to check if app is installed

* corrected triggersync

* Added option For user to choose how to open youtube links

* removed unecessary comment

* update with dandelion

* pull refresh option+shortcut to themes

* Changes request applyed

* added name in contributors list
2019-02-07 09:25:06 +00:00
Gregor Santner
b833311353 Release v1.2.5 2019-01-11 02:43:53 +01:00
Gregor Santner
6f310985d6 Update gradle tooling & gsantner-opoc 2019-01-11 02:38:30 +01:00
Gregor Santner
6d62c70359
New Crowdin translations (#224) 2019-01-11 00:16:10 +00:00
Gregor Santner
d34cbe1ed1
Remove/move serbian 2019-01-11 01:11:05 +01:00
Gregor Santner
66cbf9a47d update crowdin yaml 2019-01-11 00:56:13 +01:00
Gregor Santner
b1d5e980c2
New Crowdin translations (#221) 2019-01-10 23:31:30 +00:00
massimilianoLe
f693418d64 Make youtube links open external, by @massimilianoLe (#220) 2018-12-01 17:12:04 +01:00
Gregor Santner
04e89e516c
New Crowdin translations (#218) 2018-11-23 10:31:00 +01:00
massimilianoLe
5854075080 pull to refresh page (#219) 2018-11-23 10:28:37 +01:00
Gregor Santner
1f8babd708 Release v1.2.3 2018-11-12 01:33:36 +01:00
Gregor Santner
2618bdf5ad
New Crowdin translations (#214) 2018-11-12 01:25:36 +01:00
Gregor Santner
19884c33c1
New Crowdin translations (#212) 2018-10-09 20:57:57 +02:00
Gregor Santner
2289c04f0f Update opoc and it's license headers 2018-10-01 21:12:17 +02:00
Gregor Santner
1129f1848a
New Crowdin translations (#210) 2018-09-27 11:17:17 +02:00
Gregor Santner
c77fd1db01
add more language remappings for crowdin 2018-09-27 11:13:25 +02:00
Gregor Santner
b072111b8b
add more language remappings for crowdin 2018-09-27 10:58:04 +02:00
Gregor Santner
351b2d6447
Mark only strings.xml as translatable on crowdin 2018-09-27 10:49:31 +02:00
Gregor Santner
ddc2549c66 Update Crowdin configuration file 2018-09-25 17:55:04 +02:00
Gregor Santner
c1d34fc5db
Merge pull request #204 from muhaaliss/stringlate-tr-9470
Updated tr (Turkish) translation, by @muhaaliss
2018-09-16 09:32:10 +02:00
Muha Aliss
33db3656fa Updated tr (Turkish) translation
Commit made via Stringlate
2018-09-16 03:17:33 +03:00
Gregor Santner
e194d2159e
Add @vanitasvitae 's unfinished image-viewer patch (deleted all test/demo branches for cleanup 2018-09-05 17:00:04 +02:00
Gregor Santner
e66c72d255 release v1.2.2 2018-09-04 20:00:55 +02:00
Gregor Santner
4cd88400ee Rework string ids to tell content 2018-09-04 19:16:51 +02:00
Gregor Santner
48a00b099e
. 2018-09-04 17:02:34 +02:00
Gregor Santner
e6b2fa606e
Merge pull request #201 from asereze/patch-1
Updated sc (Sardinian) translation xml file
2018-08-07 23:59:30 +02:00
asereze
0b66ef801f
Updated sc (Sardinian) translation xml file
I hope it's ok now.
2018-08-07 23:43:07 +02:00
Gregor Santner
e1ea19f02a Release v1.2.1 2018-08-06 23:36:04 +02:00
Gregor Santner
af9e3ad8a3
Update metadata 2018-07-30 21:40:30 +02:00
Gregor Santner
d76fe4b82b
Update metadata 2018-07-30 13:32:34 +02:00
Gregor Santner
dc07beafc3
Merge pull request #199 from xmgz/master
galician (gl) strings.xml updated, by @xmgz (#199)
2018-07-29 11:55:29 +02:00
Xosé M
423970ce39 faltaban 3 cadeas 2018-07-29 10:30:51 +02:00
Xosé M
215f67308e eliminar string preferences e about 2018-07-29 09:54:34 +02:00
Xosé M
376449486b minor gl fixes 2018-07-29 09:50:16 +02:00
Gregor Santner
1e15374229 Release v1.2.0 2018-07-25 03:30:28 +02:00
Gregor Santner
dbbd3cef35 Use searchable dialog for tag and aspect/contact list
* Remove seperate fragments for both cases
* Make use of opoc/SearchOrCustomTextDialog
* Basically also removes all fragment swaps
  * Only two fragments are stream and podselection
  * Pod logout restarts app
  * Thus long known Android Supportlib bug can't occur

* Fixes #198
2018-07-25 01:59:25 +02:00
Gregor Santner
918adcf358 Add flavor dandelior*, move flavor specific to folder instead gradle generated 2018-07-22 14:03:29 +02:00
Gregor Santner
957573ea83 Update opoc 2018-05-21 14:57:41 +02:00
Gregor Santner
65ba10712f Update paths 2018-05-13 12:08:27 +02:00
Gregor Santner
099eb9ca78
Update supportlib 2018-05-09 03:25:23 +02:00
Gregor Santner
ad3966dd85
Merge string resources to one file, propagte change to all translations 2018-05-09 03:23:12 +02:00
Gregor Santner
9a6798f9f4
Update french translation, by @arnaud-jacquemin, (closes #196) 2018-05-09 03:00:33 +02:00
Gregor Santner
2cc74ea613
Release v1.1.3 2018-04-08 22:10:53 +02:00
Gregor Santner
cebf0f473b
Fix podselection custom button color 2018-04-08 22:08:21 +02:00
Gregor Santner
9da1a910b3
Add existingconnection to opoc:networkutils:performCall 2018-04-08 20:12:51 +02:00
Gregor Santner
38cf36b46c Improve sharing *a lot* +GIF - add support for multiple filetypes
* now supporting GIFs too ;)
* Create connection over netcipher
2018-04-08 19:11:12 +02:00
Gregor Santner
68be2f3a4a
Load README when ow pod URL gets called and no pod selected , fixes #193 2018-04-08 18:05:56 +02:00
Gregor Santner
51093e0c3d
Rework screenshot saving and sharing; add new share options:
* Share option: Launcher shortcut (fixes #170)
* Share option: Copy link of current page to clipboard
* Share otpion: Export as PDF / print
2018-04-08 17:52:04 +02:00
Gregor Santner
d53128e5cb
Merge license and changelog dialog on first start 2018-04-08 09:01:52 +02:00
Gregor Santner
82ccc54436
Add FF Klar to custom tabs list 2018-04-08 08:44:00 +02:00
Gregor Santner
f6ab146fd7
Update github templates 2018-04-03 23:23:16 +02:00
Gregor Santner
80f8f10bf9 Release v1.1.2 2018-03-30 03:03:19 +02:00
Gregor Santner
dcc8728171 Update changelog
* fixes #180
2018-03-30 02:52:20 +02:00
Gregor Santner
b48dc5dcac
Fix loading non-pod links outside customtab/external browser 2018-03-30 02:46:44 +02:00
Gregor Santner
618f3eaaba
Fix webview-js dialog not dismissing correctly 2018-03-30 01:41:43 +02:00
Gregor Santner
08242760bb
Migrate to opoc/basefragment; Fix redundant casts 2018-03-30 00:38:31 +02:00
Gregor Santner
a88dc5d13c
. 2018-03-30 00:24:52 +02:00
Gregor Santner
586875e32b
Update gsantner-opoc to latest state 2018-03-30 00:14:54 +02:00
Gregor Santner
43a2ad25bc Update opoc license headers 2018-03-12 00:05:53 +01:00
Gregor Santner
6cac47763c
Release v1.1.1 2018-03-05 23:45:10 +01:00
Gregor Santner
5921549a9c Fix secondlion BuildConfig, githash 2018-03-05 23:37:24 +01:00
Gregor Santner
07acb6bd02 Redo icon as adaptive icon 2018-03-05 14:23:51 +01:00
Gregor Santner
dd0432f718 Update to latest opoc version
* Move various clases
* Especially improve language preference, backported from compat lib
2018-03-02 15:56:14 +01:00
x m l p
1bb061b563 Update galician translation, by @xmgz (#189) 2018-02-22 22:42:50 +01:00
XoseM
d8d74de22b actualizando o galego 2018-02-21 12:36:28 +01:00
XoseM
8df13fe283 Merge branch 'master' of https://github.com/xmgz/dandelion
pideumo o git
2018-02-21 12:32:21 +01:00
XoseM
724a0dbc9c actualizando a gl-translation 2018-02-21 12:31:45 +01:00
XoseM
1f873e2057 fixed strings from gl-tranlation branch 2018-02-21 12:14:48 +01:00
x m l p
ea66b57979
Update .gitignore 2018-02-21 12:02:03 +01:00
XoseM
cbb98f7c60 editando desde gl-translation 2018-02-21 11:51:25 +01:00
XoseM
ed511bec01 update using git help from gsantner 2018-02-21 11:45:02 +01:00
Xosé M
204429b8d5 engadido cómo traducir 2018-02-21 08:31:04 +01:00
Xosé M
120c48f702 actualizando segundo contexto 2018-02-21 08:02:47 +01:00
Gregor Santner
e4992870fe
Release v1.1.0 2018-02-07 00:17:24 +01:00
Gregor Santner
be4309ecd6
Replace shortcut's icons with vectors 2018-02-07 00:13:42 +01:00
Gregor Santner
a07bc144d8
Remove line breaks from fdroid metadata 2018-02-06 23:21:10 +01:00
Gregor Santner
3442f018e9
Update buildscript 2018-02-06 23:11:18 +01:00
8aec1aa74f Update podlink dorf-post.de (fix #181) (#184) 2018-01-15 22:52:04 +01:00
Gaukler Faun
a3cb818db4 implemented app shortcuts, template svg-file for shortcut icons (#183) 2018-01-07 16:03:02 +01:00
Xosé M. Lamas
15240fca49 pequenos erros tipográficos 2017-11-30 08:37:16 +01:00
Xose M
32a74e293a 1a modificacion en github (#179) 2017-11-28 10:15:54 +01:00
XoseM
b1c2219b4d 1ª modificación en github 2017-11-28 09:47:44 +01:00
Gregor Santner
7215cbd7e6
Update sc localization
* Closes #177
2017-11-24 00:55:43 +01:00
Gregor Santner
06119a52cd
Update github templates 2017-11-24 00:21:56 +01:00
Daria Szatan
755adb2ad9 Polish translation (#176)
Polish translation
2017-11-23 18:07:50 +01:00
Gregor Santner
1a99d53c5d
Last crowdin translation update 2017-11-22 21:02:12 +01:00
Gregor Santner
28dac50d84
Update and improve buildscript 2017-11-18 20:04:59 +01:00
Aditya Mehta
255c6d650e replaced traditional file sharing with FileProvider (#174)
replaced traditional file sharing with FileProvider (fixes #173)
2017-11-01 05:23:19 +01:00
Gregor Santner
8ac5c2dee9 Update translations 2017-10-31 18:12:02 +01:00
Gregor Santner
0393bf274f
Fix lint warnings in opoc ; update langprefs; more power for contextutils 2017-10-31 14:18:52 +01:00
Gregor Santner
d1c4e68df3
Release v1.0.8 2017-10-29 19:39:37 +01:00
Gregor Santner
08c450fc99
Update readme 2017-10-29 19:35:35 +01:00
Gregor Santner
ae226c9e16
Add metadata again 2017-10-29 18:05:49 +01:00
Gregor Santner
086f056216 Modify toolbar item positions 2017-10-29 17:26:13 +01:00
Gregor Santner
d1d2d7b4d1 Fix drawable lint issues 2017-10-29 15:33:59 +01:00
Gregor Santner
a96e91aefb
Top toolbar with overflow icons and light/dark theme 2017-10-29 14:47:00 +01:00
Gregor Santner
aaa2445bef
Merge extended notifications menu into main menu 2017-10-29 11:07:52 +01:00
Gregor Santner
cb811d8236 Update Gradle to 3.0/4.1 ; SDK 27 2017-10-29 11:01:27 +01:00
Gregor Santner
496faa7945
Release v1.0.7 2017-10-28 09:56:33 +02:00
Gregor Santner
34882ba69f
Remove metadata...again 2017-10-28 09:56:05 +02:00
Gregor Santner
ac8b8469b0
kabyle_init 2017-09-26 18:13:57 +02:00
Gregor Santner
e767e514f7
Release v1.0.6 2017-09-23 20:33:53 +02:00
Gregor Santner
bf6bdbd821 Re add metadata module 2017-09-23 20:33:28 +02:00
Gregor Santner
fe4d646c47
Release v1.0.5 2017-09-19 15:21:37 +02:00
Gregor Santner
19161ca3e4 Update LangPref ; Remove metadata 2017-09-19 15:19:00 +02:00
Gregor Santner
9767363a7e Update screenshots in readme 2017-09-17 22:07:39 +02:00
Gregor Santner
184de1931e
Make use of opoc/LanguagePreference (fixes #169) 2017-09-15 19:56:10 +02:00
Gregor Santner
4ba1b8671d Release v1.0.4 2017-09-11 21:19:30 +02:00
Gregor Santner
6a0b30dd7b Add F-Droid metadata ( fixes #161 ) 2017-09-11 20:53:09 +02:00
Gregor Santner
58d07f9c6c
Fix profile link 2017-09-11 20:32:40 +02:00
Gregor Santner
b4608794ab Hide statusbar option for mainacitvity 2017-09-11 18:48:58 +02:00
Gregor Santner
76f33a45ba
Move sardinian 2017-09-11 18:04:22 +02:00
Gregor Santner
eb28ca3f43 Merge branch 'master' of github.com:diaspora-for-android/dandelion 2017-09-09 17:09:14 +02:00
Gregor Santner
15a34a1895
Change package ID of gsantner/opoc 2017-09-09 17:09:04 +02:00
Gregor Santner
548ff25396
Add sardinian 2017-09-08 07:31:21 +02:00
Gregor Santner
b3129e0e91
l10n update 2017-08-29 14:45:54 +02:00
Gregor Santner
05d6efd107
Include String key as parameter in AppSettingsBase 2017-08-29 14:44:43 +02:00
Gregor Santner
e9fa2082d9 Update Readme 2017-08-24 13:34:32 +02:00
Gregor Santner
ea7ceacc12
add metadata 2017-08-15 18:36:39 +02:00
Gregor Santner
23142488c2
Release v1.0.3 2017-08-13 23:05:40 +02:00
Gregor Santner
eb0e2b0997
Improve badge and podselection colors ; Update podlist 2017-08-13 23:02:04 +02:00
Gregor Santner
c988fc3bdd
Lower butterknife version to not pull in more recent appcompat 2017-08-12 22:34:15 +02:00
Gregor Santner
92bd98ea28
Update opoc 2017-08-09 17:23:19 +02:00
Gregor Santner
bdd502174d Update README.md
IRC Channel link badge
2017-08-08 14:02:20 +02:00
Gregor Santner
b07941be75
Release v1.0.2 2017-08-05 14:01:31 +02:00
Gregor Santner
e54dbedec8
Revert: Update android sdk to api 26... Upstream bug still not fixed 2017-08-05 14:00:55 +02:00
Gregor Santner
8a934b4a68
Lower gradle version so F-Droid can build it
==== detail begin ====
Available gradle versions: 4.0 3.5 3.4.1 3.4 3.3 3.2.1 3.2 3.1 3.0 2.14.1 2.14 2.13 2.12 2.11 2.10 2.9 2.8 2.7 2.6 2.5 2.4 2.3 2.2.1 2.2 2.1 1.12 1.11 1.10 1.9 1.8 1.7 1.6 1.4
Found 4.0.2 via distributionUrl
/opt/gradle/bin/gradle: line 9: /opt/gradle/versions/4.0.2/bin/gradle: No such file or directory
==== detail end ====
2017-08-05 12:26:04 +02:00
Gregor Santner
acb27766a8
Update android sdk to api 26 2017-08-04 05:42:43 +02:00
Gregor Santner
a5a307c076
Update translations and contributors 2017-07-30 15:40:27 +02:00
Gregor Santner
96daa8789a
Release v1.0.1 2017-07-30 12:36:47 +02:00
Gregor Santner
8324fe52ec
Move untranslatable strings 2017-07-29 21:20:39 +02:00
Gregor Santner
99e369088a
Update SimpleMarkdownParser 2017-07-29 04:44:28 +02:00
Gregor Santner
0e7ff63c9a Update AppSettings.java 2017-06-18 22:24:53 +02:00
Gregor Santner
4f43c56cf9
Release v1.0.0 2017-06-14 16:32:19 +02:00
Gregor Santner
bf99845379
Improve shared-by #159 2017-06-10 13:57:33 +02:00
Gregor Santner
6d93db79b8
Improve AMOLED mode 2017-06-10 13:01:57 +02:00
Gregor Santner
2d7d898bfe
- Added AMOLED mode
- Use opoc/AdBlock
- Improve NavDrawer
2017-06-08 02:33:00 +02:00
Gregor Santner
544e86073a
update gradle wrapper 2017-06-01 15:07:55 +02:00
Gregor Santner
756b31a4ea
Use opoc/Helpers 2017-05-29 19:05:37 +02:00
Gregor Santner
b075f020a3
Release v0.2.7 2017-05-26 12:14:33 +02:00
Gregor Santner
87f160f4c4
Some small improvements 2017-05-26 12:13:28 +02:00
Gregor Santner
e443a8ed6f
Use opoc/AppSettingsBase as base of AppSettings 2017-05-20 02:08:04 +02:00
Gregor Santner
1ff93b6959
Release v0.2.6 2017-05-03 23:48:22 +02:00
Gregor Santner
baff1a1d35
Fixed #156 #158 #159
* Added pod spyurk.am
* Added chinese traditional language
* Added NavSlider option: Statistics
* Changed shared-by-notice text
2017-04-15 12:00:52 +02:00
20afd6a2ad
Fix bottom bar hint text background color (Fix #157) 2017-04-10 20:04:03 +02:00
Gregor Santner
ddc0afa65a
Release v0.2.5 2017-04-10 19:50:40 +02:00
Gregor Santner
101c5f5b7d Introduce new markdown parser;
Rework existing md files;
Show changelog/update dialog
2017-03-25 16:45:32 +01:00
Gregor Santner
8d6b09c800 v0.2.4 Release - Custom default icon and color for secondlion ; fixes #155 2017-03-19 23:32:18 +01:00
5379386ecc
Added icons to notification dropdown menu 2017-03-08 10:17:49 +01:00
07bff2d71c
Fixed typo 2017-03-06 21:49:21 +01:00
Gregor Santner
0db1360853 Remove apkname property 2017-03-05 23:11:46 +01:00
Gregor Santner
ac2327d2f2 Fix #151; URL handling; language; dia.so
* Language switcher in settings (#151)
* Handle dia.so links
* Improve security at internal browser decision
2017-03-05 20:51:56 +01:00
Gregor Santner
47184fe878 Update README 2017-03-03 00:04:41 +01:00
a32d871cca
Updated changelog 2017-02-28 10:45:21 +01:00
Gregor Santner
a205f9372d Release v0.2.3 2017-02-24 23:24:00 +01:00
Gregor Santner
4ed9a0169a Update LICENSE & README; Replace leftovers of diasporaForAndroid; 2017-02-24 18:47:14 +01:00
9f39e3ca1c
Make sure Diaspora image folder exists before sharing/downloading images 2017-01-24 13:12:34 +01:00
392b76c53d
Fixed crash after clicking photo upload button twice (#139) 2017-01-24 13:04:26 +01:00
Gregor Santner
8ef2cacc79
Fix some TR's 2017-01-21 16:49:04 +01:00
06574ccbcf Merge pull request #138 from luiscruz/autorefactor-recycle
Android automatic refactor - Recycle
2017-01-06 15:53:48 +01:00
Luis Cruz
0aad48ad49 android automatic refactor recycle 2017-01-04 10:02:18 +00:00
5428113706
Added option to copy images to clipboard. Also caught mysterious classcastexception in settings. 2016-12-30 22:02:32 +01:00
Gregor Santner
98bf2d6a93
New language: Czech - thanks @bezcitu; Search single-line; Update Readme 2016-12-24 15:33:52 +01:00
Gregor Santner
9ecaf6900a
Update travis 2016-12-22 13:23:20 +01:00
Gregor Santner
165626fc6c
Added flavour secondlion* 2016-12-22 04:07:30 +01:00
Gregor Santner
a31a530c7c Release v0.2.2
* Move toggle mobile/desktop to navslider (opt-in)
* Update TR
2016-12-20 12:19:43 +01:00
Gregor Santner
05e6e4d2bd
Reduce messages by broadcast 2016-12-18 16:10:48 +01:00
Gregor Santner
175125996e
Reformat java files 2016-12-18 15:07:23 +01:00
Gregor Santner
4f3eac9977
Allow to jump to last visited page on stream; FIX NullPtr in shared text methods 2016-12-18 15:07:00 +01:00
Gregor Santner
d567b5fbdd
Update strings.xml 2016-12-18 12:31:35 +01:00
Gregor Santner
4519d16af8
Added hungarian language, Update podlist 2016-12-17 00:59:19 +01:00
Gregor Santner
c461ff5b7c
Fixes #117 - Reset NavHeader on change account, reset web profile 2016-12-16 05:24:03 +01:00
Gregor Santner
9e0c6b1741
Fix Rotation, Remove legacy code, Remove PunkBeer Pod
* Fix #92 Rotation
* Fix #111 Legacy
* Remove punkbeer
<https://diasp.org/posts/6449363>
2016-12-16 04:45:53 +01:00
Gregor Santner
19ac40c5b3 Update README.md 2016-12-02 13:07:46 +01:00
Gregor Santner
97543ced06 Announce 0.2.1-next 2016-11-24 00:41:51 +01:00
Gregor Santner
8abb662546 Release - v0.2.1 2016-11-22 19:22:44 +01:00
Gregor Santner
bea1a83f90 Changes for dandelion 2016-11-20 16:43:38 +01:00
3a4f41f758 Merge pull request #125 from Diaspora-for-Android/rotation-option
Added option to control screen rotation (Fix #92)
2016-11-20 15:49:46 +01:00
8ede0ea304
Fixed rotation 2016-11-20 15:49:01 +01:00
6037c0b3eb
Fixed #127 2016-11-13 18:21:33 +01:00
b62f8d32b7
Added option to control screen rotation 2016-11-12 15:36:56 +01:00
dbafcc065c
Fixed duplicate strings and removed unnecessary background colors 2016-11-11 20:37:27 +01:00
be0a37dbc8
Workaround for overlapping fragments. Fixes #116 2016-11-11 20:17:59 +01:00
812c4dabf7 Merge pull request #120 from Diaspora-for-Android/option-topbar-stream
Added back stream loading on topbar click. Made it toggleable in sett…
2016-11-11 20:04:51 +01:00
Gregor Santner
a3060866e9 Update ISSUE_TEMPLATE.md 2016-11-11 12:44:22 +01:00
Gregor Santner
499027a8f1 Revoking last commit 2016-11-10 23:09:22 +01:00
b8476aa107
Do not attempt to load stream when there is no registered account 2016-11-10 14:24:31 +01:00
00e238a028
Added back stream loading on topbar click. Made it toggleable in settings 2016-11-10 14:18:22 +01:00
d6c6920840
Merged translations 2016-11-10 13:30:37 +01:00
c02ededf9f New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
Translated
Translated
New translations
Translated
Translated
New translations
New translations
New translations
Translated
Translated
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
New translations
Approved. Step name: Proofread
New translations
New translations
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Translated
Translated
New translations
New translations
New translations
Translated
New translations
New translations
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
New translations

Translated
Translated
Translated
Translated
Translated
Translated
New translations
Translated
Translated
New translations
New translations
Translated
New translations
Translated
Translated
Translated
Translated
Translated
New translations
Translated
Translated
Approved. Step name: Proofread
Translated
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Translated
Approved. Step name: Proofread
New translations
New translations
New translations
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Translated
New translations
Translated
Approved. Step name: Proofread
New translations
Translated
Approved. Step name: Proofread
New translations
Translated
Translated
Translated
Translated
New translations
Translated
Translated
Translated
Translated
Translated
New translations
New translations
Approved. Step name: Proofread
Translated
New translations
New translations
Translated
Translated
Approved. Step name: Proofread
Approved. Step name: Proofread
Translated
Translated
Translated
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
New translations
Approved. Step name: Proofread
Approved. Step name: Proofread
Approved. Step name: Proofread
Translated
New translations
Translated
Translated
Translated
Approved. Step name: Proofread
Translated
Approved. Step name: Proofread
Translated
New translations
Translated
New translations
Translated
New translations
New translations
Approved. Step name: Proofread
New translations
Translated
Approved. Step name: Proofread
New translations
New translations
Translated
New translations
New translations
Translated
Translated
Approved. Step name: Proofread
Translated
New translations
Translated
New translations
Approved. Step name: Proofread
New translations
New translations
2016-11-10 12:20:52 +01:00
c5b201f456
Fixed string 2016-11-08 22:17:15 +01:00
8b48cf38ce
Fixed translatable string 2016-11-08 21:04:01 +01:00
527912e49b
Fixed a ton of lint issues 2016-11-08 20:41:53 +01:00
72a41a0b8a
Updated Issue Template 2016-11-08 16:32:27 +01:00
d0a541bc34
Replaced setTextColor on Buttons with new ThemeHelper method 2016-11-08 16:21:06 +01:00
1db57bd957 Merge pull request #115 from Diaspora-for-Android/rework-about-again
Reworked AboutFragment
2016-11-08 13:45:21 +01:00
f2ed7069a6 Reworked AboutFragment
Reworked licenseFragment

removed unused old layout

Fixed lint issues

Fixed margin

use onClick and fix string indent
2016-11-08 13:07:38 +01:00
Gregor Santner
7a0ec98ed4 Change default signed APK name 2016-11-07 20:53:16 +01:00
Gregor Santner
ff48cb8982 Announcing 0.2.0-next (again) 2016-11-07 18:07:09 +01:00
Gregor Santner
fff3c7a716 v0.2.0a 2016-11-07 17:41:01 +01:00
bea35292f8
Fixed #113 (well, that was quick n easy) 2016-11-06 20:55:51 +01:00
8e324d8f2b Added reports navdrawer entry and divided visibility options into subcategories as suggested by gsantner
Merge PR #110 from DfA/divide-visibility-options

Reports Navdrawer Item reworked
set context of webview in onAttach method of BrowserFragment

Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android
2016-11-06 20:36:43 +01:00
e6f16fce50
Suppressed unfixable warnings on clearPodSettings and clearAppSettings. 2016-11-06 19:55:45 +01:00
b07a1eba1e
Possible fix for webview crashes 2016-11-06 17:33:22 +01:00
825d9be1e0
Fixed a lint issue and caught potential null pointers in AppLog 2016-11-06 16:45:21 +01:00
73cb775af2
Merged wipe-settings 2016-11-06 16:29:19 +01:00
dd4af48b8e Fixed lint issues (suppressed, where they cant be fixed)
Release 0.2.0 (Updated translation files)

Announcing 0.2.0-next

Added wipe-settings option

Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android

Merge branch 'master' into wipe-settings

Added ThemedAlertDialogBuilder and a corresponding method in ThemeHelper

Merge branch 'master' into wipe-settings

Reworked dialog
2016-11-06 16:23:18 +01:00
76d58cb100
Added ThemedAlertDialogBuilder and a corresponding method in ThemeHelper 2016-11-06 15:48:54 +01:00
58c61a0d05 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-11-06 15:17:50 +01:00
Gregor Santner
f1dc2eb733 Announcing 0.2.0-next 2016-11-06 05:37:53 +01:00
Gregor Santner
e807003d42 Release 0.2.0 (Updated translation files) 2016-11-06 05:33:14 +01:00
d17d89f7f9
Fixed lint issues (suppressed, where they cant be fixed) 2016-11-04 23:28:57 +01:00
Gregor Santner
a151d37a4e start of 0.2.0-next 2016-11-04 10:47:33 +01:00
Gregor Santner
bc925e1a1e Release v0.2.0 2016-11-04 03:08:59 +01:00
Gregor Santner
e95082cefb Download podlist at build time 2016-11-02 17:10:29 +01:00
Gregor Santner
95dbb2cd34 TR 2016-11-01 22:49:35 +01:00
a650994626
Prevent loading stream on toggle split screen (Android 7.0.0) 2016-10-31 22:24:26 +01:00
Gregor Santner
d1f837e5f7 same 2016-10-31 18:37:21 +01:00
Gregor Santner
320360afb3 TR/Pod Update 2016-10-31 17:41:28 +01:00
Gregor Santner
caa7f8c59d Update build.gradle 2016-10-31 07:15:29 +01:00
39b45a03d0 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-10-30 21:04:46 +01:00
fd05370280
Fixed pod displaying pod domain/name in debug fragment and fixed diaspora markdown link 2016-10-30 21:04:08 +01:00
Gregor Santner
67f5b1d5e2 Update ISSUE_TEMPLATE.md 2016-10-29 17:22:12 +02:00
d8a3e029b1
Fixed some strings 2016-10-28 19:25:43 +02:00
c8eb6f598f
Made proxy description more precise and made verbose logging depended from debugging 2016-10-28 19:19:48 +02:00
666950590b
Reference to strings from font size values array 2016-10-28 19:10:23 +02:00
b9c4223a5e
Fixed intellihide not applied in onresume 2016-10-28 12:51:45 +02:00
Gregor Santner
32b747ebb7 Do not publish active6 to json 2016-10-28 02:35:17 +02:00
Gregor Santner
4d1c12a9d9 Merge PR #101 from DfA/settings_icons
Added icons to the settings
2016-10-28 00:37:44 +02:00
f89f21f979 Added icons to the settings
Chaged some icons

Moved Contacts up one in Settings
2016-10-28 00:18:44 +02:00
765a96f48b
Removed unused applogs 2016-10-27 22:46:21 +02:00
30ca937461
Added info Toasts to Proxy preference, that inform the user about required restart and successful preset setting 2016-10-27 21:42:41 +02:00
f08fb9e349 Update CHANGELOG.md 2016-10-27 13:28:20 +02:00
9d245736b3
Moved Martin and Gaukler up in the contributors list due to chronological order 2016-10-27 13:18:27 +02:00
d34c75a647
Fixed #91 in a better way 2016-10-27 12:55:42 +02:00
6e1e473aff
Fixed #91 2016-10-27 12:42:44 +02:00
Gregor Santner
9214155425 Move scroll up action to stream only 2016-10-26 23:43:53 +02:00
Gregor Santner
964b144657 update contributors 2016-10-26 23:07:01 +02:00
bafcfd46d6
Fixed #99 2016-10-26 22:35:57 +02:00
ef43ed2f7f
Fixed crashing when clearing cache before selecting pod (Fix #90) 2016-10-26 21:53:27 +02:00
Gregor Santner
4e91d101aa Update NL lanugage 2016-10-26 16:31:21 +02:00
Gregor Santner
b7ca97208a BIG REFACTORING - 0.1.6-next edition 2016-10-26 16:23:14 +02:00
Gregor Santner
e239f519e4 Merge PR #98 from Diaspora-for-Android/94_Rework_tags_fragment
Rework tags & aspects fragment
 ThemedFragment for Aspects & tagst, fixes #94 #81
2016-10-26 14:33:31 +02:00
Gregor Santner
2b0a5cd876 ThemedFragment for Aspects & tagst, fixes #94 #81 2016-10-26 14:33:05 +02:00
Gregor Santner
23e1ddc8cf #91 2016-10-26 00:00:44 +02:00
Gregor Santner
80d3d3265e Update TR 2016-10-25 23:20:12 +02:00
Gregor Santner
1cf21f057f Fixes #95 2016-10-25 23:04:16 +02:00
532b80ea84
Added ThemedVisibilityPreference and set it in NavSlider Preference Screen 2016-10-25 21:29:16 +02:00
c0f4fcd62f
Added section for in-app debug log to ISSUE_TEMPLATE 2016-10-25 18:29:10 +02:00
97d075e210
Added navslider entry contacts 2016-10-25 17:56:35 +02:00
03166de709
Moved WebView related method calls to UiThread 2016-10-25 17:37:22 +02:00
84d02a38f9 Merge pull request #89 from Diaspora-for-Android/ThemedSettingsSimple
[WIP] ThemedSettings (the easy way)
2016-10-25 17:05:27 +02:00
b9221099c2 SQUASH
Rewrote ThemedSettings by inheriting Preference classes

Fixed issues pointed out by gsantner

Added back circle color picker preview to Settings and reflect color changes immediatelly :D

Removed some debug messages and unified usage of Themeable
2016-10-25 17:04:32 +02:00
6ad634cc5b
made getAppSettings more safe 2016-10-23 00:21:17 +02:00
6cc651bfcc
Themed PodSelectionDialog 2016-10-22 23:30:22 +02:00
Gregor Santner
6e7ae16e33 #85 2016-10-22 20:10:48 +02:00
Gregor Santner
bff4ab2e97 Merge pull request #88 from Diaspora-for-Android/podselection_proxy_dialog
Show Tor preset in Pod selection
2016-10-22 19:56:59 +02:00
Gregor Santner
866672eb47 Show Tor preset in Pod selection
; Themed BadgeDrawable
; Update TR, Pods
; Show Stream option after login
2016-10-22 19:21:26 +02:00
Gregor Santner
2f5aa1e0e7 backward compatibility - proxy 2016-10-22 16:01:45 +02:00
3e7c843d7b
Update gradle and fix proxy port bug 2016-10-18 21:15:54 +02:00
6b512ee110 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-10-16 19:46:23 +02:00
Gregor Santner
a0d1992829 TR update 2016-10-15 12:42:15 +02:00
ebc70fdff0
Allow more than one line in the nav_header pod notice 2016-10-15 11:21:51 +02:00
f76207e75b
Switched intellihide toolbars on by default 2016-10-14 13:07:07 +02:00
8e852d7ff2
Added notifications dropdown menu with settings 2016-10-14 12:57:17 +02:00
54ba7b389c Merge branch 'notification_toolbar_item_rework' 2016-10-14 12:37:38 +02:00
6d4bc38ea6
Fixed SettingsActivity crash 2016-10-14 12:33:58 +02:00
0a4be1e502
Fixed typo 2016-10-14 12:23:01 +02:00
Gregor Santner
ec8eec2960 Update german translations 2016-10-14 02:06:18 +02:00
Gregor Santner
eee1f3a84a notification_toolbar_item_rework part 1 2016-10-14 01:44:43 +02:00
Gregor Santner
72189af353 Merge pull request #79 from Diaspora-for-Android/poddy_as_podsource
Use Poddy as podsource
2016-10-14 01:37:28 +02:00
Gregor Santner
71d8b886f6 Code auto reformatting; Update TR, PodList 2016-10-14 01:26:56 +02:00
Gregor Santner
110598ea85 Merge branch 'master' into poddy_as_podsource 2016-10-14 00:44:23 +02:00
Gregor Santner
627c996f89 PR fixes 2016-10-14 00:22:08 +02:00
14b9b6a8f0
Fixed Settings layout issue 2016-10-13 18:18:47 +02:00
26751ff931
Merged proper-themes 2016-10-13 17:51:35 +02:00
c67992fc37 Proxy tor preset
Set windowSoftInputMode to adjustResize, Repair sharing text into app, Repair image sharing on 4.2

Fix view intent

Update TR; Update buildToolsVersion -> 24.0.2

Update ISSUE_TEMPLATE.md
Update README.md

Switch ic_launcher back to png

Replace blowball image on splash with character

Reworked UI using Fragments

Merge branch 'master' into rework_fragments

Update README.md
Fixed top/bottom menu entry population

Added HashtagFragment

Moved WebClients and ChromeClients to webview package

Removed SplashActivity, migrated PodSelectionActivity to PodSelectionFragment

Merge branch 'master' into rework_fragments

Handle Intent.Action.Main in handleIntent()

Update strings-about.xml
Fixed image sharing to other apps

Get title for image sharing dialog from resources instead of using hardcoded string. Also do not show multiple permission dialogs stacked

Removed test Fragments and old SplashActivity related stuff

Merge branch 'master' into rework_fragments

Added some documentation to MainActivity

Fixed clear webview cache. Thanks @di72nn

Only set window title depending on webviews content, when DiasporaStreamFragment is displayed (do not overwrite other fragments title when the webview loads in the background)

Reworked custom themes

Set customtab color

Do not open load the stream when clicked on toolbar

Added note about customtabs and proxys. Fixes #77

Resolved merge conflicts

Removed duplicate method getAppSettings

Fixed default color was id instead of color value bug

Update TR

Some improvements of code quality

Moved colorpicker repo up

Fixed applying of settings

Fixed bug causing ClassCastException

Moved ThemeHelper and ColorPalette to util.theming

Added missing license headers to source files

Merge branch 'master' into proper-themes

Apply nav-slider entry visibilities in onResume

SettingsActivity: Switched to Toolbar and fixed toolbar color issue

Fixed BrowserFragment reloading in onResume and added credits to LeafPic

Added reference to ColorPicker in 3rd party licenses and updated support libraries

Merged master

Fixed applying proxy settings

Merged master proxy changes

Fixed nav slider layout color issue

Proxy tor preset

Reworked custom themes

Set customtab color

Do not open load the stream when clicked on toolbar

Added note about customtabs and proxys. Fixes #77

Resolved merge conflicts

Removed duplicate method getAppSettings

Fixed default color was id instead of color value bug

Update TR

Some improvements of code quality

Moved colorpicker repo up

Fixed applying of settings

Fixed bug causing ClassCastException

Moved ThemeHelper and ColorPalette to util.theming

Added missing license headers to source files

Merge branch 'master' into proper-themes

Apply nav-slider entry visibilities in onResume

SettingsActivity: Switched to Toolbar and fixed toolbar color issue

Fixed BrowserFragment reloading in onResume and added credits to LeafPic

Added reference to ColorPicker in 3rd party licenses and updated support libraries

Merged master

Fixed applying proxy settings

Merged master proxy changes

Fixed nav slider layout color issue

Merge branch 'proper-themes' of github.com:Diaspora-for-Android/diaspora-android into proper-themes
2016-10-13 16:56:31 +02:00
Gregor Santner
3195918dd1 codecov 2016-10-13 01:45:55 +02:00
bc2687b8cb Update CHANGELOG.md 2016-10-10 18:32:05 +02:00
5d4106e0b3
Updated support libs and added more precise breakage notice 2016-10-10 18:13:41 +02:00
f49877b792
Fixed applying proxy settings 2016-10-10 17:47:04 +02:00
c09618f191
Merged master 2016-10-10 15:07:30 +02:00
d940b6c49a
Added missing license headers to source files 2016-10-09 21:04:12 +02:00
Gregor Santner
d9740d7275 Merge branch 'master' into poddy_as_podsource 2016-10-07 14:36:50 +02:00
Gregor Santner
a2508e4df5 Go to login page instead of podpage 2016-10-07 04:29:32 +02:00
Gregor Santner
64a9d02e7c Update podlist 2016-10-07 03:47:59 +02:00
Gregor Santner
c550c2474e Rework app to use new DiasporaPod class 2016-10-07 02:43:12 +02:00
Gregor Santner
3303a48787 Update TR 2016-10-07 02:11:45 +02:00
7391431501
Added note about customtabs and proxys. Fixes #77 2016-10-06 21:44:13 +02:00
ebedfd9fb5
Do not open load the stream when clicked on toolbar 2016-10-06 21:23:24 +02:00
Gregor Santner
654a00d647 PodSelectionFragment 2016-10-06 05:26:54 +02:00
Gregor Santner
50207181f9 Let PodService fetch from DfA; PodSelection rework 2016-10-05 02:30:10 +02:00
vanitasvitae
91c706ed4a Only set window title depending on webviews content, when DiasporaStreamFragment is displayed (do not overwrite other fragments title when the webview loads in the background) 2016-10-03 23:04:09 +02:00
vanitasvitae
c005ef744d Fixed clear webview cache. Thanks @di72nn 2016-10-03 18:28:08 +02:00
vanitasvitae
68d299f894 Added some documentation to MainActivity 2016-10-02 22:22:08 +02:00
vanitasvitae
160ed992df Merge branch 'master' into rework_fragments 2016-10-02 14:15:50 +02:00
vanitasvitae
88e4636e88 Removed test Fragments and old SplashActivity related stuff 2016-10-02 13:36:57 +02:00
vanitasvitae
7ee5e0f39b Get title for image sharing dialog from resources instead of using hardcoded string. Also do not show multiple permission dialogs stacked 2016-10-02 12:55:05 +02:00
vanitasvitae
036457117c Fixed image sharing to other apps 2016-10-02 12:42:12 +02:00
vanitasvitae
2475c66830 Update strings-about.xml 2016-10-01 01:47:16 +02:00
vanitasvitae
d8cbe480ad Handle Intent.Action.Main in handleIntent() 2016-10-01 01:30:58 +02:00
vanitasvitae
e0e8adac19 Merge branch 'master' into rework_fragments 2016-10-01 01:21:19 +02:00
vanitasvitae
94895f78e0 Removed SplashActivity, migrated PodSelectionActivity to PodSelectionFragment 2016-10-01 01:18:42 +02:00
vanitasvitae
e06e2f3ba1 Moved WebClients and ChromeClients to webview package 2016-10-01 00:24:53 +02:00
vanitasvitae
fec93a0660 Added HashtagFragment 2016-09-30 23:15:10 +02:00
vanitasvitae
850f759cde Fixed top/bottom menu entry population 2016-09-29 19:44:42 +02:00
vanitasvitae
1baeac1fe5 Update README.md 2016-09-29 00:24:27 +02:00
vanitasvitae
ae26ecd112 Merge branch 'master' into rework_fragments 2016-09-28 21:48:09 +02:00
vanitasvitae
e4d4305fc1 Reworked UI using Fragments 2016-09-28 21:43:25 +02:00
Gregor Santner
8e9dabe951 Replace blowball image on splash with character 2016-09-27 01:24:07 +02:00
Gregor Santner
4c8602b37d Switch ic_launcher back to png 2016-09-27 01:07:40 +02:00
Gregor Santner
73895c9ddb Update README.md 2016-09-26 23:01:21 +02:00
vanitasvitae
8a94bf5766 Update ISSUE_TEMPLATE.md 2016-09-26 20:53:58 +02:00
Gregor Santner
a04e2051a8 Update TR; Update buildToolsVersion -> 24.0.2 2016-09-26 16:28:17 +02:00
vanitasvitae
2aaddec3a3 Fix view intent 2016-09-22 23:40:35 +02:00
vanitasvitae
5c41c62c85 Set windowSoftInputMode to adjustResize, Repair sharing text into app, Repair image sharing on 4.2 2016-09-22 23:20:13 +02:00
vanitasvitae
a1ca8596b8 forward clicks on bottom toolbar to fragments onOptionsItemSelected 2016-09-22 00:54:32 +02:00
vanitasvitae
179fb3e741 Removed onPause and onResume in oder to fix issue with image upload 2016-09-22 00:40:35 +02:00
vanitasvitae
3eb5b2c867 Moved some code from WebViewFragment to StreamFragment and vice versa 2016-09-22 00:29:32 +02:00
vanitasvitae
bd8b5381ea Prewarm customTabs 2016-09-21 22:49:37 +02:00
vanitasvitae
3d2fce6ac0 Fixed layout issue (webview below topbar 2016-09-21 21:35:03 +02:00
vanitasvitae
b2337b1955 Moved WebView in own fragments. There is still a bug, where the webview cannot be returned for some reason. 2016-09-21 21:15:34 +02:00
Gregor Santner
c94a511ace Proxy tor preset 2016-09-21 15:03:54 +02:00
Gregor Santner
52d6947d3e Refactor layout file names 2016-09-21 12:36:42 +02:00
Gregor Santner
b12e021e99 Update AppSettings.java 2016-09-20 23:55:50 +02:00
vanitasvitae
a086923804 Removed newNotificationSnackbar 2016-09-20 21:44:43 +02:00
vanitasvitae
adff9667af Version bump 2016-09-20 21:26:23 +02:00
Gregor Santner
aab63bfb13 TR Update 2016-09-20 21:08:11 +02:00
vanitasvitae
1f0861c519 Update CHANGELOG.md 2016-09-20 20:57:14 +02:00
vanitasvitae
2996c63981 Fixed a bug where on Lolipop+ one could only append one image to a post 2016-09-20 20:41:25 +02:00
vanitasvitae
4a135e50d6 Removed animation from customTab 2016-09-20 20:09:30 +02:00
vanitasvitae
504f7cd434 Fixed #68 2016-09-20 19:52:42 +02:00
Gregor Santner
ed55459019 Move Logging to own class; Allow disable normal&spam messages 2016-09-19 01:10:29 +02:00
Gregor Santner
67c416f870 Preference option - Chrome Custom Tab 2016-09-18 23:17:18 +02:00
Gregor Santner
ef0e1b792a Merge pull request #67 from Diaspora-for-Android/customTabs
Custom tabs
2016-09-18 20:26:35 +02:00
Gregor Santner
3af1d120d7 Merge branch master into customTabs 2016-09-18 20:15:59 +02:00
Gregor Santner
fb4209b13f bottom toolbar overflow style 2016-09-15 23:08:03 +02:00
Gregor Santner
e2eaa73ba1 #40 new color scheme, Replace png icons with vector drawables 2016-09-15 22:10:43 +02:00
Gregor Santner
0bf2e0aabd Update TR 2016-09-11 19:13:41 +02:00
Gregor Santner
5ba8675c39 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-09-11 17:53:25 +02:00
Gregor Santner
ac19efd847 Accent color orange; Notification/Message count badge; Reworked progressbar #40 2016-09-11 17:15:26 +02:00
vanitasvitae
1261d93a17 Moved TitleUpdateReceiver in own class and added some debug logs 2016-09-11 15:22:16 +02:00
vanitasvitae
dc8349a4e8 Moved BroadcastReceiver for CustomTabs in own class 2016-09-11 14:51:23 +02:00
vanitasvitae
916ee58690 setupUI before applying proxy settings to mitigate nullpointer on WebView 2016-09-11 13:06:13 +02:00
vanitasvitae
40592ffae8 set Animations to CustomTabs 2016-09-11 13:05:26 +02:00
vanitasvitae
ae2cefd6a5 Use customTabs to open external links. This is a very basic implementation 2016-09-11 12:35:16 +02:00
vanitasvitae
0b0b0198df Updated support libraries 2016-09-11 11:57:42 +02:00
vanitasvitae
b8ba6bb443 Added a lot of debug logs to MainActivity 2016-09-10 16:54:48 +02:00
vanitasvitae
f58fbd8364 Fixed crash when opening search dialog 2016-09-10 10:47:29 +02:00
Gregor Santner
1dcd05af10 Update design #40, fixes #65 2016-09-09 20:56:43 +02:00
vanitasvitae
1b06e20c84 Added long click action to Debug Log. User can copy log to clipboard using long click 2016-09-09 19:50:11 +02:00
vanitasvitae
83ea03ab60 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-09-09 19:27:26 +02:00
vanitasvitae
02f56f25fb Cleaned code, added debug log to DebugFragment of AboutActivity 2016-09-09 19:27:07 +02:00
vanitasvitae
d7046a1036 Update CHANGELOG.md 2016-09-08 22:11:19 +02:00
vanitasvitae
2a4706654f Translated about text to german 2016-09-08 14:28:09 +02:00
vanitasvitae
9e0a364bc8 Merge branch 'keepWebView' 2016-09-08 10:19:15 +02:00
vanitasvitae
e6446217a8 Fixed image upload on 4.2 devices 2016-09-07 23:55:25 +02:00
vanitasvitae
7dbfb10229 Added permission check to FileChooser and added missing file choosing method for Android 4.2 WIP WARNING 2016-09-07 23:12:17 +02:00
vanitasvitae
305a40c8c5 Added some experimental changes to keep the webview on orientation changes 2016-09-05 20:42:57 +02:00
Gregor Santner
87363d204a TR update 2016-09-05 20:07:46 +02:00
vanitasvitae
8721f9e45b Update CHANGELOG.md 2016-09-05 18:55:56 +02:00
vanitasvitae
e7f74eb08d Added information about android version and device to AboutActivity 2016-09-05 18:45:22 +02:00
vanitasvitae
05d9edbbdb Added contributors.txt to gitignore 2016-09-05 18:16:18 +02:00
vanitasvitae
823ab7b8d8 AboutActivity respects intellihide settings, all coordinatorlayouts do now snap, added back button to AboutActivity and SettingsActivity 2016-09-05 18:15:29 +02:00
vanitasvitae
315361e2b2 Fixed crowdin issues 2016-09-05 14:23:03 +02:00
Gregor Santner
4ad9828f2c Update CONTRIBUTORS.txt, LICENSE.md, Translations 2016-09-01 19:18:22 +02:00
Gregor Santner
06466b7743 Update and rename CONTRIBUTORS.md to CONTRIBUTORS.txt 2016-08-29 22:16:45 +02:00
Gregor Santner
78b96d9ade Improve navigation drawer, default visibilities 2016-08-28 17:54:35 +02:00
Gregor Santner
40a9823b19 Update Translations 2016-08-27 16:59:28 +02:00
Gregor Santner
c93e28cdc7 Load license, contributors, maintainers and 3party libs from ressources 2016-08-27 16:40:16 +02:00
Gregor Santner
89ee0450e9 Copy & filter repo files into android app resources 2016-08-27 15:17:02 +02:00
vanitasvitae
8ae74d97d4 Reworked search dialog to use layout resource and some code cleanup 2016-08-27 12:34:08 +02:00
vanitasvitae
18eeb76079 Forgot to add HashtagProvider 2016-08-27 09:24:14 +02:00
vanitasvitae
5a6910b447 Added license headers and some documentation to AboutActivity, HtmlTextView, HashtagProvider 2016-08-27 09:23:58 +02:00
vanitasvitae
48f0997864 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-08-27 00:46:54 +02:00
vanitasvitae
240551f34c Made hashtags in textviews clickable. Hashtags open post editor with hashtag inserted. Also cleaned up text sharing in general 2016-08-27 00:04:07 +02:00
Gregor Santner
e3a777a800 Fix new TR errors 2016-08-26 19:35:02 +02:00
vanitasvitae
f26f1539ec Added some more features and information to the AboutActivity 2016-08-26 17:08:57 +02:00
vanitasvitae
c62f38e693 Added lorem ipsum and some more visual tweaks to AboutActivity 2016-08-25 00:23:20 +02:00
vanitasvitae
50f5a79c30 Added changes to Manifest 2016-08-24 22:07:15 +02:00
vanitasvitae
0b8dbcc35d Added first design of an AboutActivity 2016-08-24 22:05:35 +02:00
Gregor Santner
12d12cdd39 TR update 2016-08-23 22:20:06 +02:00
vanitasvitae
f8d8126c0e Removed unused classes and cleaned code up 2016-08-23 21:23:36 +02:00
vanitasvitae
7091b1ba31 Updated NetCipher from 1.2.1 to 2.0.0-alpha1. This fixes #58 2016-08-23 14:36:03 +02:00
vanitasvitae
7c1510a272 Added first design of StatisticsFetchTask (currently not working/needed) 2016-08-23 14:28:34 +02:00
Gregor Santner
75106e2c12 Update strings.xml 2016-08-22 10:00:58 +02:00
vanitasvitae
5bcc99dfba Display app launcher icon instead of nothing when no avatar image set. Fix #55 2016-08-21 17:04:51 +02:00
Gregor Santner
024bba8260 TR update 2016-08-19 19:33:23 +02:00
vanitasvitae
417a695a6b Made description of navigation drawer settings more precise 2016-08-19 14:07:37 +02:00
vanitasvitae
c3006f9fb2 Fix #54 2016-08-19 13:54:03 +02:00
Gregor Santner
7f7116e843 Update README.md 2016-08-19 00:35:24 +02:00
vanitasvitae
68e5a4a081 Merge branch 'master' of github.com:Diaspora-for-Android/diaspora-android 2016-08-16 21:55:45 +02:00
vanitasvitae
03c591c974 Updated gradle 2016-08-16 21:45:17 +02:00
Gregor Santner
38ae98478c update TR 2016-08-16 21:05:36 +02:00
vanitasvitae
2e7c045e71 Update SCREENSHOTS.md
v0.1.5
2016-08-16 14:00:30 +02:00
vanitasvitae
1377bad6b9 Update ISSUE_TEMPLATE.md 2016-08-15 00:16:36 +02:00
vanitasvitae
08b39b16c9 Fixed #51 2016-08-14 18:23:23 +02:00
Gregor Santner
9bb6a383d5 gradle apk name 2016-08-14 12:14:10 +02:00
378 changed files with 28556 additions and 4503 deletions

23
.atomignore Executable file
View file

@ -0,0 +1,23 @@
.git
.github
.gradle
.idea
build
gradle
.gitlab-ci.yml
*.iml
local.properties
settings.gradle
gradlew
gradlew.bat
LICENSE.md
app/build
app/.gitignore
app/pom.xml
app/proguard-rules.pro
.hidden
.travis.yml
circle.yml
CODE_OF_CONDUCT*
gradle.properties
LICENSE*

View file

@ -1,40 +1,24 @@
#### General information #### General information
* **Device:** eg Nexus 5, Samsung Galaxy S6 * **App version:**
* **Android Version:** eg Android 6.0.1 Stock or Android 4.2 CM * **System:**
* **Pod:** eg pod.geraspora.de, self hosted * **Pod:**
* **Diaspora pod version:** eg 0.5.99.0-p9bd2337c (can be found on the bottom)
* **App source:** eg HEAD, F-Droid, PlayStore, self build (latest HEAD)
* **App version:** eg 0.1.1, or commit
#### Description
#### Log
<!-- <!--
I have: Look for already reported issues before posting!
Also take a look at documentation and wiki, or write in the project chat.
- searched open and closed issues for duplicates App version: The version of the app installed and the installation source. Example: v0.3.5 F-Droid
- read <https://github.com/Diaspora-for-Android/diaspora-android/blob/master/CONTRIBUTING.md> Please keep in mind that only the latest downloadable version is supported and that there are no backports to older versions.
- not submitted translations - see [Crowdin](https://crowdin.com/project/diaspora-for-android/invite) System: Information about where the app is running. Give all details you know, but at least the Android OS version.
Example: Android 8.0.1, Nexus 5, LineageOS
Description:
What this is about, what happens and what is expected to happen. What needs to be done for it to happen.
If a crash is happening a log is needed. Screenshots or demonstration videos are always helpful too.
--> -->
#### Steps to reproduce
1. …
2. …
3. …
#### Expected result
What is the expected output? What do you see instead?
Upload screenshots via drag&drop if needed and apply resizing:
`<img width="30%" height="30%" src="https://cloud.githubusercontent.com/assets/67..b55.jpg">`
#### Debug output
Please post the output of adb logcat. The log should begin with the start of Diaspora for Android and include all the steps it takes to reproduce the problem.
````
adb logcat -s com.github.dfa.diaspora_android
````

27
.github/PULL_REQUEST_TEMPLATE vendored Normal file
View file

@ -0,0 +1,27 @@
<!--
Hello, and thanks for contributing!
Please always do auto-reformat on code before creating a PR.
In Android-Studio do a right-click on java->Reformat and check the first two options.
After creating the PR please wait patiently till somebody from the team has time to give a review.
The top-priority requirement for this to get merged is, that building/tests don't fail.
If theres an continious integration system integrated in this project, you should see a colored checkmark in the PR window which tells the status.
## Contributors document
Add yourself! When adding your information to the `CONTRIBUTORS.md` file, please use the following format:
Schema: **[Name](Reference)**<br/>~° Text
Where:
* Name: username, first/lastname
* Reference: E-Mail, Webpage
* Text: Information about / kind of contribution
Example:
* **[Nice Guy](http://niceguy.web)**<br/>~° German localization
-->

View file

@ -0,0 +1,68 @@
##############################################################################################################################
# # Cleanup:
#const sleep = ms => () => new Promise((resolve, reject) => window.setTimeout(resolve, ms));
#Promise.resolve()
#.then(() => { document.getElementsByClassName("details-overlay details-reset position-relative d-inline-block ")[3].children[0].click(); })
#.then(sleep(500))
#.then(() => { document.getElementsByClassName("dropdown-item btn-link menu-item-danger")[0].click(); })
#.then(sleep(1000))
#.then(() => { document.getElementsByClassName("btn btn-block btn-danger")[0].click();});
#
# while [ 1 ] ; do sleep 4; xdotool key Up; sleep 0.1; xdotool key Return; done
##############################################################################################################################
name: "CI"
on: [push, pull_request]
jobs:
build:
if: "!contains(github.event.head_commit.message, 'ci skip') && (!contains(github.event_name, 'pull_request') || (contains(github.event_name, 'pull_request') && github.event.pull_request.head.repo.full_name != github.repository))"
runs-on: ubuntu-latest
steps:
- name: "Checkout: Code"
uses: actions/checkout@v2
- name: "Checkout: Code (PR)"
uses: actions/checkout@v2
if: "contains(github.event_name, 'pull_request')"
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: "Setup: Java"
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: "Cache: Gradle"
uses: actions/cache@v2
with:
path: |
~/.gradle
.gradle
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('gradle/wrapper/gradle-wrapper.*') }}
- name: "Build: Project with make"
run: make clean all
- name: "Build: List dist files"
if: always()
run: find dist -type f -maxdepth 2
- name: "Artifacts: All"
if: always()
uses: actions/upload-artifact@v2.2.1
with:
name: "all"
path: dist
retention-days: 5
- name: "Artifacts: Android APK"
uses: actions/upload-artifact@v2.2.1
with:
name: "android-apk"
path: |
dist/*.apk

116
.gitignore vendored
View file

@ -1,39 +1,76 @@
*~ ##############
### Common ###
*~*
tmp/
*.tmp
*.bak
*.log
# Gradle ################
.gradle/ ### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio
*.iml
/out/
.idea/
# if you remove the above rule, at least ignore the following:
## User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries
## Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml
# Gradle:
# .idea/gradle.xml
# .idea/libraries
## File-based project format:
*.ipr
*.iws
### Gradle ###
.gradle .gradle
build/ build/
/*/build/ dist/
gradle-app.setting
# User-specific configurations # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
local.properties !gradle-wrapper.jar
crowdin.yaml
.idea ###############
.idea/libraries/ ### Eclipse ###
.idea/runConfigurations.xml #.project
.idea/gradle.xml *.pydevproject
.idea/workspace.xml .metadata
.idea/tasks.xml *.swp
.idea/.name *~.nib
.idea/compiler.xml .settings/
.idea/copyright/profiles_settings.xml .loadpath
.idea/encodings.xml .externalToolBuilders/
.idea/misc.xml *.launch
.idea/modules.xml .cproject
.idea/scopes/scope_settings.xml .classpath
.idea/vcs.xml .factorypath
*.iml .buildpath
.target
.texlipse
# OS-specific files ############
.DS_Store ### Java ###
.DS_Store? *.class
._* .mtj.tmp/
.Trashes *.jar
ehthumbs.db *.war
Thumbs.db *.ear
hs_err_pid*
###############
### Android ###
# Built application files # Built application files
*.apk *.apk
*.ap_ *.ap_
@ -41,14 +78,27 @@ Thumbs.db
# Files for the Dalvik VM # Files for the Dalvik VM
*.dex *.dex
# Java class files
*.class
# Generated files # Generated files
bin/ bin/
gen/ gen/
# Local configuration file (sdk path, etc)
local.properties local.properties
# Proguard
proguard/ proguard/
*.log
# Android Studio Stuff
.navigation/ .navigation/
gen-external-apklibs
### Project ##
app/src/main/res/raw/changelog.*
app/src/main/res/raw/license.*
app/src/main/res/raw/readme.*
app/src/main/res/raw/contributors.*
app/flavor*
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

View file

@ -1,4 +1,3 @@
build
crowdin.yaml crowdin.yaml
diaspora-android.iml diaspora-android.iml
gradle gradle

View file

@ -1,32 +0,0 @@
language: android
jdk:
- oraclejdk8
android:
components:
- tools
- tools # TODO https://github.com/travis-ci/travis-ci/issues/6193
- platform-tools
- build-tools-24.0.1
- android-24
- extra-android-m2repository
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
script: "./gradlew $TASK"
env:
- TASK="lintDebug"
- TASK="build check --stacktrace"
branches:
except:
- l10n_master
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/e462044d3105a7bb4b4f
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: never # options: [always|never|change] default: always

View file

@ -1,6 +1,162 @@
# v0.2.0 (WIP) ### Recent changes
- See [Discussions](https://github.com/gsantner/dandelion/discussions), [Issues](https://github.com/gsantner/dandelion/issues) and [Project page](https://github.com/gsantner/dandelion#readme) to see what is going on.
# v0.1.5 ### v1.4.0
- Add seconds to 'save picture' date format
- Updated translations
- Added german F-Droid description translation
- Update to Android SDK 29
### v1.3.0
- Add option to open youtube links external/in YouTube app (optional)
- Pull to refresh
### v1.2.3
**Improved:**
- More supported languages, more complete translations!
### v1.2.1
**App release: dandelior**
- Added an (rebranded) flavor of dandelion: dandelior
- Only differenties in use are other (black) icon and AMOLED colors by default enabled
- Already available on F-Droid
**New features:**
- All new Aspects and Tags, using a searchable dialog
**Fixed:**
- Sometimes the Stream went white, which is due an still (>3 years) unfixed Android Support library bug. It should not occur very often anymore due less use of fragments.
**Improved:**
- Various small tweaks
- Updated translation files
### v1.1.3
- Improve sharing *a lot*, add support for multiple filetypes
- Support for downloading GIFs ;)
- Rework screenshot saving and sharing; add new share options:
- Merge license and changelog dialog on first start
### v1.1.2
- Fix: loading non-pod links outside customtab/external browser
- Fix: webview-js dialog not dismissing correctly
### v1.1.0
- Added: App shortcuts (Android 7+)
- Updated: podlist
- More supported languages
- File sharing fixes
### v1.0.8
- Modified: Navigation - Merge bottom toolbar into top
- Updated: Build for Android O/27
- Updated: Language change preference
- Added: B/W coloring of toolbar popup
### v1.0.5
- Updated: Language preference
### v1.0.4
- Updated: README
- Added: Hide statusbar option
- Fixed: Language list
- Added: Sardinian,Malayalam,Turkish translation
### v1.0.3
- Update opoc
- Better visibility for counter badge
- Refactor DiasporaPod model
- Update PodList (many new pods!)
- Fix CustomTab bug
### v1.0.2 (2017-08-05)
- Improve build script
- Update translation file license
### v1.0.1 (2017-07-30)
- Update SimpleMarkdownParser
- Move untranslatable strings
### v1.0.0 (2017-06-14)
- Added AMOLED mode
- Improve NavDrawer
- Improve Shared by notice
- Use opoc/Helpers,AdBlock
### v0.2.7 (2017-05-26)
- Small improvements
### v0.2.6 (2017-05-03)
- Fixed #156 #158 #159
- Added chinese traditional language
- Added NavSlider option: Statistics
- Changed shared-by-notice text
- Fix bottom bar hint text background color (Fix #157)
- Color improvements
### v0.2.5 (2017-04-10)
- Introduce minimalistic Markdown Parser
- Show LICENSE at first start
- Show CHANGELOG after update
- Convert existing Markup files to Markdown
- Update existing markdown files
- Update AboutActivity to use new Parser
- Added translations: Danish, Korean, Galician
### v0.2.4 (2017-03-19)
- Different icon and color for secondlion
- Language switcher
- Handle dia.so links
- Improve security at internal browser decision
- More icons for notification dropdown
- Update gradle build scripts
- Added CircleCI
### v0.2.3 (2017-02-24)
- Add Czech translation (thanks @bezcitu)
- Add option to copy image urls to clipboard
- Fixed some bugs related to image upload/download
- Published secondlion\* (nighly version of dandelion\*)
### v0.2.2
- Move "toggle mobile/deskop" to nav-slider
- Reduce messages sent via broadcast
- Allow to jump to last visited page on stream
- New language: Hungarian
- FIX NullPtr in shared text methods
- FIX #117 - Reset NavHeader on change account, reset web profile
- FIX #92 Roation settings
- FIX #111 Remove legacy code
### v0.2.1
- App name changed to **dandelion***
- Rotation options
- Top toolbar loads screen again (toggleable in settings)
- Fixed overlapping fragments
- Visual rework of the About-section of the app
### v0.2.0a
- Added: Customizable Theme Colors!
- Improved account setup with easy tor hidden service configuration
- Eye candy for the settings activity
- Added: "Contacts" shortcut in the navigation slider
- Increased the overall performance by using Fragments
- Lots of bugfixes
- Fixes for the bugfixes!
### v0.1.6
- Added: New languages
- Changed: New delicious visual style + launcher icon
- Changed: Notifications-/Messages-indicator does now display number of events!
- Changed: Redesigned Navigation Drawer
- Fixed: Immediately apply preference changes
- Added: About screen that shows useful information
- Changed: Updated NetCipher library to 2.0.0-alpha1
- Fixed: Do not reload stream on orientation changes
- Fixed: Image upload for older devices
- Added: Option to open external links in Chrome CustomTab
### v0.1.5
- Update title depending on what the user is doing - Update title depending on what the user is doing
- New greenish color scheme - New greenish color scheme
- Replaced SwipeToRefresh functionality with refresh button - Replaced SwipeToRefresh functionality with refresh button
@ -15,7 +171,7 @@
- Allow slider customization - Allow slider customization
- Show aspect name after selection - Show aspect name after selection
# v0.1.4 (2016-07-31) ### v0.1.4 (2016-07-31)
- by @vanitasvitae, @gsantner, @di72nn - by @vanitasvitae, @gsantner, @di72nn
- Allow turning off toolbar intellihide - Allow turning off toolbar intellihide
- Handle links from browseable intent filter #38 - Handle links from browseable intent filter #38
@ -30,7 +186,7 @@
- Share screenshot fix; Minor Aspects rework - Share screenshot fix; Minor Aspects rework
- Update to SDK 24 (Android N) - Update to SDK 24 (Android N)
# v0.1.3 (2016-07-04) ### v0.1.3 (2016-07-04)
- Added titles on top toolbar (by @scoute-dich) - Added titles on top toolbar (by @scoute-dich)
- Made bottom toolbar automatically disappear - Made bottom toolbar automatically disappear
- Added option to share images to external app - Added option to share images to external app
@ -41,7 +197,7 @@
- Removed swipe-to-refresh functionality in some places - Removed swipe-to-refresh functionality in some places
- Big thanks and good luck to @scoute-dich and @martinchodev for accompanying this project :) - Big thanks and good luck to @scoute-dich and @martinchodev for accompanying this project :)
# v0.1.2 (2016-06-05) ### v0.1.2 (2016-06-05)
- Extract and show aspects (by @gsantner) - Extract and show aspects (by @gsantner)
- Cache last podlist - Cache last podlist
- Better sharing from app - Better sharing from app
@ -54,7 +210,7 @@
- Lots of refactoring; Reworked Splash,PodSelectionActivity; Switch Pod; Clear settings; - Lots of refactoring; Reworked Splash,PodSelectionActivity; Switch Pod; Clear settings;
- Activity transitions, usability MainActivity, green accent color - Activity transitions, usability MainActivity, green accent color
# v0.1.1 ### v0.1.1
- Sharing updated (by @scoute-dich) - Sharing updated (by @scoute-dich)
- Screenshotting updated - Screenshotting updated
- Gitter integration (by @gsantner) - Gitter integration (by @gsantner)
@ -64,8 +220,8 @@
- Travis CI integration - Travis CI integration
- Bump Gradle, Build-Tools, Libs to Android Studio 2.1 defaults - Bump Gradle, Build-Tools, Libs to Android Studio 2.1 defaults
# v0.1.0 (Diaspora for Android) ### v0.1.0 (Diaspora for Android)
First version of the organization *Diaspora for Android* First version of the organization *Diaspora for Android*
Consists mostly of code from: Consists mostly of code from:
- Diaspora-Native-Webapp (by @martinchodev ) - Diaspora-Native-Webapp (by @martinchodev )
- scoutedich additions (by @scoute-dich) - scoutedich additions (by @scoute-dich)

74
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,74 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at <gsantner AT mailbox DOT org>. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

View file

@ -1,6 +0,0 @@
We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..)
If you got any questions feel free to join our XMPP/Jabber conference at `diaspora-android@conference.jabberhead.tk` or [Gitter](https://gitter.im/Diaspora-for-Android/diaspora-android).
Note that the main project members are mostly busy with their job/university/school and may not react or start coding immediately.
We use Crowdin to translate Diaspora for Android. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite>
If your desired language is not listed please contact the maintainers/owner.

32
CONTRIBUTORS.md Normal file
View file

@ -0,0 +1,32 @@
<!--
This file contains references to people who contributed to the app.
Schema: **[Name](Reference)**<br/>~° Text
Where:
* Name: username, first/lastname
* Reference: E-Mail, Webpage
* Text: Information about / kind of contribution
## LIST OF CONTRIBUTORS
-->
* **[Gregor Santner](http://github.com/gsantner)**<br/>~° Development of dandelion
* **[Paul Schaub](https://github.com/vanitasvitae)**<br/>~° Development of dandelion
* **[Martín Vukovic](martinvukovic AT protonmail DOT com)**<br/>~° Diaspora Native WebApp
* **[Gaukler Faun](https://github.com/scoute-dich)**<br/>~° Diaspora Native WebApp additions
* **[Airon90](https://diasp.eu/u/airon90)**<br/>~° Italian translation
* **[Nacho Fernández](nacho_f AT joindiaspora DOT com)**<br/>~° Spanish translation
* **[Naofumi Fukue](https://github.com/naofum)**<br/>~° Japanese translation
* **[pskosinski](email AT pskosinski DOT pl)**<br/>~° Polish translation
* **[SansPseudoFix](https://github.com/SansPseudoFix)**<br/>~° French translation
* **[Zsolt Szakács](maxigaz AT diaspora DOT zone)**<br/>~° Hungarian translation
* **[Luís F.S. Rosa](https://github.com/luisfsr)**<br/>~° Brazilian Portuguese translation
* **[Danilo Raffaelli](https://crowdin.com/profile/Daraf)**<br/>~° Italian translation
* **[Âng Iōngchun](https://pubpod.alqualonde.org/u/iongchun)**<br/>~° Chinese traditional translation
* **[Mikkel Kirkgaard Nielsen](http://www.mikini.dk)**<br/>~° Danish translation
* **[Jean Lucas](jean AT 4ray DOT co)**<br/>~° Spanish translation
* **[asereze](https://github.com/asereze)**<br/>~° Sardinian translation
* **[Xosé M. Lamas](http://xmgz.eu)**<br />~° Galician translation
* **[massimiliano](https://framagit.org/massimiliano)**<br />~° Contributor

View file

@ -1,18 +1,25 @@
# App # dandelion\*
`---------------`
This program is free software: you can redistribute it and/or modify <small>This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/. along with this program. If not, see https://www.gnu.org/licenses/.</small>
`---------------`
If you want to publish dandelion\* in an app store, you have to change the app name (dandelion\*), package name & launcher icon (blue). See "7. Additional Terms" of GPL.
You also have to provide the modifications in source code somewhere online for free. This is explicitly not about building the app and sharing with some friends, it's about app stores.
The reason is, that most app stores allow an app id just once, which would block our uploads if somebody else uploaded. Also, we want to keep control on where the app is published, and want to make sure there is no malware in it.
The F-Droid project team is explicitly allowed to publish dandelion\* without listed required modifications above at official F-Droid repository.
# Splashscreen-Images ## Miscellaneous
The splashscreen images can be found on [flickr](https://www.flickr.com/photos/129581906@N06/sets/72157651933980136/with/16594947123/).
We took some inspiration and code from LeafPic. Go check it out, its free software as well!
<https://github.com/HoraApps/LeafPic>

99
Makefile Normal file
View file

@ -0,0 +1,99 @@
# License of Makefile: Public Domain / CC0
.PHONY: $(shell sed -n -e '/^$$/ { n ; /^[^ .\#][^ ]*:/ { s/:.*$$// ; p ; } ; }' $(MAKEFILE_LIST))
.NOTPARALLEL: clean
.DEFAULT_GOAL := all
env-%:
@: $(if ${${*}},,$(error Environment variable $* not set))
####################################################################################
DIST_DIR = dist
MOVE = mv
all: $(DIST_DIR) spellcheck lint deptree test build aapt_dump_badging
####################################################################################
$(DIST_DIR):
mkdir -p ${DIST_DIR}
ANDROID_BUILD_TOOLS := $(shell test -n "$ANDROID_SDK_ROOT" && find "${ANDROID_SDK_ROOT}/build-tools" -iname "aapt" | sort -r | head -n1 | xargs dirname)
TOOL_SPELLCHECKING_ISPELL := $(shell command -v ispell 2> /dev/null)
FLAVOR := $(or ${FLAVOR},${FLAVOR},Atest)
.NOTPARALLEL: gradle gradle-analyze-log
gradle: env-ANDROID_SDK_ROOT
mkdir -p $(DIST_DIR)/log/
chmod +x gradlew
./gradlew --no-daemon --parallel --stacktrace $A 2>&1 | tee "$(DIST_DIR)/log/gradle.log"
@echo "-----------------------------------------------------------------------------------"
gradle-analyze-log:
mv "$(DIST_DIR)/log/gradle.log" "$(DIST_DIR)/log/gradle$A.log"
cat "$(DIST_DIR)/log/gradle$A.log" | grep "BUILD " | tail -n1 | grep -q "BUILD SUCCESSFUL in"
adb: env-ANDROID_SDK_ROOT
"${ANDROID_SDK_ROOT}/platform-tools/adb" $A 2>&1 | tee "$(DIST_DIR)/log/adb-$L.log"
aapt: env-ANDROID_SDK_ROOT
"${ANDROID_BUILD_TOOLS}/aapt" $A 2>&1 | grep -v 'application-label-' | tee "$(DIST_DIR)/log/aapt$L.log"
build:
rm -f $(DIST_DIR)/*.apk
$(MAKE) A="clean assembleFlavor$(FLAVOR) -x lint" gradle
find app -type f -newermt '-300 seconds' -iname '*.apk' -not -iname '*unsigned.apk' | xargs cp -R -t $(DIST_DIR)/
$(MAKE) A="-build" gradle-analyze-log
lint:
rm -Rf $(DIST_DIR)/lint
mkdir -p $(DIST_DIR)/lint/
$(MAKE) A="lintFlavorDefaultDebug" gradle
find app -type f -iname 'lint-results-*' | grep -v 'intermediates' | xargs cp -R -t $(DIST_DIR)/lint
$(MAKE) A="-lint" gradle-analyze-log
test:
rm -Rf $(DIST_DIR)/tests
$(MAKE) A="testFlavorDefaultDebugUnitTest -x lint" gradle
mkdir -p app/build/test-results/testFlavorDefaultDebugUnitTest && echo 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHRlc3RzdWl0ZSBuYW1lPSJkdW1teSIgdGVzdHM9IjEiIHNraXBwZWQ9IjAiIGZhaWx1cmVzPSIwIiBlcnJvcnM9IjAiIHRpbWVzdGFtcD0iMjAyMC0xMi0wOFQwMDowMDowMCIgaG9zdG5hbWU9ImxvY2FsaG9zdCIgdGltZT0iMC4wMSI+CiAgPHByb3BlcnRpZXMvPgogIDx0ZXN0Y2FzZSBuYW1lPSJkdW1teSIgY2xhc3NuYW1lPSJkdW1teSIgdGltZT0iMC4wMSIvPgogIDxzeXN0ZW0tb3V0PjwhW0NEQVRBW11dPjwvc3lzdGVtLW91dD4KICA8c3lzdGVtLWVycj48IVtDREFUQVtdXT48L3N5c3RlbS1lcnI+CjwvdGVzdHN1aXRlPgo=' | base64 -d > 'app/build/test-results/testFlavorDefaultDebugUnitTest/TEST-dummy.xml'
find app -type d -iname 'testFlavorDefaultDebugUnitTest' | xargs cp -R -t $(DIST_DIR)/
mv ${DIST_DIR}/testFlavorDefaultDebugUnitTest $(DIST_DIR)/tests
$(MAKE) A="-test" gradle-analyze-log
deptree:
$(MAKE) A="app:dependencies --configuration flavor$(FLAVOR)DebugRuntimeClasspath" gradle
$(MAKE) A="-dependency-tree" gradle-analyze-log
clean:
$(MAKE) A="clean" gradle
rm -Rf $(DIST_DIR) app/build app/flavor* .idea dist
find . -type f -iname "*.iml" -delete
$(MAKE) $(DIST_DIR)
@echo "-----------------------------------------------------------------------------------"
install:
$(MAKE) A="install -r $(DIST_DIR)/*.apk" L="install" adb
run:
$(MAKE) A="shell monkey -p $$(aapt dump badging $(DIST_DIR)/*.apk | grep package: | sed 's@.* name=@@' | sed 's@ .*@@' | xargs | head -n1) -c android.intent.category.LAUNCHER 1" L="run" adb
aapt_dump_badging:
$(MAKE) A="dump badging $(DIST_DIR)/*.apk" aapt
@echo "-----------------------------------------------------------------------------------"
spellcheck:
mkdir -p "$(DIST_DIR)/lint/"
ifndef TOOL_SPELLCHECKING_ISPELL
@echo "Tool ispell (spellcheck) not found in PATH. Spellcheck skipped." > "$(DIST_DIR)/lint/stringsxml-spellcheck.txt"
else
@echo "Use ispell for spellchecking the original values/strings.xml"
find . -iname "strings.xml" -path "*/main*/values/*" | head -n1 | xargs cat \
| grep "<string name=" | sed 's@.*">@@' | sed 's@</string>@@' | sed 's@\\n@ @g' | sed 's@\\@@g' \
| ispell -W3 -a | grep ^\& | sed 's@[0-9]@@g' | sort | uniq | cut -d, -f1-4 \
| sed 's@^..@- @' | column -t -s: \
> "$(DIST_DIR)/lint/stringsxml-spellcheck.txt"
@echo "\nPotential words with bad spelling:"
endif
@cat "$(DIST_DIR)/lint/stringsxml-spellcheck.txt"
@echo "-----------------------------------------------------------------------------------"

96
NEWS.md Normal file
View file

@ -0,0 +1,96 @@
# dandelion - News
## General
### Installation
You can install and update from [F-Droid](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android) or [GitHub](https://github.com/gsantner/dandelion/releases/latest).
F-Droid is a store for free & open source apps.
The *.apk's available for download are signed by the F-Droid team and guaranteed to correspond to the (open source) source code of dandelion.
Generally this is the recommended way to install dandelion & keep it updated.
### Get informed
* Check the [project readme](https://github.com/gsantner/dandelion/tree/news#readme) for general project information.
* Check the [project news](https://github.com/gsantner/dandelion/blob/master/NEWS.md#readme) for more details on what is going on.
* Check the [project git history](https://github.com/gsantner/dandelion/commits/master) for most recent code changes.
### The right place to ask
If you have questions or found an issue please head to the [dandelion project](https://github.com/gsantner/dandelion/issues/new/choose) and ask there.
[Search](https://github.com/gsantner/dandelion/issues?q=#js-issues-search) for same/similar and related issues/questions before, it might be already answered or resolved.
### Navigation
* [dandelion v1.2 - Add dandelior - Searchable Tags and Aspects](#dandelion-v12---add-dandelior---searchable-tags-and-aspects)
* [dandelion v0.1.2 - Aspekte, Pod wechseln](#dandelion-v012---aspekte-pod-wechseln)
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
# dandelion\* v1.2 - Add dandelior\* - Searchable Tags and Aspects
_12. August 2018_
## dandelior\* is a rebranded version of dandelion\*
dandelior\* is based 100% on the same code and resources as dandelion\*. Its from the same code repository, just a different build flavor.
The main purpose of dandelior\* is the most requested feature till date - to support multiple accounts / another account at dandelion\*.
- Added an (rebranded) flavor of dandelion: dandelior
- Only differenties in use are other (black) icon and AMOLED colors by default enabled
- Already available on F-Droid
**New features:**
- All new Aspects and Tags, using a searchable dialog
**Fixed:**
- Sometimes the Stream went white, which is due an still (3+ years) unfixed Android Support library bug. It should not occur very often anymore due less use of fragments.
**Improved:**
- Various small tweaks
- Updated translation files
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
# dandelion v0.1.2 - Aspekte, Pod wechseln
_05. Juni 2016_
In den letzten Tagen hat @gsantner viel Zeit in die inoffizielle diaspora\* Android App ([dandelion\*](https://github.com/gsantner/dandelion)) investiert.
Dabei wurden unter anderem folgende Änderungen beigesteuert:
- Allgemeines zur Usability
- Animationen für den Activity-Wechsel und Startup, WebView-Scroll-Top
- Podliste caching
- Aspekt-Liste und Aspekte hinzugefügt
- Verbessertes Sharing aus der App
- Material Progressbar
- Suche verbessert
- Collapsing top menu
- toolbar/actions/menu geändert, fab entfernt
- Refactoring layout & menu files, dialogs
- Überarbeitete Main,Splash,PodSelectionActivity
- Pod wechseln

106
README.md
View file

@ -1,43 +1,81 @@
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android) [![GitHub releases](https://img.shields.io/github/tag/gsantner/dandelion.svg)](https://github.com/gsantner/dandelion/releases)
[![GitHub downloads](https://img.shields.io/github/downloads/gsantner/dandelion/total.svg?logo=github&logoColor=lime)](https://github.com/gsantner/dandelion/releases)
[![Translate on Crowdin](https://img.shields.io/badge/translate-crowdin-green.svg)](https://crowdin.com/project/diaspora-for-android/invite)
[![Chat on Matrix](https://img.shields.io/badge/chat-matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org)
[![GitHub CI](https://github.com/gsantner/dandelion/workflows/CI/badge.svg)](https://github.com/gsantner/dandelion/actions)
[![Codacy code quality](https://img.shields.io/codacy/grade/aff869c440bc48b7bd64680e97cbc453)](https://www.codacy.com/app/gsantner/dandelion)
[![Build Status](https://travis-ci.org/Diaspora-for-Android/diaspora-android.svg?branch=master)](https://travis-ci.org/Diaspora-for-Android/diaspora-android) # dandelion\*
[![Crowdin](https://d322cqt584bo4o.cloudfront.net/diaspora-for-android/localized.svg)](https://crowdin.com/project/diaspora-for-android) <img src="/app/src/main/ic_launcher-web.png" align="left" width="100" hspace="10" vspace="10">
[![Join the chat at https://gitter.im/Diaspora-for-Android/diaspora-android](https://badges.gitter.im/Diaspora-for-Android/diaspora-android.svg)](https://gitter.im/Diaspora-for-Android/diaspora-android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) This is an unofficial webview based client for the community-run, distributed social network <b><a href="https://diasporafoundation.org/">diaspora*</a></b>.
<div style="display:flex;" >
<a href="https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android">
<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="80">
</a>
<!--<a href="https://play.google.com/store/apps/details?id=com.github.dfa.diaspora_android">
<img alt="Get it on Google Play" height="80" src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" />
</a>-->
</div></br>
# Diaspora for Android ## Description
This is an unofficial webview based client for the community-run, distributed social network <b><a href="https://diasporafoundation.org/">diaspora*</a></b>.
It's currently under development and should be used with that in mind. Please submit any bugs you might find.
This is an unofficial webview based client for the community-run, distributed social network **[Diaspora](https://joindiaspora.com/)**. It's currently under development and should be used with that in mind. Please submit any bugs you might find. #### WebApp
**Notice:** This is the repo of the latest version of the unoffical Diaspora Android App. The app is developed as a WebApp because currently diaspora\* doesn't have an functional API that can be used to create a native interface to retrieve the user's data, publications, direct messages and so on. That's why there are currently only WebApps for diaspora\* out there.
[Stay tuned on diaspora\* issues](https://github.com/diaspora/diaspora/labels/api) about API.
- Download ([F-Droid](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android), [Release Archive](https://github.com/Diaspora-for-Android/diaspora-android/releases)) Why is a WebApp better than using the mobile site on a browser?
- Watch [Changelog](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/CHANGELOG.md)
- See [Screenshots](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/SCREENSHOTS.md)
## Contributions
We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..)
If you got any questions feel free to join our XMPP/Jabber conference at `diaspora-android@conference.jabberhead.tk` or [Gitter](https://gitter.im/Diaspora-for-Android/diaspora-android).
Note that the main project members are mostly busy with their job/university/school and may not react or start coding immediately.
We use Crowdin to translate Diaspora for Android. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite>
If your desired language is not listed please contact the maintainers/owner.
### License
It's released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/Diaspora-for-Android/diaspora-android/blob/master/LICENSE.md)).
### WebApp
The app is developed as an WebApp because currently Diaspora doesn't have an API that can be used to create a native interface to retrieve the user's data, publications, direct messages and so on, that's why there are only WebApps for Diaspora out there.
API is discussed frequently on Diaspora, but the main developers seem to not give the API and mobile view the attention it needs. [Stay tuned on Diaspora* Issues](https://github.com/diaspora/diaspora/labels/api).
Why a WebApp is better than using the mobile site on a browser?
Basically it provides better integration with the system (events coming into and going out of the app), notifications, customized interface and functions and a nice little icon that takes you directly to your favorite social network :) Basically it provides better integration with the system (events coming into and going out of the app), notifications, customized interface and functions and a nice little icon that takes you directly to your favorite social network :)
### Device Requirements #### Device Requirements
The minimum version supported is Jelly Bean, Android v4.2.0 / API 17 The minimum Android version supported is Jelly Bean, Android v4.2.0 / API 17
### App Permissions ### Privacy & Permissions<a name="privacy"></a>
It requires access to the Internet and to external storage to be able to upload photos when creating a new post and for taking screenshots. dandelion\* requires access to the Internet and to external storage to be able to upload photos when creating a new post and for taking screenshots.
## Maintainers
- gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io)) ## Contributions
- vanitasvitae ([GitHub](https://github.com/vanitasvitae)) The project is always open for contributions and accepts pull requests.
The project uses [AOSP Java Code Style](https://source.android.com/source/code-style#follow-field-naming-conventions), with one exception: private members are `_camelCase` instead of `mBigCamel`. You may use Android Studios _auto reformat feature_ before sending a PR.
Translations can be contributed on GitHub. You can use Stringlate ([![Translate - with Stringlate](https://img.shields.io/badge/stringlate-translate-green.svg)](https://lonamiwebs.github.io/stringlate/translate?git=https%3A%2F%2Fgithub.com%2Fgsantner%2Fdandelion.git)) to translate the project directly on your Android phone. It allows you to export as E-Mail attachement and to post on GitHub.
Join our Matrix channel and say hello! Don't be afraid to start talking. [![Chat - Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org)
Note that the main project members are working on this project for free during leisure time, are mostly busy with their job/university/school, and may not react or start coding immediately.
#### Resources
* Project: [Changelog](/CHANGELOG.md) | [Issues level/beginner](https://github.com/gsantner/dandelion/issues?q=is%3Aissue+is%3Aopen+label%3Alevel%2Fbeginner) | [License](/LICENSE.txt) | [CoC](/CODE_OF_CONDUCT.md)
* Project diaspora\* account: [dandelion00@diasp.org](https://diasp.org/people/48b78420923501341ef3782bcb452bd5)
* diaspora\*: [GitHub](https://github.com/diaspora/diaspora) | [Web](https://diasporafoundation.org) | [d\* HQ account](https://pod.diaspora.software/people/7bca7c80311b01332d046c626dd55703)
* App on F-Droid: [Metadata](https://gitlab.com/fdroid/fdroiddata/blob/master/metadata/com.github.dfa.diaspora_android.txt) | [Page](https://f-droid.org/packages/com.github.dfa.diaspora_android/) | [Wiki](https://f-droid.org/wiki/page/com.github.dfa.diaspora_android) | [Build log](https://f-droid.org/wiki/page/com.github.dfa.diaspora_android/lastbuild)
## Licensing
dandelion\* is released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/gsantner/dandelion/blob/master/LICENSE.md)).
The app is licensed GPL v3. Localization files and resources (strings\*.xml) are licensed CC0 1.0.
For more licensing informations, see [`3rd party licenses`](/app/src/main/res/raw/licenses_3rd_party.md).
## Screenshots
<div style="display:flex;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/01.png" width="19%" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/02.png" width="19%" style="margin-left:10px;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/03.png" width="19%" style="margin-left:10px;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/04.png" width="19%" style="margin-left:10px;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/05.png" width="19%" style="margin-left:10px;" >
</div>
<div style="display:flex;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/06.png" width="19%" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/07.png" width="19%" style="margin-left:10px;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/08.png" width="19%" style="margin-left:10px;" >
<img src="https://raw.githubusercontent.com/gsantner/dandelion/master/metadata/en-US/phoneScreenshots/09.png" width="19%" style="margin-left:10px;" >
</div>
### Notice
#### Maintainers
- gsantner ([GitHub](https://github.com/gsantner), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
- vanitasvitae ([GitHub](https://github.com/vanitasvitae), [diaspora*](https://pod.geraspora.de/people/bbd7af90fbec013213e34860008dbc6c))

View file

@ -1,14 +0,0 @@
<table>
<tr>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806540/ada77adc-2b45-11e6-86a0-23467d4c5fc2.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806541/ada7f908-2b45-11e6-8c88-5e141ae1786f.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806544/adab9630-2b45-11e6-8337-0a84bd9c195d.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806542/adaa1580-2b45-11e6-95d9-ab4317dc0e05.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806543/adaada24-2b45-11e6-96b2-9cb391aad0f9.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806545/adac1114-2b45-11e6-8875-5ba414cb1fbd.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806546/adc6caae-2b45-11e6-86f9-48402b752000.png" height="60%" width="60%"></td>
<td><img src="https://cloud.githubusercontent.com/assets/6735650/15806547/adc73890-2b45-11e6-9e46-3bb6b2ecc1c9.png" height="60%" width="60%"></td>
</tr>
</table>

View file

@ -1,8 +0,0 @@
#aaaaaaa>> This file contains references to people who helped translating the app
#aaaaaab>> Please send a message on crowdin, and you will get included in the next commit
#aaaaaac>>
#aaaaaad>> Schemes:
#aaaaaae>> Firstname Lastname (Link)
#aaaaaaf>> Firstname Lastname (E-Mail)
#aaaaaag>> Username (Link)
#aaaaaah>> Username (E-Mail)

View file

@ -1,18 +1,63 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'android-apt' if (enable_plugin_kotlin) {
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
}
android { android {
compileSdkVersion 24 buildToolsVersion rootProject.ext.version_buildTools
buildToolsVersion "24.0.1" compileSdkVersion rootProject.ext.version_compileSdk
useLibrary 'org.apache.http.legacy'
defaultConfig { defaultConfig {
resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android"
applicationId "com.github.dfa.diaspora_android" applicationId "com.github.dfa.diaspora_android"
minSdkVersion 17 versionName "1.3.5"
targetSdkVersion 24 versionCode 46
versionCode 6 vectorDrawables.useSupportLibrary = true
versionName "0.1.5"
minSdkVersion rootProject.ext.version_minSdk
targetSdkVersion rootProject.ext.version_compileSdk
buildConfigField "boolean", "IS_TEST_BUILD", "false"
buildConfigField "boolean", "IS_GPLAY_BUILD", "false"
buildConfigField "String[]", "DETECTED_ANDROID_LOCALES", "${findUsedAndroidLocales()}"
buildConfigField "String", "BUILD_DATE", "\"${getBuildDate()}\""
buildConfigField "String", "GITHASH", "\"${getGitHash()}\""
setProperty("archivesBaseName", applicationId + "-v" + versionCode + "-" + versionName)
} }
flavorDimensions "default"
productFlavors {
flavorDefault {
}
/*
flavorGplay {
buildConfigField "boolean", "IS_GPLAY_BUILD", "true"
}*/
flavorDandelior {
applicationId "net.gsantner.dandelior"
}
flavorAtest {
applicationId "net.gsantner.secondlion"
versionCode = Integer.parseInt(new Date().format('yyMMdd'))
versionName = new Date().format('yyMMdd')
buildConfigField "boolean", "IS_TEST_BUILD", "true"
}
}
sourceSets {
main { assets.srcDirs = ['src/main/assets'] }
if (enable_plugin_kotlin) {
main.java.srcDirs += 'src/main/kotlin'
}
main.java.srcDirs += 'thirdparty/java'
main.res.srcDirs += 'thirdparty/res'
main.assets.srcDirs += 'thirdparty/assets'
}
buildTypes { buildTypes {
release { release {
minifyEnabled false minifyEnabled false
@ -20,27 +65,72 @@ android {
} }
} }
configurations.all {
resolutionStrategy {
eachDependency { details ->
if (details.requested.group == 'com.android.support') {
if (details.requested.name != 'multidex' && details.requested.name != 'multidex-instrumentation') {
details.useVersion "${rootProject.ext.version_library_appcompat}"
}
}
}
}
}
packagingOptions {
exclude 'META-INF/LICENSE-LGPL-2.1.txt'
exclude 'META-INF/LICENSE-LGPL-3.txt'
exclude 'META-INF/LICENSE-W3C-TEST'
}
compileOptions {
encoding = 'UTF-8'
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions { lintOptions {
disable 'MissingTranslation' disable 'MissingTranslation', 'InvalidPackage', 'ObsoleteLintCustomCheck', 'DefaultLocale', 'UnusedAttribute', 'VectorRaster', 'InflateParams', 'IconLocation', 'UnusedResources', 'TypographyEllipsis'
abortOnError false
} }
} }
dependencies { dependencies {
// Sub-Projects // Sub-Projects
//compile project(':subprojectFromRoot') //implementation project(':subprojectFromRoot')
// Jars // Jars
compile fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.13'
// Android standard libs // Android standard libs
compile 'com.android.support:appcompat-v7:24.1.1' implementation "com.android.support:appcompat-v7:${version_library_appcompat}"
compile 'com.android.support:design:24.1.1' implementation "com.android.support:design:${version_library_appcompat}"
compile 'com.android.support:support-v4:24.1.1' implementation "com.android.support:support-v4:${version_library_appcompat}"
implementation "com.android.support:customtabs:${version_library_appcompat}"
implementation "com.android.support:cardview-v7:${version_library_appcompat}"
implementation "com.android.support:preference-v7:${version_library_appcompat}"
// More libraries // UI libraries
compile 'com.jakewharton:butterknife:8.0.1' implementation "com.github.DASAR:ShiftColorPicker:v0.5"
compile 'info.guardianproject.netcipher:netcipher:1.2.1'
apt 'com.jakewharton:butterknife-compiler:8.0.1'
// Tool libraries
implementation 'commons-io:commons-io:2.6'
implementation "info.guardianproject.netcipher:netcipher:${version_library_netcipher}"
implementation "info.guardianproject.netcipher:netcipher-webkit:${version_library_netcipher}"
//noinspection AnnotationProcessorOnCompilePath
implementation "com.jakewharton:butterknife:${version_library_butterknife}"
if (enable_plugin_kotlin) {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${version_plugin_kotlin}"
}
// Processors
def anpros = ["com.jakewharton:butterknife-compiler:${version_library_butterknife}"]
for (anpro in anpros) {
if (enable_plugin_kotlin) {
kapt anpro
} else {
annotationProcessor anpro
}
}
} }

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M0.025,-0.07h19.95v20.14H0.025z"
android:fillColor="#492600"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="36.363636"
android:viewportHeight="36.363636">
<group android:translateX="8.181818"
android:translateY="8.181818">
<path
android:pathData="M11.337,14.123l-0.963,-1.345c-0.257,-0.36 -0.466,-0.64 -0.477,-0.64 -0.012,0 -0.416,0.544 -0.958,1.287a83.9,83.9 0,0 1,-0.947 1.287c-0.015,0 -1.86,-1.3 -1.865,-1.313 -0.002,-0.007 0.415,-0.62 0.927,-1.361 0.512,-0.742 0.931,-1.36 0.931,-1.375 0,-0.023 -0.166,-0.081 -1.468,-0.515l-1.485,-0.496c-0.013,-0.005 0.063,-0.263 0.327,-1.094 0.19,-0.599 0.349,-1.093 0.354,-1.099 0.005,-0.006 0.707,0.219 1.56,0.5 0.852,0.28 1.556,0.509 1.565,0.509 0.008,0 0.018,-0.013 0.022,-0.03 0.003,-0.015 0.01,-0.74 0.016,-1.612 0.006,-0.87 0.015,-1.59 0.02,-1.6 0.009,-0.012 0.248,-0.015 1.127,-0.015 0.614,0 1.123,0.004 1.13,0.01 0.01,0.006 0.027,0.485 0.056,1.56 0.046,1.766 0.047,1.79 0.075,1.79 0.01,0 0.686,-0.226 1.501,-0.503a50.795,50.795 0,0 1,1.49 -0.492c0.016,0.019 0.685,2.194 0.676,2.202 -0.004,0.005 -0.684,0.237 -1.51,0.517 -1.137,0.386 -1.504,0.515 -1.507,0.531 -0.003,0.012 0.388,0.597 0.886,1.324 0.49,0.716 0.888,1.308 0.886,1.314a96.945,96.945 0,0 1,-1.852 1.364c-0.006,0 -0.239,-0.317 -0.517,-0.705z"
android:fillColor="#fafafa"/>
</group>
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">secondlion*</string>
</resources>

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M0.025,-0.07h19.95v20.14H0.025z"
android:fillColor="#000000"/>
</vector>

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="36.363636"
android:viewportHeight="36.363636">
<group android:translateX="8.181818"
android:translateY="8.181818">
<path
android:pathData="M11.337,14.123l-0.963,-1.345c-0.257,-0.36 -0.466,-0.64 -0.477,-0.64 -0.012,0 -0.416,0.544 -0.958,1.287a83.9,83.9 0,0 1,-0.947 1.287c-0.015,0 -1.86,-1.3 -1.865,-1.313 -0.002,-0.007 0.415,-0.62 0.927,-1.361 0.512,-0.742 0.931,-1.36 0.931,-1.375 0,-0.023 -0.166,-0.081 -1.468,-0.515l-1.485,-0.496c-0.013,-0.005 0.063,-0.263 0.327,-1.094 0.19,-0.599 0.349,-1.093 0.354,-1.099 0.005,-0.006 0.707,0.219 1.56,0.5 0.852,0.28 1.556,0.509 1.565,0.509 0.008,0 0.018,-0.013 0.022,-0.03 0.003,-0.015 0.01,-0.74 0.016,-1.612 0.006,-0.87 0.015,-1.59 0.02,-1.6 0.009,-0.012 0.248,-0.015 1.127,-0.015 0.614,0 1.123,0.004 1.13,0.01 0.01,0.006 0.027,0.485 0.056,1.56 0.046,1.766 0.047,1.79 0.075,1.79 0.01,0 0.686,-0.226 1.501,-0.503a50.795,50.795 0,0 1,1.49 -0.492c0.016,0.019 0.685,2.194 0.676,2.202 -0.004,0.005 -0.684,0.237 -1.51,0.517 -1.137,0.386 -1.504,0.515 -1.507,0.531 -0.003,0.012 0.388,0.597 0.886,1.324 0.49,0.716 0.888,1.308 0.886,1.314a96.945,96.945 0,0 1,-1.852 1.364c-0.006,0 -0.239,-0.317 -0.517,-0.705z"
android:fillColor="#fafafa"/>
</group>
</vector>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">dandelior*</string>
</resources>

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View file

@ -1,52 +1,76 @@
/* /*
This file is part of the Diaspora for Android. This file is part of the dandelion*.
Diaspora for Android is free software: you can redistribute it and/or modify dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful, dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with the Diaspora for Android. along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android; package com.github.dfa.diaspora_android;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Build; import android.os.Build;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatDelegate;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.CookieSyncManager; import android.webkit.CookieSyncManager;
import android.webkit.WebView; import android.webkit.WebView;
import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.data.PodUserProfile; import com.github.dfa.diaspora_android.service.AvatarImageLoader;
import com.github.dfa.diaspora_android.util.AvatarImageLoader; import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
public class App extends Application { import net.gsantner.opoc.util.AdBlock;
public static final String TAG = "DIASPORA_"; import net.gsantner.opoc.util.ContextUtils;
import net.gsantner.opoc.util.ShareUtil;
public class App extends Application {
private volatile static App app;
private AppSettings appSettings; private AppSettings appSettings;
private AvatarImageLoader avatarImageLoader; private AvatarImageLoader avatarImageLoader;
private CookieManager cookieManager; private CookieManager cookieManager;
private PodUserProfile podUserProfile; private DiasporaUserProfile diasporaUserProfile;
public static App get() {
return app;
}
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
ShareUtil.setFileProviderAuthority(BuildConfig.APPLICATION_ID);
app = this;
final Context c = getApplicationContext(); final Context c = getApplicationContext();
appSettings = new AppSettings(c); appSettings = AppSettings.get();
String a = new ContextUtils(this).bcstr("FLAVOR", "");
a += "__";
if (appSettings.isAppFirstStart() && "flavorDandelior".equals(new ContextUtils(this).bcstr("FLAVOR", ""))) {
appSettings.setAmoledColorMode(true);
}
// Init app log
AppLog.setLoggingEnabled(appSettings.isLoggingEnabled());
AppLog.setLoggingSpamEnabled(appSettings.isLoggingSpamEnabled());
// Init pod profile
avatarImageLoader = new AvatarImageLoader(c); avatarImageLoader = new AvatarImageLoader(c);
podUserProfile = new PodUserProfile(this); diasporaUserProfile = new DiasporaUserProfile(this);
// Get cookie manager // Get cookie manager
@ -56,10 +80,12 @@ public class App extends Application {
CookieSyncManager.createInstance(c); CookieSyncManager.createInstance(c);
} }
cookieManager.setAcceptCookie(true); cookieManager.setAcceptCookie(true);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
AdBlock.getInstance().loadHostsFromRawAssetsAsync(this);
} }
public void resetPodData(@Nullable WebView webView){ public void resetPodData(@Nullable WebView webView) {
if(webView != null){ if (webView != null) {
webView.stopLoading(); webView.stopLoading();
webView.loadUrl(DiasporaUrlHelper.URL_BLANK); webView.loadUrl(DiasporaUrlHelper.URL_BLANK);
webView.clearFormData(); webView.clearFormData();
@ -70,8 +96,11 @@ public class App extends Application {
// Clear avatar image // Clear avatar image
new AvatarImageLoader(this).clearAvatarImage(); new AvatarImageLoader(this).clearAvatarImage();
// Clear preferences // Clear preferences__master
appSettings.clearPodSettings(); appSettings.resetPodSettings();
// Clear User profile - reload empty AppSettingsBase data
diasporaUserProfile.loadFromAppSettings();
// Clear cookies // Clear cookies
//noinspection deprecation //noinspection deprecation
@ -81,8 +110,8 @@ public class App extends Application {
} }
} }
public PodUserProfile getPodUserProfile(){ public DiasporaUserProfile getDiasporaUserProfile() {
return podUserProfile; return diasporaUserProfile;
} }
public AppSettings getSettings() { public AppSettings getSettings() {

View file

@ -0,0 +1,432 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.listener.IntellihideToolbarActivityListener;
import com.github.dfa.diaspora_android.ui.HtmlTextView;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.ui.theme.ThemedActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
import java.util.Observable;
import java.util.Observer;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Activity that holds some fragments that show information about the app in a tab layout
*/
public class AboutActivity extends ThemedActivity
implements IntellihideToolbarActivityListener {
@BindView(R.id.about__appbar)
protected AppBarLayout _appBarLayout;
@BindView(R.id.main__topbar)
protected Toolbar _toolbar;
@BindView(R.id.appbar_linear_layout)
protected LinearLayout _linearLayout;
@BindView(R.id.tabs)
protected TabLayout _tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about__activity);
ButterKnife.bind(this);
setSupportActionBar(_toolbar);
_toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24px));
_toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AboutActivity.this.onBackPressed();
}
});
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
ViewPager mViewPager = ButterKnife.findById(this, R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
_tabLayout.setupWithViewPager(mViewPager);
}
@Override
public void onResume() {
super.onResume();
setToolbarIntellihide(getAppSettings().isIntellihideToolbars());
}
@Override
protected void applyColorToViews() {
ThemeHelper.updateToolbarColor(_toolbar);
ThemeHelper.updateTabLayoutColor(_tabLayout);
ThemeHelper.setPrimaryColorAsBackground(_linearLayout);
}
public void setToolbarIntellihide(boolean enable) {
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) _linearLayout.getLayoutParams();
if (enable) {
AppLog.d(this, "Enable Intellihide");
params.setScrollFlags(toolbarDefaultScrollFlags);
} else {
AppLog.d(this, "Disable Intellihide");
params.setScrollFlags(0); // clear all scroll flags
}
_appBarLayout.setExpanded(true, true);
}
/**
* Fragment that shows general information about the app
*/
public static class AboutFragment extends ThemedFragment {
public static final String TAG = "com.github.dfa.diaspora_android.AboutActivity.AboutFragment";
@BindView(R.id.fragment_about__app_version)
TextView appVersion;
@BindView(R.id.fragment_about__spread_the_word_text)
HtmlTextView spreadText;
@BindView(R.id.fragment_about__contribute_button)
Button contributeBtn;
@BindView(R.id.fragment_about__translate_button)
Button translateBtn;
@BindView(R.id.fragment_about__feedback_button)
Button feedbackBtn;
@BindView(R.id.fragment_about__spread_the_word_button)
Button spreadBtn;
public AboutFragment() {
}
@Override
protected int getLayoutResId() {
return R.layout.about__fragment_about;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
if (isAdded()) {
try {
PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
appVersion.setText(getString(R.string.app_version_with_arg, pInfo.versionName + " (" + pInfo.versionCode + ")"));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
}
@Override
protected void applyColorToViews() {
ThemeHelper.getInstance(getAppSettings());
ThemeHelper.updateTextViewLinkColor(spreadText);
ThemeHelper.updateButtonTextColor(contributeBtn);
ThemeHelper.updateButtonTextColor(feedbackBtn);
ThemeHelper.updateButtonTextColor(spreadBtn);
ThemeHelper.updateButtonTextColor(translateBtn);
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public boolean onBackPressed() {
return false;
}
@OnClick({R.id.fragment_about__contribute_button, R.id.fragment_about__translate_button, R.id.fragment_about__feedback_button, R.id.fragment_about__spread_the_word_button})
public void buttonClicked(View view) {
switch (view.getId()) {
case R.id.fragment_about__contribute_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_about__contribute_link));
break;
case R.id.fragment_about__translate_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_about__translate_link));
break;
case R.id.fragment_about__feedback_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_About__feedback_link));
break;
case R.id.fragment_about__spread_the_word_button:
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.app_name));
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, getString(R.string.hey_checkout_dandelion_tag__appspecific, getString(R.string.fragment_about__fdroid_link)));
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_dotdotdot)));
break;
}
}
}
/**
* Fragment that shows information about the license of the app and used 3rd party libraries
*/
public static class LicenseFragment extends ThemedFragment {
public static final String TAG = "com.github.dfa.diaspora_android.AboutActivity.LicenseFragment";
@BindView(R.id.fragment_license__maintainers_text)
HtmlTextView maintainers;
@BindView(R.id.fragment_license__contributors_text)
HtmlTextView contributors;
@BindView(R.id.fragment_license__thirdparty_libs_text)
HtmlTextView thirdPartyLibs;
@BindView(R.id.fragment_license__license_button)
Button licenseBtn;
@BindView(R.id.fragment_license__leafpic_button)
Button leafpicBtn;
private String accentColor;
public LicenseFragment() {
}
@Override
protected int getLayoutResId() {
return R.layout.about__fragment_license;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
accentColor = ContextUtils.get().colorToHexString(ThemeHelper.getAccentColor());
maintainers.setTextFormatted(getString(R.string.this_app_is_currently_developed_and_maintained_by_witharg,
ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.maintainers, "")));
contributors.setTextFormatted(getString(R.string.thank_you_witharg,
ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.contributors, "")));
thirdPartyLibs.setTextFormatted(
ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.licenses_3rd_party, ""));
}
@OnClick({R.id.fragment_license__leafpic_button, R.id.fragment_license__license_button})
public void buttonClicked(View v) {
switch (v.getId()) {
case R.id.fragment_license__leafpic_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_licesen__misc_leafpic_link));
break;
case R.id.fragment_license__license_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_license__license_gpl_link));
break;
}
}
@Override
protected void applyColorToViews() {
ThemeHelper.getInstance(getAppSettings());
ThemeHelper.updateButtonTextColor(leafpicBtn);
ThemeHelper.updateButtonTextColor(licenseBtn);
ThemeHelper.updateTextViewLinkColor(maintainers);
ThemeHelper.updateTextViewLinkColor(thirdPartyLibs);
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public boolean onBackPressed() {
return false;
}
}
/**
* Fragment that shows debug information like app version, pod version...
*/
public static class DebugFragment extends Fragment implements Observer {
public static final String TAG = "com.github.dfa.diaspora_android.AboutActivity.DebugFragment";
@BindView(R.id.fragment_debug__package_name)
TextView packageName;
@BindView(R.id.fragment_debug__app_version)
TextView appVersion;
@BindView(R.id.fragment_debug__android_version)
TextView osVersion;
@BindView(R.id.fragment_debug__device_name)
TextView deviceName;
@BindView(R.id.fragment_debug__account_profile_name)
TextView podName;
@BindView(R.id.fragment_debug__account_profile_domain)
TextView podDomain;
@BindView(R.id.fragment_debug__log_box)
TextView logBox;
public DebugFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.about__fragment_debug, container, false);
ButterKnife.bind(this, rootView);
App app = (App) getActivity().getApplication();
logBox.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (isAdded()) {
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("DEBUG_LOG", AppLog.Log.getLogBuffer());
clipboard.setPrimaryClip(clip);
Toast.makeText(DebugFragment.this.getActivity(), R.string.debug_log_copied_to_clipboard, Toast.LENGTH_SHORT).show();
} else {
AppLog.d(this, "Not Added!");
}
return true;
}
});
AppLog.Log.addLogObserver(this);
update(AppLog.Log.getInstance(), null);
if (isAdded()) {
try {
PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
AppSettings appSettings = ((App) getActivity().getApplication()).getSettings();
packageName.setText(pInfo.packageName);
appVersion.setText(getString(R.string.app_version_with_arg, pInfo.versionName + " (" + pInfo.versionCode + ")"));
osVersion.setText(getString(R.string.android_version_witharg, Build.VERSION.RELEASE));
deviceName.setText(getString(R.string.device_name_witharg, Build.MANUFACTURER + " " + Build.MODEL));
if (app.getSettings().getPod() != null) {
podDomain.setText(getString(R.string.pod_domain_witharg__appspecific, app.getSettings().getPod().getPodUrl()));
podName.setText(getString(R.string.pod_profile_name_witharg__appspecific, app.getSettings().getPod().getName()));
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
return rootView;
}
@Override
public void onDestroyView() {
AppLog.Log.removeLogObserver(this);
super.onDestroyView();
}
@Override
public void update(Observable observable, Object o) {
if (logBox != null) {
logBox.setText(AppLog.Log.getLogBuffer());
}
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: //About
return new AboutFragment();
case 1: //License
return new LicenseFragment();
case 2: //Debug
default:
return new DebugFragment();
}
}
@Override
public int getCount() {
// Show 3 total pages.
return 3;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.about);
case 1:
return getString(R.string.license);
case 2:
return getString(R.string.debugging);
}
return null;
}
}
}

View file

@ -0,0 +1,416 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity;
import android.Manifest;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Toast;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.BuildConfig;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.web.BrowserFragment;
import com.github.dfa.diaspora_android.web.DiasporaStreamWebChromeClient;
import com.github.dfa.diaspora_android.web.FileUploadWebChromeClient;
import com.github.dfa.diaspora_android.web.WebHelper;
import net.gsantner.opoc.util.PermissionChecker;
import net.gsantner.opoc.util.ShareUtil;
import org.json.JSONException;
import java.io.File;
import java.io.IOException;
import java.util.Date;
/**
* Fragment that displays the Stream of the diaspora* user
* Created by vanitas on 26.09.16.
*/
public class DiasporaStreamFragment extends BrowserFragment {
public static final String TAG = "com.github.dfa.diaspora_android.StreamFragment";
protected DiasporaUrlHelper urls;
private ValueCallback<Uri[]> imageUploadFilePathCallbackNew;
private ValueCallback<Uri> imageUploadFilePathCallbackOld;
private String mCameraPhotoPath;
@SuppressLint("SetJavaScriptEnabled")
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.urls = new DiasporaUrlHelper(appSettings);
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
webView.setWebChromeClient(new DiasporaStreamWebChromeClient(webView, progressBar, fileUploadCallback, sharedTextCallback));
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JavaScriptInterface(), "AndroidBridge");
if (((MainActivity) getActivity()).getTextToBeShared() != null) {
loadUrl(urls.getNewPostUrl());
} else if (webView.getUrl() == null) {
loadUrl(urls.getStreamUrl());
}
}
});
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.stream__menu_top, menu);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
menu.findItem(R.id.action_share_pdf).setVisible(true);
}
final boolean darkBg = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor());
ContextUtils.get().tintMenuItems(menu, true, ContextCompat.getColor(getActivity(), darkBg ? R.color.white : R.color.black));
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
AppLog.d(this, "onActivityResult(): " + requestCode);
switch (requestCode) {
case MainActivity.INPUT_FILE_REQUEST_CODE_NEW:
case MainActivity.INPUT_FILE_REQUEST_CODE_OLD:
AppLog.v(this, "INPUT_FILE_REQUEST_CODE: " + requestCode);
onImageUploadResult(requestCode, resultCode, data);
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
AppLog.d(this, "StreamFragment.onOptionsItemSelected()");
ShareUtil shu = new ShareUtil(getContext());
PermissionChecker permc = new PermissionChecker(getActivity());
switch (item.getItemId()) {
case R.id.action_reload: {
if (WebHelper.isOnline(getContext())) {
reloadUrl();
return true;
} else {
return false;
}
}
case R.id.action_go_to_top: {
ObjectAnimator anim = ObjectAnimator.ofInt(webView, "scrollY", webView.getScrollY(), 0);
anim.setDuration(400);
anim.start();
return true;
}
case R.id.action_share_link: {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_dotdotdot)));
return true;
}
case R.id.action_share_pdf: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
shu.createPdf(webView, "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()));
}
return true;
}
case R.id.action_share_link_to_clipboard: {
shu.setClipboard(webView.getUrl());
Toast.makeText(getContext(), R.string.link_adress_copied, Toast.LENGTH_SHORT).show();
return true;
}
case R.id.action_create_launcher_shortcut: {
if (webView.getUrl() != null) {
Intent intent = new Intent(getContext(), MainActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(webView.getUrl()));
shu.createLauncherDesktopShortcut(intent, R.drawable.ic_launcher, webView.getTitle());
}
return true;
}
case R.id.action_take_screenshot: {
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) {
File fileSaveDirectory = appSettings.getAppSaveDirectory();
if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) {
Bitmap bmp = ShareUtil.getBitmapFromWebView(webView);
String filename = "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()) + ".jpg";
_cu.writeImageToFile(new File(fileSaveDirectory, filename), bmp);
Snackbar.make(webView, getString(R.string.saving_screenshot_as)
+ " " + filename, Snackbar.LENGTH_LONG).show();
}
}
return true;
}
case R.id.action_share_screenshot: {
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) {
shu.shareImage(ShareUtil.getBitmapFromWebView(webView));
}
return true;
}
}
return super.onOptionsItemSelected(item);
}
public void onImageUploadResult(int requestCode, int resultCode, Intent data) {
AppLog.d(this, "onImageUploadResult");
switch (requestCode) {
case MainActivity.INPUT_FILE_REQUEST_CODE_NEW: {
AppLog.v(this, "Upload image using recent method (Lollipop+)");
if (imageUploadFilePathCallbackNew == null || resultCode != Activity.RESULT_OK) {
AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackNew == null)
+ " resultCode: " + resultCode);
if (imageUploadFilePathCallbackNew != null)
imageUploadFilePathCallbackNew.onReceiveValue(new Uri[]{});
return;
}
Uri[] results = null;
if (data == null) {
if (mCameraPhotoPath != null) {
AppLog.v(this, "Intent data is null. Try to parse cameraPhotoPath");
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
} else {
AppLog.w(this, "Intent data is null and cameraPhotoPath is null");
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
AppLog.v(this, "Intent has data. Try to parse dataString");
results = new Uri[]{Uri.parse(dataString)};
} else {
AppLog.w(this, "dataString is null");
}
}
AppLog.v(this, "handle received result over to callback");
imageUploadFilePathCallbackNew.onReceiveValue(results);
imageUploadFilePathCallbackNew = null;
return;
}
case MainActivity.INPUT_FILE_REQUEST_CODE_OLD: {
AppLog.v(this, "Upload image using legacy method (Jelly Bean, Kitkat)");
if (imageUploadFilePathCallbackOld == null || resultCode != Activity.RESULT_OK) {
AppLog.e(this, "Callback is null: " + (imageUploadFilePathCallbackOld == null)
+ " resultCode: " + resultCode);
if (imageUploadFilePathCallbackOld != null)
imageUploadFilePathCallbackOld.onReceiveValue(null);
return;
}
Uri results = null;
if (data == null) {
if (mCameraPhotoPath != null) {
AppLog.v(this, "Intent has no data. Try to parse cameraPhotoPath");
results = Uri.parse(mCameraPhotoPath);
} else {
AppLog.w(this, "Intent has no data and cameraPhotoPath is null");
}
} else {
String dataString = data.getDataString();
if (dataString != null) {
AppLog.v(this, "Intent has data. Try to parse dataString");
results = Uri.parse(dataString);
} else {
AppLog.w(this, "dataString is null");
}
}
AppLog.v(this, "handle received result over to callback");
imageUploadFilePathCallbackOld.onReceiveValue(results);
imageUploadFilePathCallbackOld = null;
}
}
}
protected DiasporaStreamWebChromeClient.SharedTextCallback sharedTextCallback = new DiasporaStreamWebChromeClient.SharedTextCallback() {
@Override
public String getSharedText() {
if (getActivity() != null) {
return ((MainActivity) getActivity()).getTextToBeShared();
}
return "";
}
@Override
public void setSharedText(String shared) {
((MainActivity) getActivity()).setTextToBeShared(shared);
}
};
protected FileUploadWebChromeClient.FileUploadCallback fileUploadCallback = new FileUploadWebChromeClient.FileUploadCallback() {
@Override
public boolean imageUpload(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (Build.VERSION.SDK_INT >= 23) {
int hasWRITE_EXTERNAL_STORAGE = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new ThemedAlertDialogBuilder(getContext(), appSettings)
.setMessage(R.string.image_permission_description__appspecific)
.setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (android.os.Build.VERSION.SDK_INT >= 23)
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
}
})
.show();
return false;
}
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE_ASK_PERMISSIONS);
return false;
}
}
AppLog.v(this, "onOpenFileChooser");
imageUploadFilePathCallbackNew = filePathCallback;
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile;
try {
photoFile = ContextUtils.get().createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) {
AppLog.e(this, "ERROR creating temp file: " + ex.toString());
// Error occurred while creating the File
Snackbar.make(webView, R.string.unable_to_load_image, Snackbar.LENGTH_LONG).show();
return false;
}
// Continue only if the File was successfully created
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ACTION_GET_CONTENT);
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE);
contentSelectionIntent.setType("image/*");
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[]{takePictureIntent};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER);
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent);
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
AppLog.d(this, "startActivityForResult");
startActivityForResult(chooserIntent, MainActivity.INPUT_FILE_REQUEST_CODE_NEW);
return true;
}
@Override
public void legacyImageUpload(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
AppLog.v(this, "openFileChooser(ValCallback<Uri>, String, String");
imageUploadFilePathCallbackOld = uploadMsg;
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.putExtra("return-data", true);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
AppLog.v(this, "startActivityForResult");
startActivityForResult(Intent.createChooser(intent, "Select Picture"), MainActivity.INPUT_FILE_REQUEST_CODE_OLD);
}
};
private class JavaScriptInterface {
@SuppressWarnings("unused")
@JavascriptInterface
public void setUserProfile(final String webMessage) throws JSONException {
final Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
App app = ((App) activity.getApplication());
final DiasporaUserProfile pup = app.getDiasporaUserProfile();
if (pup.isRefreshNeeded()) {
try {
// Try to very fail-safe check if user information gets really loaded from correct pod
if (!webView.getUrl().startsWith(app.getSettings().getPod().getPodUrl().getBaseUrl())) {
return;
}
} catch (Exception ignored) {
return;
}
AppLog.v(this, "DiasporaUserProfile needs refresh; Try to parse JSON");
pup.parseJson(webMessage);
getActivity().runOnUiThread(new Runnable() {
public void run() {
pup.analyzeUrl(webView.getUrl());
}
});
}
}
});
}
}
@SuppressWarnings("unused")
@JavascriptInterface
public void contentHasBeenShared() {
if (getActivity() != null) {
((MainActivity) getActivity()).setTextToBeShared(null);
}
}
}
@Override
public String getFragmentTag() {
return TAG;
}
}

View file

@ -1,248 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.text.util.Linkify;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.CookieManager;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.task.GetPodsService;
import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.WebHelper;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnItemClick;
public class PodSelectionActivity extends AppCompatActivity {
private App app;
@BindView(R.id.podselection__edit_filter)
public EditText editFilter;
@BindView(R.id.podselection__listpods)
public ListView listPods;
@BindView(R.id.toolbar)
public Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.podselection__activity);
ButterKnife.bind(this);
app = (App) getApplication();
setSupportActionBar(toolbar);
listPods.setTextFilterEnabled(true);
setListedPods(app.getSettings().getPreviousPodlist());
LocalBroadcastManager.getInstance(this).registerReceiver(podListReceiver, new IntentFilter(GetPodsService.MESSAGE_PODS_RECEIVED));
if (!WebHelper.isOnline(PodSelectionActivity.this)) {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
}
}
private final BroadcastReceiver podListReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra("pods")) {
Bundle extras = intent.getExtras();
String[] pods = extras.getStringArray("pods");
if (pods != null && pods.length > 0) {
app.getSettings().setPreviousPodlist(pods);
setListedPods(pods);
} else {
setListedPods(app.getSettings().getPreviousPodlist());
Snackbar.make(listPods, R.string.podlist_error, Snackbar.LENGTH_SHORT).show();
}
}
}
};
@OnClick(R.id.podselection__button_select_pod)
public void onButtonSelectPodClicked(View view) {
if (editFilter.getText().length() > 4 && editFilter.getText().toString().contains("")) {
showPodConfirmationDialog(editFilter.getText().toString());
} else {
Snackbar.make(listPods, R.string.valid_pod, Snackbar.LENGTH_LONG).show();
}
}
@Override
protected void onResume() {
super.onResume();
Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class);
startService(i);
}
private void setListedPods(String[] listedPodsArr) {
final ArrayList<String> listedPodsList = new ArrayList<>();
for (String pod : listedPodsArr) {
listedPodsList.add(pod.toLowerCase());
}
final ArrayAdapter<String> adapter = new ArrayAdapter<>(
PodSelectionActivity.this,
android.R.layout.simple_list_item_1,
listedPodsList);
// save index and top position
int index = listPods.getFirstVisiblePosition();
View v = listPods.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - listPods.getPaddingTop());
listPods.setAdapter(adapter);
listPods.setSelectionFromTop(index, top);
adapter.getFilter().filter(editFilter.getText());
editFilter.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
(adapter).getFilter().filter(s.toString());
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void afterTextChanged(Editable s) {
}
});
}
@OnItemClick(R.id.podselection__listpods)
public void onListPodsItemClicked(int position) {
showPodConfirmationDialog((String) listPods.getAdapter().getItem(position));
}
private void showPodConfirmationDialog(final String selectedPod) {
// Make a clickable link
final SpannableString dialogMessage = new SpannableString(getString(R.string.confirm_pod, selectedPod));
Linkify.addLinks(dialogMessage, Linkify.ALL);
// Check if online
if (!WebHelper.isOnline(PodSelectionActivity.this)) {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
return;
}
// Show dialog
new AlertDialog.Builder(PodSelectionActivity.this)
.setTitle(getString(R.string.confirmation))
.setMessage(dialogMessage)
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
onPodSelectionConfirmed(selectedPod);
}
})
.setNegativeButton(android.R.string.no, null)
.show();
}
public void onPodSelectionConfirmed(String selectedPod) {
app.getSettings().setPodDomain(selectedPod);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
try {
CookieManager.getInstance().removeAllCookies(null);
CookieManager.getInstance().removeSessionCookies(null);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
CookieManager.getInstance().removeAllCookie();
CookieManager.getInstance().removeSessionCookie();
} catch (Exception e) {
e.printStackTrace();
}
}
Helpers.animateToActivity(this, MainActivity.class, true);
}
@Override
public void onBackPressed() {
Snackbar.make(listPods, R.string.confirm_exit, Snackbar.LENGTH_LONG)
.setAction(android.R.string.yes, new View.OnClickListener() {
public void onClick(View view) {
finish();
}
})
.show();
}
@Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(podListReceiver);
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.pods__menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_reload: {
if (WebHelper.isOnline(PodSelectionActivity.this)) {
Intent i = new Intent(PodSelectionActivity.this, GetPodsService.class);
startService(i);
return true;
} else {
Snackbar.make(listPods, R.string.no_internet, Snackbar.LENGTH_LONG).show();
return false;
}
}
}
return super.onOptionsItemSelected(item);
}
}

View file

@ -0,0 +1,311 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.SearchView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.CookieManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaPodList;
import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod;
import com.github.dfa.diaspora_android.service.FetchPodsService;
import com.github.dfa.diaspora_android.ui.PodSelectionDialog;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.ActivityUtils;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Fragment that lets the user choose a Pod
* Created by vanitas on 01.10.16.
*/
public class PodSelectionFragment extends ThemedFragment implements SearchView.OnQueryTextListener, PodSelectionDialog.PodSelectionDialogResultListener {
public static final String TAG = "com.github.dfa.diaspora_android.PodSelectionFragment";
@BindView(R.id.podselection__fragment__listpods)
protected ListView listViewPod;
@BindView(R.id.podselection__fragment__root)
RelativeLayout rootView;
@BindView(R.id.podselection__fragment__button_use_custom_pod)
AppCompatButton buttonUseCustomPod;
protected App app;
protected AppSettings appSettings;
private DiasporaPodList podList;
private ArrayAdapter<String> listViewPodAdapter;
private String filterString = "";
@Override
protected int getLayoutResId() {
return R.layout.podselection__fragment;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
app = (App) getActivity().getApplication();
appSettings = app.getSettings();
// Load local podlist
podList = new DiasporaPodList();
mergePodlistWithRessources(podList);
podList.setTrackMergeChanges(true);
updateListedPods();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
listViewPod.setNestedScrollingEnabled(true);
}
listViewPod.setTextFilterEnabled(true);
listViewPod.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String text = ((TextView) view).getText().toString();
for (DiasporaPod pod : podList) {
if (pod.getPodUrl().getHost().equals(text)) {
showPodSelectionDialog(pod);
return;
}
}
}
});
LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(FetchPodsService.MESSAGE_PODS_RECEIVED));
ActivityUtils.get(getActivity()).showInfoIfUserNotConnectedToInternet(listViewPod);
}
public void mergePodlistWithRessources(DiasporaPodList podlist) {
String sPodlist = ContextUtils.get().readTextfileFromRawRes(R.raw.podlist, "", "");
try {
JSONObject jPodlist = new JSONObject(sPodlist);
podlist.mergeWithNewerEntries(new DiasporaPodList().fromJson(jPodlist));
} catch (JSONException e) {
e.printStackTrace();
}
}
@OnClick(R.id.podselection__fragment__button_use_custom_pod)
public void onPodButtonClicked(View v) {
showPodSelectionDialog(new DiasporaPod());
}
@Override
public String getFragmentTag() {
return TAG;
}
private final BroadcastReceiver podListReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.hasExtra(FetchPodsService.EXTRA_PODLIST)) {
Bundle extras = intent.getExtras();
DiasporaPodList newPods = (DiasporaPodList) extras.get(FetchPodsService.EXTRA_PODLIST);
if (newPods != null && newPods.getPods().size() > 0) {
try {
podList.mergeWithNewerEntries(newPods);
updateListedPods();
} catch (JSONException ignored) {
}
} else {
Snackbar.make(listViewPod, R.string.could_not_retrieve_list_of_pods__appspecific, Snackbar.LENGTH_SHORT).show();
}
}
}
};
@Override
protected void applyColorToViews() {
int dividerHeight = listViewPod.getDividerHeight();
rootView.setBackgroundColor(appSettings.isAmoledColorMode() ? Color.BLACK : Color.WHITE);
listViewPod.setDivider(new ColorDrawable(Color.GRAY));
listViewPod.setDividerHeight(dividerHeight);
int bgcolor = appSettings.isAmoledColorMode() ? Color.DKGRAY : appSettings.getAccentColor();
buttonUseCustomPod.setBackgroundColor(bgcolor);
buttonUseCustomPod.setTextColor(_cu.shouldColorOnTopBeLight(bgcolor) ? Color.WHITE : Color.BLACK);
}
@Override
public void onResume() {
super.onResume();
Intent i = new Intent(getContext(), FetchPodsService.class);
getContext().startService(i);
}
private void updateListedPods() {
final ArrayList<String> listedPodsList = new ArrayList<>();
for (DiasporaPod pod : this.podList) {
listedPodsList.add(pod.getPodUrl().getHost());
}
listViewPodAdapter = new ArrayAdapter<String>(
getContext(),
android.R.layout.simple_list_item_1,
listedPodsList) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
TextView textView = view.findViewById(android.R.id.text1);
textView.setTextColor(appSettings.isAmoledColorMode() ? Color.GRAY : Color.BLACK);
return view;
}
};
// save index and top position
int index = listViewPod.getFirstVisiblePosition();
View v = listViewPod.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - listViewPod.getPaddingTop());
listViewPod.setAdapter(listViewPodAdapter);
listViewPod.setSelectionFromTop(index, top);
listViewPodAdapter.getFilter().filter(filterString);
}
private void showPodSelectionDialog(final DiasporaPod selectedPod) {
PodSelectionDialog dialog = PodSelectionDialog.newInstance(selectedPod, this);
dialog.show(getFragmentManager(), PodSelectionDialog.TAG);
}
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(podListReceiver);
super.onDestroy();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.podselection__menu, menu);
MenuItem searchItem = menu.findItem(R.id.podselection__action_search);
if (searchItem != null) {
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(this);
}
final boolean darkBg = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor());
ContextUtils.get().tintMenuItems(menu, true, ContextCompat.getColor(getActivity(), darkBg ? R.color.white : R.color.black));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_reload: {
if (!ActivityUtils.get(getActivity()).showInfoIfUserNotConnectedToInternet(listViewPod)) {
Intent i = new Intent(getContext(), FetchPodsService.class);
getContext().startService(i);
return true;
}
}
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onQueryTextChange(String newText) {
if (listViewPodAdapter != null) {
(listViewPodAdapter).getFilter().filter(newText);
}
return true;
}
@Override
public void onPodSelectionDialogResult(DiasporaPod pod, boolean accepted) {
System.out.println(accepted + ": " + pod.toString());
if (accepted) {
app.getSettings().setPod(pod);
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
CookieManager.getInstance().removeAllCookies(null);
CookieManager.getInstance().removeSessionCookies(null);
} else {
//noinspection deprecation
CookieManager.getInstance().removeAllCookie();
//noinspection deprecation
CookieManager.getInstance().removeSessionCookie();
}
} catch (Exception e) {
e.printStackTrace();
}
MainActivity mainActivity = (MainActivity) getActivity();
DiasporaUrlHelper urlHelper = new DiasporaUrlHelper(appSettings);
mainActivity.onPodSelectionDialogResult(pod, accepted);
mainActivity.openDiasporaUrl(urlHelper.getSignInUrl());
}
}
/*
* Dummy implementations
*/
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public boolean isAllowedIntellihide() {
return false;
}
}

View file

@ -1,122 +1,232 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity; package com.github.dfa.diaspora_android.activity;
import android.app.AlertDialog; import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.FragmentTransaction;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment; import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.support.design.widget.AppBarLayout;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.ui.theme.ColorPalette;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.ui.theme.ThemedActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
import com.github.dfa.diaspora_android.ui.theme.ThemedPreferenceFragment;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.web.ProxyHandler;
/** import butterknife.BindView;
* @author vanitas import butterknife.ButterKnife;
*/ import uz.shift.colorpicker.LineColorPicker;
public class SettingsActivity extends PreferenceActivity { import uz.shift.colorpicker.OnColorChangedListener;
private boolean activityRestartRequired;
public class SettingsActivity extends ThemedActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
//Toolbar
@BindView(R.id.settings__appbar)
protected AppBarLayout appBarLayout;
@BindView(R.id.settings__toolbar)
protected Toolbar toolbar;
private ProxyHandler.ProxySettings oldProxySettings;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.settings__activity);
ButterKnife.bind(this);
toolbar.setTitle(R.string.settings);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24px));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SettingsActivity.this.onBackPressed();
}
});
getAppSettings().registerPreferenceChangedListener(this);
oldProxySettings = getAppSettings().getProxySettings();
showFragment(SettingsFragmentMaster.TAG, false);
}
protected void showFragment(String tag, boolean addToBackStack) {
PreferenceFragment fragment = (PreferenceFragment) getFragmentManager().findFragmentByTag(tag);
if (fragment == null) {
switch (tag) {
case SettingsFragmentThemes.TAG:
fragment = new SettingsFragmentThemes();
break;
case SettingsFragmentNavSlider.TAG:
fragment = new SettingsFragmentNavSlider();
break;
case SettingsFragmentProxy.TAG:
fragment = new SettingsFragmentProxy();
break;
case SettingsFragmentDebugging.TAG:
fragment = new SettingsFragmentDebugging();
break;
case SettingsFragmentMaster.TAG:
default:
fragment = new SettingsFragmentMaster();
break;
}
}
FragmentTransaction t = getFragmentManager().beginTransaction();
if (addToBackStack) {
t.addToBackStack(tag);
}
t.replace(R.id.settings__fragment_container, fragment, tag).commit();
}
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void applyColorToViews() {
super.onCreate(savedInstanceState); //Toolbar
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); ThemeHelper.updateToolbarColor(toolbar);
} }
public void setActivityRestartRequired(boolean b) { @Override
this.activityRestartRequired = b; protected void onStop() {
ProxyHandler.ProxySettings newProxySettings = getAppSettings().getProxySettings();
if (!oldProxySettings.equals(newProxySettings)) {
AppLog.d(this, "ProxySettings changed.");
//Proxy on-off? => Restart app
if (oldProxySettings.isEnabled() && !newProxySettings.isEnabled()) {
AppLog.d(this, "Proxy deactivated. Restarting app...");
Intent restartActivity = new Intent(SettingsActivity.this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(SettingsActivity.this, 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
System.exit(0);
} //Proxy changed? => Update
else {
ProxyHandler.getInstance().updateProxySettings(this);
}
}
getAppSettings().unregisterPreferenceChangedListener(this);
super.onStop();
} }
public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { @Override
private SharedPreferences sharedPreferences; public void onBackPressed() {
ThemedPreferenceFragment top = getTopFragment();
if (top != null && top.getFragmentTag().equals(SettingsFragmentProxy.TAG)) {
ProxyHandler.ProxySettings newProxySettings = getAppSettings().getProxySettings();
if (oldProxySettings.isEnabled() && !newProxySettings.isEnabled()) {
Toast.makeText(this, R.string.app_needs_restart_to_disable_proxy_usage, Toast.LENGTH_LONG).show();
}
}
super.onBackPressed();
}
/**
* Return the fragment which is currently displayed in R.id.fragment_container
*
* @return top fragment or null if there is none displayed
*/
private ThemedPreferenceFragment getTopFragment() {
return (ThemedPreferenceFragment) getFragmentManager().findFragmentById(R.id.settings__fragment_container);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (key.equals(getString(R.string.pref_key__screen_rotation))) {
this.updateScreenRotation();
}
}
public static class SettingsFragmentMaster extends ThemedPreferenceFragment {
public static final String TAG = "com.github.dfa.diaspora_android.settings.SettingsFragmentMaster";
public void onCreate(Bundle savedInstances) { public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances); super.onCreate(savedInstances);
getPreferenceManager().setSharedPreferencesName("app"); getPreferenceManager().setSharedPreferencesName("app");
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences__master);
sharedPreferences = getPreferenceScreen().getSharedPreferences();
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
setPreferenceSummaries();
sharedPreferences.edit().putBoolean(getString(R.string.pref_key__proxy_was_enabled),
sharedPreferences.getBoolean(getString(R.string.pref_key__proxy_enabled), false)).apply();
}
private void setPreferenceSummaries() {
String[] editTextKeys = new String[]{
getString(R.string.pref_key__proxy_host), getString(R.string.pref_key__proxy_port)
};
for (String key : editTextKeys) {
EditTextPreference p = (EditTextPreference) findPreference(key);
p.setSummary(p.getText());
}
} }
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void updateViewColors() {
updatePreference(findPreference(key));
}
private void updatePreference(Preference preference) {
if (preference == null) {
return;
}
if (preference instanceof EditTextPreference) {
EditTextPreference textPref = (EditTextPreference) preference;
textPref.setSummary(textPref.getText());
return;
}
if (preference instanceof ListPreference) {
ListPreference listPref = (ListPreference) preference;
listPref.setSummary(listPref.getEntry());
}
} }
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
Intent intent = new Intent(getActivity(), MainActivity.class); if (isAdded() && preference.hasKey()) {
String podDomain = ((App) getActivity().getApplication()).getSettings().getPodDomain(); AppSettings settings = ((App) getActivity().getApplication()).getSettings();
switch (preference.getTitleRes()) { DiasporaUrlHelper diasporaUrlHelper = new DiasporaUrlHelper(settings);
case R.string.pref_title__personal_settings: { String key = preference.getKey();
intent.setAction(MainActivity.ACTION_OPEN_URL); /** Sub-Categories */
intent.putExtra(MainActivity.URL_MESSAGE, "https://" + podDomain + "/user/edit"); if (settings.isKeyEqual(key, R.string.pref_key__cat_themes)) {
break; ((SettingsActivity) getActivity()).showFragment(SettingsFragmentThemes.TAG, true);
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__cat_nav_slider)) {
((SettingsActivity) getActivity()).showFragment(SettingsFragmentNavSlider.TAG, true);
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__cat_proxy)) {
((SettingsActivity) getActivity()).showFragment(SettingsFragmentProxy.TAG, true);
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__cat_debugging)) {
((SettingsActivity) getActivity()).showFragment(SettingsFragmentDebugging.TAG, true);
return true;
} }
case R.string.pref_title__manage_tags: { /** Usability */
intent.setAction(MainActivity.ACTION_OPEN_URL); else if (settings.isKeyEqual(key, R.string.pref_key__is_overview_statusbar_hidden)) {
intent.putExtra(MainActivity.URL_MESSAGE, "https://" + podDomain + "/tag_followings/manage"); AppSettings.get().setRecreateMainActivity(true);
break; } else if (settings.isKeyEqual(key, R.string.pref_key__language)) {
AppSettings.get().setRecreateMainActivity(true);
} }
case R.string.pref_title__manage_contacts: { /** Network */
intent.setAction(MainActivity.ACTION_OPEN_URL); else if (settings.isKeyEqual(key, R.string.pref_key__clear_cache)) {
intent.putExtra(MainActivity.URL_MESSAGE, "https://" + podDomain + "/contacts"); Intent intent = new Intent(getActivity(), MainActivity.class);
break; intent.setAction(MainActivity.ACTION_CLEAR_CACHE);
startActivity(intent);
getActivity().finish();
return true;
} }
case R.string.pref_title__change_account: { /** Pod Settings */
new AlertDialog.Builder(getActivity()) if (settings.isKeyEqual(key, R.string.pref_key__personal_settings)) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setAction(MainActivity.ACTION_OPEN_URL);
intent.putExtra(MainActivity.URL_MESSAGE, diasporaUrlHelper.getPersonalSettingsUrl());
startActivity(intent);
getActivity().finish();
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__manage_tags)) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setAction(MainActivity.ACTION_OPEN_URL);
intent.putExtra(MainActivity.URL_MESSAGE, diasporaUrlHelper.getManageTagsUrl());
startActivity(intent);
getActivity().finish();
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__manage_contacts)) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setAction(MainActivity.ACTION_OPEN_URL);
intent.putExtra(MainActivity.URL_MESSAGE, diasporaUrlHelper.getContactsUrl());
startActivity(intent);
getActivity().finish();
return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__change_account)) {
new ThemedAlertDialogBuilder(getActivity(), AppSettings.get())
.setTitle(getString(R.string.confirmation)) .setTitle(getString(R.string.confirmation))
.setMessage(getString(R.string.pref_warning__change_account)) .setMessage(getString(R.string.logout_warning_description))
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, .setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() { new DialogInterface.OnClickListener() {
@ -129,41 +239,263 @@ public class SettingsActivity extends PreferenceActivity {
}) })
.show(); .show();
return true; return true;
}
case R.string.pref_title__clear_cache: {
intent.setAction(MainActivity.ACTION_CLEAR_CACHE);
break;
}
case R.string.pref_title__intellihide_toolbars: {
((SettingsActivity) getActivity()).setActivityRestartRequired(true);
return true;
}
default: {
intent = null;
break;
} }
} }
if (preference.getKey() != null && preference.getKey().startsWith("pref_key__visibility_nav__")) {
((SettingsActivity) getActivity()).setActivityRestartRequired(true);
return true;
}
if (intent != null) {
startActivity(intent);
getActivity().finish();
return true;
}
return super.onPreferenceTreeClick(screen, preference); return super.onPreferenceTreeClick(screen, preference);
} }
@Override
public String getFragmentTag() {
return TAG;
}
} }
@Override public static class SettingsFragmentThemes extends ThemedPreferenceFragment {
protected void onStop() { public static final String TAG = "com.github.dfa.diaspora_android.settings.SettingsFragmentThemes";
super.onStop();
if (activityRestartRequired) { public void onCreate(Bundle savedInstances) {
Intent intent = new Intent(this, MainActivity.class); super.onCreate(savedInstances);
intent.setAction(MainActivity.ACTION_RELOAD_ACTIVITY); getPreferenceManager().setSharedPreferencesName("app");
startActivity(intent); addPreferencesFromResource(R.xml.preferences__sub_themes);
}
@Override
public void updateViewColors() {
if (isAdded()) {
//Trigger redraw of whole preference screen in order to reflect changes
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.preferences__sub_themes);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
AppSettings settings = ((App) getActivity().getApplication()).getSettings();
DiasporaUrlHelper diasporaUrlHelper = new DiasporaUrlHelper(settings);
if (isAdded() && preference.hasKey()) {
String key = preference.getKey();
if (key.equals(getString(R.string.pref_key__primary_color__preference_click))) {
showColorPickerDialog(1);
return true;
} else if (key.equals(getString(R.string.pref_key__accent_color__preference_click))) {
showColorPickerDialog(2);
return true;
} else if (key.equals(getString(R.string.pref_key__manage_theme))) {
Intent intent = new Intent(getActivity(), MainActivity.class);
intent.setAction(MainActivity.ACTION_OPEN_URL);
intent.putExtra(MainActivity.URL_MESSAGE, diasporaUrlHelper.getThemeUrl());
startActivity(intent);
getActivity().finish();
return true;
}
}
return super.onPreferenceTreeClick(screen, preference);
}
@Override
public String getFragmentTag() {
return TAG;
}
/**
* Show a colorPicker Dialog
*
* @param type 1 -> Primary Color, 2 -> Accent Color
*/
@SuppressLint("InflateParams")
public void showColorPickerDialog(final int type) {
final AppSettings appSettings = ((App) getActivity().getApplication()).getSettings();
final Context context = getActivity();
//Inflate dialog layout
LayoutInflater inflater = getActivity().getLayoutInflater();
View dialogLayout = inflater.inflate(R.layout.ui__dialog__color_picker, null);
final ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(context, appSettings);
builder.setView(dialogLayout);
final FrameLayout titleBackground = dialogLayout.findViewById(R.id.color_picker_dialog__title_background);
final TextView title = dialogLayout.findViewById(R.id.color_picker_dialog__title);
final LineColorPicker base = dialogLayout.findViewById(R.id.color_picker_dialog__base_picker);
final LineColorPicker shade = dialogLayout.findViewById(R.id.color_picker_dialog__shade_picker);
title.setText(type == 1 ? R.string.primary_colors : R.string.accent_color);
title.setTextColor(getResources().getColor(R.color.white));
final int[] current = (type == 1 ? appSettings.getPrimaryColorSettings() : appSettings.getAccentColorSettings());
base.setColors((type == 1 ? ColorPalette.getBaseColors(context) : ColorPalette.getAccentColors(context)));
base.setSelectedColor(current[0]);
shade.setColors(ColorPalette.getColors(context, current[0]));
shade.setSelectedColor(current[1]);
titleBackground.setBackgroundColor(shade.getColor());
base.setOnColorChangedListener(new OnColorChangedListener() {
@Override
public void onColorChanged(int i) {
shade.setColors(ColorPalette.getColors(context, i));
titleBackground.setBackgroundColor(i);
if (i == current[0]) {
shade.setSelectedColor(current[1]);
titleBackground.setBackgroundColor(shade.getColor());
} else {
shade.setSelectedColor(i);
}
}
});
shade.setOnColorChangedListener(new OnColorChangedListener() {
@Override
public void onColorChanged(int i) {
titleBackground.setBackgroundColor(i);
}
});
//Build dialog
builder
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (type == 1) {
appSettings.setPrimaryColorSettings(base.getColor(), shade.getColor());
if (Build.VERSION.SDK_INT >= 21) {
getActivity().getWindow().setStatusBarColor(ThemeHelper.getPrimaryDarkColor());
}
((SettingsActivity) getActivity()).applyColorToViews();
} else {
appSettings.setAccentColorSettings(base.getColor(), shade.getColor());
}
updateViewColors();
}
}).show();
}
}
public static class SettingsFragmentNavSlider extends ThemedPreferenceFragment {
public static final String TAG = "com.github.dfa.diaspora_android.settings.SettingsFragmentNavSlider";
public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances);
getPreferenceManager().setSharedPreferencesName("app");
addPreferencesFromResource(R.xml.preferences__sub_navslider_vis);
}
@Override
public void updateViewColors() {
}
@Override
public String getFragmentTag() {
return TAG;
}
}
public static class SettingsFragmentProxy extends ThemedPreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String TAG = "com.github.dfa.diaspora_android.settings.SettingsFragmentProxy";
public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances);
getPreferenceManager().setSharedPreferencesName("app");
addPreferencesFromResource(R.xml.preferences__sub_proxy);
SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onActivityCreated(Bundle bundle) {
super.onActivityCreated(bundle);
updateSummaries();
}
public void updateSummaries() {
if (isAdded()) {
AppSettings settings = ((App) getActivity().getApplication()).getSettings();
findPreference(settings.rstr(R.string.pref_key__http_proxy_host)).setSummary(settings.getProxyHttpHost());
findPreference(settings.rstr(R.string.pref_key__http_proxy_port)).setSummary(Integer.toString(settings.getProxyHttpPort()));
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (isAdded() && preference.hasKey()) {
AppSettings appSettings = ((App) getActivity().getApplication()).getSettings();
String key = preference.getKey();
if (appSettings.isKeyEqual(key, R.string.pref_key__http_proxy_load_tor_preset)) {
appSettings.setProxyHttpHost("127.0.0.1");
appSettings.setProxyHttpPort(8118);
Toast.makeText(screen.getContext(), R.string.orbot_proxy_preset_loaded, Toast.LENGTH_SHORT).show();
return true;
}
}
return super.onPreferenceTreeClick(screen, preference);
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public void updateViewColors() {
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (isAdded()) {
if (key.equals(getString(R.string.pref_key__http_proxy_host)) ||
key.equals(getString(R.string.pref_key__http_proxy_port))) {
updateSummaries();
}
}
}
}
public static class SettingsFragmentDebugging extends ThemedPreferenceFragment {
public static final String TAG = "com.github.dfa.diaspora_android.settings.SettingsFragmentDebugging";
public void onCreate(Bundle savedInstances) {
super.onCreate(savedInstances);
getPreferenceManager().setSharedPreferencesName("app");
addPreferencesFromResource(R.xml.preferences__sub_debugging);
}
@Override
public void updateViewColors() {
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (isAdded() && preference.hasKey()) {
AppSettings appSettings = ((App) getActivity().getApplication()).getSettings();
String key = preference.getKey();
if (appSettings.isKeyEqual(key, R.string.pref_key__wipe_settings)) {
showWipeSettingsDialog();
return true;
}
}
return super.onPreferenceTreeClick(screen, preference);
}
private void showWipeSettingsDialog() {
final AppSettings appSettings = AppSettings.get();
ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(getActivity(), appSettings);
builder.setTitle(R.string.confirmation)
.setMessage(R.string.wipe_settings_warning__appspecific)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
appSettings.resetAppSettings();
appSettings.resetPodSettings();
new net.gsantner.opoc.util.ContextUtils(appSettings.getContext()).restartApp(MainActivity.class);
}
}).setNegativeButton(android.R.string.cancel, null)
.create().show();
} }
} }
} }

View file

@ -1,68 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.activity;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.WebHelper;
import butterknife.BindView;
import butterknife.ButterKnife;
public class SplashActivity extends AppCompatActivity {
private App app;
@BindView(R.id.splash__splashimage)
public ImageView imgSplash;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash__activity);
ButterKnife.bind(this);
app = (App) getApplication();
TypedArray images = getResources().obtainTypedArray(R.array.splash_images);
int choice = (int) (Math.random() * images.length());
imgSplash.setImageResource(images.getResourceId(choice, R.drawable.splashscreen1));
images.recycle();
int delay = getResources().getInteger(R.integer.splash_delay);
new Handler().postDelayed(startActivityRunnable, delay);
}
final Runnable startActivityRunnable = new Runnable() {
public void run() {
boolean hasPodDomain = app.getSettings().hasPodDomain();
Helpers.animateToActivity(SplashActivity.this,
hasPodDomain ? MainActivity.class : PodSelectionActivity.class,
true
);
}
};
}

View file

@ -1,297 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.data;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import com.github.dfa.diaspora_android.R;
/**
* Created by gsantner (https://gsantner.github.io/) on 20.03.16. Part of Diaspora for Android.
*/
public class AppSettings {
private final SharedPreferences prefApp;
private final SharedPreferences prefPod;
private final Context context;
public AppSettings(Context context) {
this.context = context.getApplicationContext();
prefApp = this.context.getSharedPreferences("app", Context.MODE_PRIVATE);
prefPod = this.context.getSharedPreferences("pod0", Context.MODE_PRIVATE);
}
public Context getApplicationContext() {
return context;
}
public void clearPodSettings() {
prefPod.edit().clear().apply();
}
public void clearAppSettings() {
prefApp.edit().clear().apply();
}
private void setString(SharedPreferences pref, int keyRessourceId, String value) {
pref.edit().putString(context.getString(keyRessourceId), value).apply();
}
private void setInt(SharedPreferences pref, int keyRessourceId, int value) {
pref.edit().putInt(context.getString(keyRessourceId), value).apply();
}
private void setBool(SharedPreferences pref, int keyRessourceId, boolean value) {
pref.edit().putBoolean(context.getString(keyRessourceId), value).apply();
}
private void setStringArray(SharedPreferences pref, int keyRessourceId, Object[] values) {
StringBuffer sb = new StringBuffer();
for (Object value : values) {
sb.append("%%%");
sb.append(value.toString());
}
setString(pref, keyRessourceId, sb.toString().replaceFirst("%%%", ""));
}
private String[] getStringArray(SharedPreferences pref, int keyRessourceId) {
String value = pref.getString(context.getString(keyRessourceId), "%%%");
if (value.equals("%%%")) {
return new String[0];
}
return value.split("%%%");
}
private String getString(SharedPreferences pref, int ressourceId, String defaultValue) {
return pref.getString(context.getString(ressourceId), defaultValue);
}
private boolean getBoolean(SharedPreferences pref, int ressourceId, boolean defaultValue) {
return pref.getBoolean(context.getString(ressourceId), defaultValue);
}
private int getInt(SharedPreferences pref, int ressourceId, int defaultValue) {
return pref.getInt(context.getString(ressourceId), defaultValue);
}
/*
// Setters & Getters
*/
public String getProfileId() {
return getString(prefPod, R.string.pref_key__podprofile_id, "");
}
public void setProfileId(String profileId) {
setString(prefPod, R.string.pref_key__podprofile_id, profileId);
}
public boolean isLoadImages() {
return getBoolean(prefApp, R.string.pref_key__load_images, true);
}
public int getMinimumFontSize() {
switch (getString(prefApp, R.string.pref_key__font_size, "")) {
case "huge":
return 20;
case "large":
return 16;
case "normal":
return 8;
default:
setString(prefApp, R.string.pref_key__font_size, "normal");
return 8;
}
}
public String getAvatarUrl() {
return getString(prefPod, R.string.pref_key__podprofile_avatar_url, "");
}
public void setAvatarUrl(String avatarUrl) {
setString(prefPod, R.string.pref_key__podprofile_avatar_url, avatarUrl);
}
public String getName() {
return getString(prefPod, R.string.pref_key__podprofile_name, "");
}
public void setName(String name) {
setString(prefPod, R.string.pref_key__podprofile_name, name);
}
public String getPodDomain() {
return getString(prefPod, R.string.pref_key__poddomain, "");
}
public void setPodDomain(String podDomain) {
setString(prefPod, R.string.pref_key__poddomain, podDomain);
}
public boolean hasPodDomain() {
return !getString(prefPod, R.string.pref_key__poddomain, "").equals("");
}
public String[] getPreviousPodlist() {
return getStringArray(prefApp, R.string.pref_key__previous_podlist);
}
public void setPreviousPodlist(String[] pods) {
setStringArray(prefApp, R.string.pref_key__previous_podlist, pods);
}
public void setPodAspects(PodAspect[] aspects) {
setStringArray(prefPod, R.string.pref_key__podprofile_aspects, aspects);
}
public PodAspect[] getPodAspects() {
String[] s = getStringArray(prefPod, R.string.pref_key__podprofile_aspects);
PodAspect[] aspects = new PodAspect[s.length];
for (int i = 0; i < aspects.length; i++) {
aspects[i] = new PodAspect(s[i]);
}
return aspects;
}
public String[] getFollowedTags() {
return getStringArray(prefPod, R.string.pref_key__podprofile_followed_tags);
}
public void setFollowedTags(String[] tags) {
setStringArray(prefPod, R.string.pref_key__podprofile_followed_tags, tags);
}
public int getUnreadMessageCount() {
return getInt(prefPod, R.string.pref_key__podprofile_unread_message_count, 0);
}
public void setUnreadMessageCount(int unreadMessageCount) {
setInt(prefPod, R.string.pref_key__podprofile_unread_message_count, unreadMessageCount);
}
public int getNotificationCount() {
return getInt(prefPod, R.string.pref_key__podprofile_notification_count, 0);
}
public void setNotificationCount(int notificationCount) {
setInt(prefPod, R.string.pref_key__podprofile_notification_count, notificationCount);
}
public boolean isAppendSharedViaApp() {
return getBoolean(prefApp, R.string.pref_key__append_shared_via_app, true);
}
@SuppressLint("CommitPrefEdits")
public void setProxyEnabled(boolean enabled) {
//commit instead of apply because the app is likely to be killed before apply is called.
prefApp.edit().putBoolean(context.getString(R.string.pref_key__proxy_enabled), enabled).commit();
}
/**
* Default return value: false
*
* @return whether proxy is enabled or not
*/
public boolean isProxyEnabled() {
return getBoolean(prefApp, R.string.pref_key__proxy_enabled, false);
}
public boolean wasProxyEnabled() {
return getBoolean(prefApp, R.string.pref_key__proxy_was_enabled, false);
}
/**
* Needed in order to determine, whether the proxy has just been disabled (trigger app restart)
* or if proxy was disabled before (do not restart app)
*
* @param b new value
*/
@SuppressLint("CommitPrefEdits")
public void setProxyWasEnabled(boolean b) {
prefApp.edit().putBoolean(context.getString(R.string.pref_key__proxy_was_enabled), b).commit();
}
/**
* Default value: ""
*
* @return proxy host
*/
public String getProxyHost() {
return getString(prefApp, R.string.pref_key__proxy_host, "");
}
/**
* Default value: 0
*
* @return proxy port
*/
public int getProxyPort() {
try {
return Integer.parseInt(getString(prefApp, R.string.pref_key__proxy_port, "0"));
} catch (Exception e) {
setString(prefApp, R.string.pref_key__proxy_port, "0");
return 0;
}
}
public boolean isIntellihideToolbars() {
return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, true);
}
public boolean isVisibleInNavExit() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__exit, false);
}
public boolean isVisibleInNavHelp_license() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__help_license, true);
}
public boolean isVisibleInNavPublic_activities() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__public_activities, false);
}
public boolean isVisibleInNavMentions() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__mentions, true);
}
public boolean isVisibleInNavCommented() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__commented, true);
}
public boolean isVisibleInNavLiked() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__liked, true);
}
public boolean isVisibleInNavActivities() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__activities, true);
}
public boolean isVisibleInNavAspects() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__aspects, true);
}
public boolean isVisibleInNavFollowed_tags() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__followed_tags, true);
}
public boolean isVisibleInNavProfile() {
return getBoolean(prefApp, R.string.pref_key__visibility_nav__profile, false);
}
}

View file

@ -1,43 +1,44 @@
/* /*
This file is part of the Diaspora for Android. This file is part of the dandelion*.
Diaspora for Android is free software: you can redistribute it and/or modify dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful, dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with the Diaspora for Android. along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.data; package com.github.dfa.diaspora_android.data;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.util.AppSettings;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.util.Locale; import java.util.Locale;
public class PodAspect { public class DiasporaAspect {
public long id; public long id;
public String name; public String name;
public boolean selected; public boolean selected;
public PodAspect(long id, String name, boolean selected) { public DiasporaAspect(long id, String name, boolean selected) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.selected = selected; this.selected = selected;
} }
public PodAspect(String shareabletext) { public DiasporaAspect(String shareabletext) {
// fromShareAbleText // fromShareAbleText
String[] str = shareabletext.split("%"); String[] str = shareabletext.split("%");
selected = Integer.parseInt(str[0]) == 1; selected = Integer.parseInt(str[0]) == 1;
@ -45,7 +46,7 @@ public class PodAspect {
name = shareabletext.substring(shareabletext.indexOf(str[1]) + str[1].length() + 1); name = shareabletext.substring(shareabletext.indexOf(str[1]) + str[1].length() + 1);
} }
public PodAspect(JSONObject json) throws JSONException { public DiasporaAspect(JSONObject json) throws JSONException {
if (json.has("id")) { if (json.has("id")) {
id = json.getLong("id"); id = json.getLong("id");
} }
@ -70,8 +71,8 @@ public class PodAspect {
public String toHtmlLink(final App app) { public String toHtmlLink(final App app) {
final AppSettings appSettings = app.getSettings(); final AppSettings appSettings = app.getSettings();
return String.format(Locale.getDefault(), return String.format(Locale.getDefault(),
"<a href='https://%s/aspects?a_ids[]=%d' style='color: #000000; text-decoration: none;'>%s</a>", "<a href='%s/aspects?a_ids[]=%d' style='color: #000000; text-decoration: none;'>%s</a>",
appSettings.getPodDomain(), id, name); appSettings.getPod().getPodUrl().getBaseUrl(), id, name);
} }
@Override @Override
@ -81,7 +82,7 @@ public class PodAspect {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
return o instanceof PodAspect && ((PodAspect) o).id == id; return o instanceof DiasporaAspect && ((DiasporaAspect) o).id == id;
} }
public String toShareAbleText() { public String toShareAbleText() {

View file

@ -0,0 +1,524 @@
package com.github.dfa.diaspora_android.data;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Created by gsantner (gsantner AT mailbox DOT org on 30.09.16.
* DiasporaPodList - List container for DiasporaPod's, with methods to merge with other DiasporaPodLists
* DiasporaPod - Data container for a Pod, can include N DiasporaPodUrl's
* DiasporaPodUrl - A Url of an DiasporaPod
* For all Classes a loading and saving to JSON method is available
*/
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue", "SpellCheckingInspection", "UnusedReturnValue", "JavaDoc", "FieldCanBeLocal"})
public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, Serializable {
private static final boolean EXPORT_TOJSON_POST_COUNT_LOCAL = true;
private List<DiasporaPod> pods = new ArrayList<>();
private boolean trackMergeChanges = false;
private Integer trackAddedIndexStart = -1;
private List<Integer> trackUpdatedIndexes = new ArrayList<>();
private boolean keepOldNameDuringMerge = false;
private long timestamp;
public DiasporaPodList() {
}
/**
* Load DiasporaPodList from Json
*
* @param json Json Object
*/
public DiasporaPodList fromJson(JSONObject json) throws JSONException {
JSONArray jarr;
pods.clear();
if (json.has("pods")) {
jarr = json.getJSONArray("pods");
for (int i = 0; i < jarr.length(); i++) {
DiasporaPod pod = new DiasporaPod().fromJson(jarr.getJSONObject(i));
pods.add(pod);
}
}
if (json.has("timestamp")) {
timestamp = json.getLong("timestamp");
}
return this;
}
/**
* Convert DiasporaPodList to JSON
*/
public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject();
JSONArray jpods = new JSONArray();
for (DiasporaPod pod : pods) {
jpods.put(pod.toJson());
}
json.put("pods", jpods);
json.put("timestamp", System.currentTimeMillis());
return json;
}
/**
* Merge newer entries into this podlist
* Will add new pods, and update data of pods with data from the new list
*
* @param newPodList Another podlist
*/
public void mergeWithNewerEntries(final DiasporaPodList newPodList) throws JSONException {
if (isTrackMergeChanges()) {
trackAddedIndexStart = -1;
trackUpdatedIndexes.clear();
}
for (DiasporaPod newPod : newPodList) {
int index = pods.indexOf(newPod);
if (index >= 0) {
DiasporaPod updatePodBak = new DiasporaPod().fromJson(pods.get(index).toJson());
DiasporaPod updatePod = pods.get(index);
updatePod.fromJson(newPod.toJson());
// Restore Pod id (if was set to zero)
if (updatePodBak.getId() != 0 && updatePod.getId() == 0) {
updatePod.setId(updatePodBak.getId());
}
if (updatePodBak.getPostCountLocal() != 0 && updatePod.getPostCountLocal() == 0) {
updatePod.setPostCountLocal(updatePodBak.getPostCountLocal());
}
if (updatePodBak.getScore() != 0 && updatePod.getScore() == 0) {
updatePod.setScore(updatePodBak.getScore());
}
if (!updatePodBak.getName().equals("") && keepOldNameDuringMerge) {
updatePod.setName(updatePodBak.getName());
}
if (isTrackMergeChanges()) {
trackUpdatedIndexes.add(index);
}
} else {
pods.add(newPod);
if (isTrackMergeChanges() && trackAddedIndexStart == -1) {
trackAddedIndexStart = pods.size() - 1;
}
}
}
}
/**
* Sort the pod list
*/
public void sortPods() {
Collections.sort(pods);
}
/**
* Iterator for Iterable interface (forEach, ..)
*/
public Iterator<DiasporaPod> iterator() {
return pods.iterator();
}
public int size() {
return pods.size();
}
public int indexOf(DiasporaPod pod) {
return pods.indexOf(pod);
}
public List<DiasporaPod> getPods() {
return pods;
}
public void setPods(List<DiasporaPod> pods) {
this.pods = pods;
}
public DiasporaPod getPodAt(int index) {
if (index >= 0 && index < pods.size()) {
return pods.get(index);
}
return null;
}
public boolean isTrackMergeChanges() {
return trackMergeChanges;
}
public void setTrackMergeChanges(boolean trackMergeChanges) {
this.trackMergeChanges = trackMergeChanges;
}
public Integer getTrackAddedIndexStart() {
return trackAddedIndexStart;
}
public List<Integer> getTrackUpdatedIndexes() {
return trackUpdatedIndexes;
}
public boolean isKeepOldNameDuringMerge() {
return keepOldNameDuringMerge;
}
public void setKeepOldNameDuringMerge(boolean keepOldNameDuringMerge) {
this.keepOldNameDuringMerge = keepOldNameDuringMerge;
}
/*
*
*
*
*
*
*/
public static class DiasporaPod implements Iterable<DiasporaPodList.DiasporaPod.DiasporaPodUrl>, Comparable<DiasporaPod>, Serializable {
private List<DiasporaPodUrl> _podUrls = new ArrayList<>();
private List<String> _mainLangs = new ArrayList<>();
private String _name = "";
private int _score = 0;
private int _id = 0;
private long _postCountLocal = 0;
public DiasporaPod() {
}
/**
* Load a DiasporaPod from JSON
*
* @param json Json Object
*/
public DiasporaPod fromJson(JSONObject json) throws JSONException {
JSONArray jarr;
if (json.has("name")) {
_name = json.getString("name");
}
if (json.has("mainLangs")) {
jarr = json.getJSONArray("mainLangs");
for (int i = 0; i < jarr.length(); i++) {
String val = jarr.getString(i);
if (!_mainLangs.contains(val)) {
_mainLangs.add(val);
}
}
}
if (json.has("podUrls")) {
jarr = json.getJSONArray("podUrls");
for (int i = 0; i < jarr.length(); i++) {
DiasporaPodUrl podUrl = new DiasporaPodUrl().fromJson(jarr.getJSONObject(i));
if (!_podUrls.contains(podUrl)) {
_podUrls.add(podUrl);
}
}
}
if (json.has("score")) {
_score = json.getInt("score");
}
if (json.has("postCountLocal")) {
_postCountLocal = json.getLong("postCountLocal");
}
if (json.has("id")) {
_id = json.getInt("id");
}
return this;
}
/**
* Convert DiasporaPod to JSON
*/
public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject();
json.put("name", _name);
json.put("id", _id);
if (_score != 0) {
json.put("score", _score);
}
// Only export active6 (frequently changing if told to do)
if (EXPORT_TOJSON_POST_COUNT_LOCAL && _postCountLocal > 0) {
json.put("postCountLocal", _postCountLocal);
}
// Pod urls
JSONArray jarr = new JSONArray();
for (DiasporaPodUrl value : _podUrls) {
jarr.put(value.toJson());
}
json.put("podUrls", jarr);
// main langs
jarr = new JSONArray();
for (String value : _mainLangs) {
jarr.put(value);
}
json.put("mainLangs", jarr);
return json;
}
@Override
public boolean equals(Object o) {
boolean ret = false;
if (o instanceof DiasporaPod) {
DiasporaPod otherPod = (DiasporaPod) o;
// Check if id is equal
ret = _id != 0 && _id == otherPod._id;
// Check if _host is the same (fallback if id is 0)
if (!ret) {
for (DiasporaPodUrl podUrl : _podUrls) {
for (DiasporaPodUrl otherPodUrl : otherPod.getPodUrls()) {
if (podUrl.getBaseUrl().equals(otherPodUrl.getBaseUrl())) {
ret = true;
}
}
}
}
}
return ret;
}
@Override
public int compareTo(DiasporaPod otherPod) {
if (otherPod != null) {
List<DiasporaPodUrl> myPodUrls = getPodUrls();
List<DiasporaPodUrl> otherPodUrls = otherPod.getPodUrls();
if (!myPodUrls.isEmpty() && !otherPodUrls.isEmpty()) {
return myPodUrls.get(0).getHost().compareTo(otherPodUrls.get(0).getHost());
}
return _name.compareTo(otherPod.getName());
}
return _name.compareTo("");
}
@Override
public String toString() {
return _name + "(" + _id + ")";
}
/**
* Iterator for Iterable interface (forEach, ..)
*/
public Iterator<DiasporaPodUrl> iterator() {
return _podUrls.iterator();
}
/*
* Getter & Setter
*/
public List<DiasporaPodUrl> getPodUrls() {
return _podUrls;
}
public DiasporaPod setPodUrls(List<DiasporaPodUrl> podUrls) {
_podUrls = podUrls;
return this;
}
public List<String> getMainLangs() {
return _mainLangs;
}
public DiasporaPod setMainLangs(List<String> mainLangs) {
_mainLangs = mainLangs;
return this;
}
public DiasporaPod appendMainLangs(String... values) {
_mainLangs.addAll(Arrays.asList(values));
return this;
}
/**
* Returns the first DiasporaPodUrl in the list
*/
public DiasporaPodUrl getPodUrl() {
if (_podUrls.size() > 0) {
return _podUrls.get(0);
}
return null;
}
public DiasporaPod appendPodUrls(DiasporaPodUrl... values) {
_podUrls.addAll(Arrays.asList(values));
return this;
}
public String getName() {
return _name;
}
public DiasporaPod setName(String name) {
_name = name;
return this;
}
public int getScore() {
return _score;
}
public DiasporaPod setScore(int score) {
_score = score;
return this;
}
public long getPostCountLocal() {
return _postCountLocal;
}
public DiasporaPod setPostCountLocal(long postCountLocal) {
_postCountLocal = postCountLocal;
return this;
}
public int getId() {
return _id;
}
public DiasporaPod setId(int id) {
_id = id;
return this;
}
/*
*
*
*
*
*
*/
public static class DiasporaPodUrl implements Serializable {
private String _host = "";
private String _protocol = "https";
private Integer _port = 443;
public DiasporaPodUrl() {
}
public DiasporaPodUrl(JSONObject json) throws JSONException {
fromJson(json);
}
/**
* Get the base url
*
* @return
*/
public String getBaseUrl() {
return _protocol + "://" + _host + (isPortNeeded() ? _port : "");
}
/**
* Convert JSON to DiasporaPodList
*
* @param json JSON Object
*/
public DiasporaPodUrl fromJson(JSONObject json) throws JSONException {
if (json.has("host")) {
_host = json.getString("host");
}
if (json.has("protocol")) {
_protocol = json.getString("protocol");
}
if (json.has("port")) {
_port = json.getInt("port");
}
return this;
}
/***
* Convert DiasporaPodList to JSON
*/
public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject();
json.put("host", _host);
if (!_protocol.equals("https")) {
json.put("protocol", _protocol);
}
if (_port != 443) {
json.put("port", _port);
}
return json;
}
/**
* Set default values for https
*/
public void setHttpsDefaults() {
setProtocol("https");
setPort(443);
}
/**
* Set default values for http
*/
public void setHttpDefaults() {
setProtocol("http");
setPort(80);
}
/**
* Tells if the ports needs to shown
*/
public boolean isPortNeeded() {
return !((_port == 80 && _protocol.equals("http")) || (_port == 443 && _protocol.equals("https")));
}
@Override
public String toString() {
return getBaseUrl();
}
@Override
@SuppressWarnings("SimplifiableIfStatement")
public boolean equals(Object o) {
if (o instanceof DiasporaPodUrl) {
return getBaseUrl().equals(((DiasporaPodUrl) o).getBaseUrl());
}
return false;
}
/*
* GETTER & SETTER
*/
public String getHost() {
return _host;
}
public DiasporaPodUrl setHost(String host) {
_host = host;
return this;
}
public String getProtocol() {
return _protocol;
}
public DiasporaPodUrl setProtocol(String protocol) {
_protocol = protocol;
return this;
}
public Integer getPort() {
return _port;
}
public DiasporaPodUrl setPort(Integer port) {
_port = port;
return this;
}
}
}
}

View file

@ -1,77 +1,87 @@
/* /*
This file is part of the Diaspora for Android. This file is part of the dandelion*.
Diaspora for Android is free software: you can redistribute it and/or modify dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful, dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with the Diaspora for Android. along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.data; package com.github.dfa.diaspora_android.data;
import android.os.Handler; import android.os.Handler;
import android.util.Log;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
/** /**
* Created by gsantner (https://gsantner.github.io/) on 24.03.16. Part of Diaspora for Android. * User profile
* Created by gsantner (gsantner AT mailbox DOT org) on 24.03.16. Part of dandelion*.
*/ */
public class PodUserProfile { public class DiasporaUserProfile {
private static final int MINIMUM_WEBUSERPROFILE_LOAD_TIMEDIFF = 5000; private static final int MINIMUM_USERPROFILE_LOAD_TIMEDIFF = 5000;
private Handler callbackHandler; private Handler callbackHandler;
private WebUserProfileChangedListener listener; private DiasporaUserProfileChangedListener listener;
private App app; private final App app;
private AppSettings appSettings; private final AppSettings appSettings;
DiasporaUrlHelper urls;
private JSONObject json; private JSONObject json;
private long lastLoaded; private long userProfileLastLoadedTimestamp;
private boolean isWebUserProfileLoaded; private boolean isWebUserProfileLoaded;
private String avatarUrl; private String avatarUrl;
private String guid; private String guid;
private String name; private String name;
private PodAspect[] podAspects; private DiasporaAspect[] aspects;
private String[] followedTags; private String[] followedTags;
private int notificationCount; private int notificationCount;
private int unreadMessagesCount; private int unreadMessagesCount;
private long lastVisitedPositionInStream = -1;
public PodUserProfile(App app) { public DiasporaUserProfile(App app) {
this.app = app; this.app = app;
appSettings = app.getSettings(); appSettings = app.getSettings();
urls = new DiasporaUrlHelper(appSettings);
loadFromAppSettings();
}
public void loadFromAppSettings() {
avatarUrl = appSettings.getAvatarUrl(); avatarUrl = appSettings.getAvatarUrl();
guid = appSettings.getProfileId(); guid = appSettings.getProfileId();
name = appSettings.getName(); name = appSettings.getName();
podAspects = appSettings.getPodAspects(); aspects = appSettings.getAspects();
followedTags = appSettings.getFollowedTags(); followedTags = appSettings.getFollowedTags();
notificationCount = appSettings.getNotificationCount(); notificationCount = appSettings.getNotificationCount();
unreadMessagesCount = appSettings.getUnreadMessageCount(); unreadMessagesCount = appSettings.getUnreadMessageCount();
lastVisitedPositionInStream = appSettings.getLastVisitedPositionInStream();
} }
public PodUserProfile(App app, Handler callbackHandler, WebUserProfileChangedListener listener) { public DiasporaUserProfile(App app, Handler callbackHandler, DiasporaUserProfileChangedListener listener) {
this(app); this(app);
this.listener = listener; this.listener = listener;
this.callbackHandler = callbackHandler; this.callbackHandler = callbackHandler;
} }
public boolean isRefreshNeeded() { public boolean isRefreshNeeded() {
return (System.currentTimeMillis() - lastLoaded) >= MINIMUM_WEBUSERPROFILE_LOAD_TIMEDIFF; return (System.currentTimeMillis() - userProfileLastLoadedTimestamp) >= MINIMUM_USERPROFILE_LOAD_TIMEDIFF;
} }
public boolean isWebUserProfileLoaded() { public boolean isWebUserProfileLoaded() {
@ -81,19 +91,19 @@ public class PodUserProfile {
public boolean parseJson(String jsonStr) { public boolean parseJson(String jsonStr) {
try { try {
json = new JSONObject(jsonStr); json = new JSONObject(jsonStr);
lastLoaded = System.currentTimeMillis(); userProfileLastLoadedTimestamp = System.currentTimeMillis();
// Avatar // Avatar
if (json.has("avatar")) { if (json.has("avatar")) {
JSONObject avatarJson = json.getJSONObject("avatar"); JSONObject avatarJson = json.getJSONObject("avatar");
if (avatarJson.has("medium") && setAvatarUrl(avatarJson.getString("medium"))) { if (avatarJson.has("large") && setAvatarUrl(avatarJson.getString("large"))) {
app.getAvatarImageLoader().clearAvatarImage(); app.getAvatarImageLoader().clearAvatarImage();
appSettings.setAvatarUrl(avatarUrl); appSettings.setAvatarUrl(avatarUrl);
} }
} }
// GUID (User id) // GUID (User id)
if (json.has("guid") && loadGuid(json.getString("guid"))) { if (json.has("guid") && loadGuid(json.getString("guid")) && !guid.isEmpty()) {
appSettings.setProfileId(guid); appSettings.setProfileId(guid);
} }
@ -114,7 +124,7 @@ public class PodUserProfile {
// Aspect // Aspect
if (json.has("aspects") && loadAspects(json.getJSONArray("aspects"))) { if (json.has("aspects") && loadAspects(json.getJSONArray("aspects"))) {
appSettings.setPodAspects(podAspects); appSettings.setPodAspects(aspects);
} }
// Followed tags // Followed tags
@ -125,13 +135,23 @@ public class PodUserProfile {
isWebUserProfileLoaded = true; isWebUserProfileLoaded = true;
} catch (JSONException e) { } catch (JSONException e) {
Log.d(App.TAG, e.getMessage()); AppLog.d(this, e.getMessage());
isWebUserProfileLoaded = false; isWebUserProfileLoaded = false;
} }
lastLoaded = System.currentTimeMillis(); userProfileLastLoadedTimestamp = System.currentTimeMillis();
return isWebUserProfileLoaded; return isWebUserProfileLoaded;
} }
public void analyzeUrl(String url) {
String prefix = urls.getPodUrl() + DiasporaUrlHelper.SUBURL_STREAM_WITH_TIMESTAMP;
if (url.startsWith(prefix)) {
try {
setLastVisitedPositionInStream(Long.parseLong(url.replace(prefix, "")));
} catch (NumberFormatException ignored) {
}
}
}
/* /*
// Getters & Setters // Getters & Setters
*/ */
@ -156,24 +176,48 @@ public class PodUserProfile {
return unreadMessagesCount; return unreadMessagesCount;
} }
public PodAspect[] getAspects() { public DiasporaAspect[] getAspects() {
return podAspects; return aspects;
} }
public String[] getFollowedTags() { public String[] getFollowedTags() {
return followedTags; return followedTags;
} }
public long getLastVisitedPositionInStream() {
return lastVisitedPositionInStream;
}
public void setLastVisitedPositionInStream(long lastVisitedPositionInStream) {
this.lastVisitedPositionInStream = lastVisitedPositionInStream;
appSettings.setLastVisitedPositionInStream(lastVisitedPositionInStream);
}
public boolean hasLastVisitedTimestampInStream() {
return appSettings.getLastVisitedPositionInStream() != -1;
}
public void resetLastVisitedPositionInStream() {
appSettings.setLastVisitedPositionInStream(-1);
}
/* /*
* Private property setters * Private property setters
*/ */
/**
* Sets the avatar, returns true if this was a new one, false if already the old one
*
* @param avatarUrl url
* @return true if new avatar url
*/
private boolean setAvatarUrl(final String avatarUrl) { private boolean setAvatarUrl(final String avatarUrl) {
if (!this.avatarUrl.equals(avatarUrl)) { if (!this.avatarUrl.equals(avatarUrl)) {
this.avatarUrl = avatarUrl; this.avatarUrl = avatarUrl;
if (listener != null && callbackHandler != null) { if (listener != null && callbackHandler != null) {
callbackHandler.post(new Runnable() { callbackHandler.post(new Runnable() {
public void run() { public void run() {
listener.onUserProfileAvatarChanged(avatarUrl); listener.onUserProfileAvatarChanged(DiasporaUserProfile.this, avatarUrl);
} }
}); });
} }
@ -196,7 +240,7 @@ public class PodUserProfile {
if (listener != null && callbackHandler != null) { if (listener != null && callbackHandler != null) {
callbackHandler.post(new Runnable() { callbackHandler.post(new Runnable() {
public void run() { public void run() {
listener.onUserProfileNameChanged(name); listener.onUserProfileNameChanged(DiasporaUserProfile.this, name);
} }
}); });
} }
@ -211,7 +255,7 @@ public class PodUserProfile {
if (listener != null && callbackHandler != null) { if (listener != null && callbackHandler != null) {
callbackHandler.post(new Runnable() { callbackHandler.post(new Runnable() {
public void run() { public void run() {
listener.onNotificationCountChanged(notificationCount); listener.onNotificationCountChanged(DiasporaUserProfile.this, notificationCount);
} }
}); });
} }
@ -221,9 +265,9 @@ public class PodUserProfile {
} }
private boolean loadAspects(final JSONArray jsonAspects) throws JSONException { private boolean loadAspects(final JSONArray jsonAspects) throws JSONException {
podAspects = new PodAspect[jsonAspects.length()]; aspects = new DiasporaAspect[jsonAspects.length()];
for (int i = 0; i < jsonAspects.length(); i++) { for (int i = 0; i < jsonAspects.length(); i++) {
podAspects[i] = new PodAspect(jsonAspects.getJSONObject(i)); aspects[i] = new DiasporaAspect(jsonAspects.getJSONObject(i));
} }
return true; return true;
} }
@ -242,7 +286,7 @@ public class PodUserProfile {
if (listener != null && callbackHandler != null) { if (listener != null && callbackHandler != null) {
callbackHandler.post(new Runnable() { callbackHandler.post(new Runnable() {
public void run() { public void run() {
listener.onUnreadMessageCountChanged(unreadMessagesCount); listener.onUnreadMessageCountChanged(DiasporaUserProfile.this, unreadMessagesCount);
} }
}); });
} }
@ -259,11 +303,11 @@ public class PodUserProfile {
this.callbackHandler = callbackHandler; this.callbackHandler = callbackHandler;
} }
public WebUserProfileChangedListener getListener() { public DiasporaUserProfileChangedListener getListener() {
return listener; return listener;
} }
public void setListener(WebUserProfileChangedListener listener) { public void setListener(DiasporaUserProfileChangedListener listener) {
this.listener = listener; this.listener = listener;
} }

View file

@ -0,0 +1,59 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.listener;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
/**
* Created by gsantner (gsantner AT mailbox DOT org) on 26.03.16.
* Interface that needs to be implemented by classes that listen for Profile related changes
*/
public interface DiasporaUserProfileChangedListener {
/**
* Called when the DiasporaUserProfile name changed
*
* @param diasporaUserProfile The profile
* @param name The new name
*/
void onUserProfileNameChanged(DiasporaUserProfile diasporaUserProfile, String name);
/**
* Called when the DiasporaUserProfile avatarUrl changed
*
* @param diasporaUserProfile The profile
* @param avatarUrl The new name
*/
void onUserProfileAvatarChanged(DiasporaUserProfile diasporaUserProfile, String avatarUrl);
/**
* Called when the DiasporaUserProfile notificationCount changed
*
* @param diasporaUserProfile The profile
* @param notificationCount The new notificationCount
*/
void onNotificationCountChanged(DiasporaUserProfile diasporaUserProfile, int notificationCount);
/**
* Called when the DiasporaUserProfile unreadMessageCount changed
*
* @param diasporaUserProfile The profile
* @param unreadMessageCount The new unreadMessageCount
*/
void onUnreadMessageCountChanged(DiasporaUserProfile diasporaUserProfile, int unreadMessageCount);
}

View file

@ -0,0 +1,14 @@
package com.github.dfa.diaspora_android.listener;
import android.support.design.widget.AppBarLayout;
/**
* interface that adds options to control intellihide of toolbars to the Activity
* Created by vanitas on 08.10.16.
*/
public interface IntellihideToolbarActivityListener {
int toolbarDefaultScrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP;
void setToolbarIntellihide(boolean enable);
}

View file

@ -0,0 +1,15 @@
package com.github.dfa.diaspora_android.listener;
/**
* Listener for different types of click events
*/
public interface OnSomethingClickListener<T> {
/**
* Triggered when something was clicked
*
* @param o Some object, or null
* @param i Some index, int value or null
* @param s Some String, or null
*/
void onSomethingClicked(T o, Integer i, String s);
}

View file

@ -1,33 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.listener;
/**
* Created by gsantner (https://gsantner.github.io/) on 26.03.16.
* Interface that needs to be implemented by classes that listen for Profile related changes
*/
public interface WebUserProfileChangedListener {
void onUserProfileNameChanged(String name);
void onUserProfileAvatarChanged(String avatarUrl);
void onNotificationCountChanged(int notificationCount);
void onUnreadMessageCountChanged(int unreadMessageCount);
}

View file

@ -0,0 +1,83 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.receiver;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.support.customtabs.CustomTabsIntent;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.web.custom_tab.BrowserFallback;
import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper;
/**
* BroadcastReceiver that opens links in a Chrome CustomTab
* Created by vanitas on 11.09.16.
*/
public class OpenExternalLinkReceiver extends BroadcastReceiver {
private final Activity parent;
public OpenExternalLinkReceiver(Activity parent) {
this.parent = parent;
}
@Override
public void onReceive(Context c, Intent receiveIntent) {
AppSettings appSettings = AppSettings.get();
ThemeHelper.getInstance(appSettings);
AppLog.v(this, "OpenExternalLinkReceiver.onReceive(): url");
Uri url;
try {
String sUrl = receiveIntent.getStringExtra(MainActivity.EXTRA_URL);
url = Uri.parse(sUrl);
} catch (Exception _ignored) {
AppLog.v(this, "Could not open Chrome Custom Tab (bad URL)");
return;
}
if (appSettings.isChromeCustomTabsEnabled()) {
// Setup Chrome Custom Tab
CustomTabsIntent.Builder customTab = new CustomTabsIntent.Builder();
customTab.setToolbarColor(ThemeHelper.getPrimaryColor());
customTab.addDefaultShareMenuItem();
Bitmap backButtonIcon = BitmapFactory.decodeResource(c.getResources(), R.drawable.chrome_custom_tab__back);
customTab.setCloseButtonIcon(backButtonIcon);
// Launch Chrome Custom Tab
CustomTabActivityHelper.openCustomTab(parent, customTab.build(), url, new BrowserFallback());
} else {
// Open in normal browser (via intent)
Intent openBrowserIntent = new Intent(Intent.ACTION_VIEW, url);
openBrowserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
c.startActivity(openBrowserIntent);
}
}
}

View file

@ -0,0 +1,103 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
/**
* BroadcastReceiver used to update the title of the MainActivity depending on the url of the ui__webview
* Created by vanitas on 11.09.16.
*/
public class UpdateTitleReceiver extends BroadcastReceiver {
private DiasporaUrlHelper urls;
private AppSettings appSettings;
private App app;
private TitleCallback callback;
private String lastUrl;
public UpdateTitleReceiver(App app, DiasporaUrlHelper urls, TitleCallback callback) {
this.urls = urls;
this.app = app;
this.appSettings = app.getSettings();
this.callback = callback;
}
@Override
public void onReceive(Context context, Intent intent) {
lastUrl = intent.getStringExtra(MainActivity.EXTRA_URL);
if (lastUrl != null && lastUrl.startsWith(urls.getPodUrl())) {
String subUrl = lastUrl.substring((urls.getPodUrl()).length());
AppLog.spam(this, "onReceive()- Set title for subUrl " + subUrl);
if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_STREAM)) {
setTitle(R.string.nav_stream);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_POSTS)) {
setTitle(R.string.app_name);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NOTIFICATIONS)) {
setTitle(R.string.notifications);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_CONVERSATIONS)) {
setTitle(R.string.conversations);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_NEW_POST)) {
setTitle(R.string.new_post);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_STATISTICS)) {
setTitle(R.string.statistics);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_CONTACTS)) {
setTitle(R.string.contacts);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PEOPLE + appSettings.getProfileId())) {
setTitle(R.string.nav_profile);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_ACTIVITY)) {
setTitle(R.string.nav_activities);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_LIKED)) {
setTitle(R.string.nav_liked);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_COMMENTED)) {
setTitle(R.string.nav_commented);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_MENTIONS)) {
setTitle(R.string.nav_mentions);
} else if (subUrl.startsWith(DiasporaUrlHelper.SUBURL_PUBLIC)) {
setTitle(R.string.public_);
} else if (urls.isAspectUrl(lastUrl)) {
setTitle(urls.getAspectNameFromUrl(lastUrl, app));
}
} else {
AppLog.spam(this, "onReceive()- Invalid url: " + lastUrl);
}
}
private void setTitle(int rId) {
callback.setTitle(lastUrl, rId);
}
private void setTitle(String title) {
callback.setTitle(lastUrl, title);
}
public interface TitleCallback {
void setTitle(String url, int resId);
void setTitle(String url, String title);
}
}

View file

@ -1,30 +1,30 @@
/* /*
This file is part of the Diaspora for Android. This file is part of the dandelion*.
Diaspora for Android is free software: you can redistribute it and/or modify dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful, dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with the Diaspora for Android. along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.util; package com.github.dfa.diaspora_android.service;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.widget.ImageView; import android.widget.ImageView;
import com.github.dfa.diaspora_android.task.ImageDownloadTask; import net.gsantner.opoc.util.DownloadTask;
import java.io.File; import java.io.File;
@ -54,7 +54,9 @@ public class AvatarImageLoader {
public void startImageDownload(ImageView imageView, String avatarUrl) { public void startImageDownload(ImageView imageView, String avatarUrl) {
if (!avatarUrl.equals("")) { if (!avatarUrl.equals("")) {
new ImageDownloadTask(imageView, avatarFile.getAbsolutePath()).execute(avatarUrl); new DownloadTask(new File(avatarFile.getAbsolutePath()), (ok, file) -> {
loadToImageView(imageView);
}).execute(avatarUrl);
} }
} }
} }

View file

@ -0,0 +1,114 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.service;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import com.github.dfa.diaspora_android.data.DiasporaPodList;
import com.github.dfa.diaspora_android.util.AppLog;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher;
public class FetchPodsService extends Service {
public static final String MESSAGE_PODS_RECEIVED = "com.github.dfa.diaspora.podsreceived";
public static final String EXTRA_PODLIST = "pods";
public FetchPodsService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new GetPodsTask(this).execute();
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
class GetPodsTask extends AsyncTask<Void, Void, DiasporaPodList> {
private static final String PODDY_PODLIST_URL = "https://raw.githubusercontent.com/gsantner/dandelion/master/app/src/main/res/raw/podlist.json";
private final Service service;
GetPodsTask(Service service) {
this.service = service;
}
@Override
protected DiasporaPodList doInBackground(Void... params) {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
HttpsURLConnection con = NetCipher.getHttpsURLConnection(PODDY_PODLIST_URL);
if (con.getResponseCode() == HttpsURLConnection.HTTP_OK) {
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
// Parse JSON & return pod list
JSONObject json = new JSONObject(sb.toString());
return new DiasporaPodList().fromJson(json);
} else {
AppLog.e(this, "Failed to download list of pods");
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ignored) {
}
}
}
// Could not fetch list of pods :(
return new DiasporaPodList();
}
@Override
protected void onPostExecute(DiasporaPodList pods) {
if (pods == null) {
pods = new DiasporaPodList();
}
Intent broadcastIntent = new Intent(FetchPodsService.MESSAGE_PODS_RECEIVED);
broadcastIntent.putExtra(FetchPodsService.EXTRA_PODLIST, pods);
LocalBroadcastManager.getInstance(service.getApplicationContext()).sendBroadcast(broadcastIntent);
service.stopSelf();
}
}

View file

@ -0,0 +1,60 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
This file is inspired from sourabhsoni.com/implementing-hashtags-in-android-application/
*/
package com.github.dfa.diaspora_android.service;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
public class HashtagContentProvider extends ContentProvider {
@Override
public int delete(Uri arg0, String arg1, String[] arg2) {
return 0;
}
@Override
public String getType(Uri arg0) {
return "vnd.android.cursor.item/vnd.cc.tag";
}
@Override
public Uri insert(Uri arg0, ContentValues arg1) {
return null;
}
@Override
public boolean onCreate() {
return false;
}
@Override
public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
String arg4) {
return null;
}
@Override
public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
return 0;
}
}

View file

@ -1,30 +1,31 @@
/* /*
This file is part of the Diaspora for Android. This file is part of the dandelion*.
Diaspora for Android is free software: you can redistribute it and/or modify dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful, dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with the Diaspora for Android. along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.github.dfa.diaspora_android.task; package com.github.dfa.diaspora_android.service;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.util.Log;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.data.PodUserProfile; import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -43,12 +44,14 @@ public class ProfileFetchTask extends AsyncTask<Void, Void, Void> {
// Code for getting the profile async without any UI/WebView // Code for getting the profile async without any UI/WebView
// TODO: This is an early version,needs to be converted to Service // TODO: This is an early version,needs to be converted to Service
final App app; private final App app;
final Context context; private final Context context;
private final DiasporaUrlHelper urls;
public ProfileFetchTask(final App app) { public ProfileFetchTask(final App app) {
this.context = app.getApplicationContext(); this.context = app.getApplicationContext();
this.app = app; this.app = app;
this.urls = new DiasporaUrlHelper(app.getSettings());
} }
@ -56,13 +59,13 @@ public class ProfileFetchTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) { protected Void doInBackground(Void... params) {
String extractedProfileData = null; String extractedProfileData = null;
final CookieManager cookieManager = app.getCookieManager(); final CookieManager cookieManager = app.getCookieManager();
String cookies = cookieManager.getCookie("https://" + app.getSettings().getPodDomain()); String cookies = cookieManager.getCookie(urls.getPodUrl());
Log.d(App.TAG, cookies); AppLog.d(this, cookies);
HttpsURLConnection connection; HttpsURLConnection connection;
InputStream inStream; InputStream inStream;
try { try {
URL url = new URL("https://" + app.getSettings().getPodDomain() + "/stream"); URL url = new URL(urls.getStreamUrl());
connection = NetCipher.getHttpsURLConnection(url); connection = NetCipher.getHttpsURLConnection(url);
connection.setReadTimeout(10000); connection.setReadTimeout(10000);
connection.setConnectTimeout(15000); connection.setConnectTimeout(15000);
@ -83,10 +86,10 @@ public class ProfileFetchTask extends AsyncTask<Void, Void, Void> {
} }
} }
try{ try {
br.close(); br.close();
inStream.close(); inStream.close();
} catch (IOException e){/*Nothing*/} } catch (IOException e) {/*Nothing*/}
connection.disconnect(); connection.disconnect();
@ -96,9 +99,9 @@ public class ProfileFetchTask extends AsyncTask<Void, Void, Void> {
if (extractedProfileData != null) { if (extractedProfileData != null) {
PodUserProfile profile = new PodUserProfile(app); DiasporaUserProfile profile = new DiasporaUserProfile(app);
profile.parseJson(extractedProfileData); profile.parseJson(extractedProfileData);
Log.d(App.TAG, "Extracted new_messages (service):" + profile.getUnreadMessagesCount()); AppLog.d(this, "Extracted new_messages (service):" + profile.getUnreadMessagesCount());
} }
return null; return null;

View file

@ -1,140 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.task;
import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.github.dfa.diaspora_android.App;
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher;
public class GetPodsService extends Service {
public static final String MESSAGE_PODS_RECEIVED = "com.github.dfa.diaspora.podsreceived";
private static final String TAG = App.TAG;
public GetPodsService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
getPods();
return super.onStartCommand(intent, flags, startId);
}
private void getPods() {
/*
* Most of the code in this AsyncTask is from the file getPodlistTask.java
* from the app "Diaspora Webclient".
* A few modifications and adaptations were made by me.
* Source:
* https://github.com/voidcode/Diaspora-Webclient/blob/master/src/com/voidcode/diasporawebclient/getPodlistTask.java
* Thanks to Terkel Sørensen ; License : GPLv3
*/
AsyncTask<Void, Void, String[]> getPodsAsync = new AsyncTask<Void, Void, String[]>() {
@Override
protected String[] doInBackground(Void... params) {
// TODO: Update deprecated code
StringBuilder builder = new StringBuilder();
//HttpClient client = new DefaultHttpClient();
List<String> list = null;
HttpsURLConnection connection;
InputStream inStream;
try {
connection = NetCipher.getHttpsURLConnection("https://podupti.me/api.php?key=4r45tg&format=json");
int statusCode = connection.getResponseCode();
if (statusCode == 200) {
inStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(
new InputStreamReader(inStream));
String line;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
try {
inStream.close();
} catch (IOException e) {/*Nothing to do*/}
connection.disconnect();
} else {
Log.e(TAG, "Failed to download list of pods");
}
} catch (IOException e) {
//TODO handle json buggy feed
e.printStackTrace();
}
//Parse the JSON Data
try {
JSONObject jsonObjectAll = new JSONObject(builder.toString());
JSONArray jsonArrayAll = jsonObjectAll.getJSONArray("pods");
Log.d(TAG, "Number of entries " + jsonArrayAll.length());
list = new ArrayList<>();
for (int i = 0; i < jsonArrayAll.length(); i++) {
JSONObject jo = jsonArrayAll.getJSONObject(i);
if (jo.getString("secure").equals("true"))
list.add(jo.getString("domain"));
}
} catch (Exception e) {
//TODO Handle Parsing errors here
e.printStackTrace();
}
if (list != null)
return list.toArray(new String[list.size()]);
else
return null;
}
@Override
protected void onPostExecute(String[] pods) {
Intent broadcastIntent = new Intent(MESSAGE_PODS_RECEIVED);
broadcastIntent.putExtra("pods", pods != null ? pods : new String[0]);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcastIntent);
stopSelf();
}
};
getPodsAsync.execute();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}

View file

@ -1,99 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.task;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.ImageView;
import com.github.dfa.diaspora_android.App;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher;
/**
* Task that can be used to download images from URLs and store them in storage
* Created by gsantner (https://gsantner.github.io/) on 24.03.16.
*/
public class ImageDownloadTask extends AsyncTask<String, Void, Bitmap> {
ImageView imageView;
String savePath;
/**
* Download image from URL
*
* @param imageView ImageView to set image to (null = don't set)
* @param savePath Save image to file (null = don't save)
*/
public ImageDownloadTask(@Nullable ImageView imageView, @Nullable String savePath) {
this.imageView = imageView;
this.savePath = savePath;
}
protected Bitmap doInBackground(String... urls) {
String url = urls[0];
Bitmap bitmap = null;
FileOutputStream out = null;
InputStream inStream;
HttpsURLConnection connection;
try {
connection = NetCipher.getHttpsURLConnection(url);
inStream = connection.getInputStream();
bitmap = BitmapFactory.decodeStream(inStream);
// Save to file if not null
if (savePath != null) {
out = new FileOutputStream(savePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
}
try {
inStream.close();
} catch (IOException e) {/*Nothing*/}
connection.disconnect();
} catch (Exception e) {
Log.e(App.TAG, e.getMessage());
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ignored) {
}
}
return bitmap;
}
protected void onPostExecute(Bitmap result) {
// Display on imageview if not null
if (imageView != null) {
imageView.setImageBitmap(result);
}
}
}

View file

@ -0,0 +1,132 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.NonNull;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
@SuppressWarnings("WeakerAccess")
public class BadgeDrawable extends Drawable {
// Source: http://mobikul.com/adding-badge-count-on-menu-items-like-cart-notification-etc/
private static final String BADGE_VALUE_OVERFLOW = "*";
private Paint _badgeBackground;
private Paint _badgeText;
private Rect _textRect = new Rect();
private String _badgeValue = "";
private boolean _shouldDraw;
public BadgeDrawable(Context context) {
float textSize = context.getResources().getDimension(R.dimen.textsize_badge_count);
AppSettings settings = AppSettings.get();
_badgeBackground = new Paint();
_badgeBackground.setColor(settings.getAccentColor());
_badgeBackground.setAntiAlias(true);
_badgeBackground.setStyle(Paint.Style.FILL);
_badgeText = new Paint();
_badgeText.setColor(ContextUtils.get().shouldColorOnTopBeLight(settings.getAccentColor()) ? Color.WHITE : Color.BLACK);
_badgeText.setTypeface(Typeface.DEFAULT);
_badgeText.setTextSize(textSize);
_badgeText.setAntiAlias(true);
_badgeText.setTextAlign(Paint.Align.CENTER);
}
@Override
public void draw(@NonNull Canvas canvas) {
if (!_shouldDraw) {
return;
}
Rect bounds = getBounds();
float width = bounds.right - bounds.left;
float height = bounds.bottom - bounds.top;
float oneDp = ContextUtils.get().convertDpToPx(1);
// Position the badge in the top-right quadrant of the icon.
float radius = ((Math.max(width, height) / 2)) / 2;
float centerX = (width - radius - 1) + oneDp * 2;
float centerY = radius - 2 * oneDp;
canvas.drawCircle(centerX, centerY, (int) (radius + oneDp * 5), _badgeBackground);
// Draw badge count message inside the circle.
_badgeText.getTextBounds(_badgeValue, 0, _badgeValue.length(), _textRect);
float textHeight = _textRect.bottom - _textRect.top;
float textY = centerY + (textHeight / 2f);
canvas.drawText(_badgeValue.length() > 2 ? BADGE_VALUE_OVERFLOW : _badgeValue,
centerX, textY, _badgeText);
}
// Sets the text to display. Badge displays a '*' if more than 2 characters
private void setBadgeText(String text) {
_badgeValue = text;
// Only draw a badge if the value isn't a zero
_shouldDraw = !text.equalsIgnoreCase("0");
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
}
@Override
public void setColorFilter(ColorFilter cf) {
}
@Override
public int getOpacity() {
return PixelFormat.UNKNOWN;
}
public static void setBadgeCount(Context context, LayerDrawable icon, Integer count) {
setBadgeText(context, icon, count.toString());
}
// Max of 2 characters
public static void setBadgeText(Context context, LayerDrawable icon, String text) {
BadgeDrawable badge;
// Reuse drawable if possible
Drawable reuse = icon.findDrawableByLayerId(R.id.ic_badge);
if (reuse != null && reuse instanceof BadgeDrawable) {
badge = (BadgeDrawable) reuse;
} else {
badge = new BadgeDrawable(context);
}
badge.setBadgeText(text);
icon.mutate();
icon.setDrawableByLayerId(R.id.ic_badge, badge);
}
}

View file

@ -47,7 +47,7 @@ public class BottomBarBehavior extends CoordinatorLayout.Behavior<LinearLayout>
if (defaultDependencyTop == -1) { if (defaultDependencyTop == -1) {
defaultDependencyTop = dependency.getTop(); defaultDependencyTop = dependency.getTop();
} }
if(dependency.getTop()<0) if (dependency.getTop() < 0)
child.setTranslationY(-dependency.getTop() + defaultDependencyTop); child.setTranslationY(-dependency.getTop() + defaultDependencyTop);
else else
child.setTranslationY(defaultDependencyTop); child.setTranslationY(defaultDependencyTop);

View file

@ -1,214 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.AttributeSet;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.widget.Toast;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.task.ImageDownloadTask;
import java.io.File;
/**
* Subclass of WebView which adds a context menu for long clicks on images or links to share, save
* or open with another browser
*/
@SuppressWarnings("deprecation")
public class ContextMenuWebView extends NestedWebView {
public static final int ID_SAVE_IMAGE = 10;
public static final int ID_IMAGE_EXTERNAL_BROWSER = 11;
public static final int ID_COPY_LINK = 12;
public static final int ID_SHARE_LINK = 13;
public static final int ID_SHARE_IMAGE = 14;
private Context context;
private Activity parentActivity;
private String lasLoadUrl = "";
public ContextMenuWebView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
}
public ContextMenuWebView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
}
@Override
protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
HitTestResult result = getHitTestResult();
MenuItem.OnMenuItemClickListener handler = new MenuItem.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
HitTestResult result = getHitTestResult();
String url = result.getExtra();
switch (item.getItemId()) {
//Save image to external memory
case ID_SAVE_IMAGE: {
boolean writeToStoragePermitted = true;
if (android.os.Build.VERSION.SDK_INT >= 23) {
int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
writeToStoragePermitted = false;
if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new AlertDialog.Builder(parentActivity)
.setMessage(R.string.permissions_image)
.setPositiveButton(context.getText(android.R.string.yes), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (android.os.Build.VERSION.SDK_INT >= 23)
parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE);
}
})
.setNegativeButton(context.getText(android.R.string.no), null)
.show();
}
parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE_ASK_PERMISSIONS_SAVE_IMAGE);
}
}
if (writeToStoragePermitted) {
if (url != null) {
Uri source = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(source);
File destinationFile = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/"
+ System.currentTimeMillis() + ".png");
request.setDestinationUri(Uri.fromFile(destinationFile));
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
Toast.makeText(context, context.getText(R.string.share__toast_saved_image_to_location) + " " +
destinationFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
}
}
}
break;
case ID_SHARE_IMAGE:
if (url != null) {
final Uri local = Uri.parse(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/" + System.currentTimeMillis() + ".png");
new ImageDownloadTask(null, local.getPath()) {
@Override
protected void onPostExecute(Bitmap result) {
Uri myUri = Uri.fromFile(new File(local.getPath()));
Intent sharingIntent = new Intent();
sharingIntent.setAction(Intent.ACTION_SEND);
sharingIntent.putExtra(Intent.EXTRA_STREAM, myUri);
sharingIntent.setType("image/png");
sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(Intent.createChooser(sharingIntent, "Share image using"));
}
}.execute(url);
} else {
Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show();
}
break;
case ID_IMAGE_EXTERNAL_BROWSER:
if (url != null) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(intent);
}
break;
//Copy url to clipboard
case ID_COPY_LINK:
if (url != null) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(ClipData.newPlainText("text", url));
Toast.makeText(context, R.string.share__toast_link_address_copied, Toast.LENGTH_SHORT).show();
}
break;
//Try to share link to other apps
case ID_SHARE_LINK:
if (url != null) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, url);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, getResources()
.getText(R.string.context_menu_share_link)));
}
break;
}
return true;
}
};
//Build context menu
if (result.getType() == HitTestResult.IMAGE_TYPE ||
result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
// Menu options for an image.
menu.setHeaderTitle(result.getExtra());
menu.add(0, ID_SAVE_IMAGE, 0, context.getString(R.string.context_menu_save_image)).setOnMenuItemClickListener(handler);
menu.add(0, ID_IMAGE_EXTERNAL_BROWSER, 0, context.getString(R.string.context_menu_open_external_browser)).setOnMenuItemClickListener(handler);
menu.add(0, ID_SHARE_IMAGE, 0, context.getString(R.string.context_menu_share_image)).setOnMenuItemClickListener(handler);
} else if (result.getType() == HitTestResult.ANCHOR_TYPE ||
result.getType() == HitTestResult.SRC_ANCHOR_TYPE) {
// Menu options for a hyperlink.
menu.setHeaderTitle(result.getExtra());
menu.add(0, ID_COPY_LINK, 0, context.getString(R.string.context_menu_copy_link)).setOnMenuItemClickListener(handler);
menu.add(0, ID_SHARE_LINK, 0, context.getString(R.string.context_menu_share_link)).setOnMenuItemClickListener(handler);
}
}
public void loadUrlNew(String url){
stopLoading();
loadUrl(url);
}
@Override
public void loadUrl(String url) {
super.loadUrl(url);
// Don't spam intents ;)
if (!lasLoadUrl.equals(url)) {
Intent updateActivityTitleIntent = new Intent(MainActivity.ACTION_UPDATE_TITLE_FROM_URL);
updateActivityTitleIntent.putExtra(MainActivity.EXTRA_URL, getUrl());
LocalBroadcastManager.getInstance(context).sendBroadcast(updateActivityTitleIntent);
}
lasLoadUrl = url;
}
public void setParentActivity(Activity activity) {
this.parentActivity = activity;
}
}

View file

@ -1,66 +0,0 @@
/*
This file is part of the Diaspora for Android.
Diaspora for Android is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Diaspora for Android is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the Diaspora for Android.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.webkit.CookieManager;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.github.dfa.diaspora_android.App;
public class CustomWebViewClient extends WebViewClient {
private App app;
private WebView webView;
public CustomWebViewClient(App app, WebView webView) {
this.app = app;
this.webView = webView;
}
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (!url.contains(app.getSettings().getPodDomain())) {
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
app.getApplicationContext().startActivity(i);
return true;
}
return false;
}
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
final CookieManager cookieManager = app.getCookieManager();
String cookies = cookieManager.getCookie(url);
//Log.d(App.TAG, "All the cookies in a string:" + cookies);
if (cookies != null) {
cookieManager.setCookie(url, cookies);
cookieManager.setCookie("https://" + app.getSettings().getPodDomain(), cookies);
//for (String c : cookies.split(";")) {
// Log.d(App.TAG, "Cookie: " + c.split("=")[0] + " Value:" + c.split("=")[1]);
//}
//new ProfileFetchTask(app).execute();
}
}
}

View file

@ -0,0 +1,84 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui;
import android.content.Context;
import android.support.v7.widget.AppCompatTextView;
import android.text.Html;
import android.text.SpannableString;
import android.text.util.Linkify;
import android.util.AttributeSet;
import android.util.Patterns;
import com.github.dfa.diaspora_android.activity.MainActivity;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* TextView, that renders HTML with highlited and clickable links and hashtags.
* Links are opened in a webbrowser.
* Hashtags open the MainActivity, load the new-post site of the selected pod and insert the
* hashtag into the post editor. See data/HashtagContentProvider.
*/
public class HtmlTextView extends AppCompatTextView {
public HtmlTextView(Context context) {
super(context);
init();
}
public HtmlTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
/**
* Linkify, format markdown and escape the displayed message.
*/
private void init() {
formatHtmlAndCustomTags();
}
public void setTextFormatted(String text) {
setText(text);
formatHtmlAndCustomTags();
}
private void formatHtmlAndCustomTags() {
setText(new SpannableString(Html.fromHtml(getText().toString())));
Linkify.TransformFilter filter = new Linkify.TransformFilter() {
public final String transformUrl(final Matcher match, String url) {
return match.group();
}
};
Pattern hashtagPattern = Pattern.compile("[#]+[A-Za-z0-9-_]+\\b");
String hashtagScheme = MainActivity.CONTENT_HASHTAG;
Linkify.addLinks(this, hashtagPattern, hashtagScheme, null, filter);
Pattern urlPattern = Patterns.WEB_URL;
Linkify.addLinks(this, urlPattern, null, null, filter);
}
}

View file

@ -0,0 +1,275 @@
package com.github.dfa.diaspora_android.ui;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod;
import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod.DiasporaPodUrl;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.ui.theme.ThemedAppCompatDialogFragment;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.web.ProxyHandler;
import org.json.JSONException;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnItemSelected;
/**
* Dialog that helps the user configure a pod
* Created by gsantner on 06.10.16.
*/
public class PodSelectionDialog extends ThemedAppCompatDialogFragment {
public static final String TAG = "com.github.dfa.diaspora_android.ui.PodSelectionDialog";
public interface PodSelectionDialogResultListener {
void onPodSelectionDialogResult(DiasporaPod pod, boolean accepted);
}
public static PodSelectionDialog newInstance(PodSelectionDialogResultListener resultListener) {
return newInstance(new DiasporaPod(), resultListener);
}
public static PodSelectionDialog newInstance(DiasporaPod pod, PodSelectionDialogResultListener resultListener) {
PodSelectionDialog dialog = new PodSelectionDialog();
dialog.setPod(pod);
dialog.setResultListener(resultListener);
return dialog;
}
/*
//
//
//
//
//
//
*/
@BindView(R.id.podselection__dialog__edit_podaddress)
EditText editPodAddress;
@BindView(R.id.podselection__dialog__edit_pod_name)
EditText editPodName;
@BindView(R.id.podselection__dialog__radiogroup_protocol)
RadioGroup radiogrpProtocol;
@BindView(R.id.podselection__dialog__text_profile)
TextView textProfile;
@BindView(R.id.podselection__dialog__spinner_profile)
Spinner spinnerProfile;
@BindView(R.id.podselection__dialog__check_torpreset)
CheckBox checkboxTorPreset;
@BindView(R.id.podselection__dialog__text_torpreset)
TextView textTorPreset;
@BindView(R.id.podselection__dialog__text_pod_name)
TextView textPodName;
@BindView(R.id.podselection__dialog__text_pod_address)
TextView textPodAddress;
@BindView(R.id.podselection__dialog__text_protocol)
TextView textProtocol;
@BindView(R.id.podselection__dialog__btn_ok)
Button btnOk;
@BindView(R.id.podselection__dialog__btn_cancel)
Button btnCancel;
private PodSelectionDialogResultListener resultListener;
private View root;
private DiasporaPod pod = new DiasporaPod();
private App app;
@NonNull
@Override
@SuppressLint("InflateParams")
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
app = (App) getActivity().getApplication();
// Bind UI
root = inflater.inflate(R.layout.podselection__dialog, null);
ButterKnife.bind(this, root);
editPodName.setText(pod.getName());
List<DiasporaPodUrl> podUrls = pod.getPodUrls();
if (podUrls.size() > 0) {
uiLoadDiasporaUrl(0);
}
if (podUrls.size() > 1) {
textProfile.setVisibility(View.VISIBLE);
spinnerProfile.setVisibility(View.VISIBLE);
String[] podUrlss = new String[podUrls.size()];
for (int i = 0; i < podUrls.size(); podUrlss[i] = podUrls.get(i++).getBaseUrl()) ;
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_item, podUrlss);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerProfile.setAdapter(spinnerAdapter);
}
applyColorsToViews();
builder.setView(root);
return builder.create();
}
protected void applyColorsToViews() {
ThemeHelper.getInstance(app.getSettings());
textPodAddress.setTextColor(ThemeHelper.getAccentColor());
textPodName.setTextColor(ThemeHelper.getAccentColor());
textProfile.setTextColor(ThemeHelper.getAccentColor());
textProtocol.setTextColor(ThemeHelper.getAccentColor());
textTorPreset.setTextColor(ThemeHelper.getAccentColor());
btnOk.setTextColor(ThemeHelper.getAccentColor());
btnCancel.setTextColor(ThemeHelper.getAccentColor());
ThemeHelper.updateEditTextColor(editPodAddress);
ThemeHelper.updateEditTextColor(editPodName);
ThemeHelper.updateCheckBoxColor(checkboxTorPreset);
ThemeHelper.updateRadioGroupColor(radiogrpProtocol);
}
@Override
protected AppSettings getAppSettings() {
if (isAdded()) {
return ((App) getActivity().getApplication()).getSettings();
} else {
return AppSettings.get();
}
}
@OnItemSelected(R.id.podselection__dialog__spinner_profile)
public void spinnerItemSelected(Spinner spinner, int position) {
uiLoadDiasporaUrl(position);
}
public void uiLoadDiasporaUrl(int wantedPodUrlPos) {
List<DiasporaPodUrl> podUrls = pod.getPodUrls();
if (podUrls.size() == 0) {
return;
}
wantedPodUrlPos = wantedPodUrlPos < podUrls.size() ? wantedPodUrlPos : 0;
DiasporaPodUrl url1 = podUrls.get(wantedPodUrlPos);
editPodAddress.setText(url1.getHost());
radiogrpProtocol.check(url1.getProtocol().equals("https")
? R.id.podselection__dialog__radio_https : R.id.podselection__dialog__radio_http);
// Tor
boolean isOnionUrl = url1.getHost().endsWith(".onion");
setUiVisible(textTorPreset, isOnionUrl);
setUiVisible(checkboxTorPreset, isOnionUrl);
checkboxTorPreset.setChecked(isOnionUrl);
}
public void setUiVisible(View view, boolean visible) {
if (view != null) {
view.setVisibility(visible ? View.VISIBLE : View.GONE);
}
}
@OnClick({R.id.podselection__dialog__btn_ok, R.id.podselection__dialog__btn_cancel})
public void onResultButtonClicked(View view) {
boolean POSITIVE_PRESSED = view.getId() == R.id.podselection__dialog__btn_ok;
if (POSITIVE_PRESSED) {
if (!checkInputs()) {
return;
}
DiasporaPodUrl podUrl = new DiasporaPodUrl();
if (radiogrpProtocol.getCheckedRadioButtonId() == R.id.podselection__dialog__radio_https) {
podUrl.setHttpsDefaults();
} else {
podUrl.setHttpDefaults();
}
podUrl.setHost(editPodAddress.getText().toString());
pod.setName(editPodName.getText().toString());
pod.getPodUrls().clear();
pod.getPodUrls().add(podUrl);
// Load Tor preset
if (pod.getPodUrl().getHost().endsWith(".onion") && checkboxTorPreset.isChecked()) {
AppSettings settings = app.getSettings();
settings.setProxyHttpEnabled(true);
settings.setProxyWasEnabled(false);
settings.setProxyHttpPort(8118);
settings.setProxyHttpHost("127.0.0.1");
ProxyHandler.getInstance().updateProxySettings(getContext());
}
getDialog().dismiss();
publishResult(true);
} else {
getDialog().cancel();
publishResult(false);
}
}
public boolean checkInputs() {
boolean ok = true;
String s = editPodAddress.getText().toString();
if (TextUtils.isEmpty(s) || s.length() < 3) {
editPodAddress.setError(getString(R.string.missing_value));
ok = false;
}
s = editPodName.getText().toString();
if (TextUtils.isEmpty(s) || s.length() < 3) {
editPodName.setError(getString(R.string.missing_value));
ok = false;
}
return ok;
}
public void publishResult(boolean accepted) {
if (resultListener != null) {
resultListener.onPodSelectionDialogResult(pod, accepted);
}
}
/*
* GETTER & SETTER
*/
public PodSelectionDialogResultListener getResultListener() {
return resultListener;
}
public void setResultListener(PodSelectionDialogResultListener resultListener) {
this.resultListener = resultListener;
}
public DiasporaPod getPod() {
return pod;
}
public void setPod(DiasporaPod pod) {
try {
this.pod = new DiasporaPod().fromJson(pod.toJson());
} catch (JSONException ignored) {
}
}
}

View file

@ -0,0 +1,85 @@
package com.github.dfa.diaspora_android.ui;
import android.app.Activity;
import android.support.v4.content.ContextCompat;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaAspect;
import com.github.dfa.diaspora_android.util.AppSettings;
import net.gsantner.opoc.ui.SearchOrCustomTextDialog;
import net.gsantner.opoc.util.Callback;
import java.util.ArrayList;
import java.util.Arrays;
public class SearchOrCustomTextDialogCreator {
public static final String SPECIAL_PREFIX = "\uD83D\uDCA0";
public static void showDiasporaTagsDialog(final Activity activity, final Callback.a1<String> callback) {
SearchOrCustomTextDialog.DialogOptions dopt = new SearchOrCustomTextDialog.DialogOptions();
baseConf(activity, dopt);
dopt.callback = callback;
dopt.isSearchEnabled = true;
dopt.searchHintText = R.string.search;
dopt.titleText = R.string.tags;
new Thread(() -> {
AppSettings appSettings = AppSettings.get();
ArrayList<String> hl = new ArrayList<>();
ArrayList<String> data = new ArrayList<>(Arrays.asList(appSettings.getFollowedTags()));
if (data.size() > 0) {
String highlighted = surroundString(data.remove(0));
data.add(0, highlighted);
hl.add(highlighted);
}
for (int strid : new int[]{R.string.manage_hashtags}) {
String special = surroundString(appSettings.rstr(strid));
data.add(0, special);
hl.add(special);
}
dopt.data = data;
dopt.highlightData = hl;
activity.runOnUiThread(() -> SearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt));
}).start();
}
private static String surroundString(String text) {
return SPECIAL_PREFIX + " " + text + " ";
}
public static void showDiasporaAspectsDialog(final Activity activity, final Callback.a1<String> callback) {
SearchOrCustomTextDialog.DialogOptions dopt = new SearchOrCustomTextDialog.DialogOptions();
baseConf(activity, dopt);
dopt.callback = callback;
dopt.isSearchEnabled = false;
dopt.titleText = R.string.contacts;
new Thread(() -> {
AppSettings appSettings = AppSettings.get();
ArrayList<String> hl = new ArrayList<>();
ArrayList<String> data = new ArrayList<>();
for (DiasporaAspect aspect : AppSettings.get().getAspects()) {
data.add(aspect.name);
}
for (int strid : new int[]{R.string.nav_profile, R.string.manage_your_contact_list}) {
String special = surroundString(appSettings.rstr(strid));
data.add(0, special);
hl.add(special);
}
dopt.data = data;
dopt.highlightData = hl;
activity.runOnUiThread(() -> SearchOrCustomTextDialog.showMultiChoiceDialogWithSearchFilterUI(activity, dopt));
}).start();
}
private static void baseConf(Activity activity, SearchOrCustomTextDialog.DialogOptions dopt) {
AppSettings as = new AppSettings(activity);
dopt.isDarkDialog = as.isAmoledColorMode();
dopt.textColor = ContextCompat.getColor(activity, dopt.isDarkDialog ? R.color.white : R.color.primary_text);
dopt.highlightColor = as.getAccentColor();
}
}

View file

@ -0,0 +1,289 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.graphics.Color;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import com.github.dfa.diaspora_android.R;
/**
* Class that handles Colors
* Created by dnld on 24/02/16.
*/
public class ColorPalette {
public static int[] getAccentColors(Context context) {
return new int[]{
ContextCompat.getColor(context, R.color.md_red_500),
ContextCompat.getColor(context, R.color.md_purple_500),
ContextCompat.getColor(context, R.color.md_deep_purple_500),
ContextCompat.getColor(context, R.color.md_blue_500),
ContextCompat.getColor(context, R.color.md_light_blue_500),
ContextCompat.getColor(context, R.color.md_cyan_500),
ContextCompat.getColor(context, R.color.md_teal_500),
ContextCompat.getColor(context, R.color.md_green_500),
ContextCompat.getColor(context, R.color.md_yellow_500),
ContextCompat.getColor(context, R.color.md_orange_500),
ContextCompat.getColor(context, R.color.md_deep_orange_500),
ContextCompat.getColor(context, R.color.md_brown_500),
ContextCompat.getColor(context, R.color.md_blue_grey_500),
};
}
public static int getObscuredColor(int c) {
float[] hsv = new float[3];
int color = c;
Color.colorToHSV(color, hsv);
hsv[2] *= 0.85f; // value component
color = Color.HSVToColor(hsv);
return color;
}
public static int getTransparentColor(int color, int alpha) {
return ColorUtils.setAlphaComponent(color, alpha);
}
public static int[] getTransparencyShadows(int color) {
int[] shadows = new int[10];
for (int i = 0; i < 10; i++)
shadows[i] = (ColorPalette.getTransparentColor(color, ((100 - (i * 10)) * 255) / 100));
return shadows;
}
public static int[] getBaseColors(Context context) {
return new int[]{
ContextCompat.getColor(context, R.color.md_red_500),
ContextCompat.getColor(context, R.color.md_pink_500),
ContextCompat.getColor(context, R.color.md_purple_500),
ContextCompat.getColor(context, R.color.md_deep_purple_500),
ContextCompat.getColor(context, R.color.md_indigo_500),
ContextCompat.getColor(context, R.color.md_blue_500),
ContextCompat.getColor(context, R.color.md_light_blue_500),
ContextCompat.getColor(context, R.color.md_cyan_500),
ContextCompat.getColor(context, R.color.md_teal_500),
ContextCompat.getColor(context, R.color.md_green_500),
ContextCompat.getColor(context, R.color.md_light_green_500),
ContextCompat.getColor(context, R.color.md_lime_500),
ContextCompat.getColor(context, R.color.md_yellow_500),
ContextCompat.getColor(context, R.color.md_amber_500),
ContextCompat.getColor(context, R.color.md_orange_500),
ContextCompat.getColor(context, R.color.md_deep_orange_500),
ContextCompat.getColor(context, R.color.md_brown_500),
ContextCompat.getColor(context, R.color.md_blue_grey_500),
ContextCompat.getColor(context, R.color.md_grey_500)
};
}
public static int[] getColors(Context context, int c) {
if (c == ContextCompat.getColor(context, R.color.md_red_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_red_200),
ContextCompat.getColor(context, R.color.md_red_300),
ContextCompat.getColor(context, R.color.md_red_400),
ContextCompat.getColor(context, R.color.md_red_500),
ContextCompat.getColor(context, R.color.md_red_600),
ContextCompat.getColor(context, R.color.md_red_700),
ContextCompat.getColor(context, R.color.md_red_800),
ContextCompat.getColor(context, R.color.md_red_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_pink_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_pink_200),
ContextCompat.getColor(context, R.color.md_pink_300),
ContextCompat.getColor(context, R.color.md_pink_400),
ContextCompat.getColor(context, R.color.md_pink_500),
ContextCompat.getColor(context, R.color.md_pink_600),
ContextCompat.getColor(context, R.color.md_pink_700),
ContextCompat.getColor(context, R.color.md_pink_800),
ContextCompat.getColor(context, R.color.md_pink_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_purple_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_purple_200),
ContextCompat.getColor(context, R.color.md_purple_300),
ContextCompat.getColor(context, R.color.md_purple_400),
ContextCompat.getColor(context, R.color.md_purple_500),
ContextCompat.getColor(context, R.color.md_purple_600),
ContextCompat.getColor(context, R.color.md_purple_700),
ContextCompat.getColor(context, R.color.md_purple_800),
ContextCompat.getColor(context, R.color.md_purple_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_deep_purple_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_deep_purple_200),
ContextCompat.getColor(context, R.color.md_deep_purple_300),
ContextCompat.getColor(context, R.color.md_deep_purple_400),
ContextCompat.getColor(context, R.color.md_deep_purple_500),
ContextCompat.getColor(context, R.color.md_deep_purple_600),
ContextCompat.getColor(context, R.color.md_deep_purple_700),
ContextCompat.getColor(context, R.color.md_deep_purple_800),
ContextCompat.getColor(context, R.color.md_deep_purple_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_indigo_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_indigo_200),
ContextCompat.getColor(context, R.color.md_indigo_300),
ContextCompat.getColor(context, R.color.md_indigo_400),
ContextCompat.getColor(context, R.color.md_indigo_500),
ContextCompat.getColor(context, R.color.md_indigo_600),
ContextCompat.getColor(context, R.color.md_indigo_700),
ContextCompat.getColor(context, R.color.md_indigo_800),
ContextCompat.getColor(context, R.color.md_indigo_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_blue_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_blue_200),
ContextCompat.getColor(context, R.color.md_blue_300),
ContextCompat.getColor(context, R.color.md_blue_400),
ContextCompat.getColor(context, R.color.md_blue_500),
ContextCompat.getColor(context, R.color.md_blue_600),
ContextCompat.getColor(context, R.color.md_blue_650),
ContextCompat.getColor(context, R.color.md_blue_700),
ContextCompat.getColor(context, R.color.md_blue_750),
ContextCompat.getColor(context, R.color.md_blue_800),
ContextCompat.getColor(context, R.color.md_blue_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_light_blue_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_light_blue_200),
ContextCompat.getColor(context, R.color.md_light_blue_300),
ContextCompat.getColor(context, R.color.md_light_blue_400),
ContextCompat.getColor(context, R.color.md_light_blue_500),
ContextCompat.getColor(context, R.color.md_light_blue_600),
ContextCompat.getColor(context, R.color.md_light_blue_700),
ContextCompat.getColor(context, R.color.md_light_blue_800),
ContextCompat.getColor(context, R.color.md_light_blue_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_cyan_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_cyan_200),
ContextCompat.getColor(context, R.color.md_cyan_300),
ContextCompat.getColor(context, R.color.md_cyan_400),
ContextCompat.getColor(context, R.color.md_cyan_500),
ContextCompat.getColor(context, R.color.md_cyan_600),
ContextCompat.getColor(context, R.color.md_cyan_700),
ContextCompat.getColor(context, R.color.md_cyan_800),
ContextCompat.getColor(context, R.color.md_cyan_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_teal_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_teal_200),
ContextCompat.getColor(context, R.color.md_teal_300),
ContextCompat.getColor(context, R.color.md_teal_400),
ContextCompat.getColor(context, R.color.md_teal_500),
ContextCompat.getColor(context, R.color.md_teal_600),
ContextCompat.getColor(context, R.color.md_teal_700),
ContextCompat.getColor(context, R.color.md_teal_800),
ContextCompat.getColor(context, R.color.md_teal_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_green_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_green_200),
ContextCompat.getColor(context, R.color.md_green_300),
ContextCompat.getColor(context, R.color.md_green_400),
ContextCompat.getColor(context, R.color.md_green_500),
ContextCompat.getColor(context, R.color.md_green_600),
ContextCompat.getColor(context, R.color.md_green_700),
ContextCompat.getColor(context, R.color.md_green_800),
ContextCompat.getColor(context, R.color.md_green_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_light_green_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_light_green_200),
ContextCompat.getColor(context, R.color.md_light_green_300),
ContextCompat.getColor(context, R.color.md_light_green_400),
ContextCompat.getColor(context, R.color.md_light_green_500),
ContextCompat.getColor(context, R.color.md_light_green_600),
ContextCompat.getColor(context, R.color.md_light_green_700),
ContextCompat.getColor(context, R.color.md_light_green_800),
ContextCompat.getColor(context, R.color.md_light_green_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_lime_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_lime_200),
ContextCompat.getColor(context, R.color.md_lime_300),
ContextCompat.getColor(context, R.color.md_lime_400),
ContextCompat.getColor(context, R.color.md_lime_500),
ContextCompat.getColor(context, R.color.md_lime_600),
ContextCompat.getColor(context, R.color.md_lime_700),
ContextCompat.getColor(context, R.color.md_lime_800),
ContextCompat.getColor(context, R.color.md_lime_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_yellow_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_yellow_400),
ContextCompat.getColor(context, R.color.md_yellow_500),
ContextCompat.getColor(context, R.color.md_yellow_600),
ContextCompat.getColor(context, R.color.md_yellow_700),
ContextCompat.getColor(context, R.color.md_yellow_800),
ContextCompat.getColor(context, R.color.md_yellow_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_amber_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_amber_200),
ContextCompat.getColor(context, R.color.md_amber_300),
ContextCompat.getColor(context, R.color.md_amber_400),
ContextCompat.getColor(context, R.color.md_amber_500),
ContextCompat.getColor(context, R.color.md_amber_600),
ContextCompat.getColor(context, R.color.md_amber_700),
ContextCompat.getColor(context, R.color.md_amber_800),
ContextCompat.getColor(context, R.color.md_amber_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_orange_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_orange_200),
ContextCompat.getColor(context, R.color.md_orange_300),
ContextCompat.getColor(context, R.color.md_orange_400),
ContextCompat.getColor(context, R.color.md_orange_500),
ContextCompat.getColor(context, R.color.md_orange_600),
ContextCompat.getColor(context, R.color.md_orange_700),
ContextCompat.getColor(context, R.color.md_orange_800),
ContextCompat.getColor(context, R.color.md_orange_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_deep_orange_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_deep_orange_200),
ContextCompat.getColor(context, R.color.md_deep_orange_300),
ContextCompat.getColor(context, R.color.md_deep_orange_400),
ContextCompat.getColor(context, R.color.md_deep_orange_500),
ContextCompat.getColor(context, R.color.md_deep_orange_600),
ContextCompat.getColor(context, R.color.md_deep_orange_650),
ContextCompat.getColor(context, R.color.md_deep_orange_700),
ContextCompat.getColor(context, R.color.md_deep_orange_800),
ContextCompat.getColor(context, R.color.md_deep_orange_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_brown_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_brown_200),
ContextCompat.getColor(context, R.color.md_brown_300),
ContextCompat.getColor(context, R.color.md_brown_400),
ContextCompat.getColor(context, R.color.md_brown_500),
ContextCompat.getColor(context, R.color.md_brown_600),
ContextCompat.getColor(context, R.color.md_brown_700),
ContextCompat.getColor(context, R.color.md_brown_800),
ContextCompat.getColor(context, R.color.md_brown_900)
};
} else if (c == ContextCompat.getColor(context, R.color.md_grey_500)) {
return new int[]{
ContextCompat.getColor(context, R.color.md_grey_400),
ContextCompat.getColor(context, R.color.md_grey_500),
ContextCompat.getColor(context, R.color.md_grey_600),
ContextCompat.getColor(context, R.color.md_grey_700),
ContextCompat.getColor(context, R.color.md_grey_800),
ContextCompat.getColor(context, R.color.md_grey_900),
Color.parseColor("#000000")
};
} else {
return new int[]{
ContextCompat.getColor(context, R.color.md_blue_grey_300),
ContextCompat.getColor(context, R.color.md_blue_grey_400),
ContextCompat.getColor(context, R.color.md_blue_grey_500),
ContextCompat.getColor(context, R.color.md_blue_grey_600),
ContextCompat.getColor(context, R.color.md_blue_grey_700),
ContextCompat.getColor(context, R.color.md_blue_grey_800),
ContextCompat.getColor(context, R.color.md_blue_grey_900)
};
}
}
}

View file

@ -0,0 +1,179 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
This class is inspired by org.horasapps.LeafPic
*/
package com.github.dfa.diaspora_android.ui.theme;
import android.content.DialogInterface;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Build;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.CompoundButtonCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* Singleton that can be used to color views
* Created by vanitas on 06.10.16.
*/
public class ThemeHelper {
private AppSettings appSettings;
private static ThemeHelper instance;
private ThemeHelper(AppSettings appSettings) {
this.appSettings = appSettings;
}
public static ThemeHelper getInstance(AppSettings appSettings) {
if (instance == null) {
instance = new ThemeHelper(appSettings);
}
return instance;
}
public static ThemeHelper getInstance() {
if (instance == null)
throw new IllegalStateException("ThemeHelper must be initialized using getInstance(AppSettingsBase) before it can be used!");
return instance;
}
public static void updateEditTextColor(EditText editText) {
if (editText != null) {
editText.setHighlightColor(getInstance().appSettings.getAccentColor());
if (Build.VERSION.SDK_INT >= 21) {
editText.getBackground().mutate().setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_ATOP);
}
}
}
public static void updateCheckBoxColor(CheckBox checkBox) {
if (checkBox != null) {
int states[][] = {{android.R.attr.state_checked}, {}};
int colors[] = {ThemeHelper.getAccentColor(), getNeutralGreyColor()};
CompoundButtonCompat.setButtonTintList(checkBox, new ColorStateList(states, colors));
}
}
public static void updateTabLayoutColor(TabLayout tabLayout) {
if (tabLayout != null) {
tabLayout.setBackgroundColor(getInstance().appSettings.getPrimaryColor());
tabLayout.setSelectedTabIndicatorColor(getInstance().appSettings.getAccentColor());
}
}
public static void updateTextViewLinkColor(TextView textView) {
if (textView != null) {
textView.setHighlightColor(getInstance().appSettings.getAccentColor());
textView.setLinkTextColor(getInstance().appSettings.getAccentColor());
}
}
public static void updateTextViewTextColor(TextView textView) {
if (textView != null) {
textView.setTextColor(getInstance().appSettings.getAccentColor());
}
}
public static void updateToolbarColor(Toolbar toolbar) {
if (toolbar != null) {
toolbar.setBackgroundColor(getInstance().appSettings.getPrimaryColor());
}
}
public static void updateActionMenuViewColor(ActionMenuView actionMenuView) {
if (actionMenuView != null) {
actionMenuView.setBackgroundColor(getInstance().appSettings.getPrimaryColor());
}
}
public static int getPrimaryColor() {
return getInstance().appSettings.getPrimaryColor();
}
public static int getAccentColor() {
return getInstance().appSettings.getAccentColor();
}
public static void setPrimaryColorAsBackground(View view) {
if (view != null) {
view.setBackgroundColor(getPrimaryColor());
}
}
public static int getPrimaryDarkColor() {
return ColorPalette.getObscuredColor(getPrimaryColor());
}
public static void updateProgressBarColor(ProgressBar progressBar) {
if (progressBar != null && progressBar.getProgressDrawable() != null) {
progressBar.getProgressDrawable().setColorFilter(getAccentColor(), PorterDuff.Mode.SRC_IN);
}
}
public static void updateRadioGroupColor(RadioGroup radioGroup) {
if (radioGroup != null && Build.VERSION.SDK_INT >= 21) {
for (int i = 0; i < radioGroup.getChildCount(); ++i) {
RadioButton btn = ((RadioButton) radioGroup.getChildAt(i));
btn.setButtonTintList(new ColorStateList(
new int[][]{new int[]{-android.R.attr.state_enabled}, new int[]{android.R.attr.state_enabled}},
new int[]{Color.BLACK, ThemeHelper.getAccentColor()}));
btn.invalidate();
}
}
}
public static int getNeutralGreyColor() {
return ContextCompat.getColor(getInstance().appSettings.getContext(), R.color.md_grey_800);
}
public static void updateAlertDialogColor(AlertDialog alertDialog) {
if (alertDialog != null) {
for (int i : new int[]{
DialogInterface.BUTTON_POSITIVE,
DialogInterface.BUTTON_NEUTRAL,
DialogInterface.BUTTON_NEGATIVE}) {
Button b = alertDialog.getButton(i);
if (b != null) {
b.setTextColor(getAccentColor());
}
}
}
}
public static void updateButtonTextColor(Button button) {
if (button != null) {
button.setTextColor(getAccentColor());
}
}
}

View file

@ -0,0 +1,10 @@
package com.github.dfa.diaspora_android.ui.theme;
/**
* Interface that allows setting Theme colors
* Created by vanitas on 24.10.16.
*/
public interface Themeable {
void setColors();
}

View file

@ -0,0 +1,91 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui.theme;
import android.annotation.TargetApi;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
/**
* Activity that supports color schemes
* Created by vanitas on 06.10.16.
*/
public abstract class ThemedActivity extends AppCompatActivity {
protected AppSettings getAppSettings() {
return ((App) getApplication()).getSettings();
}
@Override
protected void onResume() {
super.onResume();
ThemeHelper.getInstance(getAppSettings());
updateLanguage();
updateStatusBarColor();
updateRecentAppColor();
applyColorToViews();
updateScreenRotation();
}
protected abstract void applyColorToViews();
/**
* Update color of the status bar
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getWindow().setStatusBarColor(ThemeHelper.getPrimaryDarkColor());
}
}
/**
* Update primary color in recent apps overview
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateRecentAppColor() {
}
protected void updateScreenRotation() {
String setting = getAppSettings().getScreenRotation();
int rotation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; // Default (system settings)
if (setting.equals(getString(R.string.rotation_val_sensor))) {
rotation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
} else if (setting.equals(getString(R.string.rotation_val_portrait))) {
rotation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
} else if (setting.equals(getString(R.string.rotation_val_landscape))) {
rotation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
}
setRequestedOrientation(rotation);
}
public void updateLanguage() {
AppSettings appSettings = getAppSettings();
ContextUtils.get().setAppLanguage(appSettings.getLanguage());
}
}

View file

@ -0,0 +1,45 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import android.support.annotation.StyleRes;
import android.support.v7.app.AlertDialog;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* AlertDialog Builder that colors its buttons
* Created by vanitas on 06.11.16.
*/
public class ThemedAlertDialogBuilder extends AlertDialog.Builder {
protected AppSettings appSettings;
public ThemedAlertDialogBuilder(@NonNull Context context, AppSettings appSettings) {
super(context);
this.appSettings = appSettings;
}
public ThemedAlertDialogBuilder(@NonNull Context context, @StyleRes int themeResId, AppSettings appSettings) {
super(context, themeResId);
this.appSettings = appSettings;
}
@Override
public AlertDialog create() {
final AlertDialog dialog = super.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
applyColors(dialog);
}
});
return dialog;
}
private void applyColors(AlertDialog alertDialog) {
ThemeHelper.getInstance(appSettings);
ThemeHelper.updateAlertDialogColor(alertDialog);
}
}

View file

@ -0,0 +1,28 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.app.Dialog;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatDialogFragment;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* Themed DialogFragment
* Created by vanitas on 22.10.16.
*/
public abstract class ThemedAppCompatDialogFragment extends AppCompatDialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
ThemeHelper.getInstance(getAppSettings());
return dialog;
}
protected abstract void applyColorsToViews();
protected abstract AppSettings getAppSettings();
}

View file

@ -0,0 +1,48 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.preference.CheckBoxPreference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* CheckboxPreference that colors its checkbox with accent color
* Created by vanitas on 24.10.16.
*/
public class ThemedCheckBoxPreference extends CheckBoxPreference implements Themeable {
protected View rootLayout;
@SuppressWarnings("unused")
public ThemedCheckBoxPreference(Context context) {
super(context);
}
@SuppressWarnings("unused")
public ThemedCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressWarnings("unused")
public ThemedCheckBoxPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected View onCreateView(ViewGroup parent) {
rootLayout = super.onCreateView(parent);
setColors();
return rootLayout;
}
@Override
public void setColors() {
CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox);
ThemeHelper.getInstance(AppSettings.get());
ThemeHelper.updateCheckBoxColor(checkBox);
}
}

View file

@ -0,0 +1,64 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
/**
* Preference that shows selected Color in a circle
* Created by vanitas on 25.10.16.
*/
public class ThemedColorPickerPreference extends Preference implements Themeable {
protected ImageView colorPreview;
@SuppressWarnings("unused")
public ThemedColorPickerPreference(Context context) {
super(context);
}
@SuppressWarnings("unused")
public ThemedColorPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressWarnings("unused")
public ThemedColorPickerPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onBindView(View view) {
super.onBindView(view);
colorPreview = view.findViewById(android.R.id.icon);
setColors();
}
@Override
public void setColors() {
Drawable circle;
if (colorPreview != null && (circle = colorPreview.getDrawable()) != null) {
Context c = getContext();
AppSettings appSettings = AppSettings.get();
String key = getKey();
int color = ContextUtils.get().rcolor(R.color.primary);
if ((appSettings.isKeyEqual(key, R.string.pref_key__primary_color_shade))) {
color = appSettings.getPrimaryColor();
} else if ((appSettings.isKeyEqual(key, R.string.pref_key__accent_color_shade))) {
color = appSettings.getAccentColor();
} else {
color = appSettings.getColor(key, color, getSharedPreferences());
}
circle.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
}
}

View file

@ -0,0 +1,49 @@
/*
This file is part of the dandelion*.
dandelion* is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dandelion* is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the dandelion*.
If not, see <http://www.gnu.org/licenses/>.
*/
package com.github.dfa.diaspora_android.ui.theme;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.util.AppSettings;
import net.gsantner.opoc.activity.GsFragmentBase;
/**
* Fragment that supports color schemes
* Created by vanitas on 06.10.16.
*/
public abstract class ThemedFragment extends GsFragmentBase {
protected AppSettings getAppSettings() {
return ((App) getActivity().getApplication()).getSettings();
}
protected abstract void applyColorToViews();
@Override
public void onResume() {
super.onResume();
ThemeHelper.getInstance(getAppSettings());
applyColorToViews();
}
public boolean isAllowedIntellihide() {
return true;
}
}

View file

@ -0,0 +1,51 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.preference.PreferenceCategory;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* PreferenceCategory with a colored title
* Created by vanitas on 24.10.16.
*/
public class ThemedPreferenceCategory extends PreferenceCategory implements Themeable {
protected TextView titleTextView;
@SuppressWarnings("unused")
public ThemedPreferenceCategory(Context context) {
super(context);
}
@SuppressWarnings("unused")
public ThemedPreferenceCategory(Context context, AttributeSet attrs) {
super(context, attrs);
}
@SuppressWarnings("unused")
public ThemedPreferenceCategory(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected View onCreateView(ViewGroup parent) {
View rootLayout = super.onCreateView(parent);
this.titleTextView = rootLayout.findViewById(android.R.id.title);
setColors();
return rootLayout;
}
@Override
public void setColors() {
if (titleTextView != null) {
ThemeHelper.getInstance(AppSettings.get());
ThemeHelper.updateTextViewTextColor(titleTextView);
}
}
}

View file

@ -0,0 +1,45 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.os.Build;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceScreen;
import android.view.Window;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* PreferenceFragment with a colored status bar
* Created by vanitas on 24.10.16.
*/
public abstract class ThemedPreferenceFragment extends PreferenceFragment {
public abstract void updateViewColors();
@Override
public void onResume() {
super.onResume();
updateViewColors();
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (isAdded()) {
App app = ((App) getActivity().getApplication());
AppSettings appSettings = app.getSettings();
if (Build.VERSION.SDK_INT >= 21) {
if (preference instanceof PreferenceScreen && ((PreferenceScreen) preference).getDialog() != null) {
Window window = ((PreferenceScreen) preference).getDialog().getWindow();
if (window != null) {
ThemeHelper.getInstance(appSettings);
window.setStatusBarColor(ThemeHelper.getPrimaryDarkColor());
}
}
}
}
return super.onPreferenceTreeClick(screen, preference);
}
public abstract String getFragmentTag();
}

View file

@ -0,0 +1,35 @@
package com.github.dfa.diaspora_android.ui.theme;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.CheckBox;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings;
/**
* ThemedCheckBoxPreference with visibility icons instead of checkbox. TODO: Make more flexible?
* Created by vanitas on 25.10.16.
*/
public class ThemedVisibilityPreference extends ThemedCheckBoxPreference {
public ThemedVisibilityPreference(Context context) {
super(context);
}
public ThemedVisibilityPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ThemedVisibilityPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setColors() {
CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox);
checkBox.setButtonDrawable(R.drawable.ic_visibility_selector);
ThemeHelper.getInstance(AppSettings.get());
ThemeHelper.updateCheckBoxColor(checkBox);
}
}

View file

@ -0,0 +1,86 @@
package com.github.dfa.diaspora_android.util;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.view.View;
import com.github.dfa.diaspora_android.BuildConfig;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.web.WebHelper;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
@SuppressWarnings({"WeakerAccess", "unused", "SameParameterValue"})
public class ActivityUtils extends net.gsantner.opoc.util.ActivityUtils {
public ActivityUtils(Activity activity) {
super(activity);
}
public static ActivityUtils get(Activity activity) {
return new ActivityUtils(activity);
}
public File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("dd-MM-yy_HH-mm", Locale.getDefault()).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
AppLog.d(ActivityUtils.class, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
return new File(
imageFileName + /* prefix */
".jpg", /* suffix */
storageDir.getAbsolutePath() /* directory */
);
}
/**
* Show Information if user is offline, returns true if is not connected to internet
*
* @param anchor A view anchor
*/
public boolean showInfoIfUserNotConnectedToInternet(View anchor) {
boolean isOnline = WebHelper.isOnline(_context);
if (!isOnline) {
showSnackBar(R.string.sorry_need_to_be_connected_to_internet, true);
}
return !isOnline;
}
public void logBundle(Bundle savedInstanceState, String k) {
if (savedInstanceState != null) {
for (String key : savedInstanceState.keySet()) {
AppLog.d("Bundle", key + " is a key in the bundle " + k);
Object bun = savedInstanceState.get(key);
if (bun != null) {
if (bun instanceof Bundle) {
logBundle((Bundle) bun, k + "." + key);
} else if (bun instanceof byte[]) {
AppLog.d("Bundle", "Key: " + k + "." + key + ": " + Arrays.toString((byte[]) bun));
} else {
AppLog.d("Bundle", "Key: " + k + "." + key + ": " + bun.toString());
}
}
}
}
}
/**
* This method creates file sharing uri by using FileProvider
*
* @return
*/
public static Uri getFileSharingUri(Context context, File file) {
return FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, file);
}
}

View file

@ -0,0 +1,58 @@
package com.github.dfa.diaspora_android.util;
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
// From https://stackoverflow.com/a/19494006
public class AndroidBug5497Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity(Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private AndroidBug5497Workaround(Activity activity) {
FrameLayout content = activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard / 4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}

Some files were not shown because too many files have changed in this diff Show more