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

Compare commits

..

No commits in common. "master" and "v0.2.6" have entirely different histories.

319 changed files with 6559 additions and 19167 deletions

6
.atomignore Executable file → Normal file
View file

@ -15,9 +15,3 @@ app/build
app/.gitignore app/.gitignore
app/pom.xml app/pom.xml
app/proguard-rules.pro app/proguard-rules.pro
.hidden
.travis.yml
circle.yml
CODE_OF_CONDUCT*
gradle.properties
LICENSE*

View file

@ -1,24 +1,53 @@
#### General information #### General information
* **App version:**
* **System:**
* **Pod:**
#### Description * **Android Device:**
* **Android API Version:**
* **App version:**
* **App source:**
* **Pod version:**
#### Log
<!-- <!--
Look for already reported issues before posting! I have:
Also take a look at documentation and wiki, or write in the project chat.
App version: The version of the app installed and the installation source. Example: v0.3.5 F-Droid - At least version 0.2.0 installed, see About-> Debug. If it is not visible you have an very old version, and
Please keep in mind that only the latest downloadable version is supported and that there are no backports to older versions. your issue will be closed.
System: Information about where the app is running. Give all details you know, but at least the Android OS version. - searched open and closed issues for duplicates
Example: Android 8.0.1, Nexus 5, LineageOS - read <https://github.com/Diaspora-for-Android/dandelion/blob/master/CONTRIBUTING.md>
- not submitted translations - see [Crowdin](https://crowdin.com/project/diaspora-for-android/invite)
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 dandelion* and include all the steps it takes to reproduce the problem.
IMPORTANT: In-App debug log must be activated and the app restarted first!
````
adb logcat -s com.github.dfa.diaspora_android
````
#### In-App debug log
This is useful for visual bugs without application crashes
````
You can long click on the in-app debug log in order to copy it to the clipboard
````

View file

@ -1,27 +0,0 @@
<!--
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

@ -1,68 +0,0 @@
##############################################################################################################################
# # 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

21
.gitignore vendored
View file

@ -1,3 +1,12 @@
##############
### Project ##
app/src/main/res/raw/changelog.md
app/src/main/res/raw/contributors.md
app/src/main/res/raw/license.md
app/src/main/res/raw/readme.md
app/src/main/res/raw/contributors.txt
#app/src/main/res/raw/podlist.json
############## ##############
### Common ### ### Common ###
*~* *~*
@ -36,7 +45,6 @@ tmp/
### Gradle ### ### Gradle ###
.gradle .gradle
build/ build/
dist/
gradle-app.setting gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
@ -91,14 +99,3 @@ proguard/
# Android Studio Stuff # Android Studio Stuff
.navigation/ .navigation/
gen-external-apklibs 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

38
.travis.yml Normal file
View file

@ -0,0 +1,38 @@
language: android
jdk:
- oraclejdk8
android:
components:
- tools
- tools # TODO https://github.com/travis-ci/travis-ci/issues/6193
- platform-tools
- build-tools-24.0.3
- 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="lintFlavorDefaultDebug"
- TASK="build check --stacktrace"
branches:
except:
- l10n_master
- l10n_master2
- crowdin
notifications:
webhooks:
urls:
- "https://webhooks.gitter.im/e/e462044d3105a7bb4b4f"
- "https://scalar.vector.im/api/neb/services/hooks/dHJhdmlzLWNpLyU0MGdzYW50bmVyJTNBbWF0cml4Lm9yZy8lMjFNUERTYURTaVBMZXdSQXBxa24lM0FtYXRyaXgub3Jn"
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
after_success:
- bash <(curl -s https://codecov.io/bash)

View file

@ -1,91 +1,3 @@
### 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.
### 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) ### v0.2.6 (2017-05-03)
- Fixed #156 #158 #159 - Fixed #156 #158 #159
- Added chinese traditional language - Added chinese traditional language

View file

@ -1,74 +0,0 @@
# 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/

6
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,6 @@
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 IRC conference at `#diaspora-android @irc.freenode.net`.
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 dandelion\*. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite>
If your desired language is not listed please contact the maintainers/owner.

View file

@ -1,32 +0,0 @@
<!--
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

24
CONTRIBUTORS.txt Normal file
View file

@ -0,0 +1,24 @@
00l>> This file contains references to people who contributed to the app.
01l>> If you helped by translating the app, please send a message on Crowdin.
02l>> You can also send a mail to [gdev AT live DOT de](https://gsantner.github.io/about/email/) to get included.
03l>>
04l>> Schemes:
05l>> Firstname Lastname (Link): Text
06l>> Firstname Lastname (E-Mail): Text
07l>> Username (Link): Text
08l>> Username (E-Mail): Text
## 99l CONTRIBUTORS
Abhijith Balan (abhijithb21 AT openmailbox DOT org): Malayalam translation
Airon90 (https://diasp.eu/u/airon90): Italian translation
Gaukler Faun (https://github.com/scoute-dich): Diaspora Native WebApp additions
Martín Vukovic (martinvukovic AT protonmail DOT com): Diaspora Native WebApp
Nacho Fernández (nacho_f AT joindiaspora DOT com): Spanish translation
Naofumi Fukue (https://github.com/naofum): Japanese translation
pskosinski (email AT pskosinski DOT pl): Polish translation
SansPseudoFix (https://github.com/SansPseudoFix): French translation
secitem (secitem AT tuta DOT io): Czech translation
Zsolt Szakács (maxigaz AT diaspora DOT zone): Hungarian translation
Danilo Raffaelli (https://crowdin.com/profile/Daraf): Italian translation
O'Loubám (loubam AT diasp DOT org): Galician translation
transifex3 (https://crowdin.com/profile/transifex3): Korean translation
Âng Iōngchun (https://pubpod.alqualonde.org/u/iongchun): Chinese traditional translation

View file

@ -1,99 +0,0 @@
# 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
View file

@ -1,96 +0,0 @@
# 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

View file

@ -1,81 +1,48 @@
[![GitHub releases](https://img.shields.io/github/tag/gsantner/dandelion.svg)](https://github.com/gsantner/dandelion/releases) [![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 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) <a name="badgers"></a>[![CircleCI](https://circleci.com/gh/Diaspora-for-Android/dandelion.svg?style=shield)](https://circleci.com/gh/Diaspora-for-Android/dandelion)
[![Chat on Matrix](https://img.shields.io/badge/chat-matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/diaspora-for-android/localized.svg)](https://crowdin.com/project/diaspora-for-android)
[![GitHub CI](https://github.com/gsantner/dandelion/workflows/CI/badge.svg)](https://github.com/gsantner/dandelion/actions) [![Chat - Matrix](https://img.shields.io/badge/chat-on%20matrix-blue.svg)](https://matrix.to/#/#dandelion:matrix.org)
[![Codacy code quality](https://img.shields.io/codacy/grade/aff869c440bc48b7bd64680e97cbc453)](https://www.codacy.com/app/gsantner/dandelion)
# dandelion\* # dandelion\*
<img src="/app/src/main/ic_launcher-web.png" align="left" width="100" hspace="10" vspace="10"> FORMERLY KNOWN AS DIASPORA-FOR-ANDROID
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;" > This is an unofficial webview based client for the community-run, distributed social network **[diaspora*](https://diasporafoundation.org/)**. It's currently under development and should be used with that in mind. Please submit any bugs you might find.
<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>
- Download latest release on ([F-Droid](https://f-droid.org/repository/browse/?fdid=com.github.dfa.diaspora_android))
- Download latest nightly - [secondlion\*](https://gsantner.gitlab.io/fdroid/latest/com.github.dfa.secondlion.apk)
- Watch [Changelog](https://github.com/Diaspora-for-Android/dandelion/blob/master/CHANGELOG.md)
- See [Screenshots](https://github.com/Diaspora-for-Android/dandelion/blob/master/SCREENSHOTS.md)
- Get updates from our diaspora\* account: [dandelion00@diasp.org](https://diasp.org/people/48b78420923501341ef3782bcb452bd5)
## Description ## Contributions
This is an unofficial webview based client for the community-run, distributed social network <b><a href="https://diasporafoundation.org/">diaspora*</a></b>. We are always open for any kind of contribution. (PR's, bug reports, feature requests, translations, ..)
It's currently under development and should be used with that in mind. Please submit any bugs you might find. If you got any questions feel free to contact us on IRC, XMPP or Gitter. You can start chatting by clicking on the [blue chat badges](#badgers) listed on top.
#### WebApp We use Crowdin to translate dandelion\*. Join our project here: <https://crowdin.com/project/diaspora-for-android/invite>. If your desired language is not listed please contact the maintainers/owner.
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.
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.
### License
dandelion\* is released under GNU GENERAL PUBLIC LICENSE (see [LICENCE](https://github.com/Diaspora-for-Android/dandelion/blob/master/LICENSE.md)).
### WebApp
The app is developed as a 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.
[Stay tuned on diaspora\* issues](https://github.com/diaspora/diaspora/labels/api) about API. [Stay tuned on diaspora\* issues](https://github.com/diaspora/diaspora/labels/api) about API.
Why is a WebApp better than using the mobile site on a browser? Why is a WebApp 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 Android 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
### Privacy & Permissions<a name="privacy"></a> ### App Permissions
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. 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
## Contributions - gsantner ([GitHub](https://github.com/gsantner), [Web](https://gsantner.github.io), [diaspora*](https://pod.geraspora.de/people/d1cbdd70095301341e834860008dbc6c))
The project is always open for contributions and accepts pull requests. - Bitcoin: [1B9ZyYdQoY9BxMe9dRUEKaZbJWsbQqfXU5](https://gsantner.github.io/donate/#donate)
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)) - vanitasvitae ([GitHub](https://github.com/vanitasvitae), [diaspora*](https://pod.geraspora.de/people/bbd7af90fbec013213e34860008dbc6c))
- Bitcoin: 1Ao3W6NaQv3xKppviB7RSFKjHo6PGd8RTy

24
SCREENSHOTS.md Normal file
View file

@ -0,0 +1,24 @@
<table>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/01.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/02.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/03.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/04.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/05.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/06.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/07.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/08.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/09.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/10.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/11.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/12.png" height="60%" width="60%"></td>
</tr>
<tr>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/13.png" height="60%" width="60%"></td>
<td><img src="https://raw.githubusercontent.com/Diaspora-for-Android/diaspora-android-extras/master/graphics/screens/0.1.6/14.png" height="60%" width="60%"></td>
</tr>
</table>

View file

@ -1,63 +1,26 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
if (enable_plugin_kotlin) { apply plugin: 'android-apt'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
}
android { android {
buildToolsVersion rootProject.ext.version_buildTools compileSdkVersion 24
compileSdkVersion rootProject.ext.version_compileSdk buildToolsVersion "24.0.3"
defaultConfig { defaultConfig {
resValue "string", "manifest_package_id", "com.github.dfa.diaspora_android" minSdkVersion 17
applicationId "com.github.dfa.diaspora_android" targetSdkVersion 24
versionName "1.3.5"
versionCode 46 versionCode 16
vectorDrawables.useSupportLibrary = true versionName "0.2.6"
applicationId "com.github.dfa.diaspora_android"
resValue 'string', 'app_name', "dandelion*"
manifestPlaceholders = [appIcon: "@drawable/ic_launcher"]
minSdkVersion rootProject.ext.version_minSdk
targetSdkVersion rootProject.ext.version_compileSdk
buildConfigField "boolean", "IS_TEST_BUILD", "false" buildConfigField "boolean", "IS_TEST_BUILD", "false"
buildConfigField "boolean", "IS_GPLAY_BUILD", "false" buildConfigField "boolean", "IS_GPLAY_BUILD", "false"
buildConfigField "String[]", "DETECTED_ANDROID_LOCALES", "${findUsedAndroidLocales()}"
buildConfigField "String", "BUILD_DATE", "\"${getBuildDate()}\"" vectorDrawables.useSupportLibrary = true
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
@ -65,72 +28,85 @@ android {
} }
} }
configurations.all { productFlavors {
resolutionStrategy { flavorDefault {
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}" flavorGplay {
} buildConfigField "boolean", "IS_GPLAY_BUILD", "true"
} }
} */
flavorTest {
applicationId "com.github.dfa.secondlion"
resValue 'string', 'app_name', "secondlion*"
manifestPlaceholders = [appIcon: "@drawable/ic_launcher_test"]
versionCode = Integer.parseInt(new Date().format('yyMMdd'))
versionName = new Date().format('yyMMdd')
buildConfigField "boolean", "IS_TEST_BUILD", "true"
} }
} }
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', 'InvalidPackage', 'ObsoleteLintCustomCheck', 'DefaultLocale', 'UnusedAttribute', 'VectorRaster', 'InflateParams', 'IconLocation', 'UnusedResources', 'TypographyEllipsis' disable 'MissingTranslation'
abortOnError false }
}
// Additional repositories
repositories {
maven {
url "https://jitpack.io"
} }
} }
dependencies { dependencies {
// Sub-Projects // Sub-Projects
//implementation project(':subprojectFromRoot') //compile project(':subprojectFromRoot')
// Jars // Jars
implementation fileTree(dir: 'libs', include: ['*.jar']) compile fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13' testCompile 'junit:junit:4.12'
// Android standard libs // Android standard libs
implementation "com.android.support:appcompat-v7:${version_library_appcompat}" compile 'com.android.support:appcompat-v7:24.2.1'
implementation "com.android.support:design:${version_library_appcompat}" compile 'com.android.support:design:24.1.0' //Don't update. Broken up to 25.0.0
implementation "com.android.support:support-v4:${version_library_appcompat}" compile 'com.android.support:support-v4:24.2.1'
implementation "com.android.support:customtabs:${version_library_appcompat}" compile 'com.android.support:customtabs:24.2.1'
implementation "com.android.support:cardview-v7:${version_library_appcompat}" compile 'com.android.support:cardview-v7:24.2.1'
implementation "com.android.support:preference-v7:${version_library_appcompat}"
// UI libraries // More libraries
implementation "com.github.DASAR:ShiftColorPicker:v0.5" compile 'com.jakewharton:butterknife:8.0.1'
compile 'info.guardianproject.netcipher:netcipher:2.0.0-alpha1'
compile 'info.guardianproject.netcipher:netcipher-webkit:2.0.0-alpha1'
compile 'com.github.DASAR:ShiftColorPicker:v0.5'
apt 'com.jakewharton:butterknife-compiler:8.0.1'
}
// Tool libraries // #####################
implementation 'commons-io:commons-io:2.6' // Groovy Coding Area
implementation "info.guardianproject.netcipher:netcipher:${version_library_netcipher}" // #####################
implementation "info.guardianproject.netcipher:netcipher-webkit:${version_library_netcipher}" final String RAW_DIR = "app/src/main/res/raw"
//noinspection AnnotationProcessorOnCompilePath final String[] ROOT_TO_RAW_COPYFILES = ["README.md", "LICENSE.md", "CHANGELOG.md", "CONTRIBUTORS.txt"]
implementation "com.jakewharton:butterknife:${version_library_butterknife}"
if (enable_plugin_kotlin) { // Called before building
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${version_plugin_kotlin}" task copyRepoFiles(type: Copy) {
// Copy files over to raw dir
from rootProject.files(ROOT_TO_RAW_COPYFILES)
into RAW_DIR.replaceFirst("app/", "")
rename { String fileName ->
fileName.replace(fileName, fileName.toLowerCase())
} }
// Processors // Filter Contributors file
def anpros = ["com.jakewharton:butterknife-compiler:${version_library_butterknife}"] from(rootProject.file("CONTRIBUTORS.txt")) {
for (anpro in anpros) { into '.' // Target already changed to 'src/main/res/raw'
if (enable_plugin_kotlin) { rename { String fileName ->
kapt anpro fileName.replace(fileName, fileName.toLowerCase())
} else { }
annotationProcessor anpro filter { line ->
(line.toString().matches("..l>>.*") || line.toString().startsWith("## 99l CONTRIBUTORS")) ? null : line.toString().trim().replaceAll(" \\(.*\\)", "")
} }
} }
} }
tasks.copyRepoFiles.execute()

View file

@ -1,5 +0,0 @@
<?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

@ -1,5 +0,0 @@
<?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.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -1,9 +0,0 @@
<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

@ -1,12 +0,0 @@
<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.

Before

Width:  |  Height:  |  Size: 27 KiB

View file

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View file

@ -1,5 +0,0 @@
<?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

@ -1,5 +0,0 @@
<?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.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,9 +0,0 @@
<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

@ -1,12 +0,0 @@
<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

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

View file

@ -7,15 +7,12 @@
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<application <application
android:name="com.github.dfa.diaspora_android.App" android:name="com.github.dfa.diaspora_android.App"
android:allowBackup="false" android:allowBackup="false"
android:icon="@drawable/ic_launcher" android:icon="${appIcon}"
android:label="@string/app_name" android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:theme="@style/DiasporaLight"> android:theme="@style/DiasporaLight">
<provider <provider
@ -23,16 +20,6 @@
android:authorities="${applicationId}.mainactivity" android:authorities="${applicationId}.mainactivity"
android:exported="false" /> android:exported="false" />
<!--File provider for sharing files-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
<service <service
android:name="com.github.dfa.diaspora_android.service.FetchPodsService" android:name="com.github.dfa.diaspora_android.service.FetchPodsService"
android:enabled="true" android:enabled="true"
@ -48,29 +35,20 @@
<activity <activity
android:name="com.github.dfa.diaspora_android.activity.AboutActivity" android:name="com.github.dfa.diaspora_android.activity.AboutActivity"
android:configChanges="locale" android:configChanges="locale"
android:label="@string/about" android:label="@string/about_activity__title_about_app"
android:theme="@style/DiasporaLight.NoActionBar" /> android:theme="@style/DiasporaLight.NoActionBar" />
<activity <activity
android:name="com.github.dfa.diaspora_android.activity.MainActivity" android:name="com.github.dfa.diaspora_android.activity.MainActivity"
android:configChanges="keyboardHidden|locale|orientation|screenSize" android:configChanges="keyboardHidden|locale|orientation|screenSize"
android:icon="@drawable/ic_launcher" android:icon="${appIcon}"
android:label="@string/app_name" android:label="@string/app_name"
android:launchMode="singleTop" android:launchMode="singleTop"
android:theme="@style/DiasporaLight.NoActionBar" android:theme="@style/DiasporaLight.NoActionBar"
android:windowSoftInputMode="adjustResize"> android:windowSoftInputMode="adjustResize">
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
<intent-filter> <intent-filter>
<action android:name="sc_new_post" />
<action android:name="sc_nav_followed_tags" />
<action android:name="sc_aspects" />
<action android:name="sc_activities" />
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
@ -81,7 +59,7 @@
</intent-filter> </intent-filter>
<!-- Hashtag click intent from HtmlTextViews --> <!-- Hashtag click intent from HtmlTextViews -->
<intent-filter tools:ignore="AppLinkUrlError"> <intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.cc.tag" /> <data android:mimeType="vnd.android.cursor.item/vnd.cc.tag" />
@ -101,705 +79,151 @@
android:scheme="https" /> android:scheme="https" />
<!--@@@ PODLIST START--> <!--@@@ PODLIST START-->
<data <data android:host="joindiaspora.com" android:scheme="https" />
android:host="joindiaspora.com" <data android:host="diasporaaqmjixh5.onion" android:scheme="http" />
android:scheme="https" /> <data android:host="pod.geraspora.de" android:scheme="https" />
<data <data android:host="diasp.org" android:scheme="https" />
android:host="diasporaaqmjixh5.onion" <data android:host="framasphere.org" android:scheme="https" />
android:scheme="http" /> <data android:host="nerdpol.ch" android:scheme="https" />
<data <data android:host="despora.de" android:scheme="https" />
android:host="pod.geraspora.de" <data android:host="sechat.org" android:scheme="https" />
android:scheme="https" /> <data android:host="sechatqpscuj2npx.onion" android:scheme="http" />
<data <data android:host="berdaguermontes.eu" android:scheme="https" />
android:host="diasp.org" <data android:host="berlinspora.de" android:scheme="https" />
android:scheme="https" /> <data android:host="community.kanalinseln.de" android:scheme="https" />
<data <data android:host="d.consumium.org" android:scheme="https" />
android:host="diasporgc3d32vv4.onion" <data android:host="dia.manuelbichler.at" android:scheme="https" />
android:scheme="https" /> <data android:host="dia.myocastor.de" android:scheme="https" />
<data <data android:host="diapod.net" android:scheme="https" />
android:host="framasphere.org" <data android:host="diapod.org" android:scheme="https" />
android:scheme="https" /> <data android:host="diasp.ca" android:scheme="https" />
<data <data android:host="diasp.cz" android:scheme="https" />
android:host="nerdpol.ch" <data android:host="diasp.de" android:scheme="https" />
android:scheme="https" /> <data android:host="diasp.eu" android:scheme="https" />
<data <data android:host="diasp.eu.com" android:scheme="https" />
android:host="despora.de" <data android:host="diasp.nl" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspod.de" android:scheme="https" />
<data <data android:host="diaspora-fr.org" android:scheme="https" />
android:host="sechat.org" <data android:host="diaspora.alfter.us" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.bohramt.de" android:scheme="https" />
<data <data android:host="diaspora.com.ar" android:scheme="https" />
android:host="sechatqpscuj2npx.onion" <data android:host="diaspora.deadhexagon.com" android:scheme="https" />
android:scheme="http" /> <data android:host="diaspora.digi-merc.org" android:scheme="https" />
<data <data android:host="diaspora.dorf-post.de" android:scheme="https" />
android:host="berdaguermontes.eu" <data android:host="diaspora.espiritolivre.org" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.horwood.biz" android:scheme="https" />
<data <data android:host="diaspora.hzsogood.net" android:scheme="https" />
android:host="berlinspora.de" <data android:host="diaspora.kapper.net" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.koehn.com" android:scheme="https" />
<data <data android:host="diaspora.kosebamse.com" android:scheme="https" />
android:host="community.kanalinseln.de" <data android:host="diaspora.lebarjack.com" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.microdata.co.uk" android:scheme="https" />
<data <data android:host="diaspora.moosje.nl" android:scheme="https" />
android:host="d.consumium.org" <data android:host="diaspora.net.gr" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.permutationsofchaos.com" android:scheme="https" />
<data <data android:host="diaspora.pimpmypony.eu" android:scheme="https" />
android:host="dia.manuelbichler.at" <data android:host="diaspora.pingupod.de" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.podzimek.org" android:scheme="https" />
<data <data android:host="diaspora.poleni.com" android:scheme="https" />
android:host="dia.myocastor.de" <data android:host="diaspora.psyco.fr" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.raven-ip.com" android:scheme="https" />
<data <data android:host="diaspora.retrodigital.net" android:scheme="https" />
android:host="diapod.net" <data android:host="diaspora.soh.re" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.subsignal.org" android:scheme="https" />
<data <data android:host="diaspora.trash-talk.de" android:scheme="https" />
android:host="diapod.org" <data android:host="diaspora.u4u.org" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.unixcorn.org" android:scheme="https" />
<data <data android:host="diasporabr.com.br" android:scheme="https" />
android:host="diasp.ca" <data android:host="diasporabrazil.org" android:scheme="https" />
android:scheme="https" /> <data android:host="diasporapr.tk" android:scheme="https" />
<data <data android:host="diasporing.ch" android:scheme="https" />
android:host="diasp.cz" <data android:host="distributed.chat" android:scheme="https" />
android:scheme="https" /> <data android:host="espora.com.es" android:scheme="https" />
<data <data android:host="espora.social" android:scheme="https" />
android:host="diasp.de" <data android:host="failure.net" android:scheme="https" />
android:scheme="https" /> <data android:host="flokk.no" android:scheme="https" />
<data <data android:host="freehuman.fr" android:scheme="https" />
android:host="diasp.eu" <data android:host="iliketoast.net" android:scheme="https" />
android:scheme="https" /> <data android:host="jons.gr" android:scheme="https" />
<data <data android:host="kapok.se" android:scheme="https" />
android:host="diasp.eu.com" <data android:host="karmasphe.re" android:scheme="https" />
android:scheme="https" /> <data android:host="laba.mba" android:scheme="https" />
<data <data android:host="liberdade.digital" android:scheme="https" />
android:host="diasp.nl" <data android:host="librenet.co.za" android:scheme="https" />
android:scheme="https" /> <data android:host="librenet.gr" android:scheme="https" />
<data <data android:host="misamigos.online" android:scheme="https" />
android:host="diaspod.de" <data android:host="mondiaspora.net" android:scheme="https" />
android:scheme="https" /> <data android:host="networkwizard.de" android:scheme="https" />
<data <data android:host="nx-pod.de" android:scheme="https" />
android:host="diaspora-fr.org" <data android:host="pe.spbstu.ru" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.4ray.co" android:scheme="https" />
<data <data android:host="pod.8n1.org" android:scheme="https" />
android:host="diaspora.alfter.us" <data android:host="pod.alterworld.info" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.asap-soft.com" android:scheme="https" />
<data <data android:host="pod.cannyfoxx.me" android:scheme="https" />
android:host="diaspora.bohramt.de" <data android:host="pod.cyberdungeon.de" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.dapor.net" android:scheme="https" />
<data <data android:host="pod.datenknoten.me" android:scheme="https" />
android:host="diaspora.com.ar" <data android:host="pod.diaspora.software" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.dirkomatik.de" android:scheme="https" />
<data <data android:host="pod.disroot.org" android:scheme="https" />
android:host="diaspora.deadhexagon.com" <data android:host="pod.gedankenausbruch.com" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.gleisnetze.de" android:scheme="https" />
<data <data android:host="pod.goodsharing.at" android:scheme="https" />
android:host="diaspora.digi-merc.org" <data android:host="pod.hashtagueule.fr" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.hoizi.net" android:scheme="https" />
<data <data android:host="pod.itabs.nl" android:scheme="https" />
android:host="diaspora.dorf-post.de" <data android:host="pod.jpope.org" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.liebeleu.de" android:scheme="https" />
<data <data android:host="pod.nomorestars.com" android:scheme="https" />
android:host="diaspora.espiritolivre.org" <data android:host="pod.orkz.net" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.ponk.pink" android:scheme="https" />
<data <data android:host="pod.promedol.com" android:scheme="https" />
android:host="diaspora.horwood.biz" <data android:host="pod.psynet.su" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.roocita.com" android:scheme="https" />
<data <data android:host="pod.sertelon.fr" android:scheme="https" />
android:host="diaspora.hzsogood.net" <data android:host="pod.storel.li" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.tchncs.de" android:scheme="https" />
<data <data android:host="pod.thomasdalichow.de" android:scheme="https" />
android:host="diaspora.kapper.net" <data android:host="pod.volt.io" android:scheme="https" />
android:scheme="https" /> <data android:host="podbay.net" android:scheme="https" />
<data <data android:host="poddery.com" android:scheme="https" />
android:host="diaspora.koehn.com" <data android:host="podricing.pw" android:scheme="https" />
android:scheme="https" /> <data android:host="pubpod.alqualonde.org" android:scheme="https" />
<data <data android:host="revreso.de" android:scheme="https" />
android:host="diaspora.kosebamse.com" <data android:host="ruhrspora.de" android:scheme="https" />
android:scheme="https" /> <data android:host="russiandiaspora.org" android:scheme="https" />
<data <data android:host="shrekislove.us" android:scheme="https" />
android:host="diaspora.lebarjack.com" <data android:host="social.acclaro.digital" android:scheme="https" />
android:scheme="https" /> <data android:host="social.baldr.io" android:scheme="https" />
<data <data android:host="social.daxbau.net" android:scheme="https" />
android:host="diaspora.microdata.co.uk" <data android:host="social.elaon.de" android:scheme="https" />
android:scheme="https" /> <data android:host="social.lanham.id.au" android:scheme="https" />
<data <data android:host="social.mbuto.me" android:scheme="https" />
android:host="diaspora.moosje.nl" <data android:host="socializer.cc" android:scheme="https" />
android:scheme="https" /> <data android:host="spora.zone" android:scheme="https" />
<data <data android:host="subvillage.de" android:scheme="https" />
android:host="diaspora.net.gr" <data android:host="sysad.org" android:scheme="https" />
android:scheme="https" /> <data android:host="teki.be" android:scheme="https" />
<data <data android:host="therealtalk.org" android:scheme="https" />
android:host="diaspora.permutationsofchaos.com" <data android:host="thinkopen.net" android:scheme="https" />
android:scheme="https" /> <data android:host="tippentappen.de" android:scheme="https" />
<data <data android:host="whatsnewz.com" android:scheme="https" />
android:host="diaspora.pimpmypony.eu" <data android:host="wk3.org" android:scheme="https" />
android:scheme="https" /> <data android:host="www.datataffel.dk" android:scheme="https" />
<data <data android:host="www.diasporaix.de" android:scheme="https" />
android:host="diaspora.pingupod.de" <data android:host="diaspora.hofud.com" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.softwarelivre.org" android:scheme="https" />
<data <data android:host="confetticake.club" android:scheme="https" />
android:host="diaspora.podzimek.org" <data android:host="diaspote.org" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.zone" android:scheme="https" />
<data <data android:host="pod.userzap.de" android:scheme="https" />
android:host="diaspora.poleni.com" <data android:host="www.vodeoo.com" android:scheme="https" />
android:scheme="https" /> <data android:host="diaspora.punkbeer.me" android:scheme="https" />
<data <data android:host="ingtech.net" android:scheme="https" />
android:host="diaspora.psyco.fr" <data android:host="mmkr.co" android:scheme="https" />
android:scheme="https" /> <data android:host="pod.kneedrag.org" android:scheme="https" />
<data <data android:host="pod.mew.cat" android:scheme="https" />
android:host="diaspora.raven-ip.com"
android:scheme="https" />
<data
android:host="diaspora.retrodigital.net"
android:scheme="https" />
<data
android:host="diaspora.soh.re"
android:scheme="https" />
<data
android:host="diaspora.subsignal.org"
android:scheme="https" />
<data
android:host="diaspora.trash-talk.de"
android:scheme="https" />
<data
android:host="diaspora.u4u.org"
android:scheme="https" />
<data
android:host="diaspora.unixcorn.org"
android:scheme="https" />
<data
android:host="diasporabr.com.br"
android:scheme="https" />
<data
android:host="diasporabrazil.org"
android:scheme="https" />
<data
android:host="diasporapr.tk"
android:scheme="https" />
<data
android:host="diasporing.ch"
android:scheme="https" />
<data
android:host="distributed.chat"
android:scheme="https" />
<data
android:host="espora.com.es"
android:scheme="https" />
<data
android:host="espora.social"
android:scheme="https" />
<data
android:host="failure.net"
android:scheme="https" />
<data
android:host="flokk.no"
android:scheme="https" />
<data
android:host="freehuman.fr"
android:scheme="https" />
<data
android:host="iliketoast.net"
android:scheme="https" />
<data
android:host="jons.gr"
android:scheme="https" />
<data
android:host="kapok.se"
android:scheme="https" />
<data
android:host="karmasphe.re"
android:scheme="https" />
<data
android:host="laba.mba"
android:scheme="https" />
<data
android:host="liberdade.digital"
android:scheme="https" />
<data
android:host="librenet.co.za"
android:scheme="https" />
<data
android:host="librenet.gr"
android:scheme="https" />
<data
android:host="misamigos.online"
android:scheme="https" />
<data
android:host="mondiaspora.net"
android:scheme="https" />
<data
android:host="networkwizard.de"
android:scheme="https" />
<data
android:host="nx-pod.de"
android:scheme="https" />
<data
android:host="pe.spbstu.ru"
android:scheme="https" />
<data
android:host="pod.4ray.co"
android:scheme="https" />
<data
android:host="pod.8n1.org"
android:scheme="https" />
<data
android:host="pod.alterworld.info"
android:scheme="https" />
<data
android:host="pod.asap-soft.com"
android:scheme="https" />
<data
android:host="pod.cannyfoxx.me"
android:scheme="https" />
<data
android:host="pod.cyberdungeon.de"
android:scheme="https" />
<data
android:host="pod.dapor.net"
android:scheme="https" />
<data
android:host="pod.datenknoten.me"
android:scheme="https" />
<data
android:host="pod.diaspora.software"
android:scheme="https" />
<data
android:host="pod.dirkomatik.de"
android:scheme="https" />
<data
android:host="pod.disroot.org"
android:scheme="https" />
<data
android:host="pod.gedankenausbruch.com"
android:scheme="https" />
<data
android:host="pod.gleisnetze.de"
android:scheme="https" />
<data
android:host="pod.goodsharing.at"
android:scheme="https" />
<data
android:host="pod.hashtagueule.fr"
android:scheme="https" />
<data
android:host="pod.hoizi.net"
android:scheme="https" />
<data
android:host="pod.itabs.nl"
android:scheme="https" />
<data
android:host="pod.jpope.org"
android:scheme="https" />
<data
android:host="pod.liebeleu.de"
android:scheme="https" />
<data
android:host="pod.nomorestars.com"
android:scheme="https" />
<data
android:host="pod.orkz.net"
android:scheme="https" />
<data
android:host="pod.ponk.pink"
android:scheme="https" />
<data
android:host="pod.promedol.com"
android:scheme="https" />
<data
android:host="pod.psynet.su"
android:scheme="https" />
<data
android:host="pod.roocita.com"
android:scheme="https" />
<data
android:host="pod.sertelon.fr"
android:scheme="https" />
<data
android:host="pod.storel.li"
android:scheme="https" />
<data
android:host="pod.tchncs.de"
android:scheme="https" />
<data
android:host="pod.thomasdalichow.de"
android:scheme="https" />
<data
android:host="pod.volt.io"
android:scheme="https" />
<data
android:host="podbay.net"
android:scheme="https" />
<data
android:host="poddery.com"
android:scheme="https" />
<data
android:host="podricing.pw"
android:scheme="https" />
<data
android:host="pubpod.alqualonde.org"
android:scheme="https" />
<data
android:host="revreso.de"
android:scheme="https" />
<data
android:host="ruhrspora.de"
android:scheme="https" />
<data
android:host="russiandiaspora.org"
android:scheme="https" />
<data
android:host="shrekislove.us"
android:scheme="https" />
<data
android:host="social.acclaro.digital"
android:scheme="https" />
<data
android:host="social.baldr.io"
android:scheme="https" />
<data
android:host="social.daxbau.net"
android:scheme="https" />
<data
android:host="social.elaon.de"
android:scheme="https" />
<data
android:host="social.lanham.id.au"
android:scheme="https" />
<data
android:host="social.mbuto.me"
android:scheme="https" />
<data
android:host="socializer.cc"
android:scheme="https" />
<data
android:host="spora.zone"
android:scheme="https" />
<data
android:host="subvillage.de"
android:scheme="https" />
<data
android:host="sysad.org"
android:scheme="https" />
<data
android:host="teki.be"
android:scheme="https" />
<data
android:host="therealtalk.org"
android:scheme="https" />
<data
android:host="thinkopen.net"
android:scheme="https" />
<data
android:host="tippentappen.de"
android:scheme="https" />
<data
android:host="whatsnewz.com"
android:scheme="https" />
<data
android:host="wk3.org"
android:scheme="https" />
<data
android:host="www.datataffel.dk"
android:scheme="https" />
<data
android:host="www.diasporaix.de"
android:scheme="https" />
<data
android:host="diaspora.hofud.com"
android:scheme="https" />
<data
android:host="diaspora.softwarelivre.org"
android:scheme="https" />
<data
android:host="confetticake.club"
android:scheme="https" />
<data
android:host="diaspote.org"
android:scheme="https" />
<data
android:host="diaspora.zone"
android:scheme="https" />
<data
android:host="pod.userzap.de"
android:scheme="https" />
<data
android:host="www.vodeoo.com"
android:scheme="https" />
<data
android:host="diaspora.punkbeer.me"
android:scheme="https" />
<data
android:host="ingtech.net"
android:scheme="https" />
<data
android:host="mmkr.co"
android:scheme="https" />
<data
android:host="pod.kneedrag.org"
android:scheme="https" />
<data
android:host="spyurk.am"
android:scheme="https" />
<data
android:host="pod.mew.cat"
android:scheme="https" />
<data
android:host="dfhz.tk"
android:scheme="https" />
<data
android:host="netiz.in"
android:scheme="https" />
<data
android:host="pod1.orobouros.net"
android:scheme="https" />
<data
android:host="witchcraft.ml"
android:scheme="https" />
<data
android:host="libellula.criptica.org"
android:scheme="https" />
<data
android:host="pod.datamol.org"
android:scheme="https" />
<data
android:host="social.berdaguermontes.eu"
android:scheme="https" />
<data
android:host="mh8.lat-clan.fr"
android:scheme="https" />
<data
android:host="dp.lumy.me"
android:scheme="https" />
<data
android:host="social.souvenirfromlife.fr"
android:scheme="https" />
<data
android:host="diaspora.mokrynskyi.com"
android:scheme="https" />
<data
android:host="hub.transition-regensburg.de"
android:scheme="https" />
<data
android:host="co.zy.lc"
android:scheme="https" />
<data
android:host="diaspora.treefish.org"
android:scheme="https" />
<data
android:host="diaspora.bke.ro"
android:scheme="https" />
<data
android:host="pod.sd.vc"
android:scheme="https" />
<data
android:host="diaspora.cxx.rocks"
android:scheme="https" />
<data
android:host="social.homenet.org"
android:scheme="https" />
<data
android:host="social.cigliola.com"
android:scheme="https" />
<data
android:host="friaspora.tk"
android:scheme="https" />
<data
android:host="pod.lasserh.dk"
android:scheme="https" />
<data
android:host="hubz.tk"
android:scheme="https" />
<data
android:host="hubzilla.kosebamse.com"
android:scheme="https" />
<data
android:host="driaans.nl"
android:scheme="https" />
<data
android:host="dispersio.us"
android:scheme="https" />
<data
android:host="go.lookbehind.eu"
android:scheme="https" />
<data
android:host="diasp.ot-si.com"
android:scheme="https" />
<data
android:host="diaspora.crossfamilyweb.com"
android:scheme="https" />
<data
android:host="hub.aoeu.me"
android:scheme="https" />
<data
android:host="dia.pwn.ninja"
android:scheme="https" />
<data
android:host="3ogsbs3vuvapgg37.onion.to"
android:scheme="https" />
<data
android:host="hubz.secretlair.me"
android:scheme="https" />
<data
android:host="got.noip.me"
android:scheme="https" />
<data
android:host="pod.bitcast.info"
android:scheme="https" />
<data
android:host="f.tschlotfeldt.de"
android:scheme="https" />
<data
android:host="hubloq.net"
android:scheme="https" />
<data
android:host="hubzilla.kneedrag.org"
android:scheme="https" />
<data
android:host="gesichtsbu.ch"
android:scheme="https" />
<data
android:host="hubzi.fraengii.de"
android:scheme="https" />
<data
android:host="friendica.narf.ssji.net"
android:scheme="https" />
<data
android:host="durohr.de"
android:scheme="https" />
<data
android:host="0kcg.com"
android:scheme="https" />
<data
android:host="aegibson.me"
android:scheme="https" />
<data
android:host="redmatrix.us"
android:scheme="https" />
<data
android:host="15o2.de"
android:scheme="https" />
<data
android:host="upt.social"
android:scheme="https" />
<data
android:host="friendica.bohrshouse.com"
android:scheme="https" />
<data
android:host="hubzilla.site"
android:scheme="https" />
<data
android:host="hubzilla.zavb.de"
android:scheme="https" />
<data
android:host="diaspora.aeriesguard.com"
android:scheme="https" />
<data
android:host="pod.cornify.de"
android:scheme="https" />
<data
android:host="hochminuseins.net"
android:scheme="https" />
<data
android:host="thecrimsontint.com"
android:scheme="https" />
<data
android:host="diaspora.clubelek.fr"
android:scheme="https" />
<data
android:host="teamhubzilla.org"
android:scheme="https" />
<data
android:host="diaspora.schlimme.net"
android:scheme="https" />
<data
android:host="www.wiwiec.com"
android:scheme="https" />
<data
android:host="diasp.danletard.de"
android:scheme="https" />
<data
android:host="libertypod.com"
android:scheme="https" />
<data
android:host="hubzilla.pskosinski.pl"
android:scheme="https" />
<data
android:host="pod.juvenesco.eu"
android:scheme="https" />
<data
android:host="pirati.ca"
android:scheme="https" />
<data
android:host="diasp.sk"
android:scheme="https" />
<data
android:host="f.libreden.net"
android:scheme="https" />
<data
android:host="pod.mausdompteur.de"
android:scheme="https" />
<data
android:host="diaspora.raitisoja.com"
android:scheme="https" />
<data
android:host="squeet.me"
android:scheme="https" />
<data
android:host="pod.kakise.xyz"
android:scheme="https" />
<data
android:host="pod.diasporacaribe.org"
android:scheme="https" />
<data
android:host="hub.feder8.ru"
android:scheme="https" />
<data
android:host="hubzilla.a-zwenkau.de"
android:scheme="https" />
<data
android:host="social.punkbeer.me"
android:scheme="https" />
<data
android:host="pod.sapient.fun"
android:scheme="https" />
<data
android:host="pod.phantasie.cc"
android:scheme="https" />
<data
android:host="diaspora.masharih.me"
android:scheme="https" />
<data
android:host="hub.mariovavti.com"
android:scheme="https" />
<data
android:host="social.patur.in"
android:scheme="https" />
<data
android:host="jeroenpraat.nl"
android:scheme="https" />
<data
android:host="grindcore.ch"
android:scheme="https" />
<data
android:host="pod.vixiv.net"
android:scheme="https" />
<data
android:host="social.deuxfleurs.fr"
android:scheme="https" />
<data
android:host="parlementum.net"
android:scheme="https" />
<data
android:host="villianbook.com"
android:scheme="https" />
<data
android:host="frolix8.asia"
android:scheme="https" />
<data
android:host="hub.vilarejo.pro.br"
android:scheme="https" />
<data
android:host="social.vixiv.net"
android:scheme="https" />
<!--@@@ PODLIST END--> <!--@@@ PODLIST END-->
</intent-filter> </intent-filter>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before After
Before After

BIN
app/src/main/ic_launcher_test.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -34,35 +34,18 @@ import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper; import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
import net.gsantner.opoc.util.AdBlock;
import net.gsantner.opoc.util.ContextUtils;
import net.gsantner.opoc.util.ShareUtil;
public class App extends Application { 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 DiasporaUserProfile diasporaUserProfile; 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 = AppSettings.get(); appSettings = new AppSettings(c);
String a = new ContextUtils(this).bcstr("FLAVOR", "");
a += "__";
if (appSettings.isAppFirstStart() && "flavorDandelior".equals(new ContextUtils(this).bcstr("FLAVOR", ""))) {
appSettings.setAmoledColorMode(true);
}
// Init app log // Init app log
AppLog.setLoggingEnabled(appSettings.isLoggingEnabled()); AppLog.setLoggingEnabled(appSettings.isLoggingEnabled());
@ -81,7 +64,6 @@ public class App extends Application {
} }
cookieManager.setAcceptCookie(true); cookieManager.setAcceptCookie(true);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
AdBlock.getInstance().loadHostsFromRawAssetsAsync(this);
} }
public void resetPodData(@Nullable WebView webView) { public void resetPodData(@Nullable WebView webView) {
@ -97,9 +79,9 @@ public class App extends Application {
new AvatarImageLoader(this).clearAvatarImage(); new AvatarImageLoader(this).clearAvatarImage();
// Clear preferences__master // Clear preferences__master
appSettings.resetPodSettings(); appSettings.clearPodSettings();
// Clear User profile - reload empty AppSettingsBase data // Clear User profile - reload empty AppSettings data
diasporaUserProfile.loadFromAppSettings(); diasporaUserProfile.loadFromAppSettings();
// Clear cookies // Clear cookies

View file

@ -20,13 +20,12 @@ package com.github.dfa.diaspora_android.activity;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.os.Bundle; 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.AppBarLayout;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
@ -35,6 +34,8 @@ import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
@ -51,7 +52,7 @@ import com.github.dfa.diaspora_android.ui.theme.ThemedActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.Helpers;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
@ -67,16 +68,16 @@ public class AboutActivity extends ThemedActivity
implements IntellihideToolbarActivityListener { implements IntellihideToolbarActivityListener {
@BindView(R.id.about__appbar) @BindView(R.id.about__appbar)
protected AppBarLayout _appBarLayout; protected AppBarLayout appBarLayout;
@BindView(R.id.main__topbar) @BindView(R.id.main__topbar)
protected Toolbar _toolbar; protected Toolbar toolbar;
@BindView(R.id.appbar_linear_layout) @BindView(R.id.appbar_linear_layout)
protected LinearLayout _linearLayout; protected LinearLayout linearLayout;
@BindView(R.id.tabs) @BindView(R.id.tabs)
protected TabLayout _tabLayout; protected TabLayout tabLayout;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -84,9 +85,9 @@ public class AboutActivity extends ThemedActivity
setContentView(R.layout.about__activity); setContentView(R.layout.about__activity);
ButterKnife.bind(this); ButterKnife.bind(this);
setSupportActionBar(_toolbar); setSupportActionBar(toolbar);
_toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24px)); toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24px));
_toolbar.setNavigationOnClickListener(new View.OnClickListener() { toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
AboutActivity.this.onBackPressed(); AboutActivity.this.onBackPressed();
@ -100,33 +101,41 @@ public class AboutActivity extends ThemedActivity
ViewPager mViewPager = ButterKnife.findById(this, R.id.container); ViewPager mViewPager = ButterKnife.findById(this, R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter); mViewPager.setAdapter(mSectionsPagerAdapter);
_tabLayout.setupWithViewPager(mViewPager); tabLayout.setupWithViewPager(mViewPager);
} }
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
setToolbarIntellihide(getAppSettings().isIntellihideToolbars()); if (getAppSettings().isIntellihideToolbars()) {
this.enableToolbarHiding();
} else {
this.disableToolbarHiding();
}
} }
@Override @Override
protected void applyColorToViews() { protected void applyColorToViews() {
ThemeHelper.updateToolbarColor(_toolbar); ThemeHelper.updateToolbarColor(toolbar);
ThemeHelper.updateTabLayoutColor(_tabLayout); ThemeHelper.updateTabLayoutColor(tabLayout);
ThemeHelper.setPrimaryColorAsBackground(_linearLayout); ThemeHelper.setPrimaryColorAsBackground(linearLayout);
} }
public void setToolbarIntellihide(boolean enable) { @Override
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) _linearLayout.getLayoutParams(); public void enableToolbarHiding() {
if (enable) { AppLog.d(this, "Enable Intellihide");
AppLog.d(this, "Enable Intellihide"); AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) linearLayout.getLayoutParams();
params.setScrollFlags(toolbarDefaultScrollFlags); //scroll|enterAlways|snap
params.setScrollFlags(toolbarDefaultScrollFlags);
appBarLayout.setExpanded(true, true);
}
} else { @Override
AppLog.d(this, "Disable Intellihide"); public void disableToolbarHiding() {
params.setScrollFlags(0); // clear all scroll flags AppLog.d(this, "Disable Intellihide");
} AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) linearLayout.getLayoutParams();
_appBarLayout.setExpanded(true, true); params.setScrollFlags(0); // clear all scroll flags
appBarLayout.setExpanded(true, true);
} }
/** /**
@ -158,23 +167,20 @@ public class AboutActivity extends ThemedActivity
} }
@Override @Override
protected int getLayoutResId() { public View onCreateView(LayoutInflater inflater, ViewGroup container,
return R.layout.about__fragment_about; Bundle savedInstanceState) {
} View rootView = inflater.inflate(R.layout.about__fragment_about, container, false);
ButterKnife.bind(this, rootView);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
if (isAdded()) { if (isAdded()) {
try { try {
PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
appVersion.setText(getString(R.string.app_version_with_arg, pInfo.versionName + " (" + pInfo.versionCode + ")")); appVersion.setText(getString(R.string.fragment_debug__app_version, pInfo.versionName + " (" + pInfo.versionCode + ")"));
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
return rootView;
} }
@Override @Override
@ -192,6 +198,11 @@ public class AboutActivity extends ThemedActivity
return TAG; return TAG;
} }
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
/* Nothing to do */
}
@Override @Override
public boolean onBackPressed() { public boolean onBackPressed() {
return false; return false;
@ -201,20 +212,20 @@ public class AboutActivity extends ThemedActivity
public void buttonClicked(View view) { public void buttonClicked(View view) {
switch (view.getId()) { switch (view.getId()) {
case R.id.fragment_about__contribute_button: case R.id.fragment_about__contribute_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_about__contribute_link)); Helpers.openInExternalBrowser(getContext(), getString(R.string.fragment_about__contribute_link));
break; break;
case R.id.fragment_about__translate_button: case R.id.fragment_about__translate_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_about__translate_link)); Helpers.openInExternalBrowser(getContext(), getString(R.string.fragment_about__translate_link));
break; break;
case R.id.fragment_about__feedback_button: case R.id.fragment_about__feedback_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_About__feedback_link)); Helpers.openInExternalBrowser(getContext(), getString(R.string.fragment_About__feedback_link));
break; break;
case R.id.fragment_about__spread_the_word_button: case R.id.fragment_about__spread_the_word_button:
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND); Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.setType("text/plain"); sharingIntent.setType("text/plain");
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, getString(R.string.app_name)); 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))); sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, getString(R.string.fragment_about__spread_the_word_share_text, getString(R.string.fragment_about__fdroid_link)));
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_dotdotdot))); startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_share_dotdotdot)));
break; break;
} }
} }
@ -248,32 +259,29 @@ public class AboutActivity extends ThemedActivity
} }
@Override @Override
protected int getLayoutResId() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return R.layout.about__fragment_license; View rootView = inflater.inflate(R.layout.about__fragment_license, container, false);
} ButterKnife.bind(this, rootView);
final Context context = rootView.getContext();
accentColor = Helpers.colorToHex(ThemeHelper.getAccentColor());
@Override maintainers.setTextFormatted(getString(R.string.fragment_license__maintainers_text,
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { Helpers.loadMarkdownFromRawForTextView(context, R.raw.maintainers, "")));
super.onViewCreated(view, savedInstanceState); contributors.setTextFormatted(getString(R.string.fragment_license__contributors_thank_you,
ButterKnife.bind(this, view); Helpers.loadMarkdownFromRawForTextView(context, R.raw.contributors, "* ")));
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( thirdPartyLibs.setTextFormatted(
ContextUtils.get().loadMarkdownForTextViewFromRaw(R.raw.licenses_3rd_party, "")); Helpers.loadMarkdownFromRawForTextView(context, R.raw.license_third_party, ""));
return rootView;
} }
@OnClick({R.id.fragment_license__leafpic_button, R.id.fragment_license__license_button}) @OnClick({R.id.fragment_license__leafpic_button, R.id.fragment_license__license_button})
public void buttonClicked(View v) { public void buttonClicked(View v) {
switch (v.getId()) { switch (v.getId()) {
case R.id.fragment_license__leafpic_button: case R.id.fragment_license__leafpic_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_licesen__misc_leafpic_link)); Helpers.openInExternalBrowser(getContext(), getString(R.string.fragment_licesen__misc_leafpic_link));
break; break;
case R.id.fragment_license__license_button: case R.id.fragment_license__license_button:
ContextUtils.get().openWebpageInExternalBrowser(getString(R.string.fragment_license__license_gpl_link)); Helpers.openInExternalBrowser(getContext(), getString(R.string.fragment_license__license_gpl_link));
break; break;
} }
} }
@ -292,6 +300,11 @@ public class AboutActivity extends ThemedActivity
return TAG; return TAG;
} }
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
/* Nothing to do */
}
@Override @Override
public boolean onBackPressed() { public boolean onBackPressed() {
return false; return false;
@ -341,7 +354,7 @@ public class AboutActivity extends ThemedActivity
ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("DEBUG_LOG", AppLog.Log.getLogBuffer()); ClipData clip = ClipData.newPlainText("DEBUG_LOG", AppLog.Log.getLogBuffer());
clipboard.setPrimaryClip(clip); clipboard.setPrimaryClip(clip);
Toast.makeText(DebugFragment.this.getActivity(), R.string.debug_log_copied_to_clipboard, Toast.LENGTH_SHORT).show(); Toast.makeText(DebugFragment.this.getActivity(), R.string.fragment_debug__toast_log_copied, Toast.LENGTH_SHORT).show();
} else { } else {
AppLog.d(this, "Not Added!"); AppLog.d(this, "Not Added!");
} }
@ -356,13 +369,13 @@ public class AboutActivity extends ThemedActivity
PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0); PackageInfo pInfo = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0);
AppSettings appSettings = ((App) getActivity().getApplication()).getSettings(); AppSettings appSettings = ((App) getActivity().getApplication()).getSettings();
packageName.setText(pInfo.packageName); packageName.setText(pInfo.packageName);
appVersion.setText(getString(R.string.app_version_with_arg, pInfo.versionName + " (" + pInfo.versionCode + ")")); appVersion.setText(getString(R.string.fragment_debug__app_version, pInfo.versionName + " (" + pInfo.versionCode + ")"));
osVersion.setText(getString(R.string.android_version_witharg, Build.VERSION.RELEASE)); osVersion.setText(getString(R.string.fragment_debug__android_version, Build.VERSION.RELEASE));
deviceName.setText(getString(R.string.device_name_witharg, Build.MANUFACTURER + " " + Build.MODEL)); deviceName.setText(getString(R.string.fragment_debug__device_name, Build.MANUFACTURER + " " + Build.MODEL));
if (app.getSettings().getPod() != null) { if (app.getSettings().getPod() != null) {
podDomain.setText(getString(R.string.pod_domain_witharg__appspecific, app.getSettings().getPod().getPodUrl())); podDomain.setText(getString(R.string.fragment_debug__pod_profile_url, app.getSettings().getPod().getPodUrl()));
podName.setText(getString(R.string.pod_profile_name_witharg__appspecific, app.getSettings().getPod().getName())); podName.setText(getString(R.string.fragment_debug__pod_profile_name, app.getSettings().getPod().getName()));
} }
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
@ -420,11 +433,11 @@ public class AboutActivity extends ThemedActivity
public CharSequence getPageTitle(int position) { public CharSequence getPageTitle(int position) {
switch (position) { switch (position) {
case 0: case 0:
return getString(R.string.about); return getString(R.string.about_activity__title_about_app);
case 1: case 1:
return getString(R.string.license); return getString(R.string.about_activity__title_about_license);
case 2: case 2:
return getString(R.string.debugging); return getString(R.string.about_activity__title_debug_info);
} }
return null; return null;
} }

View file

@ -0,0 +1,197 @@
/*
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.Context;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
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.DiasporaAspect;
import com.github.dfa.diaspora_android.listener.OnSomethingClickListener;
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.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Fragment that shows a list of the Aspects
*/
public class AspectListFragment extends ThemedFragment implements OnSomethingClickListener<Object> {
public static final String TAG = "com.github.dfa.diaspora_android.AspectListFragment";
protected RecyclerView aspectsRecyclerView;
protected App app;
protected DiasporaUrlHelper urls;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AppLog.d(this, "onCreateView()");
return inflater.inflate(R.layout.recycler_list__fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
aspectsRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_list__recycler_view);
app = (App) getActivity().getApplication();
AppSettings appSettings = app.getSettings();
urls = new DiasporaUrlHelper(appSettings);
aspectsRecyclerView.setHasFixedSize(true);
aspectsRecyclerView.setNestedScrollingEnabled(false);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
aspectsRecyclerView.setLayoutManager(layoutManager);
final AspectAdapter adapter = new AspectAdapter(appSettings, this);
aspectsRecyclerView.setAdapter(adapter);
//Set window title
getActivity().setTitle(R.string.nav_aspects);
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
/* Nothing to do */
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public void onSomethingClicked(Object null1, Integer null2, String aspectId) {
((MainActivity) getActivity()).openDiasporaUrl(urls.getAspectUrl(aspectId));
}
@Override
protected void applyColorToViews() {
aspectsRecyclerView.invalidate();
}
public static class AspectAdapter extends RecyclerView.Adapter<AspectAdapter.ViewHolder> {
private final AppSettings appSettings;
private final DiasporaAspect[] aspectList;
private final List<String> aspectFavsList;
private final OnSomethingClickListener<Object> aspectClickedListener;
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.recycler_view__list_item__text)
public TextView title;
@BindView(R.id.recycler_view__list_item__favourite)
AppCompatImageView favouriteImage;
@BindView(R.id.recycler_view__list_item__root)
RelativeLayout root;
ViewHolder(View v) {
super(v);
ButterKnife.bind(this, v);
}
}
AspectAdapter(AppSettings appSettings, OnSomethingClickListener<Object> aspectClickedListener) {
this.appSettings = appSettings;
this.aspectList = appSettings.getAspects();
this.aspectFavsList = new ArrayList<>(Arrays.asList(appSettings.getAspectFavs()));
this.aspectClickedListener = aspectClickedListener;
}
@Override
public int getItemCount() {
return aspectList.length;
}
@Override
public AspectAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_list__list_item_with_fav, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
// Alternating colors
final Context c = holder.root.getContext();
final DiasporaAspect aspect = aspectList[position];
holder.title.setText(aspect.name);
if (position % 2 == 1) {
holder.root.setBackgroundColor(Helpers.getColorFromRessource(c, R.color.alternate_row_color));
}
// Favourite (Star) Image
applyFavouriteImage(holder.favouriteImage, isAspectFaved(aspect.name));
// Click on fav button
holder.favouriteImage.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isAspectFaved(aspect.name)) {
aspectFavsList.remove(aspectFavsList.indexOf(aspect.name));
} else {
aspectFavsList.add(aspect.name);
}
appSettings.setAspectFavs(aspectFavsList);
applyFavouriteImage(holder.favouriteImage, isAspectFaved(aspect.name));
}
});
holder.root.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
aspectClickedListener.onSomethingClicked(null, null, aspect.id + "");
}
});
}
private boolean isAspectFaved(String tag) {
return aspectFavsList.contains(tag);
}
private void applyFavouriteImage(AppCompatImageView imageView, boolean isFaved) {
imageView.setImageResource(isFaved ? R.drawable.ic_star_filled_48px : R.drawable.ic_star_border_black_48px);
imageView.setColorFilter(isFaved ? appSettings.getAccentColor() : 0, PorterDuff.Mode.SRC_ATOP);
}
}
}

View file

@ -25,13 +25,11 @@ import android.app.Activity;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
@ -40,30 +38,23 @@ import android.webkit.JavascriptInterface;
import android.webkit.ValueCallback; import android.webkit.ValueCallback;
import android.webkit.WebChromeClient; import android.webkit.WebChromeClient;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.Toast;
import com.github.dfa.diaspora_android.App; 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.R;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile; import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder; import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
import com.github.dfa.diaspora_android.util.AppLog; 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.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.web.BrowserFragment; import com.github.dfa.diaspora_android.web.BrowserFragment;
import com.github.dfa.diaspora_android.web.DiasporaStreamWebChromeClient; import com.github.dfa.diaspora_android.web.DiasporaStreamWebChromeClient;
import com.github.dfa.diaspora_android.web.FileUploadWebChromeClient; import com.github.dfa.diaspora_android.web.FileUploadWebChromeClient;
import com.github.dfa.diaspora_android.web.WebHelper; 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 org.json.JSONException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Date;
/** /**
* Fragment that displays the Stream of the diaspora* user * Fragment that displays the Stream of the diaspora* user
@ -101,15 +92,13 @@ public class DiasporaStreamFragment extends BrowserFragment {
} }
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.stream__menu_top, menu); inflater.inflate(R.menu.stream__menu_top, menu);
super.onCreateOptionsMenu(menu, inflater);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { @Override
menu.findItem(R.id.action_share_pdf).setVisible(true); public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
} inflater.inflate(R.menu.stream__menu_bottom, menu);
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 @Override
@ -128,8 +117,6 @@ public class DiasporaStreamFragment extends BrowserFragment {
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
AppLog.d(this, "StreamFragment.onOptionsItemSelected()"); AppLog.d(this, "StreamFragment.onOptionsItemSelected()");
ShareUtil shu = new ShareUtil(getContext());
PermissionChecker permc = new PermissionChecker(getActivity());
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_reload: { case R.id.action_reload: {
if (WebHelper.isOnline(getContext())) { if (WebHelper.isOnline(getContext())) {
@ -152,51 +139,17 @@ public class DiasporaStreamFragment extends BrowserFragment {
sharingIntent.setType("text/plain"); sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle()); sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl()); sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.share_dotdotdot))); startActivity(Intent.createChooser(sharingIntent, getResources().getString(R.string.action_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; return true;
} }
case R.id.action_take_screenshot: { case R.id.action_take_screenshot: {
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) { makeScreenshotOfWebView(false);
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; return true;
} }
case R.id.action_share_screenshot: { case R.id.action_share_screenshot: {
if (permc.doIfExtStoragePermissionGranted(getString(R.string.screenshot_permission__appspecific))) { makeScreenshotOfWebView(true);
shu.shareImage(ShareUtil.getBitmapFromWebView(webView));
}
return true; return true;
} }
} }
@ -293,7 +246,7 @@ public class DiasporaStreamFragment extends BrowserFragment {
if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) { if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { if (!shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
new ThemedAlertDialogBuilder(getContext(), appSettings) new ThemedAlertDialogBuilder(getContext(), appSettings)
.setMessage(R.string.image_permission_description__appspecific) .setMessage(R.string.permissions_image)
.setNegativeButton(android.R.string.no, null) .setNegativeButton(android.R.string.no, null)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override @Override
@ -318,7 +271,7 @@ public class DiasporaStreamFragment extends BrowserFragment {
// Create the File where the photo should go // Create the File where the photo should go
File photoFile; File photoFile;
try { try {
photoFile = ContextUtils.get().createImageFile(); photoFile = Helpers.createImageFile();
takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath); takePictureIntent.putExtra("PhotoPath", mCameraPhotoPath);
} catch (IOException ex) { } catch (IOException ex) {
AppLog.e(this, "ERROR creating temp file: " + ex.toString()); AppLog.e(this, "ERROR creating temp file: " + ex.toString());
@ -371,30 +324,13 @@ public class DiasporaStreamFragment extends BrowserFragment {
@SuppressWarnings("unused") @SuppressWarnings("unused")
@JavascriptInterface @JavascriptInterface
public void setUserProfile(final String webMessage) throws JSONException { public void setUserProfile(final String webMessage) throws JSONException {
final Activity activity = getActivity(); final DiasporaUserProfile pup = ((App) getActivity().getApplication()).getDiasporaUserProfile();
if (activity != null) { if (pup.isRefreshNeeded()) {
activity.runOnUiThread(new Runnable() { AppLog.v(this, "DiasporaUserProfile needs refresh; Try to parse JSON");
@Override pup.parseJson(webMessage);
getActivity().runOnUiThread(new Runnable() {
public void run() { public void run() {
App app = ((App) activity.getApplication()); pup.analyzeUrl(webView.getUrl());
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());
}
});
}
} }
}); });
} }

View file

@ -25,8 +25,6 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
@ -36,15 +34,14 @@ import android.support.customtabs.CustomTabsSession;
import android.support.design.widget.AppBarLayout; import android.support.design.widget.AppBarLayout;
import android.support.design.widget.NavigationView; import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat; import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.Menu; import android.view.Menu;
@ -62,8 +59,8 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.github.dfa.diaspora_android.App; 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.R;
import com.github.dfa.diaspora_android.data.DiasporaAspect;
import com.github.dfa.diaspora_android.data.DiasporaPodList; import com.github.dfa.diaspora_android.data.DiasporaPodList;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile; import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener; import com.github.dfa.diaspora_android.listener.DiasporaUserProfileChangedListener;
@ -72,25 +69,21 @@ import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver;
import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver;
import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.ui.BadgeDrawable;
import com.github.dfa.diaspora_android.ui.PodSelectionDialog; import com.github.dfa.diaspora_android.ui.PodSelectionDialog;
import com.github.dfa.diaspora_android.ui.SearchOrCustomTextDialogCreator; import com.github.dfa.diaspora_android.ui.theme.CustomFragment;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper; 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.ThemedActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder; import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.ActivityUtils;
import com.github.dfa.diaspora_android.util.AndroidBug5497Workaround;
import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings; 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.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import com.github.dfa.diaspora_android.util.SimpleMarkdownParser;
import com.github.dfa.diaspora_android.web.BrowserFragment; import com.github.dfa.diaspora_android.web.BrowserFragment;
import com.github.dfa.diaspora_android.web.ContextMenuWebView; import com.github.dfa.diaspora_android.web.ContextMenuWebView;
import com.github.dfa.diaspora_android.web.ProxyHandler; import com.github.dfa.diaspora_android.web.ProxyHandler;
import com.github.dfa.diaspora_android.web.WebHelper; import com.github.dfa.diaspora_android.web.WebHelper;
import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper; import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper;
import net.gsantner.opoc.format.markdown.SimpleMarkdownParser;
import java.io.IOException; import java.io.IOException;
import butterknife.BindView; import butterknife.BindView;
@ -121,7 +114,7 @@ public class MainActivity extends ThemedActivity
private App app; private App app;
private CustomTabActivityHelper customTabActivityHelper; private CustomTabActivityHelper customTabActivityHelper;
private AppSettings _appSettings; private AppSettings appSettings;
private DiasporaUrlHelper urls; private DiasporaUrlHelper urls;
private DiasporaUserProfile diasporaUserProfile; private DiasporaUserProfile diasporaUserProfile;
private final Handler uiHandler = new Handler(); private final Handler uiHandler = new Handler();
@ -140,6 +133,9 @@ public class MainActivity extends ThemedActivity
@BindView(R.id.main__topbar) @BindView(R.id.main__topbar)
Toolbar toolbarTop; Toolbar toolbarTop;
@BindView(R.id.main__bottombar)
ActionMenuView toolbarBottom;
@BindView(R.id.fragment_container) @BindView(R.id.fragment_container)
FrameLayout fragmentContainer; FrameLayout fragmentContainer;
@ -171,26 +167,16 @@ public class MainActivity extends ThemedActivity
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
AppLog.v(this, "onCreate()"); AppLog.v(this, "onCreate()");
// Pre UI
ContextUtils.get().setAppLanguage(AppSettings.get().getLanguage());
if (AppSettings.get().isEditorStatusBarHidden()) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
// Bind UI // Bind UI
setContentView(R.layout.main__activity); setContentView(R.layout.main__activity);
ButterKnife.bind(this); ButterKnife.bind(this);
if (AppSettings.get().isEditorStatusBarHidden()) {
AndroidBug5497Workaround.assistActivity(this);
}
app = (App) getApplication(); app = (App) getApplication();
_appSettings = app.getSettings(); appSettings = app.getSettings();
diasporaUserProfile = app.getDiasporaUserProfile(); diasporaUserProfile = app.getDiasporaUserProfile();
diasporaUserProfile.setCallbackHandler(uiHandler); diasporaUserProfile.setCallbackHandler(uiHandler);
diasporaUserProfile.setListener(this); diasporaUserProfile.setListener(this);
urls = new DiasporaUrlHelper(_appSettings); urls = new DiasporaUrlHelper(appSettings);
customTabActivityHelper = new CustomTabActivityHelper(); customTabActivityHelper = new CustomTabActivityHelper();
customTabActivityHelper.setConnectionCallback(this); customTabActivityHelper.setConnectionCallback(this);
ProxyHandler.getInstance().updateProxySettings(this); ProxyHandler.getInstance().updateProxySettings(this);
@ -201,7 +187,7 @@ public class MainActivity extends ThemedActivity
brOpenExternalLink = new OpenExternalLinkReceiver(this); brOpenExternalLink = new OpenExternalLinkReceiver(this);
brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() { brSetTitle = new UpdateTitleReceiver(app, urls, new UpdateTitleReceiver.TitleCallback() {
public void setTitle(String url, int resId) { public void setTitle(String url, int resId) {
ThemedFragment top = getTopFragment(); CustomFragment top = getTopFragment();
if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
MainActivity.this.setTitle(resId); MainActivity.this.setTitle(resId);
showLastVisitedTimestampMessageIfNeeded(url); showLastVisitedTimestampMessageIfNeeded(url);
@ -209,14 +195,14 @@ public class MainActivity extends ThemedActivity
} }
public void setTitle(String url, String title) { public void setTitle(String url, String title) {
ThemedFragment top = getTopFragment(); CustomFragment top = getTopFragment();
if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) { if (top != null && top.getFragmentTag().equals(DiasporaStreamFragment.TAG)) {
MainActivity.this.setTitle(title); MainActivity.this.setTitle(title);
} }
} }
}); });
if (!_appSettings.hasPod()) { if (!appSettings.hasPod()) {
AppLog.d(this, "We have no pod. Show PodSelectionFragment"); AppLog.d(this, "We have no pod. Show PodSelectionFragment");
updateNavigationViewEntryVisibilities(); updateNavigationViewEntryVisibilities();
showFragment(getFragment(PodSelectionFragment.TAG)); showFragment(getFragment(PodSelectionFragment.TAG));
@ -231,16 +217,25 @@ public class MainActivity extends ThemedActivity
} }
} }
// Show first start / update dialog // Show first start dialog
try { try {
if (_appSettings.isAppCurrentVersionFirstStart(true)) { if (appSettings.isAppFirstStart()) {
SimpleMarkdownParser smp = SimpleMarkdownParser.get().setDefaultSmpFilter(SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW); SimpleMarkdownParser smp = new SimpleMarkdownParser().parse(
String html = ""; getResources().openRawResource(R.raw.license),
html += smp.parse(getString(R.string.copyright_license_text_official).replace("\n", " \n"), "").getHtml(); SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
html += "<br/><br/><br/><big><big>" + getString(R.string.changelog) + "</big></big><br/>" + smp.parse(getResources().openRawResource(R.raw.changelog), "", SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, SimpleMarkdownParser.FILTER_CHANGELOG).getHtml(); String html = smp.getHtml()
html += "<br/><br/><br/><big><big>" + getString(R.string.licenses) + "</big></big><br/>" + smp.parse(getResources().openRawResource(R.raw.licenses_3rd_party), "").getHtml(); + "<br/><br/><br/>"
ActivityUtils _au = new ActivityUtils(this); + "<h1>" + getString(R.string.fragment_license__thirdparty_libs) + "</h1>"
_au.showDialogWithHtmlTextView(R.string.licenses, html); + smp.parse(getResources().openRawResource(R.raw.license_third_party),
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
html = smp.setHtml(html).removeMultiNewlines().getHtml();
Helpers.showDialogWithHtmlTextView(this, html, R.string.about_activity__title_about_license);
appSettings.isAppCurrentVersionFirstStart();
} else if (appSettings.isAppCurrentVersionFirstStart()) {
SimpleMarkdownParser smp = new SimpleMarkdownParser().parse(
getResources().openRawResource(R.raw.changelog),
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
Helpers.showDialogWithHtmlTextView(this, smp.getHtml(), R.string.changelog);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -254,17 +249,23 @@ public class MainActivity extends ThemedActivity
private void setupUI() { private void setupUI() {
AppLog.i(this, "setupUI()"); AppLog.i(this, "setupUI()");
// Setup _toolbar // Setup toolbar
setSupportActionBar(toolbarTop); setSupportActionBar(toolbarTop);
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
if (actionBar != null) { if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true);
} }
toolbarBottom.setOnMenuItemClickListener(new ActionMenuView.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
CustomFragment top = getTopFragment();
return MainActivity.this.onOptionsItemSelected(item) || (top != null && top.onOptionsItemSelected(item));
}
});
setTitle(R.string.app_name); setTitle(R.string.app_name);
//Setup snackbar //Setup snackbar
snackbarExitApp = Snackbar snackbarExitApp = Snackbar
.make(fragmentContainer, R.string.do_you_want_to_exit, Snackbar.LENGTH_LONG) .make(fragmentContainer, R.string.confirm_exit, Snackbar.LENGTH_LONG)
.setAction(android.R.string.yes, new View.OnClickListener() { .setAction(android.R.string.yes, new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
finish(); finish();
@ -273,13 +274,13 @@ public class MainActivity extends ThemedActivity
}); });
snackbarLastVisitedTimestampInStream = snackbarLastVisitedTimestampInStream =
Snackbar.make(fragmentContainer, Snackbar.make(fragmentContainer,
R.string.jump_to_last_visited_page_in_stream__appspecific, Snackbar.LENGTH_LONG) R.string.jump_to_last_visited_timestamp_in_stream, Snackbar.LENGTH_LONG)
.setAction(android.R.string.yes, new View.OnClickListener() { .setAction(android.R.string.yes, new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream())); openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream()));
} }
}); });
snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.sorry_need_to_be_connected_to_internet, Snackbar.LENGTH_LONG); snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.no_internet, Snackbar.LENGTH_LONG);
// Load app settings // Load app settings
setupNavigationSlider(); setupNavigationSlider();
@ -287,15 +288,15 @@ public class MainActivity extends ThemedActivity
} }
/** /**
* Get an instance of the ThemedFragment with the tag fragmentTag. * Get an instance of the CustomFragment with the tag fragmentTag.
* If there was no instance so far, create a new one and add it to the FragmentManagers pool. * If there was no instance so far, create a new one and add it to the FragmentManagers pool.
* If there is no Fragment with the corresponding Tag, return the top fragment. * If there is no Fragment with the corresponding Tag, return the top fragment.
* *
* @param fragmentTag tag * @param fragmentTag tag
* @return corresponding Fragment * @return corresponding Fragment
*/ */
protected ThemedFragment getFragment(String fragmentTag) { protected CustomFragment getFragment(String fragmentTag) {
ThemedFragment fragment = (ThemedFragment) fm.findFragmentByTag(fragmentTag); CustomFragment fragment = (CustomFragment) fm.findFragmentByTag(fragmentTag);
if (fragment != null) { if (fragment != null) {
return fragment; return fragment;
} else { } else {
@ -308,6 +309,14 @@ public class MainActivity extends ThemedActivity
BrowserFragment bf = new BrowserFragment(); BrowserFragment bf = new BrowserFragment();
fm.beginTransaction().add(bf, fragmentTag).commit(); fm.beginTransaction().add(bf, fragmentTag).commit();
return bf; return bf;
case TagListFragment.TAG:
TagListFragment hlf = new TagListFragment();
fm.beginTransaction().add(hlf, fragmentTag).commit();
return hlf;
case AspectListFragment.TAG:
AspectListFragment alf = new AspectListFragment();
fm.beginTransaction().add(alf, fragmentTag).commit();
return alf;
case PodSelectionFragment.TAG: case PodSelectionFragment.TAG:
PodSelectionFragment psf = new PodSelectionFragment(); PodSelectionFragment psf = new PodSelectionFragment();
fm.beginTransaction().add(psf, fragmentTag).commit(); fm.beginTransaction().add(psf, fragmentTag).commit();
@ -325,30 +334,12 @@ public class MainActivity extends ThemedActivity
* *
* @param url URL to load in the DiasporaStreamFragment * @param url URL to load in the DiasporaStreamFragment
*/ */
public void openDiasporaUrl(final String url) { public void openDiasporaUrl(String url) {
AppLog.v(this, "openDiasporaUrl()"); AppLog.v(this, "openDiasporaUrl()");
if (url != null && url.startsWith("http://127.0.0.1")) { DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG);
// This URL seems to be called somehow, but it doesn't make sense ;) showFragment(streamFragment);
toolbarTop.postDelayed(() -> { showLastVisitedTimestampMessageIfNeeded(url);
Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL); streamFragment.loadUrl(url);
i.putExtra(EXTRA_URL, "https://github.com/gsantner/dandelion/blob/master/README.md");
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
}, 1000);
return;
}
if (_appSettings.getPod() != null && _appSettings.getPod().getPodUrl() != null && _appSettings.getPod().getPodUrl().getBaseUrl() != null
&& url.startsWith(_appSettings.getPod().getPodUrl().getBaseUrl()) && !url.startsWith("https://dia.so/")) {
DiasporaStreamFragment streamFragment = (DiasporaStreamFragment) getFragment(DiasporaStreamFragment.TAG);
showFragment(streamFragment);
showLastVisitedTimestampMessageIfNeeded(url);
streamFragment.loadUrl(url);
} else {
toolbarTop.postDelayed(() -> {
Intent i = new Intent(ACTION_OPEN_EXTERNAL_URL);
i.putExtra(EXTRA_URL, url);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
}, 1000);
}
} }
public void showLastVisitedTimestampMessageIfNeeded(String url) { public void showLastVisitedTimestampMessageIfNeeded(String url) {
@ -363,21 +354,18 @@ public class MainActivity extends ThemedActivity
* *
* @param fragment Fragment to show * @param fragment Fragment to show
*/ */
protected void showFragment(ThemedFragment fragment) { protected void showFragment(CustomFragment fragment) {
if (PodSelectionFragment.TAG.equals(fragment.getTag())) {
Fragment fragment1 = fm.findFragmentByTag(DiasporaStreamFragment.TAG);
if (fragment1 != null) {
new net.gsantner.opoc.util.ContextUtils(this).restartApp(MainActivity.class);
}
}
AppLog.v(this, "showFragment()"); AppLog.v(this, "showFragment()");
ThemedFragment currentTop = (ThemedFragment) fm.findFragmentById(R.id.fragment_container); CustomFragment currentTop = (CustomFragment) fm.findFragmentById(R.id.fragment_container);
if (currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) { if (currentTop == null || !currentTop.getFragmentTag().equals(fragment.getFragmentTag())) {
AppLog.v(this, "Fragment was not visible. Replace it."); AppLog.v(this, "Fragment was not visible. Replace it.");
fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit(); fm.beginTransaction().addToBackStack(null).replace(R.id.fragment_container, fragment, fragment.getFragmentTag()).commit();
invalidateOptionsMenu(); invalidateOptionsMenu();
setToolbarIntellihide(_appSettings.isIntellihideToolbars() && fragment.isAllowedIntellihide()); if (appSettings.isIntellihideToolbars() && fragment.isAllowedIntellihide()) {
this.enableToolbarHiding();
} else {
this.disableToolbarHiding();
}
} else { } else {
AppLog.v(this, "Fragment was already visible. Do nothing."); AppLog.v(this, "Fragment was already visible. Do nothing.");
} }
@ -388,7 +376,7 @@ public class MainActivity extends ThemedActivity
*/ */
private void setupNavigationSlider() { private void setupNavigationSlider() {
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, navDrawer, toolbarTop, R.string.open_navdrawer, R.string.close_navdrawer); this, navDrawer, toolbarTop, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
navDrawer.addDrawerListener(toggle); navDrawer.addDrawerListener(toggle);
toggle.syncState(); toggle.syncState();
@ -402,7 +390,7 @@ public class MainActivity extends ThemedActivity
navProfilePictureArea.setOnClickListener(new View.OnClickListener() { navProfilePictureArea.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) { public void onClick(View view) {
navDrawer.closeDrawer(GravityCompat.START); navDrawer.closeDrawer(GravityCompat.START);
if (!_appSettings.getProfileId().equals("")) { if (!appSettings.getProfileId().equals("")) {
openDiasporaUrl(urls.getProfileUrl()); openDiasporaUrl(urls.getProfileUrl());
} }
} }
@ -411,13 +399,13 @@ public class MainActivity extends ThemedActivity
navheaderDescription = ButterKnife.findById(navHeader, R.id.podselection__podupti_notice); navheaderDescription = ButterKnife.findById(navHeader, R.id.podselection__podupti_notice);
navheaderImage = ButterKnife.findById(navHeader, R.id.navheader_user_image); navheaderImage = ButterKnife.findById(navHeader, R.id.navheader_user_image);
if (!_appSettings.getName().equals("")) { if (!appSettings.getName().equals("")) {
navheaderTitle.setText(_appSettings.getName()); navheaderTitle.setText(appSettings.getName());
} }
if (_appSettings.getPod() != null) { if (appSettings.getPod() != null) {
navheaderDescription.setText(_appSettings.getPod().getName()); navheaderDescription.setText(appSettings.getPod().getName());
} }
String avatarUrl = _appSettings.getAvatarUrl(); String avatarUrl = appSettings.getAvatarUrl();
if (!avatarUrl.equals("")) { if (!avatarUrl.equals("")) {
//Display app launcher icon instead of default avatar asset //Display app launcher icon instead of default avatar asset
//(Which would by the way not load because of missing pod domain prefix in the url) //(Which would by the way not load because of missing pod domain prefix in the url)
@ -432,6 +420,8 @@ public class MainActivity extends ThemedActivity
app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl); app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl);
} }
} }
} else if (BuildConfig.IS_TEST_BUILD) {
navheaderImage.setImageResource(R.drawable.ic_launcher_test);
} }
updateNavigationViewEntryVisibilities(); updateNavigationViewEntryVisibilities();
} }
@ -443,39 +433,38 @@ public class MainActivity extends ThemedActivity
navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), true); navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), true);
// Hide by app settings // Hide by app settings
navMenu.findItem(R.id.nav_exit).setVisible(_appSettings.isVisibleInNavExit()); navMenu.findItem(R.id.nav_exit).setVisible(appSettings.isVisibleInNavExit());
navMenu.findItem(R.id.nav_activities).setVisible(_appSettings.isVisibleInNavActivities()); navMenu.findItem(R.id.nav_activities).setVisible(appSettings.isVisibleInNavActivities());
navMenu.findItem(R.id.nav_aspects).setVisible(_appSettings.isVisibleInNavAspects()); navMenu.findItem(R.id.nav_aspects).setVisible(appSettings.isVisibleInNavAspects());
navMenu.findItem(R.id.nav_contacts).setVisible(_appSettings.isVisibleInNavContacts()); navMenu.findItem(R.id.nav_contacts).setVisible(appSettings.isVisibleInNavContacts());
navMenu.findItem(R.id.nav_commented).setVisible(_appSettings.isVisibleInNavCommented()); navMenu.findItem(R.id.nav_commented).setVisible(appSettings.isVisibleInNavCommented());
navMenu.findItem(R.id.nav_followed_tags).setVisible(_appSettings.isVisibleInNavFollowed_tags()); navMenu.findItem(R.id.nav_followed_tags).setVisible(appSettings.isVisibleInNavFollowed_tags());
navMenu.findItem(R.id.nav_about).setVisible(_appSettings.isVisibleInNavHelp_license()); navMenu.findItem(R.id.nav_about).setVisible(appSettings.isVisibleInNavHelp_license());
navMenu.findItem(R.id.nav_liked).setVisible(_appSettings.isVisibleInNavLiked()); navMenu.findItem(R.id.nav_liked).setVisible(appSettings.isVisibleInNavLiked());
navMenu.findItem(R.id.nav_mentions).setVisible(_appSettings.isVisibleInNavMentions()); navMenu.findItem(R.id.nav_mentions).setVisible(appSettings.isVisibleInNavMentions());
navMenu.findItem(R.id.nav_profile).setVisible(_appSettings.isVisibleInNavProfile()); navMenu.findItem(R.id.nav_profile).setVisible(appSettings.isVisibleInNavProfile());
navMenu.findItem(R.id.nav_public).setVisible(_appSettings.isVisibleInNavPublic_activities()); navMenu.findItem(R.id.nav_public).setVisible(appSettings.isVisibleInNavPublic_activities());
navMenu.findItem(R.id.nav_stream).setVisible(true); navMenu.findItem(R.id.nav_stream).setVisible(true);
navMenu.findItem(R.id.nav_statistics).setVisible(_appSettings.isVisibleInNavStatistics()); navMenu.findItem(R.id.nav_statistics).setVisible(appSettings.isVisibleInNavStatistics());
navMenu.findItem(R.id.nav_reports).setVisible(_appSettings.isVisibleInNavReports()); navMenu.findItem(R.id.nav_reports).setVisible(appSettings.isVisibleInNavReports());
navMenu.findItem(R.id.nav_toggle_desktop_page).setVisible(_appSettings.isVisibleInNavToggleMobileDesktop()); navMenu.findItem(R.id.nav_toggle_desktop_page).setVisible(appSettings.isVisibleToggleMobileDesktop());
navMenu.findItem(R.id.nav_product_support).setVisible(_appSettings.isVisibleInNavGsantnerAccount());
// Hide whole group (for logged in use) if no pod was selected // Hide whole group (for logged in use) if no pod was selected
if (!_appSettings.hasPod()) { if (!appSettings.hasPod()) {
navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), false); navMenu.setGroupVisible(navMenu.findItem(R.id.nav_exit).getGroupId(), false);
} }
} }
/** /**
* Open Stream when clicked on top _toolbar AND preference stream shortcut is true * Open Stream when clicked on top toolbar AND preference stream shortcut is true
* *
* @param view selected view * @param view selected view
*/ */
@OnClick(R.id.main__topbar) @OnClick(R.id.main__topbar)
public void onToolBarClicked(View view) { public void onToolBarClicked(View view) {
AppLog.i(this, "onToolBarClicked()"); AppLog.i(this, "onToolBarClicked()");
if (_appSettings.isTopbarStreamShortcutEnabled() && _appSettings.hasPod()) { if (appSettings.isTopbarStreamShortcutEnabled() && appSettings.hasPod()) {
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream)); onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_stream));
} }
} }
@ -522,7 +511,7 @@ public class MainActivity extends ThemedActivity
} }
} else if (ACTION_CHANGE_ACCOUNT.equals(action)) { } else if (ACTION_CHANGE_ACCOUNT.equals(action)) {
AppLog.v(this, "Reset pod data and show PodSelectionFragment"); AppLog.v(this, "Reset pod data and show PodSelectionFragment");
_appSettings.setPod(null); appSettings.setPod(null);
runOnUiThread(new Runnable() { runOnUiThread(new Runnable() {
public void run() { public void run() {
navheaderTitle.setText(R.string.app_name); navheaderTitle.setText(R.string.app_name);
@ -559,18 +548,6 @@ public class MainActivity extends ThemedActivity
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) { } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
/* TODO: Implement and add filter to manifest */ /* TODO: Implement and add filter to manifest */
return; return;
} else if ("sc_new_post".equals(action)) {
openDiasporaUrl(urls.getNewPostUrl());
return;
} else if ("sc_activities".equals(action)) {
openDiasporaUrl(urls.getActivityUrl());
return;
} else if ("sc_contacts".equals(action)) {
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_aspects));
return;
} else if ("sc_tags".equals(action)) {
onNavigationItemSelected(navView.getMenu().findItem(R.id.nav_followed_tags));
return;
} }
//Catch split screen recreation //Catch split screen recreation
if (action != null && action.equals(Intent.ACTION_MAIN) && getTopFragment() != null) { if (action != null && action.equals(Intent.ACTION_MAIN) && getTopFragment() != null) {
@ -601,8 +578,8 @@ public class MainActivity extends ThemedActivity
* *
* @return top fragment or null if there is none displayed * @return top fragment or null if there is none displayed
*/ */
private ThemedFragment getTopFragment() { private CustomFragment getTopFragment() {
return (ThemedFragment) fm.findFragmentById(R.id.fragment_container); return (CustomFragment) fm.findFragmentById(R.id.fragment_container);
} }
/** /**
@ -615,7 +592,7 @@ public class MainActivity extends ThemedActivity
navDrawer.closeDrawer(navView); navDrawer.closeDrawer(navView);
return; return;
} }
ThemedFragment top = getTopFragment(); CustomFragment top = getTopFragment();
if (top != null) { if (top != null) {
AppLog.v(this, "Top Fragment is not null"); AppLog.v(this, "Top Fragment is not null");
if (!top.onBackPressed()) { if (!top.onBackPressed()) {
@ -667,52 +644,48 @@ public class MainActivity extends ThemedActivity
LocalBroadcastManager.getInstance(this).registerReceiver(brSetTitle, new IntentFilter(ACTION_UPDATE_TITLE_FROM_URL)); LocalBroadcastManager.getInstance(this).registerReceiver(brSetTitle, new IntentFilter(ACTION_UPDATE_TITLE_FROM_URL));
LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL)); LocalBroadcastManager.getInstance(this).registerReceiver(brOpenExternalLink, new IntentFilter(ACTION_OPEN_EXTERNAL_URL));
invalidateOptionsMenu(); invalidateOptionsMenu();
_appSettings = getAppSettings(); this.appSettings = getAppSettings();
if (_appSettings.isRecreateMainActivity()) { if (appSettings.isIntellihideToolbars()) {
recreate(); enableToolbarHiding();
} } else {
setToolbarIntellihide(_appSettings.isIntellihideToolbars()); disableToolbarHiding();
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(AppSettings.get().isShowTitleInMainView());
} }
updateNavigationViewEntryVisibilities(); updateNavigationViewEntryVisibilities();
} }
/** /**
* Clear and repopulate top and bottom _toolbar. * Clear and repopulate top and bottom toolbar.
* Also add menu items of the displayed fragment * Also add menu items of the displayed fragment
* *
* @param menu top _toolbar * @param menu top toolbar
* @return boolean * @return boolean
*/ */
@Override @Override
public boolean onCreateOptionsMenu(Menu menu) { public boolean onCreateOptionsMenu(Menu menu) {
AppLog.v(this, "onCreateOptionsMenu()"); AppLog.v(this, "onCreateOptionsMenu()");
boolean cache;
//Clear the menus //Clear the menus
menu.clear(); menu.clear();
toolbarBottom.getMenu().clear();
toolbarBottom.setVisibility(View.VISIBLE);
ThemedFragment top = getTopFragment(); CustomFragment top = getTopFragment();
if (top != null) { if (top != null) {
if (!top.getFragmentTag().equals(PodSelectionFragment.TAG)) { //PodSelectionFragment?
cache = _appSettings.isExtendedNotificationsActivated(); if (top.getFragmentTag().equals(PodSelectionFragment.TAG)) {
getMenuInflater().inflate(R.menu.main__menu_top, menu); ///Hide bottom toolbar
menu.findItem(R.id.action_notifications).setVisible(!cache); toolbarBottom.setVisibility(View.GONE);
menu.findItem(R.id.action_notifications_extended).setVisible(cache); } else {
getMenuInflater().inflate(appSettings.isExtendedNotificationsActivated() ?
R.menu.main__menu_top__notifications_dropdown : R.menu.main__menu_top, menu);
getMenuInflater().inflate(R.menu.main__menu_bottom, toolbarBottom.getMenu());
top.onCreateBottomOptionsMenu(toolbarBottom.getMenu(), getMenuInflater());
} }
} }
ContextUtils cu = ContextUtils.get();
final boolean darkBg = cu.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor());
cu.tintMenuItems(menu, true, ContextCompat.getColor(this, darkBg ? R.color.white : R.color.black));
cu.setSubMenuIconsVisiblity(menu, true);
return true; return true;
} }
/** /**
* Set the notification and messages counter in the top _toolbar * Set the notification and messages counter in the top toolbar
* *
* @param menu menu * @param menu menu
* @return boolean * @return boolean
@ -745,7 +718,7 @@ public class MainActivity extends ThemedActivity
AppLog.i(this, "onOptionsItemSelected()"); AppLog.i(this, "onOptionsItemSelected()");
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_notifications: { case R.id.action_notifications: {
if (_appSettings.isExtendedNotificationsActivated()) { if (appSettings.isExtendedNotificationsActivated()) {
return true; return true;
} }
//Otherwise we execute the action of action_notifications_all //Otherwise we execute the action of action_notifications_all
@ -845,7 +818,7 @@ public class MainActivity extends ThemedActivity
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
@SuppressLint("InflateParams") View layout = getLayoutInflater().inflate(R.layout.ui__dialog_search__people_tags, null, false); @SuppressLint("InflateParams") View layout = getLayoutInflater().inflate(R.layout.ui__dialog_search__people_tags, null, false);
final EditText input = layout.findViewById(R.id.dialog_search__input); final EditText input = (EditText) layout.findViewById(R.id.dialog_search__input);
input.setMaxLines(1); input.setMaxLines(1);
input.setSingleLine(true); input.setSingleLine(true);
ThemeHelper.updateEditTextColor(input); ThemeHelper.updateEditTextColor(input);
@ -854,7 +827,7 @@ public class MainActivity extends ThemedActivity
public void onClick(DialogInterface dialogInterface, int which) { public void onClick(DialogInterface dialogInterface, int which) {
String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), ""); String query = input.getText().toString().trim().replaceAll((which == DialogInterface.BUTTON_NEGATIVE ? "\\*" : "\\#"), "");
if (query.equals("")) { if (query.equals("")) {
Snackbar.make(fragmentContainer, R.string.please_add_a_name, Snackbar.LENGTH_LONG).show(); Snackbar.make(fragmentContainer, R.string.search_alert_bypeople_validate_needsomedata, Snackbar.LENGTH_LONG).show();
} else { } else {
openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query)); openDiasporaUrl(which == DialogInterface.BUTTON_NEGATIVE ? urls.getSearchPeopleUrl(query) : urls.getSearchTagsUrl(query));
} }
@ -863,11 +836,11 @@ public class MainActivity extends ThemedActivity
} }
}; };
final AlertDialog dialog = new ThemedAlertDialogBuilder(this, _appSettings) final AlertDialog dialog = new ThemedAlertDialogBuilder(this, appSettings)
.setView(layout).setTitle(R.string.search_alert_title) .setView(layout).setTitle(R.string.search_alert_title)
.setCancelable(true) .setCancelable(true)
.setPositiveButton(R.string.by_tags, clickListener) .setPositiveButton(R.string.search_alert_tag, clickListener)
.setNegativeButton(R.string.by_people, clickListener) .setNegativeButton(R.string.search_alert_people, clickListener)
.create(); .create();
input.setOnEditorActionListener(new TextView.OnEditorActionListener() { input.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@ -969,7 +942,7 @@ public class MainActivity extends ThemedActivity
private void setSharedTexts(String sharedSubject, String sharedBody) { private void setSharedTexts(String sharedSubject, String sharedBody) {
AppLog.i(this, "setSharedTexts()"); AppLog.i(this, "setSharedTexts()");
String body = WebHelper.replaceUrlWithMarkdown(sharedBody); String body = WebHelper.replaceUrlWithMarkdown(sharedBody);
if (_appSettings.isAppendSharedViaApp()) { if (appSettings.isAppendSharedViaApp()) {
AppLog.v(this, "Append app reference to shared text"); AppLog.v(this, "Append app reference to shared text");
body = body + "\n\n" + getString(R.string.shared_via_app); body = body + "\n\n" + getString(R.string.shared_via_app);
} }
@ -1006,7 +979,7 @@ public class MainActivity extends ThemedActivity
public void onNotificationCountChanged(DiasporaUserProfile diasporaUserProfile, int notificationCount) { public void onNotificationCountChanged(DiasporaUserProfile diasporaUserProfile, int notificationCount) {
AppLog.i(this, "onNotificationCountChanged()"); AppLog.i(this, "onNotificationCountChanged()");
// Count saved in DiasporaUserProfile // Count saved in DiasporaUserProfile
// Invalidate the top _toolbar to update the unread messages counter // Invalidate the top toolbar to update the unread messages counter
invalidateOptionsMenu(); invalidateOptionsMenu();
} }
@ -1015,7 +988,7 @@ public class MainActivity extends ThemedActivity
public void onUnreadMessageCountChanged(DiasporaUserProfile diasporaUserProfile, int unreadMessageCount) { public void onUnreadMessageCountChanged(DiasporaUserProfile diasporaUserProfile, int unreadMessageCount) {
AppLog.i(this, "onUnreadMessageCountChanged()"); AppLog.i(this, "onUnreadMessageCountChanged()");
// Count saved in DiasporaUserProfile // Count saved in DiasporaUserProfile
// Invalidate the top _toolbar to update the unread messages counter // Invalidate the top toolbar to update the unread messages counter
invalidateOptionsMenu(); invalidateOptionsMenu();
} }
@ -1056,46 +1029,19 @@ public class MainActivity extends ThemedActivity
break; break;
case R.id.nav_profile: { case R.id.nav_profile: {
if (!_appSettings.getProfileId().equals("")) { if (!appSettings.getProfileId().equals("")) {
openDiasporaUrl(urls.getProfileUrl()); openDiasporaUrl(urls.getProfileUrl());
} }
} }
break; break;
case R.id.nav_followed_tags: { case R.id.nav_followed_tags: {
SearchOrCustomTextDialogCreator.showDiasporaTagsDialog(this, arg -> { showFragment(getFragment(TagListFragment.TAG));
if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) {
arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim();
if (arg.equals(getString(R.string.manage_hashtags))) {
openDiasporaUrl(urls.getManageTagsUrl());
} else {
openDiasporaUrl(urls.getAllFollowedTagsUrl());
}
} else {
openDiasporaUrl(urls.getSearchTagsUrl(arg));
}
});
} }
break; break;
case R.id.nav_aspects: { case R.id.nav_aspects: {
SearchOrCustomTextDialogCreator.showDiasporaAspectsDialog(this, arg -> { showFragment(getFragment(AspectListFragment.TAG));
if (arg.startsWith(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX)) {
arg = arg.replace(SearchOrCustomTextDialogCreator.SPECIAL_PREFIX, "").trim();
if (arg.equals(getString(R.string.manage_your_contact_list))) {
openDiasporaUrl(urls.getContactsUrl());
} else if (arg.equals(getString(R.string.nav_profile))) {
openDiasporaUrl(urls.getProfileUrl());
}
} else {
for (DiasporaAspect daspect : _appSettings.getAspects()) {
if (arg.equals(daspect.name)) {
openDiasporaUrl(urls.getAspectUrl(Long.toString(daspect.id)));
break;
}
}
}
});
} }
break; break;
@ -1176,11 +1122,6 @@ public class MainActivity extends ThemedActivity
} }
break; break;
case R.id.nav_product_support: {
openDiasporaUrl(urls.getProfileUrl("d1cbdd70095301341e834860008dbc6c"));
}
break;
case R.id.nav_exit: { case R.id.nav_exit: {
moveTaskToBack(true); moveTaskToBack(true);
finish(); finish();
@ -1249,31 +1190,25 @@ public class MainActivity extends ThemedActivity
@Override @Override
protected void applyColorToViews() { protected void applyColorToViews() {
ThemeHelper.updateToolbarColor(toolbarTop); ThemeHelper.updateToolbarColor(toolbarTop);
navDrawerLayout.setBackgroundColor(_appSettings.getPrimaryColor()); ThemeHelper.updateActionMenuViewColor(toolbarBottom);
navProfilePictureArea.setBackgroundColor(_appSettings.getPrimaryColor()); navDrawerLayout.setBackgroundColor(appSettings.getPrimaryColor());
if (_appSettings.isAmoledColorMode()) { navProfilePictureArea.setBackgroundColor(appSettings.getPrimaryColor());
navView.setItemTextColor(ColorStateList.valueOf(Color.GRAY));
navView.setItemIconTintList(ColorStateList.valueOf(Color.GRAY));
navView.setBackgroundColor(Color.BLACK);
navheaderTitle.setTextColor(Color.GRAY);
navheaderDescription.setTextColor(Color.DKGRAY);
}
int popupTheme = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor())
? R.style.AppTheme_PopupOverlay_Dark : R.style.AppTheme_PopupOverlay_Light;
toolbarTop.setPopupTheme(popupTheme);
} }
public void setToolbarIntellihide(boolean enable) { @Override
public void enableToolbarHiding() {
AppLog.d(this, "Enable Intellihide");
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams(); AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams();
if (enable) { //scroll|enterAlways|snap
AppLog.d(this, "Enable Intellihide"); params.setScrollFlags(toolbarDefaultScrollFlags);
params.setScrollFlags(toolbarDefaultScrollFlags); appBarLayout.setExpanded(true, true);
}
} else { @Override
AppLog.d(this, "Disable Intellihide"); public void disableToolbarHiding() {
params.setScrollFlags(0); // clear all scroll flags AppLog.d(this, "Disable Intellihide");
} AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) toolbarTop.getLayoutParams();
params.setScrollFlags(0); // clear all scroll flags
appBarLayout.setExpanded(true, true); appBarLayout.setExpanded(true, true);
} }
} }

View file

@ -22,16 +22,13 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.SearchView; import android.support.v7.widget.SearchView;
import android.view.LayoutInflater;
import android.view.Menu; import android.view.Menu;
import android.view.MenuInflater; import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
@ -41,7 +38,6 @@ import android.webkit.CookieManager;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
@ -51,10 +47,10 @@ import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod;
import com.github.dfa.diaspora_android.service.FetchPodsService; import com.github.dfa.diaspora_android.service.FetchPodsService;
import com.github.dfa.diaspora_android.ui.PodSelectionDialog; import com.github.dfa.diaspora_android.ui.PodSelectionDialog;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.ActivityUtils; import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings; 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.util.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
@ -76,13 +72,6 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
@BindView(R.id.podselection__fragment__listpods) @BindView(R.id.podselection__fragment__listpods)
protected ListView listViewPod; 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 App app;
protected AppSettings appSettings; protected AppSettings appSettings;
private DiasporaPodList podList; private DiasporaPodList podList;
@ -90,14 +79,16 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
private String filterString = ""; private String filterString = "";
@Override @Override
protected int getLayoutResId() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return R.layout.podselection__fragment; AppLog.d(this, "onCreateView()");
View view = inflater.inflate(R.layout.podselection__fragment, container, false);
ButterKnife.bind(this, view);
return view;
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
app = (App) getActivity().getApplication(); app = (App) getActivity().getApplication();
appSettings = app.getSettings(); appSettings = app.getSettings();
@ -125,11 +116,11 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
} }
}); });
LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(FetchPodsService.MESSAGE_PODS_RECEIVED)); LocalBroadcastManager.getInstance(getContext()).registerReceiver(podListReceiver, new IntentFilter(FetchPodsService.MESSAGE_PODS_RECEIVED));
ActivityUtils.get(getActivity()).showInfoIfUserNotConnectedToInternet(listViewPod); Helpers.showInfoIfUserNotConnectedToInternet(getContext(), listViewPod);
} }
public void mergePodlistWithRessources(DiasporaPodList podlist) { public void mergePodlistWithRessources(DiasporaPodList podlist) {
String sPodlist = ContextUtils.get().readTextfileFromRawRes(R.raw.podlist, "", ""); String sPodlist = Helpers.readTextfileFromRawRessource(getContext(), R.raw.podlist, "", "");
try { try {
JSONObject jPodlist = new JSONObject(sPodlist); JSONObject jPodlist = new JSONObject(sPodlist);
podlist.mergeWithNewerEntries(new DiasporaPodList().fromJson(jPodlist)); podlist.mergeWithNewerEntries(new DiasporaPodList().fromJson(jPodlist));
@ -161,7 +152,7 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
} catch (JSONException ignored) { } catch (JSONException ignored) {
} }
} else { } else {
Snackbar.make(listViewPod, R.string.could_not_retrieve_list_of_pods__appspecific, Snackbar.LENGTH_SHORT).show(); Snackbar.make(listViewPod, R.string.podlist_error, Snackbar.LENGTH_SHORT).show();
} }
} }
} }
@ -169,14 +160,7 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
@Override @Override
protected void applyColorToViews() { protected void applyColorToViews() {
int dividerHeight = listViewPod.getDividerHeight(); /* Not really anything to do. Maybe later */
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 @Override
@ -192,18 +176,10 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
listedPodsList.add(pod.getPodUrl().getHost()); listedPodsList.add(pod.getPodUrl().getHost());
} }
listViewPodAdapter = new ArrayAdapter<String>( listViewPodAdapter = new ArrayAdapter<>(
getContext(), getContext(),
android.R.layout.simple_list_item_1, android.R.layout.simple_list_item_1,
listedPodsList) { 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 // save index and top position
int index = listViewPod.getFirstVisiblePosition(); int index = listViewPod.getFirstVisiblePosition();
@ -228,7 +204,6 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.podselection__menu, menu); inflater.inflate(R.menu.podselection__menu, menu);
MenuItem searchItem = menu.findItem(R.id.podselection__action_search); MenuItem searchItem = menu.findItem(R.id.podselection__action_search);
@ -237,15 +212,14 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
searchView.setOnQueryTextListener(this); searchView.setOnQueryTextListener(this);
} }
final boolean darkBg = ContextUtils.get().shouldColorOnTopBeLight(AppSettings.get().getPrimaryColor()); super.onCreateOptionsMenu(menu, inflater);
ContextUtils.get().tintMenuItems(menu, true, ContextCompat.getColor(getActivity(), darkBg ? R.color.white : R.color.black));
} }
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_reload: { case R.id.action_reload: {
if (!ActivityUtils.get(getActivity()).showInfoIfUserNotConnectedToInternet(listViewPod)) { if (!Helpers.showInfoIfUserNotConnectedToInternet(getContext(), listViewPod)) {
Intent i = new Intent(getContext(), FetchPodsService.class); Intent i = new Intent(getContext(), FetchPodsService.class);
getContext().startService(i); getContext().startService(i);
return true; return true;
@ -294,6 +268,11 @@ public class PodSelectionFragment extends ThemedFragment implements SearchView.O
/* /*
* Dummy implementations * Dummy implementations
*/ */
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
}
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
return false; return false;

View file

@ -38,6 +38,11 @@ import butterknife.ButterKnife;
import uz.shift.colorpicker.LineColorPicker; import uz.shift.colorpicker.LineColorPicker;
import uz.shift.colorpicker.OnColorChangedListener; import uz.shift.colorpicker.OnColorChangedListener;
/**
* SettingsActivity
* Created by vanitas on 24.10.16.
*/
public class SettingsActivity extends ThemedActivity implements SharedPreferences.OnSharedPreferenceChangeListener { public class SettingsActivity extends ThemedActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
//Toolbar //Toolbar
@ -63,7 +68,7 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
SettingsActivity.this.onBackPressed(); SettingsActivity.this.onBackPressed();
} }
}); });
getAppSettings().registerPreferenceChangedListener(this); getAppSettings().registerPrefAppPreferenceChangedListener(this);
oldProxySettings = getAppSettings().getProxySettings(); oldProxySettings = getAppSettings().getProxySettings();
showFragment(SettingsFragmentMaster.TAG, false); showFragment(SettingsFragmentMaster.TAG, false);
} }
@ -121,7 +126,7 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
ProxyHandler.getInstance().updateProxySettings(this); ProxyHandler.getInstance().updateProxySettings(this);
} }
} }
getAppSettings().unregisterPreferenceChangedListener(this); getAppSettings().unregisterPrefAppPreferenceChangedListener(this);
super.onStop(); super.onStop();
} }
@ -131,7 +136,7 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
if (top != null && top.getFragmentTag().equals(SettingsFragmentProxy.TAG)) { if (top != null && top.getFragmentTag().equals(SettingsFragmentProxy.TAG)) {
ProxyHandler.ProxySettings newProxySettings = getAppSettings().getProxySettings(); ProxyHandler.ProxySettings newProxySettings = getAppSettings().getProxySettings();
if (oldProxySettings.isEnabled() && !newProxySettings.isEnabled()) { if (oldProxySettings.isEnabled() && !newProxySettings.isEnabled()) {
Toast.makeText(this, R.string.app_needs_restart_to_disable_proxy_usage, Toast.LENGTH_LONG).show(); Toast.makeText(this, R.string.toast__proxy_disabled__restart_required, Toast.LENGTH_LONG).show();
} }
} }
super.onBackPressed(); super.onBackPressed();
@ -187,12 +192,6 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
((SettingsActivity) getActivity()).showFragment(SettingsFragmentDebugging.TAG, true); ((SettingsActivity) getActivity()).showFragment(SettingsFragmentDebugging.TAG, true);
return true; return true;
} }
/** Usability */
else if (settings.isKeyEqual(key, R.string.pref_key__is_overview_statusbar_hidden)) {
AppSettings.get().setRecreateMainActivity(true);
} else if (settings.isKeyEqual(key, R.string.pref_key__language)) {
AppSettings.get().setRecreateMainActivity(true);
}
/** Network */ /** Network */
else if (settings.isKeyEqual(key, R.string.pref_key__clear_cache)) { else if (settings.isKeyEqual(key, R.string.pref_key__clear_cache)) {
Intent intent = new Intent(getActivity(), MainActivity.class); Intent intent = new Intent(getActivity(), MainActivity.class);
@ -224,9 +223,9 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
getActivity().finish(); getActivity().finish();
return true; return true;
} else if (settings.isKeyEqual(key, R.string.pref_key__change_account)) { } else if (settings.isKeyEqual(key, R.string.pref_key__change_account)) {
new ThemedAlertDialogBuilder(getActivity(), AppSettings.get()) new ThemedAlertDialogBuilder(getActivity(), new AppSettings(getActivity().getApplication()))
.setTitle(getString(R.string.confirmation)) .setTitle(getString(R.string.confirmation))
.setMessage(getString(R.string.logout_warning_description)) .setMessage(getString(R.string.pref_warning__change_account))
.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() {
@ -271,8 +270,6 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
AppSettings settings = ((App) getActivity().getApplication()).getSettings();
DiasporaUrlHelper diasporaUrlHelper = new DiasporaUrlHelper(settings);
if (isAdded() && preference.hasKey()) { if (isAdded() && preference.hasKey()) {
String key = preference.getKey(); String key = preference.getKey();
if (key.equals(getString(R.string.pref_key__primary_color__preference_click))) { if (key.equals(getString(R.string.pref_key__primary_color__preference_click))) {
@ -281,13 +278,6 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
} else if (key.equals(getString(R.string.pref_key__accent_color__preference_click))) { } else if (key.equals(getString(R.string.pref_key__accent_color__preference_click))) {
showColorPickerDialog(2); showColorPickerDialog(2);
return true; 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); return super.onPreferenceTreeClick(screen, preference);
@ -314,12 +304,12 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
final ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(context, appSettings); final ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(context, appSettings);
builder.setView(dialogLayout); builder.setView(dialogLayout);
final FrameLayout titleBackground = dialogLayout.findViewById(R.id.color_picker_dialog__title_background); final FrameLayout titleBackground = (FrameLayout) dialogLayout.findViewById(R.id.color_picker_dialog__title_background);
final TextView title = dialogLayout.findViewById(R.id.color_picker_dialog__title); final TextView title = (TextView) dialogLayout.findViewById(R.id.color_picker_dialog__title);
final LineColorPicker base = dialogLayout.findViewById(R.id.color_picker_dialog__base_picker); final LineColorPicker base = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_dialog__base_picker);
final LineColorPicker shade = dialogLayout.findViewById(R.id.color_picker_dialog__shade_picker); final LineColorPicker shade = (LineColorPicker) dialogLayout.findViewById(R.id.color_picker_dialog__shade_picker);
title.setText(type == 1 ? R.string.primary_colors : R.string.accent_color); title.setText(type == 1 ? R.string.pref_title__primary_color : R.string.pref_title__accent_color);
title.setTextColor(getResources().getColor(R.color.white)); title.setTextColor(getResources().getColor(R.color.white));
final int[] current = (type == 1 ? appSettings.getPrimaryColorSettings() : appSettings.getAccentColorSettings()); final int[] current = (type == 1 ? appSettings.getPrimaryColorSettings() : appSettings.getAccentColorSettings());
base.setColors((type == 1 ? ColorPalette.getBaseColors(context) : ColorPalette.getAccentColors(context))); base.setColors((type == 1 ? ColorPalette.getBaseColors(context) : ColorPalette.getAccentColors(context)));
@ -408,8 +398,8 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
public void updateSummaries() { public void updateSummaries() {
if (isAdded()) { if (isAdded()) {
AppSettings settings = ((App) getActivity().getApplication()).getSettings(); AppSettings settings = ((App) getActivity().getApplication()).getSettings();
findPreference(settings.rstr(R.string.pref_key__http_proxy_host)).setSummary(settings.getProxyHttpHost()); findPreference(settings.getKey(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())); findPreference(settings.getKey(R.string.pref_key__http_proxy_port)).setSummary(Integer.toString(settings.getProxyHttpPort()));
} }
} }
@ -421,7 +411,7 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
if (appSettings.isKeyEqual(key, R.string.pref_key__http_proxy_load_tor_preset)) { if (appSettings.isKeyEqual(key, R.string.pref_key__http_proxy_load_tor_preset)) {
appSettings.setProxyHttpHost("127.0.0.1"); appSettings.setProxyHttpHost("127.0.0.1");
appSettings.setProxyHttpPort(8118); appSettings.setProxyHttpPort(8118);
Toast.makeText(screen.getContext(), R.string.orbot_proxy_preset_loaded, Toast.LENGTH_SHORT).show(); Toast.makeText(screen.getContext(), R.string.toast__proxy_orbot_preset_loaded, Toast.LENGTH_SHORT).show();
return true; return true;
} }
} }
@ -482,17 +472,21 @@ public class SettingsActivity extends ThemedActivity implements SharedPreference
} }
private void showWipeSettingsDialog() { private void showWipeSettingsDialog() {
final AppSettings appSettings = AppSettings.get(); final AppSettings appSettings = new AppSettings(this.getActivity().getApplication());
ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(getActivity(), appSettings); ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(getActivity(), appSettings);
builder.setTitle(R.string.confirmation) builder.setTitle(R.string.confirmation)
.setMessage(R.string.wipe_settings_warning__appspecific) .setMessage(R.string.dialog_content__wipe_settings)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialogInterface, int i) { public void onClick(DialogInterface dialogInterface, int i) {
appSettings.resetAppSettings(); appSettings.clearAppSettings();
appSettings.resetPodSettings(); appSettings.clearPodSettings();
new net.gsantner.opoc.util.ContextUtils(appSettings.getContext()).restartApp(MainActivity.class); Intent restartActivity = new Intent(getActivity(), MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(), 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
System.exit(0);
} }
}).setNegativeButton(android.R.string.cancel, null) }).setNegativeButton(android.R.string.cancel, null)
.create().show(); .create().show();

View file

@ -0,0 +1,196 @@
/*
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.Context;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.support.v7.widget.AppCompatImageView;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
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.listener.OnSomethingClickListener;
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.DiasporaUrlHelper;
import com.github.dfa.diaspora_android.util.Helpers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
/**
* Fragment that shows a list of the HashTags the user follows
*/
public class TagListFragment extends ThemedFragment implements OnSomethingClickListener<Object> {
public static final String TAG = "com.github.dfa.diaspora_android.TagListFragment";
protected RecyclerView followedTagsRecyclerView;
protected App app;
protected DiasporaUrlHelper urls;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AppLog.d(this, "onCreateView()");
return inflater.inflate(R.layout.recycler_list__fragment, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
followedTagsRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_list__recycler_view);
app = (App) getActivity().getApplication();
AppSettings appSettings = app.getSettings();
urls = new DiasporaUrlHelper(appSettings);
followedTagsRecyclerView.setHasFixedSize(true);
followedTagsRecyclerView.setNestedScrollingEnabled(false);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getContext());
followedTagsRecyclerView.setLayoutManager(layoutManager);
final FollowedTagsAdapter adapter = new FollowedTagsAdapter(appSettings, this);
followedTagsRecyclerView.setAdapter(adapter);
//Set window title
getActivity().setTitle(R.string.nav_followed_tags);
}
@Override
public String getFragmentTag() {
return TAG;
}
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
/* Nothing to do */
}
@Override
public boolean onBackPressed() {
return false;
}
@Override
public void onSomethingClicked(Object null1, Integer null2, String tag) {
((MainActivity) getActivity()).openDiasporaUrl(urls.getSearchTagsUrl(tag));
}
@Override
protected void applyColorToViews() {
followedTagsRecyclerView.invalidate();
}
public static class FollowedTagsAdapter extends RecyclerView.Adapter<FollowedTagsAdapter.ViewHolder> {
private AppSettings appSettings;
private String[] followedTagsList;
private List<String> followedTagsFavsList;
private OnSomethingClickListener<Object> tagClickedListener;
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.recycler_view__list_item__text)
public TextView title;
@BindView(R.id.recycler_view__list_item__favourite)
AppCompatImageView favouriteImage;
@BindView(R.id.recycler_view__list_item__root)
RelativeLayout root;
ViewHolder(View v) {
super(v);
ButterKnife.bind(this, v);
}
}
FollowedTagsAdapter(AppSettings appSettings, OnSomethingClickListener<Object> tagClickedListener) {
this.appSettings = appSettings;
this.followedTagsList = appSettings.getFollowedTags();
this.followedTagsFavsList = new ArrayList<>(Arrays.asList(appSettings.getFollowedTagsFavs()));
this.tagClickedListener = tagClickedListener;
}
@Override
public int getItemCount() {
return followedTagsList.length;
}
@Override
public FollowedTagsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_list__list_item_with_fav, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// Alternating colors
final Context c = holder.root.getContext();
final String tag = followedTagsList[position];
holder.title.setText(tag);
if (position % 2 == 1) {
holder.root.setBackgroundColor(Helpers.getColorFromRessource(c, R.color.alternate_row_color));
}
// Favourite (Star) Image
applyFavouriteImage(holder.favouriteImage, isFollowedTagFaved(tag));
// Click on fav button
holder.favouriteImage.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isFollowedTagFaved(tag)) {
followedTagsFavsList.remove(followedTagsFavsList.indexOf(tag));
} else {
followedTagsFavsList.add(tag);
}
appSettings.setFollowedTagsFavs(followedTagsFavsList);
applyFavouriteImage(holder.favouriteImage, isFollowedTagFaved(tag));
}
});
holder.root.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
tagClickedListener.onSomethingClicked(null, null, tag);
}
});
}
private boolean isFollowedTagFaved(String tag) {
return followedTagsFavsList.contains(tag);
}
private void applyFavouriteImage(AppCompatImageView imageView, boolean isFaved) {
imageView.setImageResource(isFaved ? R.drawable.ic_star_filled_48px : R.drawable.ic_star_border_black_48px);
imageView.setColorFilter(isFaved ? appSettings.getAccentColor() : 0, PorterDuff.Mode.SRC_ATOP);
}
}
}

View file

@ -6,22 +6,20 @@ import org.json.JSONObject;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
/** /**
* Created by gsantner (gsantner AT mailbox DOT org on 30.09.16. * Created by gsantner (https://gsantner.github.io/ on 30.09.16.
* DiasporaPodList - List container for DiasporaPod's, with methods to merge with other DiasporaPodLists * DiasporaPodList - List container for DiasporaPod's, with methods to merge with other DiasporaPodLists
* DiasporaPod - Data container for a Pod, can include N DiasporaPodUrl's * DiasporaPod - Data container for a Pod, can include N DiasporaPodUrl's
* DiasporaPodUrl - A Url of an DiasporaPod * DiasporaPodUrl - A Url of an DiasporaPod
* For all Classes a loading and saving to JSON method is available * 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 { public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, Serializable {
private static final boolean EXPORT_TOJSON_POST_COUNT_LOCAL = true; private static final boolean EXPORT_TOJSON_ACTIVE6 = false;
private List<DiasporaPod> pods = new ArrayList<>(); private List<DiasporaPod> pods = new ArrayList<>();
private boolean trackMergeChanges = false; private boolean trackMergeChanges = false;
private Integer trackAddedIndexStart = -1; private Integer trackAddedIndexStart = -1;
@ -90,8 +88,8 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
if (updatePodBak.getId() != 0 && updatePod.getId() == 0) { if (updatePodBak.getId() != 0 && updatePod.getId() == 0) {
updatePod.setId(updatePodBak.getId()); updatePod.setId(updatePodBak.getId());
} }
if (updatePodBak.getPostCountLocal() != 0 && updatePod.getPostCountLocal() == 0) { if (updatePodBak.getActive6() != 0 && updatePod.getActive6() == 0) {
updatePod.setPostCountLocal(updatePodBak.getPostCountLocal()); updatePod.setActive6(updatePodBak.getActive6());
} }
if (updatePodBak.getScore() != 0 && updatePod.getScore() == 0) { if (updatePodBak.getScore() != 0 && updatePod.getScore() == 0) {
updatePod.setScore(updatePodBak.getScore()); updatePod.setScore(updatePodBak.getScore());
@ -181,12 +179,12 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
* *
*/ */
public static class DiasporaPod implements Iterable<DiasporaPodList.DiasporaPod.DiasporaPodUrl>, Comparable<DiasporaPod>, Serializable { public static class DiasporaPod implements Iterable<DiasporaPodList.DiasporaPod.DiasporaPodUrl>, Comparable<DiasporaPod>, Serializable {
private List<DiasporaPodUrl> _podUrls = new ArrayList<>(); private List<DiasporaPodUrl> podUrls = new ArrayList<>();
private List<String> _mainLangs = new ArrayList<>(); private List<String> mainLangs = new ArrayList<>();
private String _name = ""; private String name = "";
private int _score = 0; private int score = 0;
private int _id = 0; private int id = 0;
private long _postCountLocal = 0; private long active6 = 0;
public DiasporaPod() { public DiasporaPod() {
@ -201,14 +199,14 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
JSONArray jarr; JSONArray jarr;
if (json.has("name")) { if (json.has("name")) {
_name = json.getString("name"); name = json.getString("name");
} }
if (json.has("mainLangs")) { if (json.has("mainLangs")) {
jarr = json.getJSONArray("mainLangs"); jarr = json.getJSONArray("mainLangs");
for (int i = 0; i < jarr.length(); i++) { for (int i = 0; i < jarr.length(); i++) {
String val = jarr.getString(i); String val = jarr.getString(i);
if (!_mainLangs.contains(val)) { if (!mainLangs.contains(val)) {
_mainLangs.add(val); mainLangs.add(val);
} }
} }
} }
@ -216,19 +214,19 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
jarr = json.getJSONArray("podUrls"); jarr = json.getJSONArray("podUrls");
for (int i = 0; i < jarr.length(); i++) { for (int i = 0; i < jarr.length(); i++) {
DiasporaPodUrl podUrl = new DiasporaPodUrl().fromJson(jarr.getJSONObject(i)); DiasporaPodUrl podUrl = new DiasporaPodUrl().fromJson(jarr.getJSONObject(i));
if (!_podUrls.contains(podUrl)) { if (!podUrls.contains(podUrl)) {
_podUrls.add(podUrl); podUrls.add(podUrl);
} }
} }
} }
if (json.has("score")) { if (json.has("score")) {
_score = json.getInt("score"); score = json.getInt("score");
} }
if (json.has("postCountLocal")) { if (json.has("active6")) {
_postCountLocal = json.getLong("postCountLocal"); active6 = json.getLong("active6");
} }
if (json.has("id")) { if (json.has("id")) {
_id = json.getInt("id"); id = json.getInt("id");
} }
return this; return this;
} }
@ -238,28 +236,25 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
*/ */
public JSONObject toJson() throws JSONException { public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("name", _name); json.put("name", name);
json.put("id", _id); json.put("score", score);
json.put("id", id);
if (_score != 0) {
json.put("score", _score);
}
// Only export active6 (frequently changing if told to do) // Only export active6 (frequently changing if told to do)
if (EXPORT_TOJSON_POST_COUNT_LOCAL && _postCountLocal > 0) { if (EXPORT_TOJSON_ACTIVE6) {
json.put("postCountLocal", _postCountLocal); json.put("active6", active6);
} }
// Pod urls // Pod urls
JSONArray jarr = new JSONArray(); JSONArray jarr = new JSONArray();
for (DiasporaPodUrl value : _podUrls) { for (DiasporaPodUrl value : podUrls) {
jarr.put(value.toJson()); jarr.put(value.toJson());
} }
json.put("podUrls", jarr); json.put("podUrls", jarr);
// main langs // main langs
jarr = new JSONArray(); jarr = new JSONArray();
for (String value : _mainLangs) { for (String value : mainLangs) {
jarr.put(value); jarr.put(value);
} }
json.put("mainLangs", jarr); json.put("mainLangs", jarr);
@ -273,11 +268,11 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
DiasporaPod otherPod = (DiasporaPod) o; DiasporaPod otherPod = (DiasporaPod) o;
// Check if id is equal // Check if id is equal
ret = _id != 0 && _id == otherPod._id; ret = this.id != 0 && this.id == otherPod.id;
// Check if _host is the same (fallback if id is 0) // Check if host is the same (fallback if id is 0)
if (!ret) { if (!ret) {
for (DiasporaPodUrl podUrl : _podUrls) { for (DiasporaPodUrl podUrl : podUrls) {
for (DiasporaPodUrl otherPodUrl : otherPod.getPodUrls()) { for (DiasporaPodUrl otherPodUrl : otherPod.getPodUrls()) {
if (podUrl.getBaseUrl().equals(otherPodUrl.getBaseUrl())) { if (podUrl.getBaseUrl().equals(otherPodUrl.getBaseUrl())) {
ret = true; ret = true;
@ -297,46 +292,45 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
if (!myPodUrls.isEmpty() && !otherPodUrls.isEmpty()) { if (!myPodUrls.isEmpty() && !otherPodUrls.isEmpty()) {
return myPodUrls.get(0).getHost().compareTo(otherPodUrls.get(0).getHost()); return myPodUrls.get(0).getHost().compareTo(otherPodUrls.get(0).getHost());
} }
return _name.compareTo(otherPod.getName());
} }
return _name.compareTo(""); return name.compareTo(otherPod.getName());
} }
@Override @Override
public String toString() { public String toString() {
return _name + "(" + _id + ")"; return name + "(" + id + ")";
} }
/** /**
* Iterator for Iterable interface (forEach, ..) * Iterator for Iterable interface (forEach, ..)
*/ */
public Iterator<DiasporaPodUrl> iterator() { public Iterator<DiasporaPodUrl> iterator() {
return _podUrls.iterator(); return podUrls.iterator();
} }
/* /*
* Getter & Setter * Getter & Setter
*/ */
public List<DiasporaPodUrl> getPodUrls() { public List<DiasporaPodUrl> getPodUrls() {
return _podUrls; return podUrls;
} }
public DiasporaPod setPodUrls(List<DiasporaPodUrl> podUrls) { public DiasporaPod setPodUrls(List<DiasporaPodUrl> podUrls) {
_podUrls = podUrls; this.podUrls = podUrls;
return this; return this;
} }
public List<String> getMainLangs() { public List<String> getMainLangs() {
return _mainLangs; return mainLangs;
} }
public DiasporaPod setMainLangs(List<String> mainLangs) { public DiasporaPod setMainLangs(List<String> mainLangs) {
_mainLangs = mainLangs; this.mainLangs = mainLangs;
return this; return this;
} }
public DiasporaPod appendMainLangs(String... values) { public DiasporaPod appendMainLangs(String... values) {
_mainLangs.addAll(Arrays.asList(values)); Collections.addAll(this.mainLangs, values);
return this; return this;
} }
@ -344,50 +338,50 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
* Returns the first DiasporaPodUrl in the list * Returns the first DiasporaPodUrl in the list
*/ */
public DiasporaPodUrl getPodUrl() { public DiasporaPodUrl getPodUrl() {
if (_podUrls.size() > 0) { if (podUrls.size() > 0) {
return _podUrls.get(0); return podUrls.get(0);
} }
return null; return null;
} }
public DiasporaPod appendPodUrls(DiasporaPodUrl... values) { public DiasporaPod appendPodUrls(DiasporaPodUrl... values) {
_podUrls.addAll(Arrays.asList(values)); Collections.addAll(this.podUrls, values);
return this; return this;
} }
public String getName() { public String getName() {
return _name; return name;
} }
public DiasporaPod setName(String name) { public DiasporaPod setName(String name) {
_name = name; this.name = name;
return this; return this;
} }
public int getScore() { public int getScore() {
return _score; return score;
} }
public DiasporaPod setScore(int score) { public DiasporaPod setScore(int score) {
_score = score; this.score = score;
return this; return this;
} }
public long getPostCountLocal() { public long getActive6() {
return _postCountLocal; return active6;
} }
public DiasporaPod setPostCountLocal(long postCountLocal) { public DiasporaPod setActive6(long active6) {
_postCountLocal = postCountLocal; this.active6 = active6;
return this; return this;
} }
public int getId() { public int getId() {
return _id; return id;
} }
public DiasporaPod setId(int id) { public DiasporaPod setId(int id) {
_id = id; this.id = id;
return this; return this;
} }
@ -399,9 +393,9 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
* *
*/ */
public static class DiasporaPodUrl implements Serializable { public static class DiasporaPodUrl implements Serializable {
private String _host = ""; private String host = "";
private String _protocol = "https"; private String protocol = "https";
private Integer _port = 443; private Integer port = 443;
public DiasporaPodUrl() { public DiasporaPodUrl() {
} }
@ -413,10 +407,10 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
/** /**
* Get the base url * Get the base url
* *
* @return * @return base url with port
*/ */
public String getBaseUrl() { public String getBaseUrl() {
return _protocol + "://" + _host + (isPortNeeded() ? _port : ""); return protocol + "://" + host + (isPortNeeded() ? port : "");
} }
/** /**
@ -426,13 +420,13 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
*/ */
public DiasporaPodUrl fromJson(JSONObject json) throws JSONException { public DiasporaPodUrl fromJson(JSONObject json) throws JSONException {
if (json.has("host")) { if (json.has("host")) {
_host = json.getString("host"); host = json.getString("host");
} }
if (json.has("protocol")) { if (json.has("protocol")) {
_protocol = json.getString("protocol"); protocol = json.getString("protocol");
} }
if (json.has("port")) { if (json.has("port")) {
_port = json.getInt("port"); port = json.getInt("port");
} }
return this; return this;
} }
@ -442,12 +436,12 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
*/ */
public JSONObject toJson() throws JSONException { public JSONObject toJson() throws JSONException {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
json.put("host", _host); json.put("host", host);
if (!_protocol.equals("https")) { if (!protocol.equals("https")) {
json.put("protocol", _protocol); json.put("protocol", protocol);
} }
if (_port != 443) { if (port != 443) {
json.put("port", _port); json.put("port", port);
} }
return json; return json;
} }
@ -473,7 +467,7 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
* Tells if the ports needs to shown * Tells if the ports needs to shown
*/ */
public boolean isPortNeeded() { public boolean isPortNeeded() {
return !((_port == 80 && _protocol.equals("http")) || (_port == 443 && _protocol.equals("https"))); return !((port == 80 && protocol.equals("http")) || (port == 443 && protocol.equals("https")));
} }
@Override @Override
@ -482,7 +476,6 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
} }
@Override @Override
@SuppressWarnings("SimplifiableIfStatement")
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof DiasporaPodUrl) { if (o instanceof DiasporaPodUrl) {
return getBaseUrl().equals(((DiasporaPodUrl) o).getBaseUrl()); return getBaseUrl().equals(((DiasporaPodUrl) o).getBaseUrl());
@ -494,29 +487,29 @@ public class DiasporaPodList implements Iterable<DiasporaPodList.DiasporaPod>, S
* GETTER & SETTER * GETTER & SETTER
*/ */
public String getHost() { public String getHost() {
return _host; return host;
} }
public DiasporaPodUrl setHost(String host) { public DiasporaPodUrl setHost(String host) {
_host = host; this.host = host;
return this; return this;
} }
public String getProtocol() { public String getProtocol() {
return _protocol; return protocol;
} }
public DiasporaPodUrl setProtocol(String protocol) { public DiasporaPodUrl setProtocol(String protocol) {
_protocol = protocol; this.protocol = protocol;
return this; return this;
} }
public Integer getPort() { public Integer getPort() {
return _port; return port;
} }
public DiasporaPodUrl setPort(Integer port) { public DiasporaPodUrl setPort(Integer port) {
_port = port; this.port = port;
return this; return this;
} }
} }

View file

@ -32,7 +32,7 @@ import org.json.JSONObject;
/** /**
* User profile * User profile
* Created by gsantner (gsantner AT mailbox DOT org) on 24.03.16. Part of dandelion*. * Created by gsantner (https://gsantner.github.io/) on 24.03.16. Part of dandelion*.
*/ */
public class DiasporaUserProfile { public class DiasporaUserProfile {
private static final int MINIMUM_USERPROFILE_LOAD_TIMEDIFF = 5000; private static final int MINIMUM_USERPROFILE_LOAD_TIMEDIFF = 5000;
@ -103,7 +103,7 @@ public class DiasporaUserProfile {
} }
// GUID (User id) // GUID (User id)
if (json.has("guid") && loadGuid(json.getString("guid")) && !guid.isEmpty()) { if (json.has("guid") && loadGuid(json.getString("guid"))) {
appSettings.setProfileId(guid); appSettings.setProfileId(guid);
} }

View file

@ -21,7 +21,7 @@ package com.github.dfa.diaspora_android.listener;
import com.github.dfa.diaspora_android.data.DiasporaUserProfile; import com.github.dfa.diaspora_android.data.DiasporaUserProfile;
/** /**
* Created by gsantner (gsantner AT mailbox DOT org) on 26.03.16. * 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 * Interface that needs to be implemented by classes that listen for Profile related changes
*/ */
public interface DiasporaUserProfileChangedListener { public interface DiasporaUserProfileChangedListener {

View file

@ -10,5 +10,7 @@ import android.support.design.widget.AppBarLayout;
public interface IntellihideToolbarActivityListener { public interface IntellihideToolbarActivityListener {
int toolbarDefaultScrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP; int toolbarDefaultScrollFlags = AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP;
void setToolbarIntellihide(boolean enable); void enableToolbarHiding();
void disableToolbarHiding();
} }

View file

@ -48,7 +48,7 @@ public class OpenExternalLinkReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context c, Intent receiveIntent) { public void onReceive(Context c, Intent receiveIntent) {
AppSettings appSettings = AppSettings.get(); AppSettings appSettings = new AppSettings(c);
ThemeHelper.getInstance(appSettings); ThemeHelper.getInstance(appSettings);
AppLog.v(this, "OpenExternalLinkReceiver.onReceive(): url"); AppLog.v(this, "OpenExternalLinkReceiver.onReceive(): url");

View file

@ -24,8 +24,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.widget.ImageView; import android.widget.ImageView;
import net.gsantner.opoc.util.DownloadTask;
import java.io.File; import java.io.File;
public class AvatarImageLoader { public class AvatarImageLoader {
@ -54,9 +52,7 @@ public class AvatarImageLoader {
public void startImageDownload(ImageView imageView, String avatarUrl) { public void startImageDownload(ImageView imageView, String avatarUrl) {
if (!avatarUrl.equals("")) { if (!avatarUrl.equals("")) {
new DownloadTask(new File(avatarFile.getAbsolutePath()), (ok, file) -> { new ImageDownloadTask(imageView, avatarFile.getAbsolutePath()).execute(avatarUrl);
loadToImageView(imageView);
}).execute(avatarUrl);
} }
} }
} }

View file

@ -39,76 +39,73 @@ import javax.net.ssl.HttpsURLConnection;
import info.guardianproject.netcipher.NetCipher; import info.guardianproject.netcipher.NetCipher;
public class FetchPodsService extends Service { 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 static final String EXTRA_PODLIST = "pods";
public static final String MESSAGE_PODS_RECEIVED = "com.github.dfa.diaspora.podsreceived";
public static final String PODDY_PODLIST_URL = "https://raw.githubusercontent.com/Diaspora-for-Android/dandelion/master/app/src/main/res/raw/podlist.json";
public FetchPodsService() { public FetchPodsService() {
} }
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
new GetPodsTask(this).execute(); getPods();
return super.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId);
} }
private void getPods() {
AsyncTask<Void, Void, DiasporaPodList> getPodsAsync = new AsyncTask<Void, Void, DiasporaPodList>() {
@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(MESSAGE_PODS_RECEIVED);
broadcastIntent.putExtra(EXTRA_PODLIST, pods);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(broadcastIntent);
stopSelf();
}
};
getPodsAsync.execute();
}
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service. // TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented"); 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,98 @@
/*
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.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.annotation.Nullable;
import android.widget.ImageView;
import com.github.dfa.diaspora_android.util.AppLog;
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> {
private final ImageView imageView;
private 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) {
AppLog.e(this, 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

@ -28,80 +28,95 @@ import android.graphics.Rect;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
import android.support.annotation.NonNull; import android.support.v4.content.ContextCompat;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils;
@SuppressWarnings("WeakerAccess")
public class BadgeDrawable extends Drawable { public class BadgeDrawable extends Drawable {
// Source: http://mobikul.com/adding-badge-count-on-menu-items-like-cart-notification-etc/ // Source: http://mobikul.com/adding-badge-count-on-menu-items-like-cart-notification-etc/
private static final String BADGE_VALUE_OVERFLOW = "*"; private static final String BADGE_VALUE_OVERFLOW = "*";
private Paint _badgeBackground; private Paint badgeBackground;
private Paint _badgeText; private Paint badgeStroke;
private Rect _textRect = new Rect(); private Paint badgeText;
private Rect textRect = new Rect();
private String _badgeValue = ""; private String badgeValue = "";
private boolean _shouldDraw; private boolean shouldDraw;
public BadgeDrawable(Context context) { public BadgeDrawable(Context context) {
float textSize = context.getResources().getDimension(R.dimen.textsize_badge_count); float textSize = context.getResources().getDimension(R.dimen.textsize_badge_count);
AppSettings settings = AppSettings.get(); AppSettings settings = new AppSettings(context);
_badgeBackground = new Paint(); badgeBackground = new Paint();
_badgeBackground.setColor(settings.getAccentColor()); badgeBackground.setColor(settings.getAccentColor());
_badgeBackground.setAntiAlias(true); badgeBackground.setAntiAlias(true);
_badgeBackground.setStyle(Paint.Style.FILL); badgeBackground.setStyle(Paint.Style.FILL);
badgeStroke = new Paint();
badgeStroke.setColor(ContextCompat.getColor(context.getApplicationContext(), R.color.colorPrimaryDark));
badgeStroke.setAntiAlias(true);
badgeStroke.setStyle(Paint.Style.FILL);
_badgeText = new Paint(); badgeText = new Paint();
_badgeText.setColor(ContextUtils.get().shouldColorOnTopBeLight(settings.getAccentColor()) ? Color.WHITE : Color.BLACK); badgeText.setColor(Color.WHITE);
_badgeText.setTypeface(Typeface.DEFAULT); badgeText.setTypeface(Typeface.DEFAULT);
_badgeText.setTextSize(textSize); badgeText.setTextSize(textSize);
_badgeText.setAntiAlias(true); badgeText.setAntiAlias(true);
_badgeText.setTextAlign(Paint.Align.CENTER); badgeText.setTextAlign(Paint.Align.CENTER);
} }
@Override @Override
public void draw(@NonNull Canvas canvas) { public void draw(Canvas canvas) {
if (!_shouldDraw) { if (!shouldDraw) {
return; return;
} }
Rect bounds = getBounds(); Rect bounds = getBounds();
float width = bounds.right - bounds.left; float width = bounds.right - bounds.left;
float height = bounds.bottom - bounds.top; float height = bounds.bottom - bounds.top;
float oneDp = ContextUtils.get().convertDpToPx(1);
// Position the badge in the top-right quadrant of the icon. // Position the badge in the top-right quadrant of the icon.
float radius = ((Math.max(width, height) / 2)) / 2; float radius = ((Math.max(width, height) / 2)) / 2;
float centerX = (width - radius - 1) + oneDp * 2; float centerX = (width - radius - 1) + 5;
float centerY = radius - 2 * oneDp; float centerY = radius - 5;
canvas.drawCircle(centerX, centerY, (int) (radius + oneDp * 5), _badgeBackground); if (badgeValue.length() <= 2) {
// Draw badge circle.
canvas.drawCircle(centerX, centerY, (int) (radius + 7.5), badgeStroke);
canvas.drawCircle(centerX, centerY, (int) (radius + 5.5), badgeBackground);
} else {
canvas.drawCircle(centerX, centerY, (int) (radius + 8.5), badgeStroke);
canvas.drawCircle(centerX, centerY, (int) (radius + 6.5), badgeBackground);
//canvas.drawRoundRect(radius, radius, radius, radius, 10, 10, badgeBackground);
}
// Draw badge count message inside the circle. // Draw badge count message inside the circle.
_badgeText.getTextBounds(_badgeValue, 0, _badgeValue.length(), _textRect); badgeText.getTextBounds(badgeValue, 0, badgeValue.length(), textRect);
float textHeight = _textRect.bottom - _textRect.top; float textHeight = textRect.bottom - textRect.top;
float textY = centerY + (textHeight / 2f); float textY = centerY + (textHeight / 2f);
canvas.drawText(_badgeValue.length() > 2 ? BADGE_VALUE_OVERFLOW : _badgeValue, if (badgeValue.length() > 2)
centerX, textY, _badgeText); canvas.drawText(BADGE_VALUE_OVERFLOW, centerX, textY, badgeText);
else
canvas.drawText(badgeValue, centerX, textY, badgeText);
} }
// Sets the text to display. Badge displays a '*' if more than 2 characters /*
private void setBadgeText(String text) { Sets the count (i.e notifications) to display.
_badgeValue = text; */
public void setCount(String count) {
badgeValue = count;
// Only draw a badge if the value isn't a zero // Only draw a badge if there are notifications.
_shouldDraw = !text.equalsIgnoreCase("0"); shouldDraw = !count.equalsIgnoreCase("0");
invalidateSelf(); invalidateSelf();
} }
@Override @Override
public void setAlpha(int alpha) { public void setAlpha(int alpha) {
// do nothing
} }
@Override @Override
public void setColorFilter(ColorFilter cf) { public void setColorFilter(ColorFilter cf) {
// do nothing
} }
@Override @Override
@ -110,11 +125,11 @@ public class BadgeDrawable extends Drawable {
} }
public static void setBadgeCount(Context context, LayerDrawable icon, Integer count) { public static void setBadgeCount(Context context, LayerDrawable icon, Integer count) {
setBadgeText(context, icon, count.toString()); setBadgeCount(context, icon, count.toString());
} }
// Max of 2 characters public static void setBadgeCount(Context context, LayerDrawable icon, String count) {
public static void setBadgeText(Context context, LayerDrawable icon, String text) {
BadgeDrawable badge; BadgeDrawable badge;
// Reuse drawable if possible // Reuse drawable if possible
@ -125,7 +140,7 @@ public class BadgeDrawable extends Drawable {
badge = new BadgeDrawable(context); badge = new BadgeDrawable(context);
} }
badge.setBadgeText(text); badge.setCount(count);
icon.mutate(); icon.mutate();
icon.setDrawableByLayerId(R.id.ic_badge, badge); icon.setDrawableByLayerId(R.id.ic_badge, badge);
} }

View file

@ -18,13 +18,14 @@
*/ */
package com.github.dfa.diaspora_android.ui; package com.github.dfa.diaspora_android.ui;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.support.v7.widget.AppCompatTextView;
import android.text.Html; import android.text.Html;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Patterns; import android.util.Patterns;
import android.widget.TextView;
import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.activity.MainActivity;
@ -37,7 +38,7 @@ import java.util.regex.Pattern;
* Hashtags open the MainActivity, load the new-post site of the selected pod and insert the * Hashtags open the MainActivity, load the new-post site of the selected pod and insert the
* hashtag into the post editor. See data/HashtagContentProvider. * hashtag into the post editor. See data/HashtagContentProvider.
*/ */
public class HtmlTextView extends AppCompatTextView { public class HtmlTextView extends TextView {
public HtmlTextView(Context context) { public HtmlTextView(Context context) {
super(context); super(context);
@ -54,6 +55,12 @@ public class HtmlTextView extends AppCompatTextView {
init(); init();
} }
@TargetApi(21)
public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
/** /**
* Linkify, format markdown and escape the displayed message. * Linkify, format markdown and escape the displayed message.
*/ */

View file

@ -37,7 +37,7 @@ import butterknife.OnItemSelected;
/** /**
* Dialog that helps the user configure a pod * Dialog that helps the user configure a pod
* Created by gsantner on 06.10.16. * Created by gsantner (https://gsantner.github.io) on 06.10.16.
*/ */
public class PodSelectionDialog extends ThemedAppCompatDialogFragment { public class PodSelectionDialog extends ThemedAppCompatDialogFragment {
public static final String TAG = "com.github.dfa.diaspora_android.ui.PodSelectionDialog"; public static final String TAG = "com.github.dfa.diaspora_android.ui.PodSelectionDialog";
@ -159,7 +159,7 @@ public class PodSelectionDialog extends ThemedAppCompatDialogFragment {
if (isAdded()) { if (isAdded()) {
return ((App) getActivity().getApplication()).getSettings(); return ((App) getActivity().getApplication()).getSettings();
} else { } else {
return AppSettings.get(); return new AppSettings(getContext().getApplicationContext());
} }
} }

View file

@ -1,85 +0,0 @@
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,73 @@
/*
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.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuInflater;
/**
* Customized abstract Fragment class with some useful methods
* Created by vanitas on 21.09.16.
*/
public abstract class CustomFragment extends Fragment {
public static final String TAG = "com.github.dfa.diaspora_android.ui.theme.CustomFragment";
/**
* We have an optionsMenu
*
* @param savedInstanceState state
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
/**
* Return the tag used to identify the Fragment.
*
* @return tag
*/
public abstract String getFragmentTag();
/**
* Add fragment-dependent options to the bottom options toolbar
*
* @param menu bottom menu
* @param inflater inflater
*/
public abstract void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater);
/**
* Return true if the fragment reacted to a back button press, false else.
* In case the fragment returned false, the parent activity should handle the backPress.
*
* @return did we react to the back press?
*/
public abstract boolean onBackPressed();
public boolean isAllowedIntellihide() {
return true;
}
}

View file

@ -64,7 +64,7 @@ public class ThemeHelper {
public static ThemeHelper getInstance() { public static ThemeHelper getInstance() {
if (instance == null) if (instance == null)
throw new IllegalStateException("ThemeHelper must be initialized using getInstance(AppSettingsBase) before it can be used!"); throw new IllegalStateException("ThemeHelper must be initialized using getInstance(AppSettings) before it can be used!");
return instance; return instance;
} }
@ -154,7 +154,7 @@ public class ThemeHelper {
} }
public static int getNeutralGreyColor() { public static int getNeutralGreyColor() {
return ContextCompat.getColor(getInstance().appSettings.getContext(), R.color.md_grey_800); return ContextCompat.getColor(getInstance().appSettings.getApplicationContext(), R.color.md_grey_800);
} }
public static void updateAlertDialogColor(AlertDialog alertDialog) { public static void updateAlertDialogColor(AlertDialog alertDialog) {

View file

@ -19,14 +19,19 @@
package com.github.dfa.diaspora_android.ui.theme; package com.github.dfa.diaspora_android.ui.theme;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build; import android.os.Build;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
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.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.Helpers;
import java.util.Locale;
/** /**
* Activity that supports color schemes * Activity that supports color schemes
@ -67,7 +72,15 @@ public abstract class ThemedActivity extends AppCompatActivity {
*/ */
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateRecentAppColor() { private void updateRecentAppColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
BitmapDrawable drawable = ((BitmapDrawable) getDrawable(R.drawable.ic_launcher));
if (drawable != null) {
setTaskDescription(new ActivityManager.TaskDescription(
getResources().getString(R.string.app_name),
drawable.getBitmap(),
getAppSettings().getPrimaryColor()));
}
}
} }
protected void updateScreenRotation() { protected void updateScreenRotation() {
@ -86,6 +99,9 @@ public abstract class ThemedActivity extends AppCompatActivity {
public void updateLanguage() { public void updateLanguage() {
AppSettings appSettings = getAppSettings(); AppSettings appSettings = getAppSettings();
ContextUtils.get().setAppLanguage(appSettings.getLanguage()); Locale locale = Helpers.getLocaleByAndroidCode(appSettings.getLanguage());
Configuration config = appSettings.getApplicationContext().getResources().getConfiguration();
config.locale = locale != null ? locale : Locale.getDefault();
appSettings.getApplicationContext().getResources().updateConfiguration(config, null);
} }
} }

View file

@ -41,8 +41,8 @@ public class ThemedCheckBoxPreference extends CheckBoxPreference implements Them
@Override @Override
public void setColors() { public void setColors() {
CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox); CheckBox checkBox = (CheckBox) rootLayout.findViewById(android.R.id.checkbox);
ThemeHelper.getInstance(AppSettings.get()); ThemeHelper.getInstance(new AppSettings(getContext()));
ThemeHelper.updateCheckBoxColor(checkBox); ThemeHelper.updateCheckBoxColor(checkBox);
} }
} }

View file

@ -10,7 +10,7 @@ import android.widget.ImageView;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import com.github.dfa.diaspora_android.util.ContextUtils; import com.github.dfa.diaspora_android.util.Helpers;
/** /**
* Preference that shows selected Color in a circle * Preference that shows selected Color in a circle
@ -38,7 +38,7 @@ public class ThemedColorPickerPreference extends Preference implements Themeable
@Override @Override
protected void onBindView(View view) { protected void onBindView(View view) {
super.onBindView(view); super.onBindView(view);
colorPreview = view.findViewById(android.R.id.icon); colorPreview = (ImageView) view.findViewById(android.R.id.icon);
setColors(); setColors();
} }
@ -47,16 +47,16 @@ public class ThemedColorPickerPreference extends Preference implements Themeable
Drawable circle; Drawable circle;
if (colorPreview != null && (circle = colorPreview.getDrawable()) != null) { if (colorPreview != null && (circle = colorPreview.getDrawable()) != null) {
Context c = getContext(); Context c = getContext();
AppSettings appSettings = AppSettings.get(); AppSettings appSettings = new AppSettings(getContext());
String key = getKey(); String key = getKey();
int color = ContextUtils.get().rcolor(R.color.primary); int color = Helpers.getColorFromRessource(c, R.color.primary);
if ((appSettings.isKeyEqual(key, R.string.pref_key__primary_color_shade))) { if ((appSettings.isKeyEqual(key, R.string.pref_key__primary_color_shade))) {
color = appSettings.getPrimaryColor(); color = appSettings.getPrimaryColor();
} else if ((appSettings.isKeyEqual(key, R.string.pref_key__accent_color_shade))) { } else if ((appSettings.isKeyEqual(key, R.string.pref_key__accent_color_shade))) {
color = appSettings.getAccentColor(); color = appSettings.getAccentColor();
} else { } else {
color = appSettings.getColor(key, color, getSharedPreferences()); color = appSettings.getColor(getSharedPreferences(), key, color);
} }
circle.setColorFilter(color, PorterDuff.Mode.SRC_ATOP); circle.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
} }

View file

@ -21,14 +21,12 @@ package com.github.dfa.diaspora_android.ui.theme;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import net.gsantner.opoc.activity.GsFragmentBase;
/** /**
* Fragment that supports color schemes * Fragment that supports color schemes
* Created by vanitas on 06.10.16. * Created by vanitas on 06.10.16.
*/ */
public abstract class ThemedFragment extends GsFragmentBase { public abstract class ThemedFragment extends CustomFragment {
protected AppSettings getAppSettings() { protected AppSettings getAppSettings() {
return ((App) getActivity().getApplication()).getSettings(); return ((App) getActivity().getApplication()).getSettings();
} }
@ -41,9 +39,4 @@ public abstract class ThemedFragment extends GsFragmentBase {
ThemeHelper.getInstance(getAppSettings()); ThemeHelper.getInstance(getAppSettings());
applyColorToViews(); applyColorToViews();
} }
public boolean isAllowedIntellihide() {
return true;
}
} }

View file

@ -36,7 +36,7 @@ public class ThemedPreferenceCategory extends PreferenceCategory implements Them
@Override @Override
protected View onCreateView(ViewGroup parent) { protected View onCreateView(ViewGroup parent) {
View rootLayout = super.onCreateView(parent); View rootLayout = super.onCreateView(parent);
this.titleTextView = rootLayout.findViewById(android.R.id.title); this.titleTextView = (TextView) rootLayout.findViewById(android.R.id.title);
setColors(); setColors();
return rootLayout; return rootLayout;
} }
@ -44,7 +44,7 @@ public class ThemedPreferenceCategory extends PreferenceCategory implements Them
@Override @Override
public void setColors() { public void setColors() {
if (titleTextView != null) { if (titleTextView != null) {
ThemeHelper.getInstance(AppSettings.get()); ThemeHelper.getInstance(new AppSettings(getContext()));
ThemeHelper.updateTextViewTextColor(titleTextView); ThemeHelper.updateTextViewTextColor(titleTextView);
} }
} }

View file

@ -27,9 +27,9 @@ public class ThemedVisibilityPreference extends ThemedCheckBoxPreference {
@Override @Override
public void setColors() { public void setColors() {
CheckBox checkBox = rootLayout.findViewById(android.R.id.checkbox); CheckBox checkBox = (CheckBox) rootLayout.findViewById(android.R.id.checkbox);
checkBox.setButtonDrawable(R.drawable.ic_visibility_selector); checkBox.setButtonDrawable(R.drawable.ic_visibility_selector);
ThemeHelper.getInstance(AppSettings.get()); ThemeHelper.getInstance(new AppSettings(getContext()));
ThemeHelper.updateCheckBoxColor(checkBox); ThemeHelper.updateCheckBoxColor(checkBox);
} }
} }

View file

@ -1,86 +0,0 @@
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

@ -1,58 +0,0 @@
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);
}
}

View file

@ -17,81 +17,158 @@ package com.github.dfa.diaspora_android.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.graphics.Color; import android.support.annotation.ColorRes;
import android.os.Environment; import android.support.v4.content.ContextCompat;
import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.BuildConfig; import com.github.dfa.diaspora_android.BuildConfig;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.DiasporaAspect; import com.github.dfa.diaspora_android.data.DiasporaAspect;
import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod; import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod;
import com.github.dfa.diaspora_android.web.ProxyHandler; import com.github.dfa.diaspora_android.web.ProxyHandler;
import net.gsantner.opoc.preference.SharedPreferencesPropertyBackend;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.File;
import java.util.List; import java.util.List;
/** /**
* Settings * Settings
* Created by gsantner (gsantner AT mailbox DOT org) on 20.03.16. Part of dandelion*. * Created by gsantner (https://gsantner.github.io/) on 20.03.16. Part of dandelion*.
*/ */
@SuppressWarnings("ConstantConditions") public class AppSettings {
public class AppSettings extends SharedPreferencesPropertyBackend { private final SharedPreferences prefApp;
private final SharedPreferences _prefPod; private final SharedPreferences prefPod;
private final Context context;
private DiasporaPod currentPod0Cached; private DiasporaPod currentPod0Cached;
public static AppSettings get() {
return new AppSettings(App.get());
}
public AppSettings(Context context) { public AppSettings(Context context) {
super(context); this.context = context.getApplicationContext();
_prefPod = _context.getSharedPreferences("pod0", Context.MODE_PRIVATE); prefApp = this.context.getSharedPreferences("app", Context.MODE_PRIVATE);
prefPod = this.context.getSharedPreferences("pod0", Context.MODE_PRIVATE);
}
public Context getApplicationContext() {
return context;
} }
/** /**
* Clear all settings in _prefPod (Settings related to the configured pod) * Clear all settings in prefPod (Settings related to the configured pod)
* This uses commit instead of apply, since * This uses commit instead of apply, since
* SettingsActivity.SettingsFragmentDebugging.showWipeSettingsDialog() * SettingsActivity.SettingsFragmentDebugging.showWipeSettingsDialog()
* kills the app after the calling this, so we have to block until we are finished. * kills the app after the calling this, so we have to block until we are finished.
*/ */
@SuppressLint("CommitPrefEdits") @SuppressLint("CommitPrefEdits")
public void resetPodSettings() { public void clearPodSettings() {
super.resetSettings(_prefPod); prefPod.edit().clear().commit();
} }
/** /**
* Clear all settings in _prefApp (related to the App itself) * Clear all settings in prefApp (related to the App itself)
* This uses commit instead of apply, since * This uses commit instead of apply, since
* SettingsActivity.SettingsFragmentDebugging.showWipeSettingsDialog() * SettingsActivity.SettingsFragmentDebugging.showWipeSettingsDialog()
* kills the app after the calling this, so we have to block until we are finished. * kills the app after the calling this, so we have to block until we are finished.
*/ */
@SuppressLint("CommitPrefEdits") @SuppressLint("CommitPrefEdits")
public void resetAppSettings() { public void clearAppSettings() {
super.resetSettings(_prefApp); prefApp.edit().clear().commit();
} }
//################################# public String getKey(int stringKeyResourceId) {
//## Getter & Setter for settings return context.getString(stringKeyResourceId);
//################################# }
public boolean isKeyEqual(String key, int stringKeyRessourceId) {
return key.equals(getKey(stringKeyRessourceId));
}
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 setLong(SharedPreferences pref, int keyRessourceId, long value) {
pref.edit().putLong(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) {
StringBuilder sb = new StringBuilder();
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 String getString(SharedPreferences pref, int ressourceId, int ressourceIdDefaultValue) {
return pref.getString(context.getString(ressourceId), context.getString(ressourceIdDefaultValue));
}
private boolean getBool(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);
}
private long getLong(SharedPreferences pref, int ressourceId, long defaultValue) {
return pref.getLong(context.getString(ressourceId), defaultValue);
}
public int getColor(SharedPreferences pref, String key, int defaultColor) {
return pref.getInt(key, defaultColor);
}
public int getColorRes(@ColorRes int resColorId){
return ContextCompat.getColor(context, resColorId);
}
public void registerPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
prefApp.registerOnSharedPreferenceChangeListener(listener);
}
public void unregisterPrefAppPreferenceChangedListener(SharedPreferences.OnSharedPreferenceChangeListener listener) {
prefApp.unregisterOnSharedPreferenceChangeListener(listener);
}
/*
// Setters & Getters
*/
public String getProfileId() { public String getProfileId() {
return getString(R.string.pref_key__podprofile_id, "", _prefPod); return getString(prefPod, R.string.pref_key__podprofile_id, "");
} }
public void setProfileId(String profileId) { public void setProfileId(String profileId) {
setString(R.string.pref_key__podprofile_id, profileId, _prefPod); setString(prefPod, R.string.pref_key__podprofile_id, profileId);
} }
public boolean isLoadImages() { public boolean isLoadImages() {
return getBool(R.string.pref_key__load_images, true); return getBool(prefApp, R.string.pref_key__load_images, true);
} }
public int getMinimumFontSize() { public int getMinimumFontSize() {
switch (getString(R.string.pref_key__font_size, "")) { switch (getString(prefApp, R.string.pref_key__font_size, "")) {
case "huge": case "huge":
return 20; return 20;
case "large": case "large":
@ -99,30 +176,30 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
case "normal": case "normal":
return 8; return 8;
default: default:
setString(R.string.pref_key__font_size, "normal"); setString(prefApp, R.string.pref_key__font_size, "normal");
return 8; return 8;
} }
} }
public String getAvatarUrl() { public String getAvatarUrl() {
return getString(R.string.pref_key__podprofile_avatar_url, "", _prefPod); return getString(prefPod, R.string.pref_key__podprofile_avatar_url, "");
} }
public void setAvatarUrl(String avatarUrl) { public void setAvatarUrl(String avatarUrl) {
setString(R.string.pref_key__podprofile_avatar_url, avatarUrl, _prefPod); setString(prefPod, R.string.pref_key__podprofile_avatar_url, avatarUrl);
} }
public String getName() { public String getName() {
return getString(R.string.pref_key__podprofile_name, "", _prefPod); return getString(prefPod, R.string.pref_key__podprofile_name, "");
} }
public void setName(String name) { public void setName(String name) {
setString(R.string.pref_key__podprofile_name, name, _prefPod); setString(prefPod, R.string.pref_key__podprofile_name, name);
} }
public DiasporaPod getPod() { public DiasporaPod getPod() {
if (currentPod0Cached == null) { if (currentPod0Cached == null) {
String pref = getString(R.string.pref_key__current_pod_0, "", _prefPod); String pref = getString(prefPod, R.string.pref_key__current_pod_0, "");
try { try {
currentPod0Cached = new DiasporaPod().fromJson(new JSONObject(pref)); currentPod0Cached = new DiasporaPod().fromJson(new JSONObject(pref));
@ -135,27 +212,23 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
public void setPod(DiasporaPod pod) { public void setPod(DiasporaPod pod) {
try { try {
setString(R.string.pref_key__current_pod_0, setString(prefPod, R.string.pref_key__current_pod_0,
pod == null ? null : pod.toJson().toString(), _prefPod); pod == null ? null : pod.toJson().toString());
currentPod0Cached = pod; currentPod0Cached = pod;
} catch (JSONException ignored) { } catch (JSONException ignored) {
} }
} }
public boolean hasPod() { public boolean hasPod() {
return !getString(R.string.pref_key__current_pod_0, "", _prefPod).equals(""); return !getString(prefPod, R.string.pref_key__current_pod_0, "").equals("");
} }
public void setPodAspects(DiasporaAspect[] aspects) { public void setPodAspects(DiasporaAspect[] aspects) {
String[] strs = new String[aspects.length]; setStringArray(prefPod, R.string.pref_key__podprofile_aspects, aspects);
for (int i = 0; i < strs.length; i++) {
strs[i] = aspects[i].toShareAbleText();
}
setStringArray(R.string.pref_key__podprofile_aspects, strs, _prefPod);
} }
public DiasporaAspect[] getAspects() { public DiasporaAspect[] getAspects() {
String[] s = getStringArray(R.string.pref_key__podprofile_aspects, _prefPod); String[] s = getStringArray(prefPod, R.string.pref_key__podprofile_aspects);
DiasporaAspect[] aspects = new DiasporaAspect[s.length]; DiasporaAspect[] aspects = new DiasporaAspect[s.length];
for (int i = 0; i < aspects.length; i++) { for (int i = 0; i < aspects.length; i++) {
aspects[i] = new DiasporaAspect(s[i]); aspects[i] = new DiasporaAspect(s[i]);
@ -164,53 +237,53 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
} }
public String[] getFollowedTags() { public String[] getFollowedTags() {
return getStringArray(R.string.pref_key__podprofile_followed_tags, _prefPod); return getStringArray(prefPod, R.string.pref_key__podprofile_followed_tags);
} }
public void setFollowedTags(String[] values) { public void setFollowedTags(String[] values) {
setStringArray(R.string.pref_key__podprofile_followed_tags, values, _prefPod); setStringArray(prefPod, R.string.pref_key__podprofile_followed_tags, values);
} }
public String[] getFollowedTagsFavs() { public String[] getFollowedTagsFavs() {
return getStringArray(R.string.pref_key__podprofile_followed_tags_favs, _prefPod); return getStringArray(prefPod, R.string.pref_key__podprofile_followed_tags_favs);
} }
public void setFollowedTagsFavs(List<String> values) { public void setFollowedTagsFavs(List<String> values) {
setStringList(R.string.pref_key__podprofile_followed_tags_favs, values, _prefPod); setStringArray(prefPod, R.string.pref_key__podprofile_followed_tags_favs, values.toArray(new String[values.size()]));
} }
public String[] getAspectFavs() { public String[] getAspectFavs() {
return getStringArray(R.string.pref_key__podprofile_aspects_favs, _prefPod); return getStringArray(prefPod, R.string.pref_key__podprofile_aspects_favs);
} }
public void setAspectFavs(List<String> values) { public void setAspectFavs(List<String> values) {
setStringList(R.string.pref_key__podprofile_aspects_favs, values, _prefPod); setStringArray(prefPod, R.string.pref_key__podprofile_aspects_favs, values.toArray(new String[values.size()]));
} }
public int getUnreadMessageCount() { public int getUnreadMessageCount() {
return getInt(R.string.pref_key__podprofile_unread_message_count, 0, _prefPod); return getInt(prefPod, R.string.pref_key__podprofile_unread_message_count, 0);
} }
public void setUnreadMessageCount(int unreadMessageCount) { public void setUnreadMessageCount(int unreadMessageCount) {
setInt(R.string.pref_key__podprofile_unread_message_count, unreadMessageCount, _prefPod); setInt(prefPod, R.string.pref_key__podprofile_unread_message_count, unreadMessageCount);
} }
public int getNotificationCount() { public int getNotificationCount() {
return getInt(R.string.pref_key__podprofile_notification_count, 0, _prefPod); return getInt(prefPod, R.string.pref_key__podprofile_notification_count, 0);
} }
public void setNotificationCount(int notificationCount) { public void setNotificationCount(int notificationCount) {
setInt(R.string.pref_key__podprofile_notification_count, notificationCount, _prefPod); setInt(prefPod, R.string.pref_key__podprofile_notification_count, notificationCount);
} }
public boolean isAppendSharedViaApp() { public boolean isAppendSharedViaApp() {
return getBool(R.string.pref_key__append_shared_via_app, true); return getBool(prefApp, R.string.pref_key__append_shared_via_app, true);
} }
@SuppressLint("CommitPrefEdits") @SuppressLint("CommitPrefEdits")
public void setProxyHttpEnabled(boolean enabled) { public void setProxyHttpEnabled(boolean enabled) {
//commit instead of apply because the app is likely to be killed before apply is called. //commit instead of apply because the app is likely to be killed before apply is called.
_prefApp.edit().putBoolean(rstr(R.string.pref_key__http_proxy_enabled), enabled).commit(); prefApp.edit().putBoolean(context.getString(R.string.pref_key__http_proxy_enabled), enabled).commit();
} }
/** /**
@ -220,7 +293,7 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
*/ */
public boolean isProxyHttpEnabled() { public boolean isProxyHttpEnabled() {
try { try {
return getBool(R.string.pref_key__http_proxy_enabled, false); return getBool(prefApp, R.string.pref_key__http_proxy_enabled, false);
} catch (ClassCastException e) { } catch (ClassCastException e) {
setProxyHttpEnabled(false); setProxyHttpEnabled(false);
return false; return false;
@ -228,7 +301,7 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
} }
public boolean wasProxyEnabled() { public boolean wasProxyEnabled() {
return getBool(R.string.pref_key__proxy_was_enabled, false); return getBool(prefApp, R.string.pref_key__proxy_was_enabled, false);
} }
/** /**
@ -239,7 +312,7 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
*/ */
@SuppressLint("CommitPrefEdits") @SuppressLint("CommitPrefEdits")
public void setProxyWasEnabled(boolean b) { public void setProxyWasEnabled(boolean b) {
_prefApp.edit().putBoolean(rstr(R.string.pref_key__proxy_was_enabled), b).commit(); prefApp.edit().putBoolean(context.getString(R.string.pref_key__proxy_was_enabled), b).commit();
} }
/** /**
@ -248,11 +321,11 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
* @return proxy host * @return proxy host
*/ */
public String getProxyHttpHost() { public String getProxyHttpHost() {
return getString(R.string.pref_key__http_proxy_host, ""); return getString(prefApp, R.string.pref_key__http_proxy_host, "");
} }
public void setProxyHttpHost(String value) { public void setProxyHttpHost(String value) {
setString(R.string.pref_key__http_proxy_host, value); setString(prefApp, R.string.pref_key__http_proxy_host, value);
} }
/** /**
@ -262,17 +335,17 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
*/ */
public int getProxyHttpPort() { public int getProxyHttpPort() {
try { try {
String str = getString(R.string.pref_key__http_proxy_port, "0"); String str = getString(prefApp, R.string.pref_key__http_proxy_port, "0");
return Integer.parseInt(str); return Integer.parseInt(str);
} catch (ClassCastException e) { } catch (ClassCastException e) {
int port = getInt(R.string.pref_key__http_proxy_port, 0); int port = getInt(prefApp, R.string.pref_key__http_proxy_port, 0);
setProxyHttpPort(port); setProxyHttpPort(port);
return port; return port;
} }
} }
public void setProxyHttpPort(int value) { public void setProxyHttpPort(int value) {
setString(R.string.pref_key__http_proxy_port, Integer.toString(value)); setString(prefApp, R.string.pref_key__http_proxy_port, Integer.toString(value));
} }
public ProxyHandler.ProxySettings getProxySettings() { public ProxyHandler.ProxySettings getProxySettings() {
@ -280,201 +353,148 @@ public class AppSettings extends SharedPreferencesPropertyBackend {
} }
public boolean isIntellihideToolbars() { public boolean isIntellihideToolbars() {
return getBool(R.string.pref_key__intellihide_toolbars, false); return getBool(prefApp, R.string.pref_key__intellihide_toolbars, true);
} }
public boolean isChromeCustomTabsEnabled() { public boolean isChromeCustomTabsEnabled() {
return getBool(R.string.pref_key__chrome_custom_tabs_enabled, true); return getBool(prefApp, R.string.pref_key__chrome_custom_tabs_enabled, true);
} }
public boolean isLoggingEnabled() { public boolean isLoggingEnabled() {
return getBool(R.string.pref_key__logging_enabled, false); return getBool(prefApp, R.string.pref_key__logging_enabled, false);
} }
public boolean isLoggingSpamEnabled() { public boolean isLoggingSpamEnabled() {
return getBool(R.string.pref_key__logging_spam_enabled, false); return getBool(prefApp, R.string.pref_key__logging_spam_enabled, false);
} }
public boolean isVisibleInNavExit() { public boolean isVisibleInNavExit() {
return getBool(R.string.pref_key__visibility_nav__exit, true); return getBool(prefApp, R.string.pref_key__visibility_nav__exit, false);
} }
public boolean isVisibleInNavHelp_license() { public boolean isVisibleInNavHelp_license() {
return getBool(R.string.pref_key__visibility_nav__help_license, true); return getBool(prefApp, R.string.pref_key__visibility_nav__help_license, true);
} }
public boolean isVisibleInNavPublic_activities() { public boolean isVisibleInNavPublic_activities() {
return getBool(R.string.pref_key__visibility_nav__public_activities, false); return getBool(prefApp, R.string.pref_key__visibility_nav__public_activities, false);
} }
public boolean isVisibleInNavMentions() { public boolean isVisibleInNavMentions() {
return getBool(R.string.pref_key__visibility_nav__mentions, false); return getBool(prefApp, R.string.pref_key__visibility_nav__mentions, false);
} }
public boolean isVisibleInNavCommented() { public boolean isVisibleInNavCommented() {
return getBool(R.string.pref_key__visibility_nav__commented, true); return getBool(prefApp, R.string.pref_key__visibility_nav__commented, true);
} }
public boolean isVisibleInNavLiked() { public boolean isVisibleInNavLiked() {
return getBool(R.string.pref_key__visibility_nav__liked, true); return getBool(prefApp, R.string.pref_key__visibility_nav__liked, true);
} }
public boolean isVisibleInNavActivities() { public boolean isVisibleInNavActivities() {
return getBool(R.string.pref_key__visibility_nav__activities, true); return getBool(prefApp, R.string.pref_key__visibility_nav__activities, true);
} }
public boolean isVisibleInNavAspects() { public boolean isVisibleInNavAspects() {
return getBool(R.string.pref_key__visibility_nav__aspects, true); return getBool(prefApp, R.string.pref_key__visibility_nav__aspects, true);
} }
public boolean isVisibleInNavFollowed_tags() { public boolean isVisibleInNavFollowed_tags() {
return getBool(R.string.pref_key__visibility_nav__followed_tags, true); return getBool(prefApp, R.string.pref_key__visibility_nav__followed_tags, true);
} }
public boolean isVisibleInNavProfile() { public boolean isVisibleInNavProfile() {
return getBool(R.string.pref_key__visibility_nav__profile, true); return getBool(prefApp, R.string.pref_key__visibility_nav__profile, true);
} }
public boolean isVisibleInNavContacts() { public boolean isVisibleInNavContacts() {
return getBool(R.string.pref_key__visibility_nav__contacts, false); return getBool(prefApp, R.string.pref_key__visibility_nav__contacts, false);
} }
public boolean isVisibleInNavStatistics() { public boolean isVisibleInNavStatistics() {
return getBool(R.string.pref_key__visibility_nav__statistics, false); return getBool(prefApp, R.string.pref_key__visibility_nav__statistics, false);
} }
public boolean isVisibleInNavReports() { public boolean isVisibleInNavReports() {
return getBool(R.string.pref_key__visibility_nav__reports, false); return getBool(prefApp, R.string.pref_key__visibility_nav__reports, false);
} }
public boolean isVisibleInNavGsantnerAccount() { public boolean isVisibleToggleMobileDesktop() {
return getBool(R.string.pref_key__visibility_nav__gsantner_account, false); return getBool(prefApp, R.string.pref_key__visibility_nav__toggle_mobile_desktop, false);
}
public boolean isVisibleInNavToggleMobileDesktop() {
return getBool(R.string.pref_key__visibility_nav__toggle_mobile_desktop, false);
} }
public boolean isTopbarStreamShortcutEnabled() { public boolean isTopbarStreamShortcutEnabled() {
return getBool(R.string.pref_key__topbar_stream_shortcut, false); return getBool(prefApp, R.string.pref_key__topbar_stream_shortcut, false);
}
public boolean isOpenYoutubeExternalEnabled() {
return getBool(R.string.pref_key__open_youtube_external_enabled, true);
}
public boolean isSwipeRefreshEnabled() {
return getBool(R.string.pref_key__swipe_refresh_enabled, true);
} }
public String getScreenRotation() { public String getScreenRotation() {
return getString(R.string.pref_key__screen_rotation, R.string.rotation_val_system); return getString(prefApp, R.string.pref_key__screen_rotation, R.string.rotation_val_system);
} }
public boolean isAppFirstStart() { public boolean isAppFirstStart(){
boolean value = getBool(R.string.pref_key__app_first_start, true); boolean value = getBool(prefApp, R.string.pref_key__app_first_start, true);
setBool(R.string.pref_key__app_first_start, false); setBool(prefApp, R.string.pref_key__app_first_start, false);
return value; return value;
} }
public boolean isAppCurrentVersionFirstStart(boolean doSet) { public boolean isAppCurrentVersionFirstStart(){
int value = getInt(R.string.pref_key__app_first_start_current_version, -1); int value = getInt(prefApp, R.string.pref_key__app_first_start_current_version, -1);
if (doSet) { setInt(prefApp, R.string.pref_key__app_first_start_current_version, BuildConfig.VERSION_CODE);
setInt(R.string.pref_key__app_first_start_current_version, BuildConfig.VERSION_CODE);
}
return value != BuildConfig.VERSION_CODE && !BuildConfig.IS_TEST_BUILD; return value != BuildConfig.VERSION_CODE && !BuildConfig.IS_TEST_BUILD;
} }
public File getAppSaveDirectory() {
return new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/dandelion");
}
public long getLastVisitedPositionInStream() { public long getLastVisitedPositionInStream() {
return getLong(R.string.pref_key__podprofile_last_stream_position, -1, _prefPod); return getLong(prefPod, R.string.pref_key__podprofile_last_stream_position, -1);
} }
public void setLastVisitedPositionInStream(long timestamp) { public void setLastVisitedPositionInStream(long timestamp) {
setLong(R.string.pref_key__podprofile_last_stream_position, timestamp, _prefPod); setLong(prefPod, R.string.pref_key__podprofile_last_stream_position, timestamp);
} }
public void setLanguage(String value) { public void setLanguage(String value){
setString(R.string.pref_key__language, value); setString(prefApp, R.string.pref_key__language, value);
} }
public String getLanguage() { public String getLanguage(){
return getString(R.string.pref_key__language, ""); return getString(prefApp, R.string.pref_key__language, "");
} }
public void setPrimaryColorSettings(int base, int shade) { public void setPrimaryColorSettings(int base, int shade) {
setInt(R.string.pref_key__primary_color_base, base); setInt(prefApp, R.string.pref_key__primary_color_base, base);
setInt(R.string.pref_key__primary_color_shade, shade); setInt(prefApp, R.string.pref_key__primary_color_shade, shade);
} }
public int[] getPrimaryColorSettings() { public int[] getPrimaryColorSettings() {
return new int[]{ return new int[]{
getInt(R.string.pref_key__primary_color_base, rcolor(R.color.md_blue_650)), getInt(prefApp, R.string.pref_key__primary_color_base, getColorRes(R.color.md_blue_650)),
getInt(R.string.pref_key__primary_color_shade, rcolor(R.color.primary)) getInt(prefApp, R.string.pref_key__primary_color_shade, getColorRes(R.color.primary))
}; };
} }
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public int getPrimaryColor() { public int getPrimaryColor() {
if (isAmoledColorMode()) { return getInt(prefApp, R.string.pref_key__primary_color_shade, getColorRes(
return Color.BLACK; BuildConfig.IS_TEST_BUILD ? R.color.md_brown_800 : R.color.primary));
} else {
return getInt(R.string.pref_key__primary_color_shade, rcolor(
BuildConfig.IS_TEST_BUILD ? R.color.md_brown_800 : R.color.primary));
}
} }
public void setAccentColorSettings(int base, int shade) { public void setAccentColorSettings(int base, int shade) {
setInt(R.string.pref_key__accent_color_base, base); setInt(prefApp, R.string.pref_key__accent_color_base, base);
setInt(R.string.pref_key__accent_color_shade, shade); setInt(prefApp, R.string.pref_key__accent_color_shade, shade);
} }
public int[] getAccentColorSettings() { public int[] getAccentColorSettings() {
return new int[]{ return new int[]{
getInt(R.string.pref_key__accent_color_base, rcolor(R.color.md_green_400)), getInt(prefApp, R.string.pref_key__accent_color_base, getColorRes(R.color.md_green_400)),
getInt(R.string.pref_key__accent_color_shade, rcolor(R.color.accent)) getInt(prefApp, R.string.pref_key__accent_color_shade, getColorRes(R.color.accent))
}; };
} }
public int getAccentColor() { public int getAccentColor() {
return getInt(R.string.pref_key__accent_color_shade, rcolor(R.color.accent)); return getInt(prefApp, R.string.pref_key__accent_color_shade, getColorRes(R.color.accent));
} }
public boolean isExtendedNotificationsActivated() { public boolean isExtendedNotificationsActivated() {
return getBool(R.string.pref_key__extended_notifications, false); return getBool(prefApp, R.string.pref_key__extended_notifications, false);
} }
}
public boolean isAmoledColorMode() {
return getBool(R.string.pref_key__primary_color__amoled_mode, false);
}
public void setAmoledColorMode(boolean enable) {
setBool(R.string.pref_key__primary_color__amoled_mode, enable);
}
public boolean isAdBlockEnabled() {
return getBool(R.string.pref_key__adblock_enable, true);
}
public boolean isEditorStatusBarHidden() {
return getBool(R.string.pref_key__is_overview_statusbar_hidden, false);
}
public void setRecreateMainActivity(boolean value) {
setBool(R.string.pref_key__recreate_main_activity, value);
}
public boolean isRecreateMainActivity() {
boolean value = getBool(R.string.pref_key__recreate_main_activity, false);
setRecreateMainActivity(false);
return value;
}
public boolean isShowTitleInMainView() {
return getBool(R.string.pref_key__show_title, false);
}
}

View file

@ -1,58 +0,0 @@
package com.github.dfa.diaspora_android.util;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import com.github.dfa.diaspora_android.App;
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 ContextUtils extends net.gsantner.opoc.util.ContextUtils {
protected ContextUtils(Context context) {
super(context);
}
public static ContextUtils get() {
return new ContextUtils(App.get());
}
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(ContextUtils.class, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
return new File(
imageFileName + /* prefix */
".jpg", /* suffix */
storageDir.getAbsolutePath() /* directory */
);
}
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());
}
}
}
}
}
}

View file

@ -27,7 +27,7 @@ import com.github.dfa.diaspora_android.data.DiasporaPodList.DiasporaPod;
* Helper class that provides easy access to specific urls related to diaspora * Helper class that provides easy access to specific urls related to diaspora
* Created by vanitasvitae on 10.08.16. * Created by vanitasvitae on 10.08.16.
*/ */
@SuppressWarnings({"unused", "SpellCheckingInspection", "SameParameterValue", "WeakerAccess"}) @SuppressWarnings("unused")
public class DiasporaUrlHelper { public class DiasporaUrlHelper {
private final AppSettings settings; private final AppSettings settings;
@ -62,14 +62,13 @@ public class DiasporaUrlHelper {
public static final String SUBURL_NOTIFICATIONS_MENTIONED = "/notifications?type=mentioned"; public static final String SUBURL_NOTIFICATIONS_MENTIONED = "/notifications?type=mentioned";
public static final String SUBURL_NOTIFICATIONS_RESHARED = "/notifications?type=reshared"; public static final String SUBURL_NOTIFICATIONS_RESHARED = "/notifications?type=reshared";
public static final String SUBURL_NOTIFICATIONS_STARTED_SHARING = "/notifications?type=started_sharing"; public static final String SUBURL_NOTIFICATIONS_STARTED_SHARING = "/notifications?type=started_sharing";
public static final String SUBURL_THEME = "/user/edit";
public DiasporaUrlHelper(AppSettings settings) { public DiasporaUrlHelper(AppSettings settings) {
this.settings = settings; this.settings = settings;
} }
/** /**
* Return a url of the pod set in AppSettingsBase. * Return a url of the pod set in AppSettings.
* Eg. https://pod.geraspora.de * Eg. https://pod.geraspora.de
* *
* @return https://(pod-domain.tld) * @return https://(pod-domain.tld)
@ -152,7 +151,7 @@ public class DiasporaUrlHelper {
* @param profileId Id of the profile to be shown * @param profileId Id of the profile to be shown
* @return https://(pod-domain.tld)/people/(profileId) * @return https://(pod-domain.tld)/people/(profileId)
*/ */
public String getProfileUrl(String profileId) { public String getProfileUrl(long profileId) {
return getPodUrl() + SUBURL_PEOPLE + profileId; return getPodUrl() + SUBURL_PEOPLE + profileId;
} }
@ -230,15 +229,6 @@ public class DiasporaUrlHelper {
return getPodUrl() + SUBURL_SEARCH_TAGS + query; return getPodUrl() + SUBURL_SEARCH_TAGS + query;
} }
/**
* Return a url that queries posts for the given hashtag query
*
* @return https://(pod-domain.tld)/followed_tags
*/
public String getAllFollowedTagsUrl() {
return getPodUrl() + SUBURL_FOLOWED_TAGS;
}
/** /**
* Return a url that queries user accounts for query * Return a url that queries user accounts for query
* *
@ -354,13 +344,4 @@ public class DiasporaUrlHelper {
} }
return app.getString(R.string.aspects); return app.getString(R.string.aspects);
} }
/**
* Return a url that points to the settings of the pod.
*
* @return https://(pod-domain.tld)/user/edit
*/
public String getThemeUrl() {
return getPodUrl() + SUBURL_THEME;
}
} }

View file

@ -0,0 +1,200 @@
/*
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.util;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.RawRes;
import android.support.annotation.StringRes;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.Html;
import android.text.SpannableString;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.TypedValue;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.web.WebHelper;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
public class Helpers {
public static int getColorFromRessource(Context context, int ressourceId) {
Resources res = context.getResources();
if (Build.VERSION.SDK_INT >= 23) {
return res.getColor(ressourceId, context.getTheme());
} else {
return res.getColor(ressourceId);
}
}
public static 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(Helpers.class, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
return new File(
imageFileName + /* prefix */
".jpg", /* suffix */
storageDir.getAbsolutePath() /* directory */
);
}
public static Locale getLocaleByAndroidCode(String code) {
if (!TextUtils.isEmpty(code)) {
return code.contains("-r")
? new Locale(code.substring(0, 2), code.substring(4, 6)) // de-rAT
: new Locale(code); // de
}
return Locale.getDefault();
}
public static String readTextfileFromRawRessource(Context context, int rawRessourceId, String linePrefix, String linePostfix) {
StringBuilder sb = new StringBuilder();
String line;
BufferedReader br = null;
linePrefix = linePrefix == null ? "" : linePrefix;
linePostfix = linePostfix == null ? "" : linePostfix;
try {
br = new BufferedReader(new InputStreamReader(context.getResources().openRawResource(rawRessourceId)));
while ((line = br.readLine()) != null) {
sb.append(linePrefix);
sb.append(line);
sb.append(linePostfix);
sb.append("\n");
}
} catch (Exception ignored) {
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ignored) {
}
}
}
return sb.toString();
}
public static String loadMarkdownFromRawForTextView(Context context, @RawRes int rawMdFile, String prepend) {
try {
return new SimpleMarkdownParser()
.parse(context.getResources().openRawResource(rawMdFile),
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, prepend)
.replaceColor("#000001", ContextCompat.getColor(context, R.color.accent))
.removeMultiNewlines().replaceBulletCharacter("*").getHtml();
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
public static void showDialogWithHtmlTextView(Context context, String html, @StringRes int resTitleId) {
LinearLayout layout = new LinearLayout(context);
TextView textView = new TextView(context);
textView.setMovementMethod(LinkMovementMethod.getInstance());
ScrollView root = new ScrollView(context);
int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
context.getResources().getDisplayMetrics());
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
layoutParams.setMargins(margin, 0, margin, 0);
layout.setLayoutParams(layoutParams);
layout.addView(textView);
root.addView(layout);
textView.setText(new SpannableString(Html.fromHtml(html)));
AlertDialog.Builder dialog = new AlertDialog.Builder(context)
.setPositiveButton(android.R.string.ok, null)
.setTitle(resTitleId)
.setView(root);
dialog.show();
}
public static String colorToHex(int color) {
return "#" + Integer.toHexString(color & 0x00ffffff);
}
public static void printBundle(Bundle savedInstanceState, String k) {
if (savedInstanceState != null) {
for (String key : savedInstanceState.keySet()) {
AppLog.d("SAVED", key + " is a key in the bundle " + k);
Object bun = savedInstanceState.get(key);
if (bun != null) {
if (bun instanceof Bundle) {
printBundle((Bundle) bun, k + "." + key);
} else if (bun instanceof byte[]) {
AppLog.d("SAVED", "Key: " + k + "." + key + ": " + Arrays.toString((byte[]) bun));
} else {
AppLog.d("SAVED", "Key: " + k + "." + key + ": " + bun.toString());
}
}
}
}
}
/**
* Show Information if user is offline, returns true if is not connected to internet
*
* @param context Context
* @param anchor A view anchor
*/
public static boolean showInfoIfUserNotConnectedToInternet(Context context, View anchor) {
boolean isOnline = WebHelper.isOnline(context);
if (!isOnline) {
Snackbar.make(anchor, R.string.no_internet, Snackbar.LENGTH_LONG).show();
}
return !isOnline;
}
/**
* Send an Intent that opens url in any browser
*
* @param context context
* @param url url
*/
public static void openInExternalBrowser(Context context, String url) {
Intent openBrowserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
openBrowserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(openBrowserIntent);
}
}

View file

@ -0,0 +1,202 @@
/*
* ----------------------------------------------------------------------------
* "THE COKE-WARE LIBRARY LICENSE" (Revision 255):
* Gregor Santner <gsantner.github.io> wrote this file. You can do whatever
* you want with this stuff. If we meet some day, and you think this stuff is
* worth it, you can buy me a coke in return. Provided as is without any kind
* of warranty. No attribution required. - Gregor Santner
* ----------------------------------------------------------------------------
*/
package com.github.dfa.diaspora_android.util;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Simple Markdown Parser
* <p>
* Parses most common markdown tags. Only inline tags are supported, multiline/block syntax
* is not supported (citation, multiline code, ..). This is intended to stay as easy as possible.
* <p>
* You can e.g. apply a accent color by replacing #000001 with your accentColor string.
* <p>
* FILTER_ANDROID_TEXTVIEW output is intended to be used at simple Android TextViews,
* were a limited set of html tags is supported. This allow to still display e.g. a simple
* CHANGELOG.md file without inlcuding a WebView for showing HTML, or other additional UI-libraries.
* <p>
* FILTER_HTMLPART is intended to be used at engines understanding most common HTML tags.
* <p>
* You can use this anywhere you want, no backlink/attribution required, but I would appreciate it.
*/
@SuppressWarnings({"WeakerAccess", "CaughtExceptionImmediatelyRethrown"})
public class SimpleMarkdownParser {
public interface SimpleLineFilter {
String filterLine(String line);
}
public static final SimpleLineFilter FILTER_ANDROID_TEXTVIEW = new SimpleLineFilter() {
@Override
public String filterLine(String line) {
// TextView supports a limited set of html tags, most notably
// a href, b, big, font size&color, i, li, small, u
line = line
.replace("", "&nbsp;&nbsp;") // double space/half tab
.replaceAll("^### ([^<]*)", "<br/><big><b><font color='#000000'>$1</font></b></big> ") // h3
.replaceAll("^## ([^<]*)", "<br/><big><big><b><font color='#000000'>$1</font></b></big></big><br/> ") // h2 (DEP: h3)
.replaceAll("^# ([^<]*)", "<br/><big><big><big><b><font color='#000000'>$1</font></b></big></big></big><br/> ") // h1 (DEP: h2,h3)
.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // img
.replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img)
.replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img)
.replaceAll("^(-|\\*) ([^<]*)", "<font color='#000001'>&#8226;</font> $2 ") // unordered list + end line
.replaceAll("^ (-|\\*) ([^<]*)", "&nbsp;&nbsp;<font color='#000001'>&#8226;</font> $2 ") // unordered list2 + end line
.replaceAll("`([^<]*)`", "<font face='monospace'>$1</font>") // code
.replace("\\*", "") // temporary replace escaped star symbol
.replaceAll("\\*\\*([^<]*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star)
.replaceAll("\\*([^<]*)\\*", "<i>$1</i>") // italic (DEP: temp star code)
.replace("", "*") // restore escaped star symbol (DEP: b,i)
.replaceAll(" $", "<br/>") // new line (DEP: ul)
;
return line.isEmpty() ? line + "<br/>" : line;
}
};
public static final SimpleLineFilter FILTER_HTMLPART = new SimpleLineFilter() {
@Override
public String filterLine(String line) {
line = line
.replaceAll("", "&nbsp;&nbsp;") // double space/half tab
.replaceAll("^### ([^<]*)", "<h3>$1</h3>") // h3
.replaceAll("^## ([^<]*)", "<h2>$1</h2>") /// h2 (DEP: h3)
.replaceAll("^# ([^<]*)", "<h1>$1</h1>") // h1 (DEP: h2,h3)
.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<img src=\\'$2\\' alt='$1' />") // img
.replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img)
.replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img)
.replaceAll("^(-|\\*) ([^<]*)", "<font color='#000001'>&#8226;</font> $2 ") // unordered list + end line
.replaceAll("^ (-|\\*) ([^<]*)", "&nbsp;&nbsp;<font color='#000001'>&#8226;</font> $2 ") // unordered list2 + end line
.replaceAll("`([^<]*)`", "<code>$1</code>") // code
.replace("\\*", "") // temporary replace escaped star symbol
.replaceAll("\\*\\*([^<]*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star)
.replaceAll("\\*([^<]*)\\*", "<b>$1</b>") // italic (DEP: temp star)
.replace("", "*") // restore escaped star symbol (DEP: b,i)
.replaceAll(" $", "<br/>") // new line (DEP: ul)
;
return line.isEmpty() ? line + "<br/>" : line;
}
};
//########################
//##
//## Members
//##
//########################
private String html;
public SimpleMarkdownParser parse(String filepath, SimpleLineFilter simpleLineFilter) throws IOException {
return parse(new FileInputStream(filepath), simpleLineFilter, "");
}
public SimpleMarkdownParser parse(InputStream inputStream, SimpleLineFilter simpleLineFilter, String lineMdPrefix) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
String line;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
while ((line = br.readLine()) != null) {
sb.append(simpleLineFilter.filterLine(lineMdPrefix + line));
sb.append("\n");
}
} catch (IOException rethrow) {
html = "";
throw rethrow;
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ignored) {
}
}
}
html = sb.toString().trim();
return this;
}
public String getHtml() {
return html;
}
public SimpleMarkdownParser setHtml(String html) {
this.html = html;
return this;
}
public SimpleMarkdownParser removeMultiNewlines() {
html = html.replace("\n", "").replaceAll("(<br/>){3,}", "<br/><br/>");
return this;
}
public SimpleMarkdownParser replaceBulletCharacter(String replacment) {
html = html.replace("&#8226;", replacment);
return this;
}
public SimpleMarkdownParser replaceColor(String hexColor, int newIntColor) {
html = html.replace(hexColor, colorToHexString(newIntColor));
return this;
}
public static String colorToHexString(int intColor) {
return String.format("#%06X", 0xFFFFFF & intColor);
}
@Override
public String toString() {
return html != null ? html : "";
}
}
/*
// Apply to Android TextView:
textView.setText(new SpannableString(Html.fromHtml(htmlFromParser)));
// As wrapper method, includes applying accent color
public static String loadMarkdownFromRawForTextView(Context context, @RawRes int rawMdFile, String prepend) {
try {
return new SimpleMarkdownParser()
.parse(context.getResources().openRawResource(rawMdFile),
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, prepend)
.replaceColor("#000001", ContextCompat.getColor(context, R.color.accent))
.removeMultiNewlines().replaceBulletCharacter("*").getHtml();
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
// Show HTML a TextView in a scrollable Dialog
public static void showDialogWithHtmlTextView(Context context, String html, @StringRes int resTitleId) {
LinearLayout layout = new LinearLayout(context);
TextView textView = new TextView(context);
textView.setMovementMethod(LinkMovementMethod.getInstance());
ScrollView root = new ScrollView(context);
int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
context.getResources().getDisplayMetrics());
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
layoutParams.setMargins(margin, 0, margin, 0);
layout.setLayoutParams(layoutParams);
layout.addView(textView);
root.addView(layout);
textView.setText(new SpannableString(Html.fromHtml(html)));
AlertDialog.Builder dialog = new AlertDialog.Builder(context)
.setPositiveButton(android.R.string.ok, null)
.setTitle(resTitleId)
.setView(root);
dialog.show();
}
*/

View file

@ -18,10 +18,21 @@
*/ */
package com.github.dfa.diaspora_android.web; package com.github.dfa.diaspora_android.web;
import android.Manifest;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.MutableContextWrapper; import android.content.MutableContextWrapper;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout; import android.os.Environment;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.webkit.WebSettings; import android.webkit.WebSettings;
@ -30,11 +41,21 @@ import android.widget.ProgressBar;
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.activity.MainActivity;
import com.github.dfa.diaspora_android.ui.theme.ThemeHelper; import com.github.dfa.diaspora_android.ui.theme.ThemeHelper;
import com.github.dfa.diaspora_android.ui.theme.ThemedFragment; import com.github.dfa.diaspora_android.ui.theme.ThemedFragment;
import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppLog;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.util.AppSettings;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/** /**
* Fragment with a webView and a ProgressBar. * Fragment with a webView and a ProgressBar.
* This Fragment retains its instance. * This Fragment retains its instance.
@ -44,6 +65,7 @@ import com.github.dfa.diaspora_android.util.AppSettings;
public class BrowserFragment extends ThemedFragment { public class BrowserFragment extends ThemedFragment {
public static final String TAG = "com.github.dfa.diaspora_android.BrowserFragment"; public static final String TAG = "com.github.dfa.diaspora_android.BrowserFragment";
protected View rootLayout;
protected ContextMenuWebView webView; protected ContextMenuWebView webView;
protected ProgressBar progressBar; protected ProgressBar progressBar;
protected AppSettings appSettings; protected AppSettings appSettings;
@ -51,14 +73,20 @@ public class BrowserFragment extends ThemedFragment {
protected WebSettings webSettings; protected WebSettings webSettings;
protected String pendingUrl; protected String pendingUrl;
protected SwipeRefreshLayout swipe;//pull to refresh
@Override @Override
protected int getLayoutResId() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return R.layout.browser__fragment; AppLog.d(this, "onCreateView()");
if (rootLayout == null) {
LayoutInflater inflater1 = inflater.cloneInContext(new MutableContextWrapper(getContext()));
rootLayout = inflater1.inflate(R.layout.browser__fragment, container, false);
} else {
MutableContextWrapper context = (MutableContextWrapper) rootLayout.getContext();
context.setBaseContext(getContext());
}
return rootLayout;
} }
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
AppLog.d(this, "onViewCreated()"); AppLog.d(this, "onViewCreated()");
@ -69,7 +97,7 @@ public class BrowserFragment extends ThemedFragment {
} }
if (this.webView == null) { if (this.webView == null) {
this.webView = view.findViewById(R.id.webView); this.webView = (ContextMenuWebView) view.findViewById(R.id.webView);
getActivity().runOnUiThread(new Runnable() { getActivity().runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -81,7 +109,7 @@ public class BrowserFragment extends ThemedFragment {
} }
if (this.progressBar == null) { if (this.progressBar == null) {
this.progressBar = view.findViewById(R.id.progressBar); this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
} }
if (pendingUrl != null) { if (pendingUrl != null) {
@ -92,26 +120,14 @@ public class BrowserFragment extends ThemedFragment {
webView.setParentActivity(getActivity()); webView.setParentActivity(getActivity());
this.setRetainInstance(true); this.setRetainInstance(true);
//pull to refresh
swipe = view.findViewById(R.id.swipe);
swipe.setDistanceToTriggerSync(2000);
swipe.setOnRefreshListener(() -> reloadUrl());
if (appSettings.isSwipeRefreshEnabled()) {
swipe.setEnabled(true);
} else {
swipe.setRefreshing(false);
swipe.setEnabled(false);
return;
}
} }
@Override @Override
public void onDestroyView() { public void onDestroyView() {
super.onDestroyView(); super.onDestroyView();
if (getRetainInstance() && getView() != null && getView().getParent() instanceof ViewGroup) { if (getRetainInstance() && rootLayout.getParent() instanceof ViewGroup) {
((ViewGroup) getView().getParent()).removeView(getView()); ((ViewGroup) rootLayout.getParent()).removeView(rootLayout);
} }
} }
@ -149,11 +165,98 @@ public class BrowserFragment extends ThemedFragment {
} }
} }
@SuppressWarnings("ResultOfMethodCallIgnored")
protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) {
AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()");
if (android.os.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 AlertDialog.Builder(getContext())
.setMessage(R.string.permissions_screenshot)
.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;
}
}
Date dateNow = new Date();
DateFormat dateFormat = new SimpleDateFormat("yy_MM_dd--HH_mm_ss", Locale.getDefault());
File fileSaveDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/Diaspora");
String fileSaveName = hasToShareScreenshot ? ".DfA_share.jpg" : String.format("DfA_%s.jpg", dateFormat.format(dateNow));
if (!fileSaveDirectory.exists()) {
if (!fileSaveDirectory.mkdirs()) {
AppLog.w(this, "Could not mkdir " + fileSaveDirectory.getAbsolutePath());
}
}
if (!hasToShareScreenshot) {
Snackbar.make(webView, getString(R.string.share__toast_screenshot) + " " + fileSaveName, Snackbar.LENGTH_LONG).show();
}
Bitmap bitmap;
webView.setDrawingCacheEnabled(true);
bitmap = Bitmap.createBitmap(webView.getDrawingCache());
webView.setDrawingCacheEnabled(false);
OutputStream bitmapWriter = null;
try {
bitmapWriter = new FileOutputStream(new File(fileSaveDirectory, fileSaveName));
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, bitmapWriter);
bitmapWriter.flush();
bitmap.recycle();
} catch (Exception e) {
return false;
} finally {
if (bitmapWriter != null) {
try {
bitmapWriter.close();
} catch (IOException _ignSaveored) {/* Nothing */}
}
}
// Only show share intent when Action Share Screenshot was selected
if (hasToShareScreenshot) {
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("image/jpeg");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, webView.getTitle());
sharingIntent.putExtra(Intent.EXTRA_TEXT, webView.getUrl());
Uri bmpUri = Uri.fromFile(new File(fileSaveDirectory, fileSaveName));
sharingIntent.putExtra(Intent.EXTRA_STREAM, bmpUri);
startActivity(Intent.createChooser(sharingIntent, getString(R.string.action_share_dotdotdot)));
} else {
// Broadcast that this file is indexable
File file = new File(fileSaveDirectory, fileSaveName);
Uri uri = Uri.fromFile(file);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri);
getActivity().sendBroadcast(intent);
}
return true;
}
@Override @Override
public String getFragmentTag() { public String getFragmentTag() {
return TAG; return TAG;
} }
@Override
public void onCreateBottomOptionsMenu(Menu menu, MenuInflater inflater) {
/* Nothing to do here */
}
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);
@ -206,7 +309,6 @@ public class BrowserFragment extends ThemedFragment {
@Override @Override
public void run() { public void run() {
getWebView().reload(); getWebView().reload();
swipe.setRefreshing(false);//pull to refresh
} }
}); });

View file

@ -18,27 +18,30 @@
*/ */
package com.github.dfa.diaspora_android.web; package com.github.dfa.diaspora_android.web;
import android.Manifest;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.app.DownloadManager;
import android.content.ClipData; import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Environment;
import android.support.v4.content.LocalBroadcastManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import com.github.dfa.diaspora_android.BuildConfig;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.AppSettings; import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.service.ImageDownloadTask;
import net.gsantner.opoc.util.DownloadTask;
import net.gsantner.opoc.util.PermissionChecker;
import net.gsantner.opoc.util.ShareUtil;
import java.io.File; import java.io.File;
import java.util.Date;
/** /**
* Subclass of WebView which adds a context menu for long clicks on images or links to share, save * Subclass of WebView which adds a context menu for long clicks on images or links to share, save
@ -78,46 +81,106 @@ public class ContextMenuWebView extends NestedWebView {
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
HitTestResult result = getHitTestResult(); HitTestResult result = getHitTestResult();
String url = result.getExtra(); String url = result.getExtra();
final ShareUtil shu = new ShareUtil(context);
final PermissionChecker permc = new PermissionChecker(parentActivity);
final AppSettings appSettings = new AppSettings(context);
switch (item.getItemId()) { switch (item.getItemId()) {
//Save image to external memory //Save image to external memory
case ID_SAVE_IMAGE: { case ID_SAVE_IMAGE: {
if (permc.doIfExtStoragePermissionGranted(context.getString(R.string.image_permission_description__appspecific))) { boolean writeToStoragePermitted = true;
File fileSaveDirectory = appSettings.getAppSaveDirectory(); if (android.os.Build.VERSION.SDK_INT >= 23) {
if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) { int hasWRITE_EXTERNAL_STORAGE = parentActivity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
String filename = "dandelion-" + ShareUtil.SDF_SHORT.format(new Date()) + url.substring(url.lastIndexOf(".")); if (hasWRITE_EXTERNAL_STORAGE != PackageManager.PERMISSION_GRANTED) {
/*Uri source = Uri.parse(url); writeToStoragePermitted = false;
DownloadManager.Request request = new DownloadManager.Request(source); if (!parentActivity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
request.setDestinationUri(Uri.fromFile(new File(fileSaveDirectory, filename))); new AlertDialog.Builder(parentActivity)
((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);*/ .setMessage(R.string.permissions_image)
new DownloadTask(new File(fileSaveDirectory, filename), (ok, dlfile) -> { .setPositiveButton(context.getText(android.R.string.yes), new DialogInterface.OnClickListener() {
if (ok) { @Override
Toast.makeText(context, context.getText(R.string.saving_image_to) + " " + dlfile.getName(), Toast.LENGTH_LONG).show(); public void onClick(DialogInterface dialog, int which) {
} if (android.os.Build.VERSION.SDK_INT >= 23)
}).execute(url); parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE);
}
})
.setNegativeButton(context.getText(android.R.string.no), null)
.show();
}
parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE);
} }
} }
break; if (writeToStoragePermitted) {
} //Make sure, Diaspora Folder exists
File destinationFolder = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora");
if(!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
case ID_SHARE_IMAGE: { if (url != null) {
if (permc.doIfExtStoragePermissionGranted(context.getString(R.string.image_permission_description__appspecific))) { Uri source = Uri.parse(url);
File fileSaveDirectory = appSettings.getAppSaveDirectory(); DownloadManager.Request request = new DownloadManager.Request(source);
if (permc.mkdirIfStoragePermissionGranted(fileSaveDirectory)) { File destinationFile = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora/"+ System.currentTimeMillis() + ".png");
String filename = ".dandelion-shared" + url.substring(url.lastIndexOf("."));
new DownloadTask(new File(fileSaveDirectory, filename), (ok, dlfile) -> { request.setDestinationUri(Uri.fromFile(destinationFile));
if (ok) { ((DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE)).enqueue(request);
Toast.makeText(context, context.getText(R.string.saving_image_to) + " " + dlfile.getName(), Toast.LENGTH_LONG).show();
shu.shareStream(dlfile, "image/" + dlfile.getAbsolutePath().lastIndexOf(".") + 1); Toast.makeText(context, context.getText(R.string.share__toast_saved_image_to_location) + " " +
} destinationFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
}).execute(url);
} }
} }
break;
} }
break;
case ID_SHARE_IMAGE:
if (url != null) {
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__ACCESS_EXTERNAL_STORAGE);
}
})
.setNegativeButton(context.getText(android.R.string.no), null)
.show();
} else {
parentActivity.requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
MainActivity.REQUEST_CODE__ACCESS_EXTERNAL_STORAGE);
}
}
}
if (writeToStoragePermitted) {
//Make sure, Diaspora Folder exists
File destinationFolder = new File(Environment.getExternalStorageDirectory() + "/Pictures/Diaspora");
if(!destinationFolder.exists()) {
destinationFolder.mkdirs();
}
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, getResources().getString(R.string.action_share_dotdotdot)));
}
}.execute(url);
}
} else {
Toast.makeText(context, "Cannot share image: url is null", Toast.LENGTH_SHORT).show();
}
break;
case ID_IMAGE_EXTERNAL_BROWSER: case ID_IMAGE_EXTERNAL_BROWSER:
if (url != null) { if (url != null) {
@ -132,7 +195,7 @@ public class ContextMenuWebView extends NestedWebView {
if (url != null) { if (url != null) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(ClipData.newPlainText("text", url)); clipboard.setPrimaryClip(ClipData.newPlainText("text", url));
Toast.makeText(context, R.string.link_adress_copied, Toast.LENGTH_SHORT).show(); Toast.makeText(context, R.string.share__toast_link_address_copied, Toast.LENGTH_SHORT).show();
} }
break; break;
@ -144,7 +207,7 @@ public class ContextMenuWebView extends NestedWebView {
sendIntent.putExtra(Intent.EXTRA_TEXT, url); sendIntent.putExtra(Intent.EXTRA_TEXT, url);
sendIntent.setType("text/plain"); sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, getResources() context.startActivity(Intent.createChooser(sendIntent, getResources()
.getText(R.string.share_link_address))); .getText(R.string.context_menu_share_link)));
} }
break; break;
} }
@ -157,16 +220,16 @@ public class ContextMenuWebView extends NestedWebView {
result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) { result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
// Menu options for an image. // Menu options for an image.
menu.setHeaderTitle(result.getExtra()); menu.setHeaderTitle(result.getExtra());
menu.add(0, ID_SAVE_IMAGE, 0, context.getString(R.string.save_image)).setOnMenuItemClickListener(handler); 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.open_in_external_browser)).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.share_image)).setOnMenuItemClickListener(handler); menu.add(0, ID_SHARE_IMAGE, 0, context.getString(R.string.context_menu_share_image)).setOnMenuItemClickListener(handler);
menu.add(0, ID_COPY_IMAGE_LINK, 0, context.getString(R.string.copy_image_address_to_clipboard)).setOnMenuItemClickListener(handler); menu.add(0, ID_COPY_IMAGE_LINK, 0, context.getString(R.string.context_menu_copy_image_link)).setOnMenuItemClickListener(handler);
} else if (result.getType() == HitTestResult.ANCHOR_TYPE || } else if (result.getType() == HitTestResult.ANCHOR_TYPE ||
result.getType() == HitTestResult.SRC_ANCHOR_TYPE) { result.getType() == HitTestResult.SRC_ANCHOR_TYPE) {
// Menu options for a hyperlink. // Menu options for a hyperlink.
menu.setHeaderTitle(result.getExtra()); menu.setHeaderTitle(result.getExtra());
menu.add(0, ID_COPY_LINK, 0, context.getString(R.string.copy_link_adress_to_clipboard)).setOnMenuItemClickListener(handler); 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.share_link_address)).setOnMenuItemClickListener(handler); menu.add(0, ID_SHARE_LINK, 0, context.getString(R.string.context_menu_share_link)).setOnMenuItemClickListener(handler);
} }
} }

View file

@ -18,51 +18,32 @@
*/ */
package com.github.dfa.diaspora_android.web; package com.github.dfa.diaspora_android.web;
import android.annotation.TargetApi;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import android.webkit.CookieManager; import android.webkit.CookieManager;
import android.webkit.WebResourceResponse;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.data.DiasporaPodList; import com.github.dfa.diaspora_android.data.DiasporaPodList;
import com.github.dfa.diaspora_android.util.AppSettings;
import net.gsantner.opoc.util.AdBlock;
public class CustomWebViewClient extends WebViewClient { public class CustomWebViewClient extends WebViewClient {
private final App app; private final App app;
private String lastLoadUrl = ""; private String lastLoadUrl = "";
private boolean isAdBlockEnabled = false;
AppSettings appSettings = AppSettings.get();
public CustomWebViewClient(App app, WebView webView) { public CustomWebViewClient(App app, WebView webView) {
this.app = app; this.app = app;
isAdBlockEnabled = AppSettings.get().isAdBlockEnabled();
} }
//Open non-diaspora links in customtab/external browser //Open non-diaspora links in customtab/external browser
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
DiasporaPodList.DiasporaPod pod = AppSettings.get().getPod(); String host = app.getSettings().getPod().getPodUrl().getHost();
String host = null;
if (pod != null && pod.getPodUrl() != null && pod.getPodUrl().getHost() != null) {
host = pod.getPodUrl().getHost();
}
if (url.startsWith("https://dia.so/") if (url.startsWith("https://" + host)
|| (host != null && (url.startsWith("https://" + host) || url.startsWith("http://" + host)
|| url.startsWith("http://" + host)))) { || url.startsWith("https://dia.so/")) {
return false; return false;
}//make youtube links open external-->never customtab
else if (appSettings.isOpenYoutubeExternalEnabled() && (url.startsWith("https://youtube.com/") || url.startsWith("https://www.youtube.com/") || url.startsWith("https://m.youtube.com/") || url.startsWith("https://youtu.be/"))) {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
} else { } else {
Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL); Intent i = new Intent(MainActivity.ACTION_OPEN_EXTERNAL_URL);
i.putExtra(MainActivity.EXTRA_URL, url); i.putExtra(MainActivity.EXTRA_URL, url);
@ -76,7 +57,7 @@ public class CustomWebViewClient extends WebViewClient {
final CookieManager cookieManager = app.getCookieManager(); final CookieManager cookieManager = app.getCookieManager();
String cookies = cookieManager.getCookie(url); String cookies = cookieManager.getCookie(url);
DiasporaPodList.DiasporaPod pod = AppSettings.get().getPod(); DiasporaPodList.DiasporaPod pod = app.getSettings().getPod();
if (cookies != null) { if (cookies != null) {
cookieManager.setCookie(url, cookies); cookieManager.setCookie(url, cookies);
@ -91,15 +72,4 @@ public class CustomWebViewClient extends WebViewClient {
} }
} }
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
if (isAdBlockEnabled && AdBlock.getInstance().isAdHost(url)) {
return AdBlock.createEmptyResponse();
}
return super.shouldInterceptRequest(view, url);
}
} }

View file

@ -18,6 +18,7 @@
*/ */
package com.github.dfa.diaspora_android.web; package com.github.dfa.diaspora_android.web;
import android.content.DialogInterface;
import android.webkit.JsResult; import android.webkit.JsResult;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
@ -61,16 +62,23 @@ public class DiasporaStreamWebChromeClient extends FileUploadWebChromeClient {
@Override @Override
public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) { public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(view.getContext(), AppSettings.get()); ThemedAlertDialogBuilder builder = new ThemedAlertDialogBuilder(view.getContext(), new AppSettings(view.getContext()));
builder.setTitle(view.getContext().getString(R.string.confirmation)) builder.setTitle(view.getContext().getString(R.string.confirmation))
.setMessage(message) .setMessage(message)
.setPositiveButton(android.R.string.ok, (dialog, which) -> result.confirm()) .setPositiveButton(android.R.string.ok,
.setNegativeButton(android.R.string.cancel, (dialog, which) -> result.cancel()) new DialogInterface.OnClickListener() {
.setOnCancelListener(dialog -> { public void onClick(DialogInterface dialog, int which) {
result.cancel(); result.confirm();
dialog.dismiss(); }
}) })
.create().show(); .setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
result.cancel();
}
})
.create()
.show();
return true; return true;
} }

View file

@ -89,9 +89,9 @@ public class NestedWebView extends WebView implements NestedScrollingChild {
stopNestedScroll(); stopNestedScroll();
break; break;
} }
if (event != null) { if (event != null) {
event.recycle(); event.recycle();
} }
return returnValue; return returnValue;
} }

View file

@ -55,7 +55,7 @@ public class ProxyHandler {
public void updateProxySettings(Context context) { public void updateProxySettings(Context context) {
AppLog.d(this, "UpdateProxySettings()"); AppLog.d(this, "UpdateProxySettings()");
AppSettings appSettings = AppSettings.get(); AppSettings appSettings = new AppSettings(context);
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(tmp); StrictMode.setThreadPolicy(tmp);
@ -86,7 +86,7 @@ public class ProxyHandler {
private void updateWebViewProxySettings(WebView wv, Context context) { private void updateWebViewProxySettings(WebView wv, Context context) {
AppLog.d(this, "UpdateWebViewProxySettings()"); AppLog.d(this, "UpdateWebViewProxySettings()");
AppSettings appSettings = AppSettings.get(); AppSettings appSettings = new AppSettings(context);
StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(tmp); StrictMode.setThreadPolicy(tmp);

View file

@ -32,6 +32,7 @@ import com.github.dfa.diaspora_android.activity.MainActivity;
/** /**
* Created by Gregor Santner on 07.08.16. * Created by Gregor Santner on 07.08.16.
* https://gsantner.github.io
*/ */
public class WebHelper { public class WebHelper {
@ -106,11 +107,10 @@ public class WebHelper {
"})();"); "})();");
} }
private static String lastUpdateTitleByUrl = ""; private static String lastUpdateTitleByUrl ="";
public static synchronized void sendUpdateTitleByUrlIntent(String url, Context context){
public static synchronized void sendUpdateTitleByUrlIntent(String url, Context context) {
// Ignore javascript stuff // Ignore javascript stuff
if (url != null && url.startsWith("javascript:")) { if (url != null && url.startsWith("javascript:")){
return; return;
} }

View file

@ -41,9 +41,6 @@ public class CustomTabsHelper {
static final String BETA_PACKAGE = "com.chrome.beta"; static final String BETA_PACKAGE = "com.chrome.beta";
static final String DEV_PACKAGE = "com.chrome.dev"; static final String DEV_PACKAGE = "com.chrome.dev";
static final String LOCAL_PACKAGE = "com.google.android.apps.chrome"; static final String LOCAL_PACKAGE = "com.google.android.apps.chrome";
static final String CHROMIUM = "org.chromium.chrome";
static final String FENNEC = "org.mozilla.fennec_fdroid";
static final String KLAR = "org.mozilla.klar";
private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE = private static final String EXTRA_CUSTOM_TABS_KEEP_ALIVE =
"android.support.customtabs.extra.KEEP_ALIVE"; "android.support.customtabs.extra.KEEP_ALIVE";
@ -104,12 +101,6 @@ public class CustomTabsHelper {
sPackageNameToUse = DEV_PACKAGE; sPackageNameToUse = DEV_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) { } else if (packagesSupportingCustomTabs.contains(LOCAL_PACKAGE)) {
sPackageNameToUse = LOCAL_PACKAGE; sPackageNameToUse = LOCAL_PACKAGE;
} else if (packagesSupportingCustomTabs.contains(CHROMIUM)) {
sPackageNameToUse = CHROMIUM;
} else if (packagesSupportingCustomTabs.contains(FENNEC)) {
sPackageNameToUse = FENNEC;
} else if (packagesSupportingCustomTabs.contains(KLAR)) {
sPackageNameToUse = KLAR;
} }
return sPackageNameToUse; return sPackageNameToUse;
} }
@ -146,6 +137,6 @@ public class CustomTabsHelper {
* @return All possible chrome package names that provide custom tabs feature. * @return All possible chrome package names that provide custom tabs feature.
*/ */
public static String[] getPackages() { public static String[] getPackages() {
return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE, CHROMIUM, FENNEC, KLAR}; return new String[]{"", STABLE_PACKAGE, BETA_PACKAGE, DEV_PACKAGE, LOCAL_PACKAGE};
} }
} }

View file

@ -1,160 +0,0 @@
/*#######################################################
*
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
*
* License: Apache 2.0
* https://github.com/gsantner/opoc/#licensing
* https://www.apache.org/licenses/LICENSE-2.0
*
#########################################################*/
package net.gsantner.opoc.activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import net.gsantner.opoc.android.dummy.MenuItemDummy;
import net.gsantner.opoc.util.ContextUtils;
import butterknife.ButterKnife;
/**
* A common base fragment to extend from
*/
public abstract class GsFragmentBase extends Fragment {
private boolean _fragmentFirstTimeVisible = true;
private final Object _fragmentFirstTimeVisibleSync = new Object();
protected ContextUtils _cu;
protected Bundle _savedInstanceState = null;
protected Menu _fragmentMenu = new MenuItemDummy.Menu();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
/**
* Inflate the fragments layout. Don't override this method, just supply the needed
* {@link LayoutRes} via abstract method {@link #getLayoutResId()}, super does the rest
*/
@Deprecated
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
_cu = new ContextUtils(inflater.getContext());
_cu.setAppLanguage(getAppLanguage());
_savedInstanceState = savedInstanceState;
if (getLayoutResId() == 0) {
Log.e(getClass().getCanonicalName(), "Error: GsFragmentbase.onCreateview: Returned 0 for getLayoutResId");
}
View view = inflater.inflate(getLayoutResId(), container, false);
ButterKnife.bind(this, view);
return view;
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.postDelayed(() -> {
synchronized (_fragmentFirstTimeVisibleSync) {
if (getUserVisibleHint() && isVisible() && _fragmentFirstTimeVisible) {
_fragmentFirstTimeVisible = false;
onFragmentFirstTimeVisible();
}
}
}, 1);
}
/**
* Get a tag from the fragment, allows faster distinction
*
* @return This fragments tag
*/
public abstract String getFragmentTag();
/**
* Get the layout to be inflated in the fragment
*
* @return Layout resource id
*/
@LayoutRes
protected abstract int getLayoutResId();
/**
* Event to be called when the back button was pressed
* True should be returned when this was handled by the fragment
* and no further handling in the view hierarchy is needed
*
* @return True if back handled by fragment
*/
public boolean onBackPressed() {
return false;
}
/**
* Set the language to be used in this fragment
* Defaults to resolve the language from sharedpreferences: pref_key__language
*
* @return Empty string for system language, or an android locale code
*/
public String getAppLanguage() {
if (getContext() != null) {
return getContext().getSharedPreferences("app", Context.MODE_PRIVATE)
.getString("pref_key__language", "");
}
return "";
}
/**
* This will be called when this fragment gets the first time visible
*/
public void onFragmentFirstTimeVisible() {
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
synchronized (_fragmentFirstTimeVisibleSync) {
if (isVisibleToUser && _fragmentFirstTimeVisible) {
_fragmentFirstTimeVisible = false;
onFragmentFirstTimeVisible();
}
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
_fragmentMenu = menu;
}
public Menu getFragmentMenu() {
return _fragmentMenu;
}
/**
* Get the toolbar from activity
* Requires id to be set to @+id/toolbar
*/
@SuppressWarnings("ConstantConditions")
protected Toolbar getToolbar() {
try {
return (Toolbar) getActivity().findViewById(new ContextUtils(getActivity()).getResId(ContextUtils.ResType.ID, "toolbar"));
} catch (Exception e) {
return null;
}
}
}

View file

@ -1,351 +0,0 @@
/*
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
* License: Creative Commons Zero (CC0 1.0) / Public Domain
* http://creativecommons.org/publicdomain/zero/1.0/
*
* You can do whatever you want with this. If we meet some day, and you think it is worth it,
* you can buy me a drink in return. Provided as is without any kind of warranty. Do not blame
* or ask for support if something goes wrong. - Gregor Santner
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package net.gsantner.opoc.android.dummy;
import android.content.ComponentName;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.view.ActionProvider;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
public class MenuItemDummy implements MenuItem {
private final int _itemId;
public MenuItemDummy(final int itemId) {
_itemId = itemId;
}
@Override
public int getItemId() {
return _itemId;
}
@Override
public int getGroupId() {
return 0;
}
@Override
public int getOrder() {
return 0;
}
@Override
public MenuItem setTitle(CharSequence title) {
return null;
}
@Override
public MenuItem setTitle(int title) {
return null;
}
@Override
public CharSequence getTitle() {
return null;
}
@Override
public MenuItem setTitleCondensed(CharSequence title) {
return null;
}
@Override
public CharSequence getTitleCondensed() {
return null;
}
@Override
public MenuItem setIcon(Drawable icon) {
return null;
}
@Override
public MenuItem setIcon(int iconRes) {
return null;
}
@Override
public Drawable getIcon() {
return null;
}
@Override
public MenuItem setIntent(Intent intent) {
return null;
}
@Override
public Intent getIntent() {
return null;
}
@Override
public MenuItem setShortcut(char numericChar, char alphaChar) {
return null;
}
@Override
public MenuItem setNumericShortcut(char numericChar) {
return null;
}
@Override
public char getNumericShortcut() {
return 0;
}
@Override
public MenuItem setAlphabeticShortcut(char alphaChar) {
return null;
}
@Override
public char getAlphabeticShortcut() {
return 0;
}
@Override
public MenuItem setCheckable(boolean checkable) {
return null;
}
@Override
public boolean isCheckable() {
return false;
}
@Override
public MenuItem setChecked(boolean checked) {
return null;
}
@Override
public boolean isChecked() {
return false;
}
@Override
public MenuItem setVisible(boolean visible) {
return null;
}
@Override
public boolean isVisible() {
return false;
}
@Override
public MenuItem setEnabled(boolean enabled) {
return null;
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public boolean hasSubMenu() {
return false;
}
@Override
public SubMenu getSubMenu() {
return null;
}
@Override
public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
return null;
}
@Override
public ContextMenu.ContextMenuInfo getMenuInfo() {
return null;
}
@Override
public void setShowAsAction(int actionEnum) {
}
@Override
public MenuItem setShowAsActionFlags(int actionEnum) {
return null;
}
@Override
public MenuItem setActionView(View view) {
return null;
}
@Override
public MenuItem setActionView(int resId) {
return null;
}
@Override
public View getActionView() {
return null;
}
@Override
public MenuItem setActionProvider(ActionProvider actionProvider) {
return null;
}
@Override
public ActionProvider getActionProvider() {
return null;
}
@Override
public boolean expandActionView() {
return false;
}
@Override
public boolean collapseActionView() {
return false;
}
@Override
public boolean isActionViewExpanded() {
return false;
}
@Override
public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
return null;
}
public static class Menu implements android.view.Menu {
@Override
public MenuItem add(CharSequence title) {
return add(0, 0, 0, "");
}
@Override
public MenuItem add(int titleRes) {
return add(0, 0, 0, "");
}
@Override
public MenuItem add(int groupId, int itemId, int order, CharSequence title) {
return new MenuItemDummy(itemId);
}
@Override
public MenuItem add(int groupId, int itemId, int order, int titleRes) {
return add(0, 0, 0, "");
}
@Override
public SubMenu addSubMenu(CharSequence title) {
return null;
}
@Override
public SubMenu addSubMenu(int titleRes) {
return null;
}
@Override
public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) {
return null;
}
@Override
public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) {
return null;
}
@Override
public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) {
return 0;
}
@Override
public void removeItem(int id) {
}
@Override
public void removeGroup(int groupId) {
}
@Override
public void clear() {
}
@Override
public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
}
@Override
public void setGroupVisible(int group, boolean visible) {
}
@Override
public void setGroupEnabled(int group, boolean enabled) {
}
@Override
public boolean hasVisibleItems() {
return false;
}
@Override
public MenuItem findItem(int id) {
return null;
}
@Override
public int size() {
return 0;
}
@Override
public MenuItem getItem(int index) {
return null;
}
@Override
public void close() {
}
@Override
public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
return false;
}
@Override
public boolean isShortcutKey(int keyCode, KeyEvent event) {
return false;
}
@Override
public boolean performIdentifierAction(int id, int flags) {
return false;
}
@Override
public void setQwertyMode(boolean isQwerty) {
}
}
}

View file

@ -1,58 +0,0 @@
/*
* Maintained 2017-2023 by Gregor Santner <gsantner AT mailbox DOT org>
* License: Creative Commons Zero (CC0 1.0) / Public Domain
* http://creativecommons.org/publicdomain/zero/1.0/
*
* You can do whatever you want with this. If we meet some day, and you think it is worth it,
* you can buy me a drink in return. Provided as is without any kind of warranty. Do not blame
* or ask for support if something goes wrong. - Gregor Santner
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
package net.gsantner.opoc.android.dummy;
import android.text.Editable;
import android.text.TextWatcher;
import net.gsantner.opoc.util.Callback;
@SuppressWarnings({"unused", "SpellCheckingInspection"})
public class TextWatcherDummy implements TextWatcher {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
}
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
}
@Override
public void afterTextChanged(final Editable s) {
}
public static TextWatcher before(final Callback.a4<CharSequence, Integer, Integer, Integer> impl) {
return new TextWatcherDummy() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
impl.callback(s, start, count, after);
}
};
}
public static TextWatcher on(final Callback.a4<CharSequence, Integer, Integer, Integer> impl) {
return new TextWatcherDummy() {
public void onTextChanged(final CharSequence s, final int start, final int before, final int count) {
impl.callback(s, start, before, count);
}
};
}
public static TextWatcher after(final Callback.a1<Editable> impl) {
return new TextWatcherDummy() {
public void afterTextChanged(final Editable s) {
impl.callback(s);
}
};
}
}

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